4

简介及相关资料:

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

下图显示了它的外观。

在此处输入图像描述

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

此时,单击它们时激活的操作是不相关的。

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

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

橙色静态控件上的贴图,左上标识为EMF文件,右上标识为PNG文件,其他图片为位图。

橙色静态控件有 4 个子静态控件,它们owner drawn也有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_VREDRAWCS_HREDRAW从我的窗口类中排除了 - 因此不应该因此而导致闪烁。

我忘了提到,我的窗户有WS_CLIPCHILDREN风格,所以我现在提一下,以回应成员Roger Rowland的评论。

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

问题:

  1. 如何修改演示项目中的代码以消除闪烁?

  2. 我需要关于如何优化WM_PAINTWM_CTLCOLORSTATIC处理程序的建议,以便我的绘画代码变得更高效、更快。

第二个问题的小说明:

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

这样,我只会NULL_BRUSH在我的WM_CTLCOLORSTATIC处理程序中返回,并在WM_PAINT.

我在这个想法的正确轨道上吗?这行得通吗?

谢谢你。问候。

4

1 回答 1

1

首先,您的应用程序漏洞百出。还没有寻找泄漏,但它们中的大多数应该在WM_CTLCOLORSTATIC您忘记删除 HBITMAP 的情况下(使用这个简洁的免费软件http://www.nirsoft.net/utils/gdi_handles.html来查找 gdi 泄漏)。

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

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

大大简化您的代码。

反正讲的够多了,让我们回到你的问题。在WM_CTLCOLORSTATIC你必须返回画笔时,你想用它来绘制背景。您现在正在做的是使用 手动绘制背景Bitblt(),然后返回 NULL 画笔并程序将其绘制在您已经绘制的背景上。与其自己画,不如让画笔来完成。简单地而不是最后一次Bitblt()使用CreatePatternBrush(),但是你需要照顾这个刷子,这是你应该做的:

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;
            }
//.......
于 2013-11-02T22:59:04.720 回答