代码之家  ›  专栏  ›  技术社区  ›  Ayrosa

如何在模式对话框中使用加速器表?

  •  1
  • Ayrosa  · 技术社区  · 15 年前

    我是用Win32 API编程的,不是MFC。

    3 回复  |  直到 15 年前
        1
  •  1
  •   Community Mohan Dere    9 年前

    问题是 DialogBox

    • 使用 SetWindowsHookEx WH_GETMESSAGE 类型-这使您能够在消息返回到之前查看消息 的消息循环
    • 在钩子过程中,过滤出感兴趣的消息( 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;
    }
    
        2
  •  0
  •   JustBoo    15 年前

    确保您拥有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); 
        }
    }
    

    确保在控件标题前加一个符号“激活”加速度。例如:& ;;OK或&取消现在,在第一个字母下面应该显示一条小下划线,表示它起作用了。这个字母变成了加速键。它不必是第一个字母。E&退出。线显示在“x”下,这是加速键。

        3
  •  0
  •   Oleg    15 年前