问题的第一部分:
窗口在调整大小时会产生类似闪烁的(慢速重绘效果)
我有一个复杂的绘画要在我的主窗口的WM_PAINT
处理程序中实现。
我已经提交了一张图片。
标有1和2的徽标使用GDI+
绘制。标记为1的徽标为metafile
,标记为2的徽标为PNG
。
如果我省略了第二个徽标的绘图,我的窗口不会闪烁,但如果我在WM_PAINT
中添加第二个徽标的图形,则会出现以下效果,如下图所示(这只是在Paint中制作的草图,但希望它能清除一切):
看起来好像重新涂漆很慢。
重要说明:此效果发生在子窗口上,背景绘制正确。
以防万一,关于子窗口的信息:
所有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版本没有资源编辑器,资源文件和资源标头是使用ResEdit
从http://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+
已提交)?
同样,我相信我的其他绘画代码效果很好,但如果需要我会发布。
更新:
关于上面提供的更新,我该怎么做才能解决上面描述的过多内存消耗问题?
有人可以查看上面提供的小型演示项目,并尝试给我有用的建议吗?
谢谢。
问候。
答案 0 :(得分:1)
通过此链接中的详细解释解决了该问题: http://www.codeproject.com/Questions/666738/Window-produces-flicker-like-slow-repainting-like
如果链接失效,这就是我必须做的事情:
将左侧徽标调整到合适的尺寸;
删除一些我错过的内存泄漏;
将Image
个对象设为全局;
第三个动作是最重要的,因为每次调用主窗口的程序时我都会重复加载巨大的图像,这最终会耗尽内存。
希望这将有助于将来的人。
答案 1 :(得分:0)
不要使用GDI +的多个Graphics对象。 还要注意,在将Bitmap复制回真实DC后,将运行此Graphics对象的解构。 Thios也可能引起副作用。
将所有Graphics对象放在自己的块中,以便在将mem DC复制回绘制DC之前进行解构。