目标
我想要实现的是在对话框具有焦点时按Ctrl C(和Ctrl Ins)的能力,然后我希望能够通过将一些信息复制到剪贴板来对此作出反应.因此,如果有人知道在WTL中使用模态对话框的方法,那也会回答我的问题.
我现在正在做什么
现在我现在所做的是从CDialogImpl< T>中导出我的对话框类.和cmessageFilter为了让我负责PreTranslateMessage.在那里,我只使用CAccelerator :: TranslateAccelerator和CWindow :: IsDialogMessage来处理加速和对话框消息.
在OnInitDialog中,我填充加速表并将消息过滤器添加到(“全局”)消息循环中.加速表与对话框本身具有相同的资源ID:
m_accel.Attach(AtlLoadAccelerators(IDD));cmessageLooP* pLoop = _Module.GetMessageLoop();pLoop->AddMessageFilter(this);
然后我通过名称PretendModal为DoModal创建了一个代理,它使用“全局”消息循环.
现在,我看到的效果(出现在任务栏上的对话框除外)是应用程序,一旦模态对话框关闭,就不能再关闭了.确切地说,主消息循环接收WM_QUIT(WTL :: cmessageLoop :: Run()中的ATLTRACE2给出了它,但是在这个特技之后它仍然挂起(主框架窗口关闭,WM_QUIT被发布,但是进程没有如果我在PretendModal中使用单独的cmessageLoop(而不是“全局”),整个事情的行为都是一样的.
甚至将另一个单独的cmessageLoop新实例移动到其自己的线程中(在所有消息循环都是线程本地之后)似乎无法解决此问题.这让我感到困惑的是,我在这里做错了什么.
注意:IDCANCEL和IDOK的处理程序从消息循环中删除对话框类(即消息过滤器).
题
在尝试使用无模式对话框模拟模态对话框时,我做错了什么?或者,当使用仅从CDialogImpl< T>派生的模态对话框时,如何捕获Ctrl C(和Ctrl Ins).
班级
class CAboutDlg : public CDialogImpl<CAboutDlg>,public cmessageFilter{ CAccelerator m_accel;public: enum { IDD = IDD_ABOUT }; BEGIN_MSG_MAP(CAboutDlg) MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog) COMMAND_ID_HANDLER(IDOK,OnCloseCmd) COMMAND_ID_HANDLER(IDCANCEL,OnCloseCmd) END_MSG_MAP() virtual BOol PreTranslateMessage(MSG* pMsg) { if (!m_accel.IsNull() && m_accel.TranslateAccelerator(m_hWnd,pMsg)) return TRUE; return CWindow::IsDialogMessage(pMsg); } LRESulT OnInitDialog(UINT,WParaM,LParaM,BOol&) { m_accel.Attach(AtlLoadAccelerators(IDD)); if (m_bModal) { cmessageLooP* pLoop = _Module.GetMessageLoop(); pLoop->AddMessageFilter(this); } return TRUE; } voID PretendModal(HWND hwndParent = ::GetActiveWindow()) { cmessageLooP* pLoop = _Module.GetMessageLoop(); if (pLoop && ::IsWindow(hwndParent)) { HWND dlg = Create(*this); if (::IsWindow(dlg)) { ShowWindow(SW_SHOW); pLoop->Run(); } } } LRESulT OnCloseCmd(WORD,WORD,HWND,BOol&) { if (m_bModal) EndDialog(0); else { cmessageLooP* pLoop = _Module.GetMessageLoop(); pLoop->RemoveMessageFilter(this); ::DestroyWindow(*this); } return 0; }};解决方法 所以同时我设法实现了我想要的.这似乎很好地工作,我还没有发现任何负面的副作用.
为了做我想做的事,我介绍了一个EmulateModal()函数,它模仿DialogImpl的DoModal()函数.
该功能如下:
voID EmulateModal(_In_ HWND hWndParent = ::GetActiveWindow(),_In_ LParaM DWInitParam = NulL){ ATLASSERT(!m_bModal); ::EnableWindow(hWndParent,FALSE); Create(hWndParent,DWInitParam); ShowWindow(SW_SHOW); m_loop.AddMessageFilter(this); m_loop.Run(); ::EnableWindow(hWndParent,TRUE); ::SetForegrounDWindow(hWndParent); DestroyWindow();}
m_loop成员是CDialogImpl派生类所拥有的cmessageLoop(它也继承自cmessageFilter,如问题所示).
唯一需要的其他特殊处理是将以下代码添加到命令ID处理程序中,该处理程序监视IDOK和IDCANCEL(在我的情况下都是关闭对话框),即在OnCloseCmd内部.
if(m_bModal){ EndDialog(wID);}else{ m_loop.RemoveMessageFilter(this); PostMessage(WM_QUIT);}
在调用DestroyWindow()之前从消息循环中删除消息过滤器(即PreTranslateMessage)很重要.退出由CDialogImpl派生类所拥有的“内部”消息循环以及从上面的EmulateModal()调用其Run()也非常重要.
所以要点是:
>从我的问题中删除PretendModal()方法>使用“内部”消息循环而不是使用顶级消息循环
总结以上是内存溢出为你收集整理的visual-c – 如何在WTL中模拟模态对话框?全部内容,希望文章能够帮你解决visual-c – 如何在WTL中模拟模态对话框?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)