Announcement

Collapse
No announcement yet.

Trapping Keyboard Input; a basic question from a GUI programming novice

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

    Trapping Keyboard Input; a basic question from a GUI programming novice

    I've been working my way round the forum and the MSDN website yesterday trying to sort this out and am still confused. I know this is a simple problem, but if anyone could provide add the minimum code necessary to the following program outline, that would be so helpful and instructive.

    Code:
      
    #COMPILER PBWIN 9
    #COMPILE EXE
    #INCLUDE "Win32API.inc"
    DEFLNG a-z
    
    GLOBAL main_handle AS LONG
    
    FUNCTION PBMAIN () AS LONG
    
        DIALOG NEW 0, a$, , , 400, 200,_
        %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU OR %WS_THICKFRAME OR %WS_CLIPCHILDREN, 0 TO main_handle
    
        DIALOG SHOW MODAL main_handle, CALL GS_DlgProc() TO a
    
    END FUNCTION
    
    CALLBACK FUNCTION GS_DlgProc()
    
        SELECT CASE CB.MSG
            CASE %WM_INITDIALOG
     
            CASE %WM_KEYDOWN
                
                MSGBOX "Key pressed"
    
            CASE %WM_SYSKEYDOWN
    
                MSGBOX "<ALT> Key pressed"
    
    
        END SELECT
        
    END FUNCTION
    What I want to be able to do is to get the key pressed on the keyboard (all of them, not just the letters!), along with information on whether the <SHIFT>, <CONTROL>, <ALT> or <ALTGR> keys were pressed at the same time. In PBCC, the latter information was provided by the INSHIFT function, but missing in PBWin.

    I've looked at the various TranslateMessage and ToASCIIEx functions described on the MSDN website, but really can't see whether, how and/or where to insert these into the simple callback code above.

    Can the above callback loop be simply modified to get the keyboard codes easily?

    Peter

    #2
    Code by Egbert Zijlema slightly modified

    Code:
    'Reposted several times trying to get the weird characters out
    #DIM ALL
    #INCLUDE "win32api.inc"
    'in DDT.INC
    %mod_alt                 = &h00000001
    %mod_control             = &h00000002
    %mod_shift               = &h00000004
    %mod_win                 = &h00000008
    %mod_left                = &h00008000
    %mod_right               = &h00004000
    %mod_on_keyup            = &h00000800
    %mod_ignore_all_modifier = &h00000400
    
    GLOBAL ghKeyb AS DWORD, ghDlg AS DWORD                               ' global handles
    FUNCTION PBMAIN() AS LONG
      LOCAL sTxt AS STRING
      'Code by Egbert Zijlema slightly modified, it doesn't have to be!
      'Noticed beep (coming from the label control) added a textbox
      'http://www.powerbasic.com/support/pbforums/showthread.php?t=24721
      'Added CASE %VK_RETURN : sTmp = sTmp & "Enter/Return key"
      DIALOG NEW 0, " Test KeyBoardHook", , , 200, 100, %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU TO ghDlg
      CONTROL ADD LABEL,  ghDlg,  1001,   "", 10, 30, 180, 12, %SS_CENTER OR %SS_SUNKEN OR %SS_CENTERIMAGE
      CONTROL ADD TEXTBOX,  ghDlg,  1002,   "", 10, 50, 180, 12, %SS_CENTER OR %SS_SUNKEN OR %SS_CENTERIMAGE
      CONTROL ADD BUTTON, ghDlg, %IDOK, "OK", 80, 70,  40, 14, %BS_DEFPUSHBUTTON
      DIALOG SHOW MODAL ghDlg CALL MainDlgProc
    END FUNCTION
    FUNCTION KeyBoardProc(BYVAL iCode AS INTEGER, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS DWORD
      LOCAL  lShiftMode AS LONG
      IF ISFALSE(lParam AND &H80000000) THEN                             ' bit 31 (2^31) NOT set: some key is pressed
        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, %WM_USER + 101, wParam, lShiftMode            ' wParam holds virtual keycode
      END IF
      FUNCTION = CallNextHookEx(ghKeyb, iCode, wParam, lParam)           ' proceed
    END FUNCTION
    CALLBACK FUNCTION MainDlgProc()
      SELECT CASE CBMSG
        CASE %WM_INITDIALOG
          CONTROL SET COLOR CBHNDL, 1001, -1, %WHITE
          CONTROL SET COLOR CBHNDL, 1002, -1, %WHITE
          ghKeyb = SetWindowsHookEx(%WH_KEYBOARD, CODEPTR(KeyBoardProc), 0, GetCurrentThreadId)
        CASE %WM_DESTROY
          UnhookWindowsHookEx ghKeyb
        CASE %WM_COMMAND
          SELECT CASE CBCTLMSG
            CASE %BN_CLICKED
              IF CBCTL = %IDOK THEN
                MSGBOX "About to end dialog"
                DIALOG END CBHNDL
              END IF
          END SELECT
        CASE %WM_HELP
          CONTROL SET TEXT CBHNDL, 1001, "F1 (help)"
        CASE %WM_USER + 101
          LOCAL sTmp AS STRING
          ' check shift mode info by processing lParam
          IF (CBLPARAM AND %MOD_ALT) THEN sTmp = "Alt+"
          IF (CBLPARAM AND %MOD_CONTROL) THEN sTmp = sTmp & "Ctrl+"
          IF (CBLPARAM AND %MOD_SHIFT) THEN sTmp = sTmp & "Shift+"
          ' now check which key (virt. key code or ASCII code) has been pressed
          SELECT CASE AS LONG CBWPARAM
            CASE 8          : sTmp = sTmp & "BackSpace"
            CASE 9          : sTmp = sTmp & "Tab"
            CASE %VK_PGUP   : sTmp = sTmp & "PgUp"
            CASE %VK_PGDN   : sTmp = sTmp & "PgDn"
            CASE %VK_END    : sTmp = sTmp & "End"
            CASE %VK_HOME   : sTmp = sTmp & "Home"
            CASE %VK_LEFT   : sTmp = sTmp & "Left Arrow"
            CASE %VK_UP     : sTmp = sTmp & "Up Arrow"
            CASE %VK_RIGHT  : sTmp = sTmp & "Right Arrow"
            CASE %VK_DOWN   : sTmp = sTmp & "Down Arrow"
            CASE %VK_INSERT : sTmp = sTmp & "Ins"
            CASE %VK_DELETE : sTmp = sTmp & "Del"
            CASE %VK_RETURN : sTmp = sTmp & "Enter/Return key"
            CASE %VK_F1
              SELECT CASE AS LONG CBLPARAM
                CASE 0, _                                                ' no shift keys pressed
                     %MOD_CONTROL, _                                     ' Ctrl pressed
                     %MOD_SHIFT, _                                       ' Shift pressed
                     %MOD_CONTROL + %MOD_SHIFT, _                        ' Ctrl + Shift pressed
                     %MOD_ALT + %MOD_CONTROL + %MOD_SHIFT                ' Alt + Ctrl + Shift pressed
                  ' NOTE: F1, Ctrl/F1, Shift/F1, Ctrl/Shift/F1 and Alt/Ctrl/Shift/F1 fire the %WM_HELP message
                  ' so let %WM_HELP do the job and exit here
                  EXIT FUNCTION
              END SELECT
              sTmp = sTmp & "F1"
            CASE %VK_F2 TO %VK_F10                                       ' function keys F2 - F10
              sTmp = sTmp & "F" & FORMAT$(CBWPARAM - %VK_F1 + 1)
            ' numpad keys
            CASE %VK_NUMPAD0 TO %VK_NUMPAD9
              sTmp = sTmp & CHR$(CBWPARAM - %VK_NUMPAD0 + 48) & " (numpad)"
            CASE %VK_MULTIPLY  : sTmp = sTmp & "Multiply (numpad)"
            CASE %VK_ADD       : sTmp = sTmp & "Add (numpad)"
            CASE %VK_SUBTRACT  : sTmp = sTmp & "Substract (numpad)"
            CASE %VK_DECIMAL   : sTmp = sTmp & "Decimal (numpad)"
            ' end numpad keys
            ' printable chars
            CASE 48 TO 57, 65 TO 90                                      ' 0 - 9, A - Z (ASCII codes)
              sTmp = sTmp & CHR$(CBWPARAM)
            CASE ELSE                                                    ' don't process unwanted keys
              CONTROL SET TEXT CBHNDL, 1001, "UNWANTED" + STR$(CBWPARAM)
              EXIT FUNCTION
          END SELECT
          CONTROL SET TEXT CBHNDL, 1001, sTmp  + " >  " + STR$(CBWPARAM) 'doesn't cause beep
      END SELECT
    END FUNCTION
    Last edited by Mike Doty; 31 Jul 2009, 06:43 AM. Reason: Added %MOD equates and reposted due to weird characters inserted.

    Comment


      #3
      Brilliant, well almost, .. the equates beginning with %MOD_ are not defined. Are they supposed to be in win32api.inc

      Peter

      Comment


        #4
        Equates with %MOD?
        Are you using an older win32api.inc?

        Comment


          #5
          I use the includes by Jose Roca.
          Found these in ddt.inc, sorry.

          Reposted above.
          Also noticed weird characters in middle of posting.
          Maybe code /code must be upper case.
          Haven't been able to figure it out.
          I get bad source code postings most of the time.

          Code:
          %mod_alt                 = &h00000001
          %mod_control             = &h00000002
          %mod_shift              = &h00000004
          %mod_win                 = &h00000008
          %mod_left                = &h00008000
          %mod_right               = &h00004000
          %mod_on_keyup            = &h00000800
          %mod_ignore_all_modifier = &h00000400
          Last edited by Mike Doty; 31 Jul 2009, 06:45 AM.

          Comment


            #6
            Reposted again.
            Not sure why my postings get weird characters in them.
            It might be using code /code block lower case?

            Comment


              #7
              Yes, works now, the wife and children will be pleased as well.....!

              Peter

              Comment


                #8
                In general "GUI" programs do not process all the keyboard input; they wait until they receive a notification that a key has been pressed whilst a 'control of interest' has the keyboard focus.

                If there are certain 'keys of interest' you want to trap at various times, you can use keyboard accelerators and/or the RegisterHotKey() function; in either case you will receive a specific notification message when that 'key of interest' has been pressed and released.
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                  #9
                  Michael,
                  Thanks for cleaning up your unedited posting.
                  Why not post a working example?
                  He stated he wants all the keys.
                  What I want to be able to do is to get the key pressed on the keyboard (all of them, not just the letters!), along with information on whether the <SHIFT>, <CONTROL>, <ALT> or <ALTGR> keys were pressed at the same time. In PBCC, the latter information was provided by the INSHIFT function, but missing in PBWin.
                  Last edited by Mike Doty; 31 Jul 2009, 07:59 AM.

                  Comment


                    #10
                    >He stated he wants all the keys.

                    He may have said that, but I doubt that's really the case. I will bet there is a fairly short list of keys in which there is any realy interest.

                    Methinks this is yet another case of deciding "how" to <do something> without really considering alternatives.

                    You don't need another example: Egbert's code (Keyboard hook) does get all the keys.

                    Your mod says you "'Added CASE %VK_RETURN." But since you don't have a CASE for ALL possible keys, you really do't NEED all the keys, do you?

                    As I said, I think someone got locked into a 'how' without considering alternatives: to the man who knows but the hammer, all challenges look like a nail. The solution remains the same: get some more tools.

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

                    Comment


                      #11
                      Why not post some code to show another way?
                      %VK_RETURN was added to show that it is returned before the dialog ends.
                      I also added a message box so the dialog wasn't destroyed before seeing the return code.
                      All the virtual keys can be displayed without the CASE statements.
                      Last edited by Mike Doty; 31 Jul 2009, 08:51 AM.

                      Comment


                        #12
                        >Why not post some code to show another way?

                        Because Egbert's code (keyboard hook) is the best way I can think of - if you REALLY "Want all keys." If it ain't broke, why should I fix it?

                        I simply don't believe OP REALLY "wants all keys." eg, I cannot imagine what possible interest there is in LEFT-SHIFT+ALT+lowercase "q"

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

                        Comment


                          #13
                          Besides, we should not encourage the use of keyboard hooks by a self-described "GUI programming novice."

                          Better he should walk before he runs.

                          Better still he should understand the GUI programming model before writing GUI applications.

                          Yes, that is subjective. But I'm stickin' with it.


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

                          Comment


                            #14
                            Just to interrupt... The old program written in PBCC did have a huge series of keyboard shortcuts, including <CNTRL>F1 to F12, <ALT>F1-F12, CNTRL<PageUp>, basically any combination of <ALT>, <SHIFT> and <CONTROL> with all the keys (except CAPS LOCK!!). The program now means I can implement them, and still pass on the <ALT>F etc. codes needed for the menu. The only non-standard thing is that many of the items within the menus have <ALT> shortcuts, which I want to keep even though it might annoy some users.

                            Playing around with the callback this afternoon seems to have produced a workable system, although unfortunately many the codes returned by non-character keys in Windows are different from the old values returned by INKEY$ in PBCC. Anyway, so far, I can read the keyboard through callback within the new program,although I'm sure there will be further hurdles to overcome...

                            Ar least I don't have to use GRAPHIC INKEY$ !!!

                            Peter

                            Comment


                              #15
                              > The old program written in PBCC...

                              Console programs are not GUI programs.
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                                #16
                                The old program written in PBCC did have a huge series of keyboard shortcuts, including <CNTRL>F1 to F12, <ALT>F1-F12, CNTRL<PageUp>, basically any combination of <ALT>, <SHIFT> and <CONTROL>
                                Keyboard accelerators are calling to you.......
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                  #17
                                  Virtual Keyboard

                                  Sorry, I thought I had posted this earlier but would my Virtual Keyboard in the source code forum be of any help?

                                  (I will try to revisit the code and modify if it is of use)

                                  Engineer's Motto: If it aint broke take it apart and fix it

                                  "If at 1st you don't succeed... call it version 1.0"

                                  "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                  "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                  Comment


                                    #18
                                    Problem with menu bar in Mike Doty's program

                                    I've just gone back to the "project" and have incorporated the keyboard trap written by Mike Doty (in post #2). As mentioned it works well, but there is a problem that it continues to work when really not appropriate.

                                    one example is pull down menus. If you click on a pull down menu and use up and down arrow keys to scroll through the choices, this still activates the keyboard callback whereas ideally it shouldn't. To make the problem worse, none of the callback function values (eg. CBHNDL, CBCTL) differentiate between keypresses in a menu from those done elsewhere (CBCTL actually reports the key value, ie. the same value as CBWPARAM).

                                    Another problem is that if the main dialog (with the trap in its callback function) calls a child (modal) dialog, the keyboard trap still catches keypresses whereas I had hoped that by running the child menu modally it shouldn't interfere.

                                    Is there any way to turn off the keyboard trap when required and to identify in what context the keypress occurs?

                                    Thanks

                                    Peter

                                    Comment


                                      #19
                                      If you click on a pull down menu and use up and down arrow keys to scroll through the choices, this still activates the keyboard callback whereas ideally it shouldn't.
                                      It shouldn't? The keyboard was used, wasn't it?

                                      To make the problem worse, none of the callback function values (eg. CBHNDL, CBCTL) differentiate between keypresses in a menu from those done elsewhere (CBCTL actually reports the key value, ie. the same value as CBWPARAM).
                                      The DDT system variables "CB*" are not valid for use with menus.. they are only valid in response to a notification message sent to a dialog procedure or DDT-specific control-level callback function named in a 'CONTROL ADD statement.'

                                      Another problem is that if the main dialog (with the trap in its callback function) calls a child (modal) dialog, the keyboard trap still catches keypresses whereas I had hoped that by running the child menu modally it shouldn't interfere.
                                      ???

                                      Above you complain that the keyboard trap does not work when you think it should; now you are complaining that it does work when it shouldn't. ("should" and "shouldn't" here highly subjective and used only to provide context). Do you want to fish or cut bait?

                                      Why don't you just quit screwing around with keyboard traps and use the tools provided?

                                      Any user action - any user action - will generate a notification message to your dialog procedure; all you have to do is process those notification messages. Yes, some 'actions of interest' may - may - require you to subclass a control or two, but there are plenty of examples of doing that on this board.

                                      Yes, you may have to 'rethink' how your program reacts to user actions... but this is not MS-DOS, and for sure it's not your father's Oldsmobasic.

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

                                      Comment


                                        #20
                                        Egbert is the author.
                                        PowerBASIC and related source code. Please do not post questions or discussions, just source code.

                                        Comment

                                        Working...
                                        X
                                        😀
                                        🥰
                                        🤢
                                        😎
                                        😡
                                        👍
                                        👎