我的绘画代码消耗了太多的内存(为了更清晰而改写)

时间:2013-10-11 04:44:14

标签: c++ winapi gdi+

介绍及相关信息:

问题的第一部分:

窗口在调整大小时会产生类似闪烁的(慢速重绘效果)

我有一个复杂的绘画要在我的主窗口的WM_PAINT处理程序中实现。 我已经提交了一张图片。

enter image description here

标有1和2的徽标使用GDI+绘制。标记为1的徽标为metafile,标记为2的徽标为PNG

如果我省略了第二个徽标的绘图,我的窗口不会闪烁,但如果我在WM_PAINT中添加第二个徽标的图形,则会出现以下效果,如下图所示(这只是在Paint中制作的草图,但希望它能清除一切):

enter image description here

看起来好像重新涂漆很慢。

重要说明:此效果发生在子窗口上,背景绘制正确。

以防万一,关于子窗口的信息:

所有5个子窗口都是静态控件。

蓝色渐变的静态控件在GDI中使用WM_CTLCOLORSTATIC绘制了双缓冲。

橙色静态控件为subclassed,为ownerdrawn

重要提示:我必须说这是我第一次使用GDI+

在我的WM_PAINT处理程序中,我已经制作了双缓冲所需的兼容内存DC,如下所示:

   HDC hdc = BeginPaint( hwnd, &ps), hdcMemImg, MemDC;
   MemDC = CreateCompatibleDC(hdc); // back buffer.

兼容位图具有主窗口客户区的尺寸。

正如我所说,一切似乎都运行良好,因为我使用GDI和双缓冲来绘制/绘制。

当我需要绘制标有1和2的徽标时,我会使用以下代码进行绘制:

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        Image image(L".\\resources\\BG.emf"), image1(L".\\resources\\RGF.png");
        switch(msg)
        {
        case WM_ERASEBKGND:
           return (LRESULT)1;
        case WM_PAINT:
           {
              PAINTSTRUCT ps;
              HDC hdc = BeginPaint( hwnd, &ps), hdcMemImg, MemDC;
              MemDC = CreateCompatibleDC(hdc); // back buffer.
              // CreateCompatibleBitmap and other usual stuff
              /******************** left logo *******************/
              Graphics graphics( MemDC );
              //============= aspect ratio ================//
              UINT o_height = image.GetHeight(),
                   o_width =  image.GetWidth();
              INT n_width = 80;
              INT n_height = 100;
              double ratio = ( (double)o_width ) / ( (double)o_height );
              if (o_width > o_height)
              {
                  // Resize down by width
                  n_height = static_cast<UINT>( ( (double)n_width ) / ratio );
              }
              else
                  n_width = static_cast<UINT>(n_height * ratio);
              //========== ensure high graphic quality ======================//
              graphics.SetSmoothingMode( SmoothingModeHighQuality );
              graphics.SetInterpolationMode( InterpolationModeHighQualityBicubic );
              graphics.DrawImage( &image, r.left + 5, r.top + 10, n_width, n_height );
              /******************** right logo *******************/
              Graphics graphics1( MemDC );
              //============= aspect ratio ================//
              o_height = image1.GetHeight(), 
              o_width = image1.GetWidth();
              n_width = 90;
              n_height = 100;
              ratio = ( (double)o_width ) / ( (double)o_height );
              if (o_width > o_height)
              {
                  // Resize down by width
                  n_height = static_cast<UINT>( ( (double)n_width ) / ratio );
              }
              else
                 n_width = static_cast<UINT>(n_height * ratio);
              //=========== ensure high graphic quality ============//
              graphics1.SetSmoothingMode( SmoothingModeHighQuality );
              graphics1.SetInterpolationMode( InterpolationModeHighQualityBicubic );
              graphics1.DrawImage( &image1, r.right - r.left - 90, r.top + 10, n_width, n_height );
              // Then do BitBlt of MeDC to hdc, and clean it up

如果需要额外的代码段,请询问,我将编辑我的帖子,但是现在,它们被省略以使帖子简洁明了。

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

我的CPU是单核(2,67 GHz),我有768 MB的RAM。

重要更新:

当我打开Task Manager时,我可以看到我的应用程序天空消耗的内存消耗。

它永远不会掉落,它总会增长,特别是当我调整窗口大小时。

我可以在下面找到解决这个问题的详细描述。

我决定接受更有经验和更好的开发人员的建议,并提供演示项目的链接。

一条注意事项,因为VS 的Express版本没有资源编辑器,资源文件和资源标头是使用ResEdithttp://www.resedit.net/创建的

以下是演示项目的链接(所有必要的评论和解释都在项目评论中):http://www.uploadmb.com/dw.php?id=1382012579

我努力解决问题:

浏览互联网,SO档案,CodeProject和CodeGuru,我无法看到问题 - 似乎(我也相信),GDI+和{{1}中的双缓冲原则是一样的。

重要更新:

我已从http://vld.codeplex.com/下载了GDI,按照他们的说明操作,但VLD未检测到任何内存泄漏。

另外,我已经制作了一个项目副本并删除了静态控件,只留下窗口的背景来简化我的调试。

上述内存消耗仍然存在。

只有在我不绘制徽标时才会停止。

问题:

由于这是我第一次使用VLD,因为发布/删除了一些GDI+对象或类似内容(所有GDI+代码),我是否会遗漏某些内容用于绘制GDI+已提交)?

同样,我相信我的其他绘画代码效果很好,但如果需要我会发布。

更新:

关于上面提供的更新,我该怎么做才能解决上面描述的过多内存消耗问题?

有人可以查看上面提供的小型演示项目,并尝试给我有用的建议吗?

谢谢。

问候。

2 个答案:

答案 0 :(得分:1)

通过此链接中的详细解释解决了该问题: http://www.codeproject.com/Questions/666738/Window-produces-flicker-like-slow-repainting-like

如果链接失效,这就是我必须做的事情:

  1. 将左侧徽标调整到合适的尺寸;

  2. 删除一些我错过的内存泄漏;

  3. Image个对象设为全局;

  4. 第三个动作是最重要的,因为每次调用主窗口的程序时我都会重复加载巨大的图像,这最终会耗尽内存。

    希望这将有助于将来的人。

答案 1 :(得分:0)

不要使用GDI +的多个Graphics对象。 还要注意,在将Bitmap复制回真实DC后,将运行此Graphics对象的解构。 Thios也可能引起副作用。

将所有Graphics对象放在自己的块中,以便在将mem DC复制回绘制DC之前进行解构。