Holy cow, I wrote a book!
For some reason, there appears to be some confusion over
what TranslateAccelerator does.
It's very simple, and
it's all spelled out in the documentation.
You give it a message, and if the message is a keypress that
matches an entry in the accelerator table,
the corresponding WM_COMMAND or WM_SYSCOMMAND
message is sent to the window you said you are translating messages for.
One point of confusion is which window receives the translated
Is it the window in the MSG structure or the window
passed as the first parameter to
This confusion shouldn't last long, though, because of the two options,
one of them raises more questions than it resolves.
If the message matches an accelerator,
the WM_COMMAND or WM_SYSCOMMAND message
goes to the window you passed as the first parameter to
Once you understand this, you can answer the next question:
My program has two dialogs containing tabs, both running on the
same UI thread.
I want to make sure that the Ctrl+Tab hotkey switches between the
tabs on the correct dialog.
I've already created an accelerator table,
but how do I decide which window to pass as the first parameter
Right now, I'm using GetForegroundWindow().
Well, first off, GetForegroundWindow() is completely
wrong, since the foreground window need not be one of your two
The user may be working with Notepad,
and now you sent a WM_COMMAND to Notepad with one
of your private command codes,
a command code that has a completely different meaning to Notepad.
Okay, back to the question.
How do you know which window to pass as the first parameter
Well, it's the window that you want the WM_COMMAND
message to go to:
You want it to go to the dialog that contains the window
that the user typed Ctrl+Tab into.
You can determine this window by looking at the MSG
structure, since keyboard messages are delivered to the window
with keyboard focus.
if (IsChild(hwnd1, msg.hwnd))
TranslateAccelerator(hwnd1, hAccel, &msg);
else if (IsChild(hwnd2, msg.hwnd))
TranslateAccelerator(hwnd2, hAccel, &msg);
The window handle in the MSG structure tells
you which window the user typed the key into;
if that window is part of the first dialog,
then translate the message and send any translated message
to the first dialog.
Otherwise, check the same thing with the second dialog.
Easy as pie.