Announcement

Collapse
No announcement yet.

accelerators

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

  • accelerators

    I have never worked with accelerators other than the "&Name" style and am having a little trouble with this. I get a table handle but the "translateaccelerator" portion of the message-loop never fires.

    Code:
    #COMPILE EXE
    #DEBUG ERROR ON
    #DEBUG DISPLAY ON
    
    DEFLNG I - N
    #INCLUDE "win32api.inc"
    
    $MainCls = "MAIN_CLASS"
    
    ENUM MenuItems SINGULAR
    '<---------- files ------------->
    MnuLoad = 20
    MnuSave
    END ENUM
    
    TYPE HANDLES_Struct
    MainDlg AS DWORD
    Accel AS DWORD
    END TYPE
    
    TYPE Point_Struct
    X AS LONG
    Y AS LONG
    END TYPE
    
    TYPE Rect_Struct
    Point_Struct
    X1 AS LONG
    Y1 AS LONG
    END TYPE
    
    DECLARE FUNCTION FN_AppendMenu LIB "User32.dll" ALIAS "AppendMenuA" _
    (BYVAL hMenu AS DWORD, BYVAL uFlags AS DWORD, BYVAL uIDNewItem AS DWORD, _
    BYVAL lpNewItem AS DWORD) AS LONG
    
    GLOBAL tHnd AS HANDLES_Struct
    
    '/==========================================================================================/'
    FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, _
    BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG
    
    LOCAL tMsg AS tagMSG
    
    CALL MainWin(tHnd.MainDlg)
    CALL MakeMenu(tHnd.MainDlg)
    
    showwindow(tHnd.MainDlg, %SW_SHOW)
    sendmessage(tHnd.MainDlg, %WM_ACTIVATE, 1, 0)
    
    DO
    IF iswindow(tHnd.MainDlg) = 0 THEN EXIT DO
    
    GetMessage(tMsg, 0, 0, 0)
    
    IF TranslateAccelerator(tHnd.MainDlg, tHnd.Accel, tMsg) = 0 THEN
    IF IsDialogMessage(tHnd.MainDlg, tMsg) = 0 THEN
    CALL TranslateMessage(tMsg)
    CALL DispatchMessage(tMsg)
    END IF
    END IF
    LOOP
    END FUNCTION
    
    '--------------------------------------------------------------------------------------
    '--------------------------------------------------------------------------------------
    
    FUNCTION MainWin_CB(BYVAL Hndl AS DWORD, BYVAL Msg AS DWORD, BYVAL wParam AS LONG, _
    BYVAL lParam AS LONG) AS LONG
    
    LOCAL CtlMsg, _
    CtlId AS DWORD
    
    SELECT CASE Msg
    CASE %WM_SIZE
    
    CASE %WM_COMMAND
    CtlMsg = HI(WORD, wParam)
    Ctlid = LO(WORD, wParam)
    SELECT CASE CtlMsg
    CASE %BN_CLICKED, 1
    SELECT CASE CtlId
    CASE %MnuLoad TO %MnuSave
    END SELECT
    END SELECT
    END SELECT
    MainWin_CB = defwindowproc(Hndl, Msg, wParam, lParam)
    END FUNCTION
    
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    
    FUNCTION MainWin(Hndl AS DWORD) AS LONG
    
    LOCAL MainStyle, _
    ExtStyle, _
    I AS DWORD
    
    LOCAL Zname AS ASCIIZ * 16
    
    LOCAL tRect AS Rect_Struct
    
    Zname$ = $MainCls
    MainStyle = %WS_OVERLAPPEDWINDOW OR %DS_3DLOOK OR %WS_CLIPCHILDREN OR %WS_CLIPSIBLINGS OR _
    %WS_VISIBLE
    
    ExtStyle = %WS_EX_APPWINDOW OR %WS_EX_CLIENTEDGE OR %WS_EX_CONTROLPARENT
    
    I = FN_RegisterCustomCtrl(Zname$, CODEPTR(MainWin_CB), 0, 0, %DEFAULT_PALETTE)
    
    CALL MakeCustWindow(Zname$, "TEST", 0, MainStyle, 10, 10, 400, 400, 0, 0, ExtStyle, _
    Hndl)
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------------------
    
    SUB MakeMenu(BYVAL Hndl AS DWORD)
    
    LOCAL MnuHndl, _
    Pop1, _
    Pop2, _
    Pop3, _
    Pop AS DWORD
    
    LOCAL tAccel() AS ACCELAPI
    
    MnuHndl = FN_NewMenu()
    Pop = FN_NewPopUpMenu()
    Pop1 = FN_NewPopUpMenu()
    
    '/=============================== FILES ================================================/'
    I = FN_AddMenuItem(MnuHndl, %MF_POPUP OR %MF_STRING OR %MF_ENABLED, Pop, "&FILES\alt f") ', OPTIONAL DwPtr AS DWORD
    I = FN_AddMenuItem(Pop, %MF_POPUP OR %MF_STRING OR %MF_ENABLED, %MnuLoad, "Load")
    I = FN_AddMenuItem(Pop, %MF_POPUP OR %MF_STRING OR %MF_ENABLED, %MnuSave, "Save")
    
    I = FN_AttachMenu(Hndl, MnuHndl)
    I = FN_DrawMenu(Hndl)
    
    I = %FVIRTKEY OR %FCONTROL OR _
    %FNOINVERT
    DIM tAccel(1 TO 2)
    tAccel(1).fVirt = I
    tAccel(1).key = ASC("0")
    tAccel(1).cmd = %MnuLoad
    
    tAccel(2).fVirt = I
    tAccel(2).key = ASC("1")
    tAccel(2).cmd = %MnuSave
    tHnd.Accel = createacceleratortable(tAccel(1), 2)
    END SUB
    
    '--------------------------------------------------------------------------------------------
    '--------------------------------------------------------------------------------------------
    
    FUNCTION FN_RegisterCustomCtrl ALIAS "FN_RegisterCustomCtrl"(Nam AS ASCIIZ * 16, _
    BYVAL Code_Ptr AS DWORD, BYVAL Inst AS DWORD, BYVAL Extra AS DWORD, _
    BYVAL BkBrush AS DWORD) EXPORT AS DWORD
    
    LOCAL Init, _
    Atom AS LONG
    
    LOCAL tWindow AS WNDCLASSEX
    
    
    LOCAL Styl AS DWORD
    
    Styl = %CS_HREDRAW OR %CS_VREDRAW OR %CS_PARENTDC
    Styl = Styl OR Extra
    
    Init = GetClassInfoEx(EXE.INST, Nam$, tWindow)
    
    IF Init THEN
    'FN_InitClass = Init
    MSGBOX "class exists"
    EXIT FUNCTION
    END IF
    
    'IF Code_Ptr = 0 THEN Code_Ptr = CODEPTR(FN_ChildDlg_CB)
    
    Inst = %HWND_DESKTOP
    
    tWindow.cbSize = SIZEOF(tWindow)
    tWindow.style = Styl
    tWindow.lpfnWndProc = Code_Ptr
    tWindow.cbClsExtra = 0
    tWindow.cbWndExtra = 32
    tWindow.hInstance = Inst 'GetWindowLong(Inst, %GWL_HINSTANCE)
    tWindow.hIcon = %NULL
    tWindow.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW)
    
    IF BkBrush = 0 THEN
    tWindow.hbrBackground = 0
    ELSE
    tWindow.hbrBackground = GetStockObject(BkBrush)
    END IF
    
    tWindow.lpszMenuName = %NULL
    tWindow.lpszClassName = VARPTR(Nam$)
    tWindow.hIconSm = %NULL
    
    Atom = RegisterClassEx(tWindow)
    FN_RegisterCustomCtrl = Atom
    END FUNCTION
    
    '----------------------------------------------------------------------------
    '----------------------------------------------------------------------------
    
    SUB MakeCustWindow ALIAS "MakeCustWindow"(Nam AS ASCIIZ * 32, Title AS ASCIIZ * 32, _
    BYVAL Owner AS DWORD, BYVAL Styl AS DWORD, BYVAL X1 AS DWORD, BYVAL Y1 AS DWORD, _
    BYVAL X2 AS DWORD, BYVAL Y2 AS DWORD, BYVAL Inst AS DWORD, BYVAL CtlId AS DWORD, _
    BYVAL StyleX AS DWORD, Hndl AS DWORD, OPTIONAL BYVAL Cs AS DWORD) EXPORT
    
    Inst = GetWindowLong(Owner, %GWL_HINSTANCE)
    
    Hndl = CreateWindowEx(STYLEX, _ ' extended Window style
    Nam$, _ ' window class name
    Title$, _ ' window caption
    Styl, _ ' window style
    X1, _ ' initial x position
    Y1, _ ' initial y position
    X2, _ ' initial x size
    Y2, _ ' initial y size
    Owner, _ ' parent window handle
    BYVAL CtlId, _ ' window menu handle
    Inst, _ ' program instance handle
    BYVAL Cs)
    
    END SUB
    
    '---------------------------------------------------------------
    '---------------------------------------------------------------
    
    FUNCTION FN_NewMenu ALIAS "FN_NewMenu"() EXPORT AS LONG
    
    LOCAL MnuHndl AS DWORD
    
    MnuHndl = createmenu()
    FN_NewMenu = MnuHndl
    END FUNCTION
    
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    
    FUNCTION FN_NewPopUpMenu ALIAS "FN_NewPopUpMenu"() EXPORT AS DWORD
    
    LOCAL PopUpHndl AS DWORD
    
    PopUpHndl = createpopupmenu()
    FN_NewPopUpMenu = PopUpHndl
    END FUNCTION
    
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    
    FUNCTION FN_AddMenuItem ALIAS "FN_AddMenuItem"(BYVAL MnuHndl AS DWORD, _
    BYVAL MnuParams AS DWORD, BYVAL MnuId AS DWORD, BYVAL MnuTitle AS STRING, _
    OPTIONAL BYVAL DwPtr AS DWORD) EXPORT AS LONG
    
    LOCAL Za AS ASCIIZ * 80
    
    LOCAL Result AS LONG
    
    IF DwPtr THEN
    Result = FN_appendmenu(MnuHndl, MnuParams, MnuId, DwPtr)
    FN_AddMenuItem = Result
    EXIT FUNCTION
    END IF
    
    Za$ = MnuTitle$
    Result = FN_appendmenu(MnuHndl, MnuParams, MnuId, VARPTR(Za$))
    
    FN_AddMenuItem = Result
    END FUNCTION
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    
    FUNCTION FN_AttachMenu ALIAS "FN_AttachMenu"(BYVAL WinHndl AS DWORD, _
    BYVAL MnuHndl AS DWORD) EXPORT AS LONG
    
    LOCAL Result AS LONG
    
    Result = setmenu(WinHndl, MnuHndl)
    FN_AttachMenu = Result
    END FUNCTION
    
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    
    FUNCTION FN_DrawMenu ALIAS "FN_DrawMenu"(BYVAL WinHndl AS DWORD) EXPORT AS LONG
    
    LOCAL Result AS LONG
    
    Result = DrawMenuBar(WinHndl)
    FN_DrawMenu = Result
    END FUNCTION
    '------------------------------------------------------------------------------------------
    '------------------------------------------------------------------------------------------
    What am I doing incorrectly?
    Walt Decker

  • #2
    Quick test and it looks like it works - inserted MSGBOX STR$(CtlId) under CASE %MnuLoad TO %MnuSave in FUNCTION MainWin_CB - and it shows up with correct id when Ctrl + 0 or 1 is pressed.

    Comment


    • #3
      I think the selection should be displayed in the drop-down. Then on ENTER the selection should be passed to WM_COMMAND. At least that is the way I think it should work. I'll look at it again with some additional sub-menus.

      Thank you Mr. Hagsten.
      Walt Decker

      Comment


      • #4
        Howdy, Walt!

        Are you doing what the PowerBASIC Accel Attach function does?

        Comment


        • #5
          Mr. Beene, that is what I'm trying to do. I have not payed much attention to accelerators other than the ALT + type, so am in unfamiliar ground. I suspect that WM_MENUSELECT is involved.
          Walt Decker

          Comment


          • #6
            Not sure I understand, but if you want shortcut to show up in menu, just add $TAB + "shortcut text", like:

            I = FN_AddMenuItem(Pop, %MF_POPUP OR %MF_STRING OR %MF_ENABLED, %MnuLoad, "Load" + $TAB + "Control + 0")

            Comment


            • #7
              Walt,

              With menu accelerators, pressing the keys sequentially will pop up the menus, such as Alt-F-S does in the IDE menu. Pressing Enter is not required.

              With the Accel Attach, your app just jumps directly to the specified WM_Command case - is not associated with a drop down menu. Pressing Enter is not required.

              Which of the two are you wanting?

              Comment


              • #8
                I have done a couple of DDT apps with menu accelerators layed out something like this:

                FILES\Alt f
                --->Itm0\Ctl 0
                --->Itm1\Ctl 1
                ------->Sub1\Ctl S
                ------->Sub2\Ctl U

                When Ctl + "chr" is pressed the item is hilighted but not selected until enter is pressed. That's what I am looking for.


                Looking deeper into menus I have found that windows sends at least 3 messages before sending the WM_COMMAND message with a value of 1 in place of BN_CLICKED when using the keyboard. However, none of those 3 messages indicates which menu item it is.

                The most informative is WM_INITMENUPOPUP which at least, in the case of submenu item, gives the submenu item handle. The problem is, the same three messages are sent with a mouse click.

                I'm beginning to think that it really is not worth the effort in a real app since I will have to keep a copy of the table in memory, perform a hittest to determine whether the item was selected via mouse or keyboard, do an asynckeystate to determine the key pressed, then parse the table to find the item id and finally do a programatic hilite to bring up the item. Since a programatic hilite disables the enter key I will have to figure out some way to take care of that.
                Walt Decker

                Comment

                Working...
                X