Mastodon
Programmierung

nSonic Homepage

> yes, but what is the virtual-key code for ALT+F?
>

There ain’t one, this is a key *combination*, not a single keystroke.
It would require several messages:

wm_syskeydown for VK_MENU (alt)
wm_syskeydown for Ord(‘F’)
wm_syschar for ‘F’
wm_syskeyup for Ord(‘F’),
wm_syskeyup for VM_MENU

The wm_syschar is not required if you use POstMessage instead of
SendMessage. However, it will probably still not work if the receiver
window checks for Alt down with GetKeyState instead of looking at the
Alt bit in the messages lparam, sending these messages does not change
the keystate array. The following procedure fixes this by changing the
array manually:

[code lang=”delphi”]{************************************************************
* Procedure PostKeyEx
*
* Parameters:
* hWindow: target window to be send the keystroke
* key : virtual keycode of the key to send. For printable
* keys this is simply the ANSI code (Ord(character)).
* shift : state of the modifier keys. This is a set, so you
* can set several of these keys (shift, control, alt,
* mouse buttons) in tandem. The TShiftState type is
* declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to
* specify a key on the numeric keypad, for example.
* If this parameter is true, bit 24 of the lparam for
* the posted WM_KEY* messages will be set.
* Description:
* This procedure sets up Windows key state array to correctly
* reflect the requested pattern of modifier keys and then posts
* a WM_KEYDOWN/WM_KEYUP message pair to the target window. Then
* Application.ProcessMessages is called to process the messages
* before the keyboard state is restored.
* Error Conditions:
* May fail due to lack of memory for the two key state buffers.
* Will raise an exception in this case.
* NOTE:
* Setting the keyboard state will not work across applications
* running in different memory spaces on Win32 unless
AttachThreadInput
* is used to connect to the target thread first.
*Created: 02/21/96 16:39:00 by P. Below
************************************************************}
Procedure PostKeyEx( hWindow: HWnd; key: Word; Const shift:
TShiftState;
specialkey: Boolean );
Type
TBuffers = Array [0..1] of TKeyboardState;
Var
pKeyBuffers : ^TBuffers;
lparam: LongInt;
Begin
(* check if the target window exists *)
If IsWindow(hWindow) Then Begin
(* set local variables to default values *)
pKeyBuffers := Nil;
lparam := MakeLong(0, MapVirtualKey(key, 0));

(* modify lparam if special key requested *)
If specialkey Then
lparam := lparam or $1000000;

(* allocate space for the key state buffers *)
New(pKeyBuffers);
try
(* Fill buffer 1 with current state so we can later restore it.
Null out buffer 0 to get a “no key pressed” state. *)
GetKeyboardState( pKeyBuffers^[1] );
FillChar(pKeyBuffers^[0], Sizeof(TKeyboardState), 0);

(* set the requested modifier keys to “down” state in the buffer
*)
If ssShift In shift Then
pKeyBuffers^[0][VK_SHIFT] := $80;
If ssAlt In shift Then Begin
(* Alt needs special treatment since a bit in lparam needs also
be set *)
pKeyBuffers^[0][VK_MENU] := $80;
lparam := lparam or $20000000;
End;
If ssCtrl In shift Then
pKeyBuffers^[0][VK_CONTROL] := $80;
If ssLeft In shift Then
pKeyBuffers^[0][VK_LBUTTON] := $80;
If ssRight In shift Then
pKeyBuffers^[0][VK_RBUTTON] := $80;
If ssMiddle In shift Then
pKeyBuffers^[0][VK_MBUTTON] := $80;

(* make out new key state array the active key state map *)
SetKeyboardState( pKeyBuffers^[0] );

(* post the key messages *)
If ssAlt In Shift Then Begin
PostMessage( hWindow, WM_SYSKEYDOWN, key, lparam);
PostMessage( hWindow, WM_SYSKEYUP, key, lparam or $C0000000);
End
Else Begin
PostMessage( hWindow, WM_KEYDOWN, key, lparam);
PostMessage( hWindow, WM_KEYUP, key, lparam or $C0000000);
End;
(* process the messages *)
Application.ProcessMessages;

(* restore the old key state map *)
SetKeyboardState( pKeyBuffers^[1] );
finally
(* free the memory for the key state buffers *)
If pKeyBuffers <> Nil Then
Dispose( pKeyBuffers );
End; { If }
End;
End; { PostKeyEx }

PostKeyEx( targetWnd, Ord(‘F’), [ssAlt], false );
[/code]

would send an Alt-F. But only if the target window is in the current
process. Since each thread has its own keystate array the code cannot
work properly if the receiver is in another process or even another
thread of the current process. In this case the only option is to make
the receiver window active (SetForegroundWindow) and use keybd_event to
manufacture the keystrokes.

[code lang=”delphi”]{************************************************************
* Procedure PostKeyEx32
*
* Parameters:
* key : virtual keycode of the key to send. For printable
* keys this is simply the ANSI code (Ord(character)).
* shift : state of the modifier keys. This is a set, so you
* can set several of these keys (shift, control, alt,
* mouse buttons) in tandem. The TShiftState type is
* declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to
* specify a key on the numeric keypad, for example.
* Description:
* Uses keybd_event to manufacture a series of key events matching
* the passed parameters. The events go to the control with focus.
* Note that for characters key is always the upper-case version of
* the character. Sending without any modifier keys will result in
* a lower-case character, sending it with [ssShift] will result
* in an upper-case character!
*Created: 17.7.98 by P. Below
************************************************************}
Procedure PostKeyEx32( key: Word; Const shift: TShiftState;
specialkey: Boolean );
Type
TShiftKeyInfo = Record
shift: Byte;
vkey : Byte;
End;
byteset = Set of 0..7;
Const
shiftkeys: Array [1..3] of TShiftKeyInfo =
((shift: Ord(ssCtrl); vkey: VK_CONTROL ),
(shift: Ord(ssShift); vkey: VK_SHIFT ),
(shift: Ord(ssAlt); vkey: VK_MENU ));
Var
flag: DWORD;
bShift: ByteSet absolute shift;
i: Integer;
Begin
For i := 1 To 3 Do Begin
If shiftkeys[i].shift In bShift Then
keybd_event( shiftkeys[i].vkey,
MapVirtualKey(shiftkeys[i].vkey, 0),
0, 0);
End; { For }
If specialkey Then
flag := KEYEVENTF_EXTENDEDKEY
Else
flag := 0;

keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );
flag := flag or KEYEVENTF_KEYUP;
keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );

For i := 3 DownTo 1 Do Begin
If shiftkeys[i].shift In bShift Then
keybd_event( shiftkeys[i].vkey,
MapVirtualKey(shiftkeys[i].vkey, 0),
KEYEVENTF_KEYUP, 0);
End; { For }
End; { PostKeyEx32 }
[/code]

[tags]Delphi, Misc, Keyboard[/tags]

0 Kommentare zu “nSonic Homepage

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.