CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  界面

dll 中的无模式对话框,快捷键失灵

楼主sks(可子)2005-01-26 19:02:59 在 VC/MFC / 界面 提问

按钮上的快捷键,TAB键,都没有效果了。什么原因啊? 问题点数:50、回复次数:6Top

1 楼kingzai(stevenzhu)回复于 2005-01-26 19:45:54 得分 20

PRB:   Modeless   Dialog   Box   in   a   DLL   Does   Not   Process   TAB   Key   (233263)  
  http://support.microsoft.com/default.aspx?kbid=233263  
  SYMPTOMS  
  When   a   modeless   dialog   box   is   launched   from   a   dynamic-link   library   (DLL),   the   TAB   key   and   the   arrow   keys   do   not   move   the   focus   from   control   to   control   as   you   would   expect.    
  CAUSE  
  For   a   modeless   dialog   box   to   process   a   TAB   key,   the   message   pump   needs   to   call   the   IsDialogMessage   API.   However,   if   you   are   writing   a   DLL   and   do   not   have   access   to   the   .exe's   source   code,   you   cannot   modify   the   message   pump   to   do   this.    
  RESOLUTION  
  To   work   around   this   problem,   you   can   use   a   WH_GETMESSAGE   hook   to   capture   the   keystroke   messages   and   call   the   IsDialogMessage   API.   If   IsDialogMessage   returns   TRUE,   then   do   not   pass   the   message   on   to   the   message   pump.   Set   the   hook   when   handling   WM_INITDIALOG   and   unset   it   when   handling   the   WM_DESTROY   message.    
  STATUS  
  This   behavior   is   by   design.    
  MORE   INFORMATION  
  The   following   code   illustrates   how   to   set   and   unset   the   hook   as   well   as   how   to   use   IsDialogMessage()   to   process   TAB   key   messages:   BOOL   CALLBACK   DllDlgProc(   HWND   hwndDlg,   UINT   uMsg,   WPARAM   wParam,   LPARAM   lParam   )  
  {  
        switch   (   uMsg   )  
        {  
            case   WM_INITDIALOG:  
                    hHook   =   SetWindowsHookEx(   WH_GETMESSAGE,   GetMsgProc,  
                                                                        NULL,   GetCurrentThreadId()   );  
                    return   TRUE;  
   
            case   WM_COMMAND:  
                    if   (LOWORD(wParam)   ==   IDOK   ||   LOWORD(wParam)   ==   IDCANCEL)  
                    {  
                          DestroyWindow(   hwndDlg   );  
                          hwndDllDlg   =   NULL;  
                    }  
                    return   TRUE;  
   
            case   WM_DESTROY:  
                    UnhookWindowsHookEx(   hHook   );  
                    return   FALSE;  
        }  
        return   FALSE;  
  }  
   
  The   hook   procedure,   GetMsgProc,   should   resemble   the   following:  
  LRESULT   FAR   PASCAL   GetMsgProc(int   nCode,   WPARAM   wParam,   LPARAM   lParam)  
  {  
        LPMSG   lpMsg   =   (LPMSG)   lParam;  
   
        if   (   nCode   >=   0   &&   PM_REMOVE   ==   wParam   )  
        {  
              //   Don't   translate   non-input   events.  
              if   (   (lpMsg->message   >=   WM_KEYFIRST   &&   lpMsg->message   <=   WM_KEYLAST)   )  
              {  
                    if   (   IsDialogMessage(hwndDllDlg,   lpMsg)   )  
                    {  
                          //   The   value   returned   from   this   hookproc   is   ignored,  
                          //   and   it   cannot   be   used   to   tell   Windows   the   message   has   been   handled.  
                          //   To   avoid   further   processing,   convert   the   message   to   WM_NULL  
                          //   before   returning.  
                          lpMsg->message   =   WM_NULL;  
                          lpMsg->lParam     =   0;  
                          lpMsg->wParam     =   0;  
                    }  
              }  
        }  
   
        return   CallNextHookEx(hHook,   nCode,   wParam,   lParam);  
  }  
   
  Top

