c++ - 改进WM_PAINT和WM_CTLCOLORSTATIC处理程序的代码

标签 c++ winapi gdi+ gdi wm-paint

简介和相关信息:

我已经实现了对主窗口背景及其子静态控件的复杂绘制。

下图显示了外观。

静态控件具有SS_NOTIFY样式,这一点很重要,因为用户单击它们时会发生某些事情。

此时,单击它们时激活的 Action 不相关。

主窗口和静态控件都具有渐变背景,这些背景是通过使用GradientFill(...) API制成的。

主窗口的顶部横幅是使用灰色画笔创建的,而网格线是使用LineTo(...)MoveTo(...) API创建的。

橙色静态控件上的Map,左上角的徽标是EMF文件,右上角的徽标是PNG文件,其他图片是位图。

橙色静态控件有4个子静态控件,它们分别是owner drawnSS_NOTIFY样式。

这是我唯一想到的方法,它使我能够按照要求的方式来绘制控件(如果我可以对此进行改进,请提出建议,我将接受任何合理的建议)。

为了绘制橙色静态控件,我决定在WM_CTLCOLORSTATIC处理程序中绘制其背景,并决定所有者在子类过程中绘制子静态控件。

从子静态控件收到的通知也将在橙色静态控件子类过程中处理,因为我不知道如何将其转发到父窗口,但由于此时它们也无关紧要,因此将其省略。

我决定提供到演示项目的链接,而不是使用代码段使这篇文章冗长。

我尝试过尽可能地提交演示应用程序。

我没有对注解有所了解,因此我相信一切都已在源代码中很好地涵盖和解释。

如果仍有问题,请发表评论,我会尽快答复(通常立即或至少在同一天)。

这是演示项目的链接:http://www.filedropper.com/geotermistgrafika_1

重要更新:

/================================================= =========/

方括号中的文本波纹管是问题的原始部分,但由于该项目存在内存泄漏,因此现在省略了。上面的链接链接到改进的版本。

[已更新,以响应xMRi成员的评论:此链接应该可以:http://www.filedropper.com/geotermistgrafika]

/================================================= =========/

我使用MS Visual Studio C++和纯Win32 API在Windows XP上工作。

一个注意事项:,因为VS Express版没有资源编辑器,资源文件和资源 header 是使用ResEdit从此处创建的:http://www.resedit.net/

问题:

调整窗口大小时,静态控件会稍微闪烁。

我为解决问题而付出的努力:

我相信我的代码没有内存泄漏,因此我怀疑这是问题所在,但是由于没有经验,如果能以某种方式确认我的假设,我将不胜感激。

我认为我已经正确处理了WM_ERASEBKGND,并且从窗口类中排除了样式CS_VREDRAWCS_HREDRAW,因此不应因此而引起闪烁。

我忘记提及了,我的窗口具有WS_CLIPCHILDREN样式,因此,我现在提到这一点是为了响应成员Roger Rowland的吼叫。

为了避免闪烁,我为两个处理程序都实现了双重缓冲。

问题:

  • 如何在演示项目中修改代码以消除闪烁?
  • 我需要有关如何同时优化WM_PAINTWM_CTLCOLORSTATIC处理程序的建议,以便使我的绘画代码更高效,更快速。

  • 第二个问题的小注意事项:

    我当时想通过在主窗口的背景上绘制整个图片来改进代码,并在与该静态控件背景相对应的图片部分的顶部放置透明的静态控件。

    这样,我将只在NULL_BRUSH处理程序中返回WM_CTLCOLORSTATIC,并在WM_PAINT中完成所有工作。

    我对这个想法是否正确?能行吗?

    谢谢你。
    问候。

    最佳答案

    首先,您的应用程序像 hell 般漏水。尚未查找泄漏,但是大多数都应该在WM_CTLCOLORSTATIC中,因为您忘记删除HBITMAP(使用此简洁的免费软件http://www.nirsoft.net/utils/gdi_handles.html查找gdi泄漏)。

    其次,您的代码很庞大。我注意到您没有使用函数,可能是因为您不知道它们的功能。例如,我将使用:

    void DrawBackground(HDC &hDC, SOMEINFOSTRUCT GradientInfo, LPCTSTR Text);
    

    大大简化了您的代码。

    无论如何讲课,让我们回到您的问题上。在WM_CTLCOLORSTATIC中,您必须返回brush,您要使用其绘制背景。您现在正在执行的操作是使用Bitblt()手动绘制背景,然后返回NULL画笔,并程序将其绘制在您已绘制的背景上。不用自己绘画,而让画笔来完成这项工作。
    不用最后一个Bitblt()而是使用CreatePatternBrush(),但是您需要照顾好此Brush,这是您应该做的:
    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;
                }
    //.......
    

    关于c++ - 改进WM_PAINT和WM_CTLCOLORSTATIC处理程序的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19739179/

    相关文章:

    c# - 如何将弯曲的文本渲染成位图?

    c++ - 使 MFC CTabCtrl 不使用绘图选项卡的完整控件宽度

    delphi - SetWindowsHookEx WH_MOUSE 在 Win7 中断点卡住

    c++ - 如何使用具有多个比较器功能的 std::multiset?

    c++ - 使聚光灯静止

    c - 如何让 Windows 触摸板像 Mac 触摸板一样工作?

    c++ - 无法删除 GDI+ 图像

    c++ - 从内存中获取 jpeg 的大小(使用 GDI++ 转换)

    c++ - boost property_tree 在循环中添加节点

    c++ - CMake - 使用不正确数量的参数调用 add_executable