在dll中弹出非模态对话框 分享


最近在写视频嵌入的插件,其实就是在dll中去实现exe中需要的视频功能,好处是,可以同时支持多厂家的视频设备。需要 做的是制订好exe与dll的接口,然后针对该接口开发出调用各个厂家视频功能的dlls。

最常用的功能大概就是视频实时预览了,设计的目标是在dll中弹出一个非模态对话框,其上面显示视频以 及必要的控制,如云镜控制、录像抓图、灯光控制等等。之所以要非模态的对话框,是因为exe界面上还有很多功能,不能因为弹出了视频窗口而无法使用。

就是这样一个小case,却出了问题:dll弹出非模态对话框后,无法通过按ESC键将其关闭,TAB 键也无法使用。因为对话框上尚无过多控件,还没去测试其他按键消息能否响应。

测试软件界面如图:

 在dll中弹出非模态对话框 分享_第1张图片

 

仔细检查了对话框的消息响应函数,没有问题。也试过重载其PreTranslateMessage() 函数,发现按键消息根本不能进入此函数来处理! 既然它没有处理按键消息,那应该是exe的框架 处理了按键消息?试了一下,果然,对话框得到焦点时,按键消息却被exe处理了。

回忆了一下以前做过的程序,也常会用到非模态的对话框,可从来没遇到此问题啊。。。再经过仔细的思索, 发现从前使用过非模态对话框,也在dll中弹出过对话框(模态),可却从未将两者结合起来使用,即:从来还没有在dll中弹出过非模态对话框!看来是首次 遇到的问题了。

在网上搜索了一下,确实有人曾经遇到过相同的问题,竟然据称是用hook来解决的!~杀鸡焉用牛 刀。。。

又经过一番search,最终目光定位到一个Windows API上:IsDialogMessage(),----- 利用它解决了此问题:在exe的PreTranslateMessage()中,看看pMsg的接收窗口,如果是对话框或对话框的控件,则调用它来处理此 条消息,一切OK了!

还没有去深究产生这个现象的原因,猜测和MFC封装的消息流程有关,手头还有不少活要忙,先不求甚解 了。

 

我正在玩搜狐微博,快来“关注”我,了解我的最新 动态吧。
http://medave.t.sohu.com/
分享到搜狐微博
分享 分享  |  评论 ( 5 ) |  阅读 ( 161 )  |  固定链接  |  类别 ( 工作、学习 ) |  发表于 13:10  | 最后修改于 2008-12-04 13:20

评论      想第一时间抢沙发么?

搜狐白社会 推荐: 活动:偷菜不如盖楼,玩游戏就能挣50万元 | 2010年种菜偷菜不如盖房收租 | 比偷菜还好玩的钓鱼游戏 | 每日测试:你这辈子有富贵命吗?
能编软件真爽.
我觉得你找 的工作很适合你啊 微笑 大笑

发布者 搜狐网友 (未验证) (http://blog.sohu.com/)
2008-12-04 15:59

回复

大侠 你的QQ是多少啊 我也遇到了相同的问题 想请教您。。

发布者 搜狐网友 (未验证) (http://blog.sohu.com/)
2009-10-11 22:30

回复

搜狐网友 在上文中提到:
大侠 你的QQ是多少啊 我也遇到了相同的问题 想请教您。。

请在这里说就可以了。

发布者 搜狐网友 (未验证) (http://blog.sohu.com/)
2009-10-12 08:50

回复

我的主程序是要产生一个线程,在线程函数中调用DLL来显示一个modeless对话框(嵌入到MainFram中做其子窗口) 一开始我的对话框中的控件也跟您的情况一样点击毫无反应,我尝试在CMainFram中重载PreTranslateMessage()函数 但是我不懂怎么分发消息(例如什么消息该由主框架自己来处理,什么消息由子窗口处理) 因为我跟踪了一下,所有的消息pMsg->m_hWnd都来自于主框架,根本区分不出来 后来我干脆把所有的消息Send给子窗口处理一遍后再由主框架继续传递下去 这样做虽然控件都有反应了,不过产生了新的问题 我调整主框架Size和移动时子窗口也处理了这个消息 在不关闭子窗口时关闭主程序产生异常 代码在公司,不能上码实属遗憾! 希望大侠指条明路,不慎感激!谢谢!

发布者 搜狐网友 (未验证) (http://blog.sohu.com/)
2009-10-13 18:55

回复

我把我的代码贴出来你看看有没有帮 助:
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
//
// 以下代码为了解决在dll弹出的非模态对话框上不接受按键消息的问题。
//
char szClassName[128];
// 看当前接收消息的窗口是不是对话框
HWND hwnd = pMsg->hwnd;
::GetClassName(hwnd, szClassName, 128);
if (strcmp(szClassName, "#32770") == 0)
{
if (::IsDialogMessage(hwnd, pMsg)) return TRUE;
}
else
{
// 看当前接收消息的窗口的父窗口是不是对话框
::GetClassName(::GetParent(hwnd), szClassName, 128);
if (strcmp(szClassName, "#32770") == 0)
{
if (::IsDialogMessage(::GetParent(hwnd), pMsg)) return TRUE;
}
}
}
return CFrameWnd::PreTranslateMessage(pMsg);
}
另外,我建 议你最好通过发消息的方式来显示dll中的对话框,而不是在某个线程中直接调用dll导出函数来创建对话框。

你可能感兴趣的:(编程杂烩)