Thursday, November 12, 2009

DialogBox + Accelerators

Can't be done. Sorry. You have to write the modal loop yourself.

With the help of The Old New Thing (Yes, its not thread safe. Who even does UI from multiple threads anyway), this function does a standard modal dialog, except it dispatches F1 as IDHELP.

Big caveat! You can't call EndDialog() in your dialog proc - in this, you have to replace EndDialog() with s_ModalDialogResult = . You could also write a function to emulate EndDialog pretty trivially (along with making it thread safe)

static S32 s_ModalDialogResult = -1;
S32 DialogBoxWithHelp(LPCSTR i_Template, LPARAM i_Param, HWND i_Owner, DLGPROC i_Proc)
{
MSG msg;
s_ModalDialogResult = -1;

HWND hDialog = CreateDialogParam(hInstance, i_Template, i_Owner, i_Proc, i_Param);
if (hDialog == 0) return -1;

ShowWindow(hDialog, SW_SHOW);
EnableWindow(i_Owner, FALSE);

ACCEL helper[] =
{
{ FVIRTKEY, VK_F1, IDHELP }
};
HACCEL hAccel = CreateAcceleratorTable(helper, 1);

while (s_ModalDialogResult == -1)
{
S32 msgresult = GetMessage(&msg, 0, 0, 0);
if (msgresult > 0)
{
if (TranslateAccelerator(hDialog, hAccel, &msg) == 0 &&
IsDialogMessage(hDialog, &msg) == 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// We received a WM_QUIT message; bail out!
// Re-post the message that we retrieved
if (msgresult == 0) PostQuitMessage(msg.wParam);

// otherwise it was an error, bail.
break;
}
}

DestroyAcceleratorTable(hAccel);
EnableWindow(i_Owner, TRUE);
DestroyWindow(hDialog);

return s_ModalDialogResult;
}

References:
http://blogs.msdn.com/oldnewthing/archive/2005/02/18/376080.aspx
http://blogs.msdn.com/oldnewthing/archive/2005/02/24/379635.aspx
http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx

No comments:

Post a Comment