Announcement

Collapse
No announcement yet.

KeyBd_Event question

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • KeyBd_Event question

    The following code sends a Ctrl-F to my callback but needs an additional press of the Control key to allow typing. If I unremark the last statement it doesn't send the Ctrl-F. What is the correct way to use KeyBd_Event to send a Ctrl-F.

    Thanks,

    Bob Mechler
    Code:
                  KeyBd_Event %VK_CONTROL, MapVirtualKey(%VK_CONTROL,0),0,0: SLEEP 0
                  KeyBd_Event %VK_F,MapVirtualKey(%VK_F,0),0,0: SLEEP 0
                  KeyBd_Event %VK_F,MapVirtualKey(%VK_F, 0), %KEYEVENTF_KEYUP, 0: SLEEP 0
                  'KeyBd_Event %VK_CONTROL, MapVirtualKey(%VK_CONTROL, 0), %KEYEVENTF_KEYUP, 0: SLEEP 0

  • #2
    Bob,

    'SendInput' is less critical what timing is concerned than 'KeyBd_Event'.
    I suggest you try that instead.
    This small sub sends a CTRL-ed key.
    Code:
    SendCTRLKey(%VK_F)
    Code:
    SUB SendCTRLKey(BYVAL kbvalue AS LONG)
        LOCAL inpAPI() AS INPUTAPI
        DIM inpAPI(0:3)
    
        inpAPI(0).dtype          = %INPUT_KEYBOARD  
        inpAPI(0).m.ki.wVk         = %VK_CONTROL    
        inpAPI(0).m.ki.dwFlags     = 0                               
        inpAPI(0).m.ki.wScan       = MAPVIRTUALKEY(%VK_CONTROL, 0)                
    
        
        inpAPI(1).dtype          = %INPUT_KEYBOARD  
        inpAPI(1).m.ki.wVk         = kbvalue             
        inpAPI(1).m.ki.dwFlags     = 0                
        inpAPI(1).m.ki.wScan       = MAPVIRTUALKEY(kbvalue, 0)                
                        
        inpAPI(2).dtype          = %INPUT_KEYBOARD   
        inpAPI(2).m.ki.wVk         = kbvalue             
        inpAPI(2).m.ki.dwFlags     = %KEYEVENTF_KEYUP  
        inpAPI(2).m.ki.wScan       = MAPVIRTUALKEY(kbvalue, 0)                
    
        inpAPI(3).dtype          = %INPUT_KEYBOARD   
        inpAPI(3).m.ki.wVk         = %VK_CONTROL
        inpAPI(3).m.ki.dwFlags     = %KEYEVENTF_KEYUP  
        inpAPI(3).m.ki.wScan       = MAPVIRTUALKEY(%VK_CONTROL, 0)                
                  
        SendInput(4, inpAPI(0), SIZEOF(inpAPI(0)))
    
    END SUB
    Kind regards
    Last edited by Eddy Van Esch; 5 Apr 2008, 06:56 PM.
    Eddy

    Comment


    • #3
      Nice code Eddie. I'm sure it works find in the standard situation. I think the keyboard hooking I'm doing is part of the problem. I've been trying to adapt the keyboard hook code from Egbert Zijlema to pass a Ctrl-F and then send a WM_COMMAND message to the desired control callback. See the second piece of code.

      When I press Ctrl-F it fires the Add_Party_Button properly. If I trigger a Control-F via a menu item callback it doesn't work with the code I posted or your code. I probably have a %TRUE or %FALSE in the wrong place. All the code in Poffs does it the way I was doing it (with the last line unremmed out).

      I probably need to use accelerators or keyboard hooking but not both on the same key combination.

      Code:
      FUNCTION KeyboardHook(BYVAL HookCode AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS DWORD
      LOCAL lShiftMode AS LONG
       FUNCTION = CallNextHookEx(hKeyboardHook, HookCode, wParam, lParam)
      
       IF HookCode = %HC_ACTION THEN
         IF ISFALSE(lParam AND &H80000000) THEN 'Key is released
           SELECT CASE wParam
             CASE %VK_F1 TO %VK_F12,%VK_RIGHT,%VK_LEFT
               'Send a custom message to our dialog
               IF ISTRUE(lParam AND &H20000000) THEN lShiftMode = %MOD_ALT      ' bit 29 (2^29) set: Alt-key is down
               IF (GetAsyncKeyState(%VK_CONTROL) AND &H8000) THEN _
                                   lShiftMode = lShiftMode + %MOD_CONTROL      ' eventually add Ctrl
               IF (GetAsyncKeyState(%VK_SHIFT) AND &H8000) _
                                THEN lShiftMode = lShiftMode + %MOD_SHIFT      ' eventually add Shift
               PostMessage ghDlg(0), %HookedKeyboardMessage, wParam, lShiftMode'lParam
               FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
             CASE %VK_F         
               'Send a custom message to our dialog
               IF ISTRUE(lParam AND &H20000000) THEN lShiftMode = %MOD_ALT      ' bit 29 (2^29) set: Alt-key is down
               IF (GetAsyncKeyState(%VK_CONTROL) AND &H8000) THEN _
                                   lShiftMode = lShiftMode + %MOD_CONTROL      ' eventually add Ctrl
               IF (GetAsyncKeyState(%VK_SHIFT) AND &H8000) _
                                THEN lShiftMode = lShiftMode + %MOD_SHIFT      ' eventually add Shift
               IF lShiftMode <> 0 THEN                          
                 PostMessage ghDlg(0), %HookedKeyboardMessage, wParam, lShiftMode   'lParam
                 FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
               ELSE  
                 FUNCTION = %FALSE 'Allows a plain F to pass through to the dialog otherwise I couldn't type an F in a textbox 
               END IF  
           END SELECT 
         END IF
       END IF
      
      END FUNCTION
      '
      '
      '
         CASE %HookedKeyboardMessage
           SELECT CASE CBWPARAM
             CASE %VK_F 'This works fine if CTRL-F is typed but not if I use KEYBD_EVENT as in the previous post
               IF CBLPARAM = %MOD_CONTROL THEN
                  DIALOG SEND CBHNDL, %WM_COMMAND, MAKDWD(%Find_Acct, %BN_CLICKED), GetDlgItem(CBHNDL, %Find_Acct)           
               END IF 
             CASE %VK_F1
             CASE %VK_F2
               CONTROL SEND CBHNDL, %tab_control, %TCM_GETCURSEL, 0, 0 TO tabhit 
      	 SELECT CASE tabhit 'tabhit tells us which tab dialog is active
      	   CASE 0
      	   CASE 1
      	   CASE 2
      	   CASE 3
                          DIALOG SEND gHdlg(4), %WM_COMMAND, MAKDWD(%Add_Party_Button, %BN_CLICKED), GetDlgItem(gHdlg(4), %Add_Party_Button) 'F2 Add Party
      	   CASE 4
      	   CASE 5
      	   CASE 6
      	END SELECT  
             CASE %VK_F3,%VK_LEFT
                DIALOG SEND CBHNDL, %WM_COMMAND, MAKDWD(%b_PrevRec, %BN_CLICKED), GetDlgItem(CBHNDL, %b_PrevRec)
             CASE %VK_F4,%VK_RIGHT
                DIALOG SEND CBHNDL, %WM_COMMAND, MAKDWD(%b_NextRec, %BN_CLICKED), GetDlgItem(CBHNDL, %b_NextRec)
             CASE %VK_F5
             CASE %VK_F6
                DIALOG SEND CBHNDL, %WM_COMMAND, MAKDWD(%b_NameLookup, %BN_CLICKED), GetDlgItem(CBHNDL, %b_NameLookup)                
             CASE %VK_F10
               
           END SELECT
      Last edited by BOB MECHLER; 5 Apr 2008, 09:20 PM. Reason: More information added

      Comment


      • #4
        Instead of generating a Ctrl-F when I already had this key hooked to send a message to a control, I decided to just send the message from the menu item callback instead of the Ctrl-F. The Ctrl-F on the menu item serves to remind the user of the keyboard shortcut.

        Bob Mechler

        Comment


        • #5
          Also, keyboard input - real or faked - goes to the window with the keyboard focus. If something has grabbed the focus (eg a MSGBOX with focus not restored) then that input goes "somewhere else."

          But I think you are on a better track to cut out the multiple methods of making something happen.. and better still to to send the matching WM_COMMAND command message to yourself, keeping control out of foreign hands.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Are accelerators like those created in PB Forms to work with menus really just a more convenient way of creating a keyboard hook? They seem so similar in how they work. I detached the menu code and the accelerators seemed to still work just like a keyboard hook. I'l a little confused about when to use which method. The Alt-A where the caption of a button is &Add Record seems very sound. The menu builder seems to prefer Ctrl- keys.

            Bob Mechler

            Comment


            • #7
              The difference is, with a hook procedure - if global (systemwide) in implementation - striking the "magic key" can be made to send a signal or message to any process regardless of the current active process or who has the keyboard focus, whereas accelerators only pick off keystrokes when the target process is the current process.

              Darned, I'm afraid I've given another answer which is "application-specific." I sure seem to do that a lot, don't I?

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment

              Working...
              X