MFC控件的不创建窗口也允许激活的选项查探
来源:互联网 发布:java方法重写 原则 编辑:程序博客网 时间:2024/06/07 02:38
最近在写一个控件,其包含两部分的接口,一部分是无需要窗口即可调用的,一部分是必需和窗口关联的调用。
无需要窗口调用的,是指这个控件的全局性接口,在我的工程中它们不需要特定的某个控件实例。比如在一个工程中,可以在一个窗口上拖放多个此控件,那无需窗口就可调用的接口是对每个实例都有效的这种接口。比如传入一个字符串,然后把它保存到文件中。
必需和窗口关联的接口,是指和窗口有关系的情况,比如传入一个用户名,而这个用户名必需在一个窗口上显示。
为了更好地表现无需要窗口就可调用的接口,在建立控件工程的向导时注意了一个相关的选项,其中刚好发现了一个选项:Windowless activation,解释为:允许不创建窗口来激活控件,看似不错,虽然没有用过,还是把它勾上了,先看看再说。完成向导,编译成功。创建demo工程测试,也没有问题。
后向控件中添加接口,其中包含了一个事件,在控件的CxxCtrl::OnCreate()中触发这个事件,在demo中处理这个事件。
运行demo发现这个事件无法触发,由于这个写法之前用其它工程已经测试过了,完全没有问题,而这个控件却不行,有点奇怪。
在控件的OnCreate中下断点然后运行demo,结果OnCreate没有进来!
后对CxxCtrl添加OnClose()函数,并下断点,在关闭demo时发现,CxxCtrl的m_hWnd为0!
知道了,原来这就是所谓的不创建窗口也允许激活控件的功能。工程中对应的代码:
<pre class="cpp" name="code">DWORD CxxCtrl::GetControlFlags(){DWORD dwFlags = COleControl::GetControlFlags();// The control can activate without creating a window.// TODO: when writing the control's message handlers, avoid using//the m_hWnd member variable without first checking that its//value is non-NULL.dwFlags |= windowlessActivate;return dwFlags;}
就是dwFlags |= 的这一行。
不过,在控件显示后,还是会有一个椭圆显示在上面!
画这个东西就是在一个窗口上画的,那说明还是有个窗口在的,但不是CxxCtrl。在CxxCtrl::OnDraw()中下断点,然后运行demo,在断点处停住后,查看调用堆栈:
CocxdemoDlg::OnPaint()CDialog::OnPaint()CWnd::PaintWindowlessControls(CDC *pDC)COleControlContainer::OnPaint(CDC* pDC)COleControl::XViewObject::Draw(DWORD dwDrawAspect, LONG lindex, void* pvAspect, DVTARGETDEVICE* ptd, HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL (CALLBACK* pfnContinue)(DWORD_PTR), DWORD_PTR dwContinue)COleControl::DrawContent(CDC* pDC, CRect& rc)CxxCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
注意,以上是按照调用顺序来贴上去的,实际调试时,vs中是从下往上列出这些调用函数的。
最终发现,这个窗口竟然是装控件的窗口!为了证明确实是这个窗口,对CxxCtrl的OnDraw修改如下:
void CxxCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid){if (!pdc)return;// TODO: Replace the following code with your own drawing code.CRect rcDraw(rcBounds);pdc->FillRect(rcDraw, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));rcDraw.right += rcBounds.Width();rcDraw.bottom += rcBounds.Height()/2;pdc->Ellipse(rcDraw);}
控件背景的大小没有修改,只对椭圆的宽度增加一倍,高度增加1/2。再运行demo,出现了预期中的效果,即控件背景的区域大小没变,但是椭圆增大了指定的尺寸。如果这个pdc不是这个窗口,则肯定无法看到超过控件区域的图像。
原来如此。效果如下图所示:
为了查看windowlessActivate的影响,把DWORD CxxCtrl::GetControlFlags()中的dwFlags |= windowlessActivate;一行注释掉:
DWORD CxxCtrl::GetControlFlags(){DWORD dwFlags = COleControl::GetControlFlags();// The control can activate without creating a window.// TODO: when writing the control's message handlers, avoid using//the m_hWnd member variable without first checking that its//value is non-NULL.//dwFlags |= windowlessActivate;return dwFlags;}
然后再编译运行,发现此次的CxxCtrl::OnDraw()是通过CWnd来调用的,显示和之前走的就不是同一个分支了。同时,增大了的椭圆就只显示了控件区域中的那一部分了,超出的部分没有显示。另外,CxxCtrl::OnCreate()也进来了。效果如下图所示:
当时建立工程时,从网上也搜索了一下Windowless activation选项,结果都只进行了简单的翻译,没啥解释。今天运行时这个控件的demo时,发现OnCreate()没有进来,于是去网上搜索,顺便搜索出来了其它的一些问题,比如:
http://bbs.csdn.net/topics/200016476
http://blog.csdn.net/gxulg/article/details/311057
于是就想把它搞明白,然后进行了以上的跟踪尝试,终于发现了问题所在。当然以上的跟踪比较浅显,还没有仔细查看有关 CWnd::PaintWindowlessControls(CDC *pDC) 的分支是如何整体进行工作的。以后如果需要时再进行分析
- MFC控件的不创建窗口也允许激活的选项查探
- MFC 窗口的创建
- MFC窗口的创建
- MFC创建窗口的过程
- MFC浮动窗口的创建
- MFC的选项卡控件使用
- MFC选项卡控件的使用
- 创建类似于输入法窗口的非激活窗口
- 创建类似于输入法窗口的非激活窗口--续
- 创建类似于输入法窗口的非激活窗口
- 创建类似于输入法窗口的非激活窗口
- 创建基于MFC的ActiveX控件时各选项的说明
- MFC 树控件,也挺麻烦的
- 只允许创建一个实例的VB.NET窗口
- gcc不常用但也很重要的编译选项
- MFC操作父窗口的子控件
- MFC操作父窗口的子控件
- MFC 各个窗口 控件的风格等
- sudo配置文件/etc/sudoers格式
- Linux用户组用户管理
- Spring的控制反转(IOC)和依赖注入(DI)详解
- 未能加载文件或程序集“System.EnterpriseServices 或它的某一个依赖项
- 【 D3.js 进阶系列 — 1.1 】 其他表格文件的读取
- MFC控件的不创建窗口也允许激活的选项查探
- android系统编译错误解决
- Android Svn中不需要上传的文件(可忽略的文件)
- JavaScript学习笔记
- 广州高清卫星地图 用百度卫星地图服务器下载 含标签、道路数据叠加 可商用
- Cisco路由器缓解密码猜测攻击的方法
- selenium 详解教程
- 浅谈C++中指针和引用的区别
- Secrets of the Ftrace function tracer