News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Accelerator rsrc

Started by John T, February 16, 2016, 12:49:14 PM

Previous topic - Next topic

John T

I'm having trouble getting accelerator keys (done in resource) to work.
The following code DOES respond to SHIFT E to shut the app down IF THE FILE MENU IS POPPED UP, but nothing happens at all otherwise.

My understanding is that TranslateAccelerator will intercept the keystroke and (if in the accel table) will place a WM_COMMAND message back in that window's queue to be intercepted the next time around the main-loop.

---------- rc file ----------

#include "\masm32\include\resource.h"
#define IDA_Accels      1
#define IDM_MainMenu   200
#define IDM_About      201
#define IDM_Exit      202

IDA_Accels   ACCELERATORS MOVEABLE PURE LOADONCALL DISCARDABLE
   BEGIN
      "^E", IDM_Exit
   END

IDM_MainMenu   MENU MOVEABLE PURE LOADONCALL DISCARDABLE
   BEGIN
      POPUP "&File"
      BEGIN
         MENUITEM   "About...",   IDM_About
         MENUITEM   SEPARATOR
         MENUITEM   "&Exit",   IDM_Exit
      END
   END
   
---------- program ----------

M_WinProc         PROTO   :DWORD, :DWORD, :DWORD, :DWORD
M_TendTo_WM_COMMAND   PROTO   :DWORD
M_DoClickEvent      PROTO   :WORD

.data
IDA_Accels   = 1
v_AppInst   DWORD   0

.code
start:
    invoke GetModuleHandle, 0
    mov v_AppInst, eax
    invoke WinMain, v_AppInst, 0, 0, 0
    invoke ExitProcess, 0
   
WinMain PROC hInst :DWORD, hPrevInst :DWORD, CndLine :DWORD, CmdShow :DWORD
   LOCAL   msg      :MSG
   LOCAL   hAccels   :HACCEL
   
   invoke LoadAccelerators, v_AppInst, IDA_Accels
   mov   hAccels, eax
   
   ; do registry, create main window, load menu here, blah blah
   ; everything all works except for the hot key: Ctrl E

   ;--- mainloop ---
   StartLoop:
      invoke GetMessage, ADDR msg, 0, 0, 0
      cmp   eax, 0
      je   ExitLoop
      
      invoke TranslateAccelerator, m_Win, hAccels, ADDR msg
      cmp   eax, 0
      jne   StartLoop
      
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage, ADDR msg
      jmp   StartLoop
   ExitLoop:
      mov   eax, msg.wParam
      ret
WinMain ENDP

;-----

M_WinProc PROC hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD
   ; ...
   .elseif uMsg == WM_COMMAND
      invoke M_TendTo_WM_COMMAND, wParam
   .else
      invoke DefWindowProc, hWin, uMsg, wParam, lParam
      ret
   .endif

    return 0
M_WinProc ENDP

;-----

M_TendTo_WM_COMMAND PROC wParam :DWORD
   mov   eax, wParam
   and   eax, 0FFFF0000h
   shr   eax, 16
   cmp   ax, BN_CLICKED
   jne   @J2
      mov   eax, wParam
      invoke M_DoClickEvent, ax   ; loword(wParam)
@J2:
   ret
M_TendTo_WM_COMMAND ENDP

;-----

M_DoClickEvent PROC ctrlID :WORD
   ; ...
   .elseif ctrlID == IDM_Exit
      invoke PostQuitMessage, 0
   ; ...
   .endif
   ret
M_DoClickEvent ENDP

end start
      

dedndave

this is an MDI window with menus and accelerators

John T

Well...
Still having complete trouble with it.
Trying to do it without MDI - I only want a main window.
I also tried setting a table up (array of ACCEL) and using CreateAcceleratorTable rather than using rsrc.
No help there either.
Olly says (with or w/o rsrc) the hAccel table IS there - or something is (e.g. not NULL), so I'm guessing I'm doing something wrong when using TranslateAccelerator.

BTW - Any idea what the layout (byte by byte) of the hAccel table is when its in memory?
I'll check that next.

Here's the snip I've been trying:

   .data
accTabl            ACCEL   2 DUP (<>)

   .code
   ; ...
   mov      edi, offset accTabl
   
   mov      [edi].ACCEL.fVirt,   FCONTROL
   mov      [edi].ACCEL.key,   0045h
   mov      [edi].ACCEL.cmd,   IDM_Exit
   add      edi, sizeof ACCEL
   
   mov      [edi].ACCEL.fVirt,   FCONTROL
   mov      [edi].ACCEL.key,   0065h
   mov      [edi].ACCEL.cmd,   IDM_Exit
   
   invoke CreateAcceleratorTable, offset accTabl, 2
   mov      v_Accels, eax
   
   ; ...
   
   MainLoop:
      invoke   GetMessage, ADDR msg, 0, 0, 0
      cmp      eax, 0
      je      ExitLoop

      invoke TranslateAccelerator, m_Win, v_Accels, ADDR msg
      cmp   eax, 0
      je   @Cont1
                           int 3
      jmp   MainLoop
      
      
   @Cont1:
      invoke   TranslateMessage, ADDR msg
      invoke   DispatchMessage, ADDR msg
      jmp   MainLoop
   ExitLoop:
   return   msg.wParam
   
The int 3 is getting hit on a SHIFT-E, but not CONTROL-E
Hmmmmmm


jj2007

Have a closer looks at the docs to get the difference between TranslateMessage and TranslateAccelerator.
Normally we use this:

  mov edi, offset msg
  .While 1
xor eax, eax
invoke GetMessage, edi, eax, eax, eax
inc eax
shr eax, 1
.Break .if Zero? ; 0 (OK) or -1 (error)
invoke TranslateMessage, edi
invoke DispatchMessage, edi
  .Endw