首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的绘画代码消耗了太多的内存(为了更清晰而重新措辞)

我的绘画代码消耗了太多的内存(为了更清晰而重新措辞)
EN

Stack Overflow用户
提问于 2013-10-11 04:44:14
回答 2查看 344关注 0票数 1

简介及相关信息:

以前的问题标题:

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

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

标志标记为1和2,使用GDI+绘制。标志标记为1,是metafile,标志用2标记为PNG

如果我遗漏了第二个徽标的绘图,我的窗口就不会闪烁,但是如果我将第二个徽标的绘图添加到我的WM_PAINT中,则会出现以下效果,如下图所示(这只是一个用油漆制作的素描,但希望它能使事情变得更清晰):

重新油漆的速度似乎很慢。

重要注意:这一效果发生在子窗口上,背景画得很好。

以防万一,有关子窗口的信息如下:

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

带有蓝色梯度的静态控件在WM_CTLCOLORSTATIC中使用WM_CTLCOLORSTATIC使用双重缓冲进行绘制。

橙色静态控件是subclassed,是ownerdrawn

注意:我必须说,这是我第一次使用GDI+__。

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

代码语言:javascript
复制
   HDC hdc = BeginPaint( hwnd, &ps), hdcMemImg, MemDC;
   MemDC = CreateCompatibleDC(hdc); // back buffer.

兼容位图有主窗口的工作区的尺寸。

正如我已经说过的,一切看起来都很好,因为我使用GDI和双缓冲来绘制/绘制。

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

代码语言:javascript
复制
    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上工作,使用C++和纯Win32 API。

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

重要更新:

当我打开Task Manager的时候,我可以看到我的应用天空的内存消耗是火箭。

它永远不会掉落,它总是会生长,特别是当我调整窗户的尺寸时。

关于我为解决这一问题所作努力的详细说明见下文。

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

一个注意事项:自从VS的速成版没有资源编辑器以来,就使用ResEdithttp://www.resedit.net/创建了资源文件和资源头。

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

我解决问题的努力:

在互联网上浏览,所以存档、CodeProject和CodeGuru,我没有看到问题--似乎(我也相信),GDI+GDI中双重缓冲的原则是一样的。

重要更新:

我从http://vld.codeplex.com/下载了http://vld.codeplex.com/,按照他们的指示,但是VLD没有检测到任何内存泄漏。

此外,我做了一个项目的副本,并删除了静态控件,只留下窗口的背景,以方便我的调试。

上述内存消耗仍在发生。

只有当我不画徽标的时候,它才会停止。

问题:

由于这是我第一次使用GDI+,在释放/删除某些GDI+对象或类似的东西(所有用于在WM_PAINT中绘图的GDI+代码都提交了)时,是否遗漏了什么?

再次,我相信我的其他绘画代码工作良好,但我会张贴它,如果需要。

更新:

关于上面提供的更新,我应该做些什么来解决上面描述的内存消耗过大的问题?

有人能回顾一下上面提供的小型演示项目,并尝试给我一些有用的建议吗?

谢谢。

致以问候。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-01 12:16:38

这个问题在这个链接中得到了很详细的解释:http://www.codeproject.com/Questions/666738/Window-produces-flicker-like-slow-repainting-like

如果这个链接死了,这就是我必须做的:

  1. 调整我的左徽标到适当的尺寸;
  2. 删除一些我错过的记忆泄漏;
  3. 使Image对象具有全局性;

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

希望这能对将来的人有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2013-10-11 08:18:06

不要使用GDI+的多个Graphics对象。请注意,在您将位图复制回真实的DC之后,解构这个Graphics对象也会运行。硫酸钠也可能引起副作用。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19310407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档