Modeless dialogs Vs.TAB key, arrow keys, and accelerator keys (II)

I think the last solution is an overkill.  Remember what was the problem:

In some point the pump gets the modeless window handler and it is not able to get the corresponding window to call the PreTranslateMessage member funcion.


BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{
...

for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
{
//FromHandlePermanent will return NULL, causing our issue
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{
if (pWnd->PreTranslateMessage(pMsg))
return TRUE;
}
}
...
}


So we put a hook to the thread, the result: thousands of callings to our PreTranslateMessage member funcion with another thousand messages being delivered through the hook.

So I was doing some researching and I found the IsDialogMessage function:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645498(v=vs.85).aspx

It determines whether a message is intended for the specified dialog box and, if it is, processes the message. So we can do the following in our CWinApp derived class:


BOOL YourCWinApp ::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
CWnd *pWndPermanent = CWnd::FromHandlePermanent(pMsg->hwnd);

//If FromHandlePermanent returns NULL then it should be a control of a modeless windows
//or a modeless window itself.
if (!pWndPermanent && pMsg->hwnd)
{
//If it's a control inside the modeless window, we have to get the top parent
HWND hTopParent= AppGetTopParent(pMsg->hwnd);
return IsDialogMessage(hTopParent, pMsg);
}
}
}

return CRazorEXE::PreTranslateMessage(pMsg);
}


HWND AppGetTopParent(HWND hWnd)
{
#define APP_IsSet(flag, flagToTest) ((flag&(flagToTest))==(flagToTest))
#define APP_GetWindowStyle(hwnd)    ((LONG_PTR)(GetWindowLongPtr(hwnd, GWL_STYLE)))

#define APP_IsChildWindow(hwnd)     APP_IsSet(APP_GetWindowStyle(hwnd), WS_CHILD)

if(hWnd == NULL)
return NULL;

HWND hWndParent = hWnd;
while(hWndParent != NULL && APP_IsChildWindow(hWndParent) == TRUE)
hWndParent = ::GetParent(hWndParent);

return hWndParent;
}

Comentarios

Publicar un comentario

Entradas populares