c – 改进WM_PAINT和WM_CTLCOLORSTATIC处理程序的代码
介绍及相关资料:
我已经实现了主窗口背景及其子静态控件的复杂绘制. 下图显示了它的外观. 静态控件具有SS_NOTIFY样式,这一点很重要,因为当用户点击它们时会发生某些事情. 此时,单击它们时激活的操作不相关. 主窗口和静态控件都具有渐变背景,这是通过使用GradientFill(…)API实现的. 使用灰色画笔创建主窗口的顶部横幅,并使用LineTo(…)和MoveTo(…)API创建网格线. 在橙色静态控件上映射,左上角的徽标是EMF文件,右上角的徽标是PNG文件,其他图片是位图. 橙色静态控件有4个子静态控件,它们是所有者绘制的,并且还具有SS_NOTIFY样式. 这是我能想到的唯一方式,这使我能够按照我的要求绘制控件(如果我可以改进,请提出建议,我会接受任何合理的建议). 为了绘制橙色静态控件,我决定在WM_CTLCOLORSTATIC处理程序中绘制其背景,并在所有者中绘制子类过程中的子静态控件. 从子静态控件接收的通知也在橙色静态控件子类过程中处理,因为我不知道如何将它们转发到父窗口,但由于它们此时也无关紧要而被省略. 我决定提供演示项目的链接,而不是使用代码片段使这篇文章相当冗长. 我试图尽可能小而简单地提交演示应用程序. 我没有吝啬评论,所以我相信一切都很好,并在源代码中解释. 如果仍有问题,请发表评论,我会尽快回复(通常是立即,或至少在同一天). 以下是演示项目的链接:http://www.filedropper.com/geotermistgrafika_1 重要更新: / ================================================= ========= / 方括号中的文字是问题的原始部分,但现在省略了,因为项目有内存泄漏.上面的链接链接到改进的版本. [更新以回应成员xMRi的评论:此链接应该没问题:http://www.filedropper.com/geotermistgrafika] / ================================================= ========= / 我在Windows XP上工作,使用MS Visual Studio C和纯Win32 API. 一个注意事项:由于VS的Express版本没有资源编辑器,因此使用ResEdit从这里创建资源文件和资源头:http://www.resedit.net/. 问题: 当我调整窗口大小时,静态控件会略微闪烁. 我努力解决问题: 我相信我的代码没有内存泄漏 – 因此我怀疑这是问题所在,但由于缺乏经验,如果我的假设可以某种方式得到确认,我将非常感激. 我认为我已经正确处理了WM_ERASEBKGND,并且我已经从我的窗口类中排除了CS_VREDRAW和CS_HREDRAW样式 – 因此不应该因此引起闪烁. 我忘了提一下,我的窗口有WS_CLIPCHILDREN样式,所以我现在提到这一点,以回应成员Roger Rowland的评论. 我为这两个处理程序实现了双缓冲,以避免闪烁. 问题: >如何修改演示项目中的代码以消除闪烁? 第二个问题的小注: 我想通过在主窗口的背景上绘制整个图片来改进我的代码,并将透明的静态控件放在与静态控件背景相对应的图片部分的顶部. 这样,我只会在WM_CTLCOLORSTATIC处理程序中返回NULL_BRUSH,并在WM_PAINT中完成所有工作. 这个想法我在正确的轨道上吗?这可行吗? 谢谢. 解决方法
首先,你的应用程序漏洞了.没有找到泄漏,但大多数应该在WM_CTLCOLORSTATIC,因为你忘了删除HBITMAP(使用这个整洁的免费软件
http://www.nirsoft.net/utils/gdi_handles.html来寻找gdi泄漏).
其次,你的代码是大的.我注意到你没有使用函数,可能是因为你不知道它们的功能.例如,我会使用: void DrawBackground(HDC &hDC,SOMEINFOSTRUCT GradientInfo,LPCTSTR Text); 简化你的代码很多. 无论如何,演讲,让我们回到你的问题.在WM_CTLCOLORSTATIC中你必须返回画笔,你想要用背景画.你现在正在做的是使用Bitblt()手动绘制背景,然后返回NULL画笔并在你已绘制的背景上绘制程序.而不是自己绘画,让刷子完成工作. HBRUSH TempBrush = NULL; //Create global brush //Some Code.... case WM_CTLCOLORSTATIC: { if (TempBrush != NULL) { DeleteObject(TempBrush); TempBrush = NULL; } //Let's skip to the end.... GradientFill( MemDC,vertex3,3,&gTriangle,1,GRADIENT_FILL_TRIANGLE ); TempBrush = CreatePatternBrush(bmp);// these 3 line should be at the //end of every if DeleteDC(MemDC); // or put them once outside if's DeleteObject(bmp); // also if you delete HDC first,you don't need to //unselect hbitmap } return (LRESULT)TempBrush; } break; case WM_CLOSE: { if (TempBrush != NULL) { DeleteObject(TempBrush); TempBrush = NULL; } //....... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |