我正在使用Win32 API进行编程,而不是MFC。
答案 0 :(得分:1)
问题是DialogBox
API没有要转换的加速器,必须在分派消息之前在消息循环上完成。
这个问题可以通过以下方式解决:
SetWindowsHookEx
API安装WH_GETMESSAGE
类型的线程挂钩 - 这使您可以在消息返回DialogBox
的消息循环之前查看消息PM_REMOVE
,然后WM_KEYFIRST
.. WM_LAST
消息,然后窗口也是你感兴趣的)TranslateAccelerator
,如果成功,则通过MSG.mesasge
更新WM_NULL
以使其从API消息循环中“删除”来使其失效用户Mick P.添加了一个遵循上述说明的代码段(出于某种原因,此处被同行评审拒绝了,但值得发布)并且他们的工作效果很好。这是代码(有些事情是有问题的,但对于需要快速启动的人来说,它总比没有好):
static HWND g_hDialog = NULL;
static HHOOK g_hHook = NULL;
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LRESULT nResult = 1;
if(nCode == HC_ACTION && wParam == PM_REMOVE)
{
MSG *p = (MSG*) lParam;
if(p->message >= WM_KEYFIRST && p->message <= WM_KEYLAST)
if(g_hDialog == GetForegroundWindow())
{
HWND gf = GetFocus(); // ignore if edit-able control
if(DLGC_HASSETSEL & ~SendMessage(gf, WM_GETDLGCODE, 0, 0)
|| ES_READONLY & GetWindowLong(gf, GWL_STYLE))
{
static HACCEL ha = // leaky
LoadAccelerators(..., MAKEINTRESOURCEW(IDR_MYACCEL));
if(TranslateAcceleratorW(g_hDialog, ha, p))
{
p->message = WM_NULL;
nResult = 0;
}
}
}
}
if(nCode < 0 || nResult)
return CallNextHookEx(g_hHook,nCode,wParam,lParam);
return nResult;
}
static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_INITDIALOG:
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, HookProc, ..., GetCurrentThreadId());
g_hDialog = hWnd;
return 1;
case WM_NCDESTROY:
UnhookWindowsHookEx(g_hHook);
break;
}
return 0;
}
答案 1 :(得分:0)
确保您的消息泵中具有TranslateMessage(...)功能。如果是这样,加速键应该工作。实现模态对话框冻结应用程序中的所有其他窗口,直到它被解除。
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if( bRet == -1 )
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg); //<< make sure this is present
DispatchMessage(&msg);
}
}
确保在控制标题前放置一个&符号以“激活”加速度。示例:&amp;确定或&amp;取消。现在应该在第一个字母下面显示一个小的下划线,表明它有效。那封信成了加速键。它不一定是第一个字母。 E&放大器; XIT。线显示在“x”下,即加速键。
答案 2 :(得分:0)
请看这个例子http://msdn.microsoft.com/en-us/library/ms646337.aspx#editable_acc。可能你正在寻找什么。