分析:由 XToolTip类 联想到 WTL (MFC) 消息循环

9 篇文章 0 订阅
2 篇文章 0 订阅

这篇文章从一个问题出发:我想自己写一个XToolTip类。

 

XToolTip类的思路:

1,创建一个WS_POPUP样式的窗口;

2,加入需要显示tooltip的控件(XToolTip类采用map<HWND,string>来保存这些控件句柄和提示字符串);

3,在PreTranslateMessage中调用XToolTip的RelayMsg函数;

4,在RelayMsg函数中过滤消息(WM_MOUSEMOVE,WM_MOUSELEAVE,WM_LBUTTONDOWN,WM_MBUTTONDOWNWM_RBUTTONDOWN);

5,当要显示tooltip时,先计算显示字符串需要的宽度和高度,然后调用SetWindowPos(NULL,rc,SWP_NOACTIVE | SWP_SHOWWINDOW);(此处特别注意,SWP_NOACTIVE | SWP_SHOWWINDOW这两个标记不能分开成这样,先SWP_NOACTIVE 再ShowWindow。否则tooltip显示时原窗口会失去焦点)。

 

看起来似乎一切尽在掌握,但是问题才刚刚开始,就引发了一个巨大的问题

 

在WTL中,非模态对话框才会执行到PreTranslateMessage:因为wtl中有一个message loop(这是在主线程中循环),里面是一个数组,用来保存每个继承CMessageFilter的窗口对象,然后在循环中遍历这个数组,依次调用每一个类对象的PreTranslateMessage函数。

 

基于此,我在设计模态对话框时是这么设计的:先禁用父窗口,再创建自己(自己并没有消息循环,所以导致DoModal之后不会阻塞主线程消息循环)。这样,在整个程序中,只有主线程这一个消息循环,那么不管是非模态还是“模态”窗口都可以执行到PreTranslateMessage。看似很好,但是这个“模态”对话框并不是我们想要的,我想要的是如同mfc那样阻塞的(比如:XDlg dlg;  dlg.DoModal();  printf("hello"); 就是在DoModal返回后再输出hello,而上面这样做,在DoModal之后hello立马就输出了,如果我要知道这个XDlg DoModal的返回值,还得通过XDlg在自杀之前给我发信,这明显不符合需要)。

 

那么,第二种模态对话框的方式自然就是如同mfc的模态一样,在DoModal中自己写消息循环,这样DoModal就是阻塞了。在自己写的消息循环中调用PreTranslateMessage,那么tooltip也没问题了。但是非模态对话框呢?主线程消息循环被我的子消息循环阻塞了,那么非模态对话框自然就执行不到PreTranslateMessage了,此时tooltip自然无法提示了。

 

两者不可兼得的情况下,我意外发现,不管是modal还是非modal对话框,我把鼠标放到 右上角 “关闭”按钮上时,会出现tooltip。那么windows又是如何做到的呢?我觉得有如下几种方式,但肯定不是消息循环。

1:重定向对话框的WindowProc函数,在这里过滤消息。

2:采用 鼠标钩子(可能是线程钩子,也可能是全局钩子),在钩子函数中过滤。 

 

那么,对于MFC呢?mfc与wtl明显不同,而且在这一点上做的比wtl好。mfc不管是模态还是非模态都可以调用到PreTranslateMessage,因为非模态对话框会共享模态对话框的消息循环。从这一点就可以明显看出,wtl和mfc在设计上的不同,CWnd做了大量的工作,而wtl却把这些工作给分离开了,需要就继承,不需要就不继承,所以wtl最后生成的exe才会很小。

所以,如果要在wtl做到模态和非模态都可以调用到PreTranslateMessage,那么可以模仿mfc的做法,把所有窗口都遍历一次调用PreTranslateMessage。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值