{"id":182,"date":"2007-05-12T16:44:15","date_gmt":"2007-05-12T14:44:15","guid":{"rendered":" http:\/\/www.nsonic.de\/blog\/2007\/05\/nsonic-homepage-2\/"},"modified":"2007-05-12T16:44:17","modified_gmt":"2007-05-12T14:44:17","slug":"nsonic-homepage-2","status":"publish","type":"post","link":"https:\/\/www.nsonic.de\/blog\/2007\/05\/nsonic-homepage-2\/","title":{"rendered":"nSonic Homepage"},"content":{"rendered":"<p><em>> yes, but what is the virtual-key code for ALT+F?<br \/>\n><br \/>\n<\/em><br \/>\nThere ain&#8217;t one, this is a key *combination*, not a single keystroke.<br \/>\nIt would require several messages:<\/p>\n<p>  wm_syskeydown for VK_MENU (alt)<br \/>\n  wm_syskeydown for Ord(&#8216;F&#8217;)<br \/>\n  wm_syschar    for &#8216;F&#8217;<br \/>\n  wm_syskeyup   for Ord(&#8216;F&#8217;),<br \/>\n  wm_syskeyup   for VM_MENU<\/p>\n<p>The wm_syschar is not required if you use POstMessage instead of<br \/>\nSendMessage. However, it will probably still not work if the receiver<br \/>\nwindow checks for Alt down with GetKeyState instead of looking at the<br \/>\nAlt bit in the messages lparam, sending these messages does not change<br \/>\nthe keystate array. The following procedure fixes this by changing the<br \/>\narray manually:<br \/>\n<!--more--><br \/>\n[code lang=&#8221;delphi&#8221;]{************************************************************<br \/>\n * Procedure PostKeyEx<br \/>\n *<br \/>\n * Parameters:<br \/>\n *  hWindow: target window to be send the keystroke<br \/>\n *  key    : virtual keycode of the key to send. For printable<br \/>\n *           keys this is simply the ANSI code (Ord(character)).<br \/>\n *  shift  : state of the modifier keys. This is a set, so you<br \/>\n *           can set several of these keys (shift, control, alt,<br \/>\n *           mouse buttons) in tandem. The TShiftState type is<br \/>\n *           declared in the Classes Unit.<br \/>\n *  specialkey: normally this should be False. Set it to True to<br \/>\n *           specify a key on the numeric keypad, for example.<br \/>\n *           If this parameter is true, bit 24 of the lparam for<br \/>\n *           the posted WM_KEY* messages will be set.<br \/>\n * Description:<br \/>\n *  This procedure sets up Windows key state array to correctly<br \/>\n *  reflect the requested pattern of modifier keys and then posts<br \/>\n *  a WM_KEYDOWN\/WM_KEYUP message pair to the target window. Then<br \/>\n *  Application.ProcessMessages is called to process the messages<br \/>\n *  before the keyboard state is restored.<br \/>\n * Error Conditions:<br \/>\n *  May fail due to lack of memory for the two key state buffers.<br \/>\n *  Will raise an exception in this case.<br \/>\n * NOTE:<br \/>\n *  Setting the keyboard state will not work across applications<br \/>\n *  running in different memory spaces on Win32 unless<br \/>\nAttachThreadInput<br \/>\n *  is used to connect to the target thread first.<br \/>\n *Created: 02\/21\/96 16:39:00 by P. Below<br \/>\n ************************************************************}<br \/>\nProcedure PostKeyEx( hWindow: HWnd; key: Word; Const shift:<br \/>\nTShiftState;<br \/>\n                     specialkey: Boolean );<br \/>\nType<br \/>\n  TBuffers = Array [0..1] of TKeyboardState;<br \/>\nVar<br \/>\n  pKeyBuffers : ^TBuffers;<br \/>\n  lparam: LongInt;<br \/>\nBegin<br \/>\n  (* check if the target window exists *)<br \/>\n  If IsWindow(hWindow) Then Begin<br \/>\n    (* set local variables to default values *)<br \/>\n    pKeyBuffers := Nil;<br \/>\n    lparam := MakeLong(0, MapVirtualKey(key, 0));<\/p>\n<p>    (* modify lparam if special key requested *)<br \/>\n    If specialkey Then<br \/>\n      lparam := lparam or $1000000;<\/p>\n<p>    (* allocate space for the key state buffers *)<br \/>\n    New(pKeyBuffers);<br \/>\n    try<br \/>\n      (* Fill buffer 1 with current state so we can later restore it.<br \/>\n         Null out buffer 0 to get a &#8220;no key pressed&#8221; state. *)<br \/>\n      GetKeyboardState( pKeyBuffers^[1] );<br \/>\n      FillChar(pKeyBuffers^[0], Sizeof(TKeyboardState), 0);<\/p>\n<p>      (* set the requested modifier keys to &#8220;down&#8221; state in the buffer<br \/>\n*)<br \/>\n      If ssShift In shift Then<br \/>\n        pKeyBuffers^[0][VK_SHIFT] := $80;<br \/>\n      If ssAlt In shift Then Begin<br \/>\n        (* Alt needs special treatment since a bit in lparam needs also<br \/>\nbe set *)<br \/>\n        pKeyBuffers^[0][VK_MENU] := $80;<br \/>\n        lparam := lparam or $20000000;<br \/>\n      End;<br \/>\n      If ssCtrl In shift Then<br \/>\n        pKeyBuffers^[0][VK_CONTROL] := $80;<br \/>\n      If ssLeft In shift Then<br \/>\n        pKeyBuffers^[0][VK_LBUTTON] := $80;<br \/>\n      If ssRight In shift Then<br \/>\n        pKeyBuffers^[0][VK_RBUTTON] := $80;<br \/>\n      If ssMiddle In shift Then<br \/>\n        pKeyBuffers^[0][VK_MBUTTON] := $80;<\/p>\n<p>      (* make out new key state array the active key state map *)<br \/>\n      SetKeyboardState( pKeyBuffers^[0] );<\/p>\n<p>      (* post the key messages *)<br \/>\n      If ssAlt In Shift Then Begin<br \/>\n        PostMessage( hWindow, WM_SYSKEYDOWN, key, lparam);<br \/>\n        PostMessage( hWindow, WM_SYSKEYUP, key, lparam or $C0000000);<br \/>\n      End<br \/>\n      Else Begin<br \/>\n        PostMessage( hWindow, WM_KEYDOWN, key, lparam);<br \/>\n        PostMessage( hWindow, WM_KEYUP, key, lparam or $C0000000);<br \/>\n      End;<br \/>\n      (* process the messages *)<br \/>\n      Application.ProcessMessages;<\/p>\n<p>      (* restore the old key state map *)<br \/>\n      SetKeyboardState( pKeyBuffers^[1] );<br \/>\n    finally<br \/>\n      (* free the memory for the key state buffers *)<br \/>\n      If pKeyBuffers <> Nil Then<br \/>\n        Dispose( pKeyBuffers );<br \/>\n    End; { If }<br \/>\n  End;<br \/>\nEnd; { PostKeyEx }            <\/p>\n<p>PostKeyEx( targetWnd, Ord(&#8216;F&#8217;), [ssAlt], false );<br \/>\n[\/code]<\/p>\n<p>would send an Alt-F. But only if the target window is in the current<br \/>\nprocess. Since each thread has its own keystate array the code cannot<br \/>\nwork properly if the receiver is in another process or even another<br \/>\nthread of the current process. In this case the only option is to make<br \/>\nthe receiver window active (SetForegroundWindow) and use keybd_event to<br \/>\nmanufacture the keystrokes.<\/p>\n<p>[code lang=&#8221;delphi&#8221;]{************************************************************<br \/>\n * Procedure PostKeyEx32<br \/>\n *<br \/>\n * Parameters:<br \/>\n *  key    : virtual keycode of the key to send. For printable<br \/>\n *           keys this is simply the ANSI code (Ord(character)).<br \/>\n *  shift  : state of the modifier keys. This is a set, so you<br \/>\n *           can set several of these keys (shift, control, alt,<br \/>\n *           mouse buttons) in tandem. The TShiftState type is<br \/>\n *           declared in the Classes Unit.<br \/>\n *  specialkey: normally this should be False. Set it to True to<br \/>\n *           specify a key on the numeric keypad, for example.<br \/>\n * Description:<br \/>\n *  Uses keybd_event to manufacture a series of key events matching<br \/>\n *  the passed parameters. The events go to the control with focus.<br \/>\n *  Note that for characters key is always the upper-case version of<br \/>\n *  the character. Sending without any modifier keys will result in<br \/>\n *  a lower-case character, sending it with [ssShift] will result<br \/>\n *  in an upper-case character!<br \/>\n *Created: 17.7.98 by P. Below<br \/>\n ************************************************************}<br \/>\nProcedure PostKeyEx32( key: Word; Const shift: TShiftState;<br \/>\n                     specialkey: Boolean );<br \/>\n  Type<br \/>\n    TShiftKeyInfo = Record<br \/>\n                      shift: Byte;<br \/>\n                      vkey : Byte;<br \/>\n                    End;<br \/>\n    byteset = Set of 0..7;<br \/>\n  Const<br \/>\n    shiftkeys: Array [1..3] of TShiftKeyInfo =<br \/>\n      ((shift: Ord(ssCtrl); vkey: VK_CONTROL ),<br \/>\n       (shift: Ord(ssShift); vkey: VK_SHIFT ),<br \/>\n       (shift: Ord(ssAlt); vkey: VK_MENU ));<br \/>\n  Var<br \/>\n    flag: DWORD;<br \/>\n    bShift: ByteSet absolute shift;<br \/>\n    i: Integer;<br \/>\n  Begin<br \/>\n    For i := 1 To 3 Do Begin<br \/>\n      If shiftkeys[i].shift In bShift Then<br \/>\n        keybd_event( shiftkeys[i].vkey,<br \/>\n                     MapVirtualKey(shiftkeys[i].vkey, 0),<br \/>\n                     0, 0);<br \/>\n    End; { For }<br \/>\n    If specialkey Then<br \/>\n      flag := KEYEVENTF_EXTENDEDKEY<br \/>\n    Else<br \/>\n      flag := 0;<\/p>\n<p>    keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );<br \/>\n    flag := flag or KEYEVENTF_KEYUP;<br \/>\n    keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );<\/p>\n<p>    For i := 3 DownTo 1 Do Begin<br \/>\n      If shiftkeys[i].shift In bShift Then<br \/>\n        keybd_event( shiftkeys[i].vkey,<br \/>\n                     MapVirtualKey(shiftkeys[i].vkey, 0),<br \/>\n                     KEYEVENTF_KEYUP, 0);<br \/>\n    End; { For }<br \/>\n  End; { PostKeyEx32 }<br \/>\n[\/code]<\/p>\n<p>[tags]Delphi, Misc, Keyboard[\/tags]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>> yes, but what is the virtual-key code for ALT+F? > There ain&#8217;t one, this is a key *combination*, not a single keystroke.&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[11],"tags":[75,111,107],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p71Tml-2W","_links":{"self":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/182"}],"collection":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/comments?post=182"}],"version-history":[{"count":0,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/182\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/media?parent=182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/categories?post=182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/tags?post=182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}