Announcement

Collapse
No announcement yet.

Menu accelerator doesn't work

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

  • Menu accelerator doesn't work

    Can't get this one solved:

    This is a code snippet to demonstrate the effect. Whatever I've tried, the menu is not responding to ALT+F when the dialog owns no other controls. As soon as you add a command button everything works as expected.

    I won't use the "b-word", but this seems to be at least an undocumented feature

    Knuth

    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "DDT.INC"
    
    %MNU_FILE_EXIT = 102
    
    FUNCTION PbMain
    
    LOCAL hDlg AS LONG            'Dialog handle
    LOCAL hMnu AS LONG
    LOCAL hmnuFile AS LONG
    
    
    DIALOG NEW 0, "Menu Test", , , 470, 280, , TO hDlg
    
    '** When uncommenting the line below, the menu works as expected...
    'CONTROL ADD BUTTON, hDlg, 1, "Testbutton", 10, 10, 80, 20
    
    IF hDlg = 0 THEN EXIT FUNCTION  ' Error occurred
    
    'Add the menu
    MENU NEW BAR TO hMnu
    MENU NEW POPUP TO hmnuFile
    MENU ADD STRING, hmnuFile, "E&xit", %MNU_FILE_EXIT, %MF_ENABLED
    MENU ADD POPUP, hMnu, "&File", hmnuFile, %MF_ENABLED
    MENU ATTACH hMnu, hDlg
    
    DIALOG SHOW MODAL hDlg
    
    
    'Success
    PbMain = 0
    
    END FUNCTION

  • #2
    Knuth,

    DDT does not support keyboard accelerators. And I haven't found a way to use DDT and the WinAPI to support them.

    It's on the list as a feature update for the next version.

    --Dave


    ------------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Home of the BASIC Gurus
    www.basicguru.com

    Comment


    • #3
      > DDT does not support keyboard accelerators

      See the in sample from PB/DLL help. Could be I don't understand, what means keyboard accelerators, but looks that in general DDT supports accelerators

      [This message has been edited by Semen Matusovski (edited February 24, 2000).]

      Comment


      • #4
        Semen --

        I think we're dealing with crossed definitions here...

        Technically speaking, Alt-F (for a top-level &File menu item) is not an "accelerator key", it is more like a "hot key". An accelerator key can be an Alt-key, but it is more commonly a Ctrl-key, such as when a menu is structured like this...

        Code:
        &File
             New        Ctrl-N
             Open       Ctrl-O
             Close      Alt-C
             Close All  F2
        An accelerator key is associated with a bottom-level menu item -- a "command" -- not a top-level pulldown.

        I believe I am correct in saying that hot keys like Alt-F are supported by DDT when there is at least one control on the dialog to pass the keystroke to the menu. (This is typical of the way Win32 applications work, not just DDT. I would not consider it to be a bug.) But true accelerator keys (like Ctrl-N above) are not currently supported.

        True?

        -- Eric

        ------------------
        Perfect Sync: Perfect Sync Development Tools
        Email: mailto:[email protected][email protected]</A>



        [This message has been edited by Eric Pearson (edited February 24, 2000).]
        "Not my circus, not my monkeys."

        Comment


        • #5
          Eric --
          I understand about what you.
          Unfortunately, just now I don't see a sample with "real" accelerators (skeleton.bas, like I see, doesn't support them), but, perhaps, if to replace Dialog Show Modal by Dialog Show Modeless and instead of Dialog Doevents to execute something like this
          Code:
            WHILE GetMessage(msg, %NULL, 0, 0)
              IF IsDialogMessage (hWnd, msg) THEN
                'Skip
              ELSEIF TranslateAccelerator(hWnd, hAccel, msg) THEN
                'Skip
              ELSE
                TranslateMessage msg
                DispatchMessage  msg      
              END IF
            WEND
          I hope that all will work. Why not ?

          [This message has been edited by Semen Matusovski (edited February 24, 2000).]

          Comment


          • #6
            > replace Dialog Show Modal by Dialog Show Modeless and
            > instead of Dialog Doevents to execute something like this

            As I understand it, that is not allowed. If you use DDT to create a dialog or control, you must use DDT to "service" it. That means that you must use either 1) DIALOG SHOW MODELESS plus periodic DIALOG DOEVENTS, or 2) DIALOG SHOW MODAL.

            Maybe it would be possible to subclass the dialog and look for WM_KEYDOWN messages. The TranslateAccelerator API actually transforms "registered" key combinations into WM_COMMAND messages, so the handling would be different. When you press Ctrl-N for example, your app sees the same WM_COMMAND message that it would if somebody selected the New menu item. It does not see a keystroke. But I don't know of anything that would keep you from detecting something like Ctrl-N "directly" and simulating the action of an accelerator key. I've never tried it... maybe somebody knows about a problem with that idea...?

            -- Eric

            ------------------
            Perfect Sync: Perfect Sync Development Tools
            Email: mailto:[email protected][email protected]</A>

            "Not my circus, not my monkeys."

            Comment


            • #7
              To make the accelerator keys work in SKELETON.BAS, change "PBACCEL" to "SKACCEL" and re-compile.

              And Eric's definition is correct.

              --Dave


              ------------------
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Home of the BASIC Gurus
              www.basicguru.com

              Comment


              • #8
                Eric, Dave --
                I found a sample in Petzold (from http://www.powerbasic.com/files/pub/pbwin/ ), chapter 11 - poppad.bas- and recompiled it.
                Sorry, but for me Ctrl-O, F3, Ctrl-R and so on works fine.

                <font face="Courier New, Courier" size="3"><pre>
                #Compile Exe
                #Register None
                #Dim All
                #Include "WIN32API.INC"
                #Resource "POPPAD.PBR"
                %IDM_NEW = 10
                %IDM_OPEN = 11
                %IDM_SAVE = 12
                %IDM_SAVEAS = 13
                %IDM_PRINT = 14
                %IDM_EXIT = 15
                %IDM_UNDO = 20
                %IDM_CUT = 21
                %IDM_COPY = 22
                %IDM_PASTE = 23
                %IDM_CLEAR = 24
                %IDM_SELALL = 25
                %IDM_FIND = 30
                %IDM_NEXT = 31
                %IDM_REPLACE = 32
                %IDM_FONT = 40
                %IDM_HELP = 50
                %IDM_ABOUT = 51

                %IDTEXT = 100

                Global UserName As String

                CallBack Function OkButton()
                Control Get Text CbHndl, %IDTEXT To UserName
                Dialog End CbHndl, 1
                End Function

                CallBack Function CancelButton()
                Dialog End CbHndl, 0
                End Function

                Global Stop%
                CallBack Function DlgProc()
                If CbMsg = %WM_COMMAND Then
                Select Case CbCtl
                Case %IDM_NEW : MsgBox "New"
                Case %IDM_OPEN : MsgBox "Open"
                Case %IDM_SAVE : MsgBox "Save"
                Case %IDM_SAVEAS : MsgBox "Save as"
                Case %IDM_PRINT : MsgBox "Print"
                Case %IDM_EXIT : MsgBox "Exit"
                Case %IDM_UNDO : MsgBox "Undo"
                Case %IDM_CUT : MsgBox "Cut"
                Case %IDM_COPY : MsgBox "Copy"
                Case %IDM_PASTE : MsgBox "Paste"
                Case %IDM_CLEAR : MsgBox "Clear"
                Case %IDM_SELALL : MsgBox "Select All"
                Case %IDM_FIND : MsgBox "Find"
                Case %IDM_NEXT : MsgBox "Next"
                Case %IDM_REPLACE : MsgBox "Replace"
                Case %IDM_FONT : MsgBox "Font"
                Case %IDM_HELP : MsgBox "Help"
                Case %IDM_ABOUT : MsgBox "About"
                End Select
                End If
                If CbMsg = %WM_DESTROY Then Stop% = 1
                End Function

                Function WinMain (ByVal hCurrInstance As Long,_
                ByVal hPrevInstance As Long,_
                lpCmdLine As Asciiz Ptr,_
                ByVal nCmdShow As Long) As Long


                Local hDlg As Long
                Local result As Long

                ' ** Create a new dialog template
                Dialog New 0, "What is your name?", ,, 160, 60, 0, 0 To hDlg

                ' ** Add controls to it
                Control Add TextBox, hDlg, %IDTEXT, "", 14, 12, 134, 12, 0
                Control Add Button, hDlg, %IDOK, "OK", 34, 32, 40, 14, %BS_DEFAULT Call OkButton

                Control Add Button, hDlg, %IDCANCEL, "Cancel", 84, 32, 40, 14, 0 Call CancelButton
                Dim hAccel As Long, msg As tagMsg, hMenu As Long
                hMenu = LoadMenu (hCurrInstance, "POPPAD")
                hAccel = LoadAccelerators(hCurrInstance, "POPPAD")
                Menu Attach hMenu, hDlg
                Dialog Show Modeless hDlg, Call DlgProc
                While GetMessage(msg, %NULL, 0, 0)
                If TranslateAccelerator(hDlg, hAccel, msg) Then ' Skip
                ElseIf IsDialogMessage (hDlg, msg) Then
                Else
                TranslateMessage msg
                DispatchMessage msg
                End If
                If Stop% = 1 Then Exit Do
                Wend
                MsgBox "Hello " & UserName
                End Function


                =========== POPPAD.RC ===========

                #include <c:\pbdll60\winapi\resource.h>
                #define IDM_NEW 10
                #define IDM_OPEN 11
                #define IDM_SAVE 12
                #define IDM_SAVEAS 13
                #define IDM_PRINT 14
                #define IDM_EXIT 15

                #define IDM_UNDO 20
                #define IDM_CUT 21
                #define IDM_COPY 22
                #define IDM_PASTE 23
                #define IDM_CLEAR 24
                #define IDM_SELALL 25

                #define IDM_FIND 30
                #define IDM_NEXT 31
                #define IDM_REPLACE 32

                #define IDM_FONT 40

                #define IDM_HELP 50
                #define IDM_ABOUT 51

                #define IDD_FNAME 10

                PopPad MENU
                {
                POPUP "&File"
                {
                MENUITEM "&New\tCtrl+N", IDM_NEW
                MENUITEM "&Open...\tCtrl+O", IDM_OPEN
                MENUITEM "&Save\tCtrl+S", IDM_SAVE
                MENUITEM "Save &As...", IDM_SAVEAS
                MENUITEM SEPARATOR
                MENUITEM "&Print...\tCtrl+P", IDM_PRINT
                MENUITEM SEPARATOR
                MENUITEM "E&xit", IDM_EXIT
                }
                POPUP "&Edit"
                {
                MENUITEM "&Undo\tCtrl+Z", IDM_UNDO
                MENUITEM SEPARATOR
                MENUITEM "Cu&t\tCtrl+X", IDM_CUT
                MENUITEM "&Copy\tCtrl+C", IDM_COPY
                MENUITEM "&Paste\tCtrl+V", IDM_PASTE
                MENUITEM "De&lete\tDel", IDM_CLEAR
                MENUITEM SEPARATOR
                MENUITEM "&Select All", IDM_SELALL
                }
                POPUP "&Search"
                {
                MENUITEM "&Find...\tCtrl+F", IDM_FIND
                MENUITEM "Find &Next\tF3", IDM_NEXT
                MENUITEM "R&eplace...\tCtrl+R", IDM_REPLACE
                }
                POPUP "F&ormat"
                {
                MENUITEM "&Font...", IDM_FONT
                }
                POPUP "&Help"
                {
                MENUITEM "&Help", IDM_HELP
                MENUITEM "&About PopPad...", IDM_ABOUT
                }
                }

                PopPad ACCELERATORS
                {
                "^N", IDM_NEW
                "^O", IDM_OPEN
                "^S", IDM_SAVE
                "^P", IDM_PRINT
                "^Z", IDM_UNDO
                VK_BACK, IDM_UNDO, VIRTKEY, ALT
                "^X", IDM_CUT
                VK_DELETE, IDM_CUT, VIRTKEY, SHIFT
                "^C", IDM_COPY
                VK_INSERT, IDM_COPY, VIRTKEY, CONTROL
                "^V", IDM_PASTE
                VK_INSERT, IDM_PASTE, VIRTKEY, SHIFT
                VK_DELETE, IDM_CLEAR, VIRTKEY
                "^F", IDM_FIND
                VK_F3, IDM_NEXT, VIRTKEY
                "^R", IDM_REPLACE
                VK_F1, IDM_HELP, VIRTKEY
                }

                </pre></font>

                [This message has been edited by Semen Matusovski (edited February 24, 2000).]

                Comment


                • #9
                  eric --
                  you wrote --
                  "if you use ddt to create a dialog or control, you must use ddt to "service" it. that means that you must use either 1) dialog show modeless plus periodic dialog doevents, or 2) dialog show modal".

                  not agree. look lance' enough clear reply in http://www.powerbasic.com/support/pb...ad.php?t=11099
                  this is a reaction on my suggestion in http://www.powerbasic.com/support/pb...ad.php?t=12662




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

                  Comment


                  • #10
                    Well, I did preface that statement with "As I understand it..."

                    Interesting... That could be very useful. I'll be very interested to follow this discussion, and see if it leads to a reliable technique and a change in PowerBASIC's official recommendations. To be fair, so far Lance seems to be saying "it looks promising, try it and see if it causes any problems".

                    -- Eric


                    ------------------
                    Perfect Sync: Perfect Sync Development Tools
                    Email: mailto:[email protected][email protected]</A>



                    [This message has been edited by Eric Pearson (edited February 24, 2000).]
                    "Not my circus, not my monkeys."

                    Comment


                    • #11
                      Dave, Eric,

                      sorry, I mixed up words. Eric explained it the way I should have expalined it. The hotkey Alt+F to access the File menu doesn't work as long as there is no other control within the dialog. I worked around that limitation by placing a hidden label on the dialog.

                      If this is "by design" as Eric explained, what is the official recommended way to get that to work with DDT?

                      Knuth
                      ------------------


                      [This message has been edited by Knuth Konrad (edited February 25, 2000).]

                      Comment


                      • #12
                        Konrad --
                        this is workaround
                        Code:
                        #Dim All
                        #Compile Exe
                        #Include "WIN32API.INC"
                        Global Stop%
                        CallBack Function DlgProc()
                          If CbMsg = %WM_DESTROY Then Stop% = 1
                        End Function
                        
                        Function PbMain
                          Local hDlg As Long
                          Local hMnu As Long
                          Local hmnuFile As Long
                          Local msg As tagMsg
                          
                          Dialog New 0, "Menu Test", , , 470, 280, , To hDlg
                          Menu New Bar To hMnu
                          Menu New Popup To hmnuFile
                          Menu Add String, hmnuFile, "E&xit", 101, %MF_ENABLED
                          Menu Add Popup, hMnu, "&File", hmnuFile, %MF_ENABLED
                          ' You can uncomment these two lines
                          'Menu Add String, hmnuFile, "S&leep", 102, %MF_ENABLED
                          'Menu Add Popup, hMnu, "&Go", hmnuFile, %MF_ENABLED
                          Menu Attach hMnu, hDlg
                          Dialog Show Modeless hDlg, Call DlgProc
                          While GetMessage(msg, %NULL, 0, 0)
                             TranslateMessage msg
                             DispatchMessage  msg
                             If Stop% = 1 Then Exit Do
                          Wend
                        
                        End Function
                        PS. Could be it will be interesting for R&D, but a mistake is exactly in DIALOG DOEVENTS

                        Try to replace
                        While GetMessage(msg, %NULL, 0, 0)
                        TranslateMessage msg
                        DispatchMessage msg
                        If Stop% = 1 Then Exit Do
                        Wend

                        by
                        Do
                        Dialog DoEvents
                        If Stop% = 1 Then Exit Do
                        Loop

                        and it will be the same problem as with DIALOG SHOW MODAL

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


                        [This message has been edited by Semen Matusovski (edited February 25, 2000).]

                        Comment


                        • #13
                          Knuth --

                          > If this is "by design" as Eric explained

                          I'm not sure that it was "intentional" because Microsoft probably didn't anticipate anybody designing a dialog with no controls at all. (At first glance it doesn't seem to make sense, but I have needed to do it myself.) But yes, that is the way the Win32 GUI system apparently works.

                          > what is the official recommended way to
                          > get that to work with DDT?

                          You could add a control like a button that is not visible to the user. Place it outside the boundary of the dialog and it would not be seen.

                          I'm not sure, but I think that instead of a button you could use CONTROL ADD LABEL to add a label with a single space, so nothing would actually show. I'm pretty sure that labels process keystrokes like other controls, because they have to "see" the hot-keys that they define (like &Label).

                          Semen's workaround will probably also work, but it relies on a technique that has not yet been officially approved by PowerBASIC. I'm a little too conservative to use it in my production code until that happens.

                          -- Eric


                          ------------------
                          Perfect Sync: Perfect Sync Development Tools
                          Email: mailto:[email protected][email protected]</A>



                          [This message has been edited by Eric Pearson (edited February 25, 2000).]
                          "Not my circus, not my monkeys."

                          Comment


                          • #14
                            Eric --
                            I am also enough conservative, when I make changes in programs for customers.
                            But:
                            1) I tried "clear" API for Konrad's sample - works.
                            Changed CreateWindow by Dialog New - works.
                            Dialog Show Modal - not works
                            Dialog Show Modeless with Dispatch - works.
                            Where is a problem ?

                            2) I accept DDT like comfortable macroes - not less, not more.
                            Even I with my knowledge of API can replace each separate (!)DDT statement by API functions.
                            Upto now I didn't meat any serious difficults in using "mixing" style (except CALLBACK - here is necessary to be very careful).

                            PS. With single label Konrad's sample works fine. Strange ?
                            ------------------


                            [This message has been edited by Semen Matusovski (edited February 25, 2000).]

                            Comment


                            • #15
                              Adding an empty label instead of a button is probably the leanest
                              and easiest way to make it work. At least the following works fine:

                              Code:
                              #COMPILE EXE
                              #REGISTER NONE
                              #INCLUDE "DDT.INC"
                               
                              %MNU_FILE_EXIT = 102
                              DECLARE CALLBACK FUNCTION DlgProc
                               
                              '--------------------------------------------------------------------
                              FUNCTION PBMAIN
                                LOCAL hDlg AS LONG            'Dialog handle
                                LOCAL hMnu AS LONG
                                LOCAL hmnuFile AS LONG
                               
                                DIALOG NEW 0, "Menu Test", , , 470, 280, , TO hDlg  '%WS_SYSMENU
                               
                                'an empty label, just to make the menu accelerators work..
                                CONTROL ADD LABEL, hDlg, -1, "", 0, 0, 0, 0
                               
                                IF hDlg = 0 THEN EXIT FUNCTION  ' Error occurred
                               
                                'Add the menu
                                MENU NEW BAR TO hMnu
                                MENU NEW POPUP TO hmnuFile
                                MENU ADD STRING, hmnuFile, "E&xit", %MNU_FILE_EXIT, %MF_ENABLED
                                MENU ADD POPUP, hMnu, "&File", hmnuFile, %MF_ENABLED
                                MENU ATTACH hMnu, hDlg
                               
                                DIALOG SHOW MODAL hDlg CALL DlgProc
                               
                                'Success
                                PBMAIN = 0
                               
                              END FUNCTION
                               
                              '--------------------------------------------------------------------
                              CALLBACK FUNCTION DlgProc
                                  SELECT CASE CBMSG
                                    CASE %WM_COMMAND
                               
                                      SELECT CASE CBCTL
                                        CASE %MNU_FILE_EXIT
                                          MSGBOX "%MNU_FILE_EXIT"
                                          DIALOG END CBHNDL
                               
                                      END SELECT
                                  END SELECT
                               
                              END FUNCTION


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

                              Comment


                              • #16
                                Thanks to all who responded so far.

                                As I said in my second message I worked around this by adding a hidden label to the dialog, exactly Borje suggested later on.

                                The DDT/DispatchMessage approach might help me for solving another issue that I may have: I don't recieve %WM_USER + ??? messages send from a 3rdparty control within my DDT dialog callback function. I'm not sure if they're not send or if I still do something wrong.

                                Have a nice weekend!

                                Knuth
                                P.S. Semen, "Knuth" is my firstname.
                                ------------------


                                [This message has been edited by Knuth Konrad (edited February 25, 2000).]

                                Comment


                                • #17
                                  Semen --

                                  > Where is a problem ?

                                  Semen, as I said, I suspect that your technique will work just fine! My only point is that PowerBASIC is reserving judgement, so I am too. Until the technique has been tested with a variety of DDT programs on Windows 95a-c, 98, 98SE, NT4 (SP0-6) and 2000, or until an "official blessing" has been given by PB R&D and they change their current "best advice" of always using DDT to service DDT elements, I can't recommend using it for production code. Especially when other, 100% PB-endorsed techniques will produce the same results, as they will in this case.

                                  I applaud you for pioneering this technique, and it may lead to some very desirable DDT enhancements, but "promoting" it may be... premature. IMO it is conceivable that R&D could say that this technique should not be used and not give a reason or a workaround, because doing so might compromise a proprietary secret. Where would that leave people that are using it?

                                  Patience, my friend, patience! They are inspecting it now, so let's wait for an official sea-worthiness certificate before we climb into the boat!

                                  > PS. With single label Konrad's sample works fine. Strange ?

                                  Not in my opinion, as I said above. I have written 100% API-based dialogs -- before DDT was released -- and I sometimes had to add "dummy" controls to get things to work properly.

                                  -- Eric

                                  ------------------
                                  Perfect Sync: Perfect Sync Development Tools
                                  Email: mailto:[email protected][email protected]</A>



                                  [This message has been edited by Eric Pearson (edited February 25, 2000).]
                                  "Not my circus, not my monkeys."

                                  Comment

                                  Working...
                                  X