OK, I got it working. The problem wasn't with the accelerator code itself; it was a much more complicated problem, which I actually solved all my myself. May be instructive to describe it.
The problem was one of keyboard focus. My program starts with a main window which spawns a child window that's used for editing a dialog template. When a dialog is being edited, that's the window that has the keyboard focus, not the main window, which is why I wasn't getting any accelerator action.
So I had to get a little tricky. I changed the TranslateAccelerator() call to use the dialog-editing window handle. Problem: this handle didn't exist until I created or loaded a dialog to edit. Since I didn't want bad things to happen by calling this function with a bogus handle, I had to protect it:
;============= Message loop ===================
mssglp: INVOKE GetMessage, ADDR msg, NULL, 0, 0
TEST EAX, EAX ;EAX = 0 = exit
JZ exit99
; Check for keyboard accelerators ONLY if dialog-editing window is up
; (because it'll have the keyboard focus):
CMP DlgEditWinHandle, NULL
JE @F
INVOKE TranslateAccelerator, DlgEditWinHandle, AccelHandle, ADDR msg
TEST EAX, EAX ;If this was an accelerator message, it's been handled,
JNZ mssglp ; so go back and get the next one.
@@: INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
JMP mssglp
exit99:
(I make sure to NULL-out this handle when the editing window closes)
Now the problem was that the accelerator command was being sent to the wrong window. All the menu-handling code (load, save, etc.) is in the main window. So I did a little song and dance: I looked for the WM_COMMAND message in my editing window instead. When I got it (checking for this one menu ID), I turned around and sent my own WM_COMMAND message to the right window (the main one). A little klugey, but it works. (Hey, it's called "inter-process communication"!)
(in dialog-editing proc)
MOV EAX, uMsg
CMP EAX, WM_CREATE
JE do_create
.....
; This is solely to catch the $menuSaveAll command:
CMP EAX, WM_COMMAND
JE do_command
; See if the WM_COMMAND msg. is for "Save all":
do_command:
CMP WORD PTR wParam, $menuSaveAll
JNE dodefault ;Nope.
INVOKE SendMessage, MainWinHandle, WM_COMMAND, $menuSaveAll, NULL
JMP dodefault