Announcement

Collapse
No announcement yet.

Key strokes....again!

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

  • Key strokes....again!

    Hello,
    I'm working on a vehicle model with a 3-D view. It's too hard to drive using mouse clicks on buttons. I've searched through the forums for info on processing key strokes and am lost. Using "Programming Windows 95" as a reference, I still am having problems.
    I'm using DDT, and tried getting a key press by capturing %WM_CHAR in the main dialog callback function. The WParam is supposed to be the ASCII code for the key (right?).

    Code:
    CALLBACK FUNCTION Maincallback()
    SELECT CASE CBMSG
        CASE %WM_CHAR
             IF CBWPARAM= ASC("A") THEN
                INCR SOMETHING
                END IF
    
         CASE %WM_TIMER
         CALL DRAW_STUFF()
        END SELECT
    END FUNCTION
    This attempt is just the latest of many. This main dialog is Modal. Since the program beeps anytime a key is pressed at all, regardless of whether I try to capture anything or not, I haven't continued beyond this. There's numerous postings on this type of thing throughout the forum, and I'd be happy to look at any of them. What should I be looking for? Do I need to (trembling in fear) sub class something? I'd like to use the keypad here, but getting any keys at all to work would be fine.
    Thanks!





    [This message has been edited by Todd Wasson (edited May 16, 2000).]
    Todd Wasson
    http://PerformanceSimulations.Com
    PowerBasic Racing Simulator (October 2007 clip - 15.1MB wmv file) http:http://www.performancesimulations.co...m-GenIV-12.wmv

  • #2
    keystroke messages are translated by the message loop of the window with focus, and dispatched to the appropriate control callback function. the 'problem' is that the message pump for a modal dialog is handled by windows, and therefore you can't intercept the keystoke messages.

    there are a few ways to achieve your goal:

    1. change the code to use a modeless dialog, and use a getmessage() message pump instead of a dialog doevents pump (you have to provide your own message pump loop for non-modal dialogs and windows). within this loop you can intercept keystroke messages and handle them separately. this is not an "officially supported" technique, but no problems have been reported yet. semen posted some code to do this a couple of months back - http://www.powerbasic.com/support/pb...ead.php?t=2037


    2. use a hook function and intercept keystroke messages. see the win32.hlp file topic "hooks".

    3. redesign your app to use a native window instead of a dialog (this is an extreme solution!), but this way you can provide a conventional message pump in your winmain() function in which you can trap and handle keystroke messages.

    4. subclass all controls on the dialog and handle %wm_char messages. this works until no controls have keyboard focus... not an ideal solution, but this technique does have it's uses:


    ------------------
    lance
    powerbasic support
    mailto:[email protected][email protected]</a>
    Lance
    mailto:[email protected]

    Comment


    • #3
      Thanks, Lance. Semen's code works great (as usual ) In PBMAIN(), I used this:
      Code:
       DIALOG SHOW MODELESS hdlgmain CALL Maincallback
       WHILE GetMessage(Msg, %NULL, 0, 0)
             SELECT CASE Msg.message
                    CASE %WM_KEYDOWN
                         SELECT CASE Msg.wParam
                                CASE %VK_LEFT
                                     STEERING_ANGLE(4)=STEERING_ANGLE(4)-.25
                                     STEERING_ANGLE(1)=STEERING_ANGLE(1)-.25
                                CASE %VK_RIGHT
                                     STEERING_ANGLE(4)=STEERING_ANGLE(4)+.25
                                     STEERING_ANGLE(1)=STEERING_ANGLE(1)+.25
                                CASE %VK_UP
                                     THROTTLE=THROTTLE+100
                                CASE %VK_DOWN
                                     THROTTLE=THROTTLE-100
                                     
                          END SELECT
             END SELECT
          TranslateMessage Msg
          DispatchMessage Msg
       WEND
      Thanks,
      Todd Wasson


      ------------------
      Todd Wasson
      http://PerformanceSimulations.Com
      PowerBasic Racing Simulator (October 2007 clip - 15.1MB wmv file) http:http://www.performancesimulations.co...m-GenIV-12.wmv

      Comment


      • #4
        Local keyboard hook is enough simple and is very powerful, because allows to refuse from event.
        Code:
           #Register None
           #Dim All
           #Include "win32Api.inc"
           Global ghKbrdHook As Long
           Global lpfnKbrdHook As Long
           Global hDlg As Long
           
           Function KeyboardHook(ByVal iCode As Integer, ByVal wParam As Long, _
              ByVal lParam As Long) As Dword
              Function = CallNextHookEx(ghKbrdHook, iCode, wParam, lParam)
              If iCode = %HC_ACTION Then
                 If IsFalse(lParam And &H80000000) Then ' KeyUp
                    Static nHook As Long
                    Incr nHook: SetWindowText hDlg, "hook #" + Str$(nHook) + ": " + Str$(wParam)
                    'Function = 1: Exit Function ' sample of ignoring !!!
                 End If
              End If
           End Function
           
           CallBack Function Cb
              Select Case CbMsg
                 Case %WM_INITDIALOG
                    ghKbrdHook = SetWindowsHookEx(%WH_KEYBOARD, CodePtr(KeyboardHook), _
                       0, GetCurrentThreadId)
                 Case %WM_DESTROY: UnhookWindowsHookEx ghKbrdHook
              End Select
           End Function
        
              Function PbMain
                 Local i As Long
                 Dialog New 0,"Test",,, 200, 150, %ws_sysmenu To hdlg
                 Control Add TextBox, hdlg, 101, "", 10, 10, 180, 12, %WS_BORDER
                 Control Add ListBox, hdlg, 102, , 10, 40, 180, 60, %WS_BORDER
                 For i = 1 To 5: ListBox Add hDlg, 102, "Item" + Str$(i): Next
                 Dialog Show Modal hdlg Call Cb
              End Function
        WH_CALLWNDPROC is also very useful hook for such purposes.

        ------------------

        Comment


        • #5
          Off the subject, how can I copy and paste these code bits quickly and in one big chunk?

          ------------------
          Todd Wasson
          http://PerformanceSimulations.Com
          PowerBasic Racing Simulator (October 2007 clip - 15.1MB wmv file) http:http://www.performancesimulations.co...m-GenIV-12.wmv

          Comment


          • #6
            todd --
            if you use ie, look http://www.powerbasic.com/support/pb...ad.php?t=22962
            i included this program in startup.
            select a code in browser, press ctrl-c, then alt-f10.

            ------------------

            Comment


            • #7
              Click on the "Edit this Message" icon (the paper and pen icon) above the message. When the edit box appears, simply click, drag and EDIT|COPY. This should work fine with IE. Netscape allows you do it directly from the message thread.


              ------------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment


              • #8
                Great, that works fine. Thanks. With the new message pump in there, I'm confused as to how I can display a dialog from a DDT menu without exiting the message pump, or perhaps re-entering the pump when a dialog closes. As it is now, when I pop up my little dialog and close it, the magic keystrokes disappear. How can I get back to Semen's message pump?

                Thank you,
                Todd


                ------------------
                Todd Wasson
                http://PerformanceSimulations.Com
                PowerBasic Racing Simulator (October 2007 clip - 15.1MB wmv file) http:http://www.performancesimulations.co...m-GenIV-12.wmv

                Comment


                • #9
                  When the menu item is clicked the dialog callback will get a %WM_COMMAND message. In response to this message (picking out the correct control ID obvously), you simply create and display a new dialog... the original code just continues along as it was. If this dialog item launches a modeless dialog, simply start a new DIALOG DOEVENTS message loop immediately after the DIALOG SHOW MODELESS.

                  Simply substitute your API based message pump for the DIALOG DOEVENTS loop. There is no "problem" having more than one message pump in your code running at the same.

                  BTW (for the lurkers), there is an example of implementing a standard DDT modeless dialog in the ADDRESS.BAS example.

                  Code:
                  'Psuedocode
                  CALLBACK MyCallBack
                    SELECT CASE CBMSG
                      CASE %WM_COMMAND
                        IF CBCTL = ...
                           DIALOG NEW...
                           CONTROL ADD...
                           DIALOG SHOW MODELESS...
                           DO 
                             DIALOG DOEVENTS
                             DIALOG GET SIZE...
                           LOOP UNTIL dialogsize = 0
                        END IF
                  ------------------
                  Lance
                  PowerBASIC Support
                  mailto:[email protected][email protected]</A>
                  Lance
                  mailto:[email protected]

                  Comment

                  Working...
                  X