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 message. Is it the window in the MSG structure or the window passed as the first parameter to TranslateAccelerator? This confusion shouldn't last long, though, because of the two options, one of them raises more questions than it resolves.

  • If it went to the window in the MSG structure, then there would be no need for a hWnd parameter to TranslateAccelerator, since it wouldn't be used for anything.
  • If it went to the window in the MSG structure, there wouldn't be much need to have a TranslateAccelerator function anyway, because even without it, the message would have gone to the window in the MSG structure anyway.

If the message matches an accelerator, the WM_COMMAND or WM_SYSCOMMAND message goes to the window you passed as the first parameter to TranslateAccelerator.

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 to TranslateAccelerator? Right now, I'm using GetForegroundWindow().

Well, first off, GetForegroundWindow() is completely wrong, since the foreground window need not be one of your two dialogs. 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 to TranslateAccelerator? 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.