2 楼orbit(走了走了)回复于 2005-01-26 20:22:47 得分 24

MFC中处理快捷键是在PreTranslateMessage中完成的,dll中没有消息循环,也就是没有周期性的调用CWinApp::PreTranslateMessage函数,所以从MainFrame窗口开始的各个窗口类的PreTranslateMessage都没有被调用,所以没有处理Tab键。  
  有两个方法解决这个问题:  
  1。在dll中创建一个线程(从CWinThread派生),在线程中创建无模式对话框,将无模式对话框的窗口指针赋值给线程类的m_pMainWnd  
  2。在dll中创建一个导出函数,如BOOL   FunctionName(MSG   *pMsg),在函数中通过无模式对话框的窗口指针调用对话框类的PreTranslateMessage,在调用这个dll的主程序的CxxxWinApp类的PreTranslateMessage函数(从CWinApp派生)中调用FunctionName。Top

3 楼sks(可子)回复于 2005-01-27 09:01:39 得分 0

谢谢两位的回复。  
   
  我先尝试了导出函数的方法,但是好像不灵。不知道为什么。然后用   kingzai   给出的方法成功了。但是调试的时候遇到几个问题。  
   
  1.GetMsgProc这个函数里面不能使用this指针,所以我用了一个static   *pThis变量来指向this,这样就可以使用   pThis->m_hWnd   了。  
   
  2.GetMsgProc函数的最后一句中   hHook   应该在哪里定义呢?我的做法是定义成this的成员变量,然后用   pThis->m_hHook   。但总觉得这个方法比较龌龊。  
   
  请大家指点一下。谢谢Top

4 楼kingzai(stevenzhu)回复于 2005-01-27 09:37:40 得分 4

写钩子函数hHook一般是写在共享代码段的,全局变量,你查一下钩子的通用写法便知Top

5 楼windyhui(冷月清风)回复于 2005-01-28 14:57:39 得分 2

帮你顶一下Top

6 楼sks(可子)回复于 2005-01-31 11:13:53 得分 0

还有一个很重要的问题。用了那个钩子的方法后,对话框上的编辑框内输入汉字时,都变成乱码。  
   
  我想了一个办法,判断当前焦点是否为输入框,是的话,就跳过这条消息。但总觉得这不是好办法。  
   
  而且还有,自己定义了快捷键后,要在pretransmessage这个函数中添加一句话  
  TranslateAccelerator(   pThis->m_hWnd,   pThis->m_hAccel,   lpMsg)  
  我把这句话放在那个GetMsgProc函数中,会有一些副作用。当那个非模式对话框没有焦点时,也可以接受快捷键的消息。  
   
  总的来说,似乎MS提供的这个方法有很多不完备的地方,也许我对“钩子”的使用还了解吧。  
   
  我觉得用线程的方法可能会从根本上解决问题。那位仁兄能提供详细一点的说明吗?我想不明白应该怎么做。Top

相关问题

  • 如何在对话框中响应快捷键?
  • 如何在对话框中实现快捷键?
  • 我将对话框的按钮设置了快捷键
  • 求教:对话框Dialog上控件的快捷键
  • 对话框的UpdateData好像失灵了
  • 如何在基于对话框的程序中加入快捷键(不用hotkey)
  • 怎么为对话框中的工具条上实现快捷键?
  • 怎么在基于对话框的程序中响应“快捷键消息”
  • 对话框的快捷键,没搞定,那个大虾给看看..
  • 在对话框中使用快捷键出现断言错误,急,在线等

关键词

  • 函数
  • 模式
  • 指针
  • 消息
  • 快捷键
  • lpmsg
  • getmsgproc
  • 调用
  • 钩子
  • hhook

得分解答快速导航

  • 帖主:sks
  • kingzai
  • orbit
  • kingzai
  • windyhui

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo