Win32:窗口在整个生命周期中都具有相同的HDC吗? [英] Win32: Does a window have the same HDC for its entire lifetime?

查看:145
本文介绍了Win32:窗口在整个生命周期中都具有相同的HDC吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以在涂漆周期之外使用DC吗? 我的窗户的DC可以保证永远有效吗?

Am i allowed to use a DC outside of a paint cycle? Is my window's DC guaranteed to be valid forever?

我试图弄清楚控件的设备上下文(DC)的有效期.

i'm trying to figure out how long my control's Device Context (DC) is valid.

我知道我可以打电话:

GetDC(hWnd);

获取我控件窗口的设备上下文,但是允许吗?

to get the device context of my control's window, but is that allowed?

Windows向我发送WM_PAINT消息时,我应该打电话给 BeginPaint / EndPaint 以正确确认我已经画好了,并在内部清除了无效区域:

When Windows sends me a WM_PAINT message, i am supposed to call BeginPaint/EndPaint to properly acknowledge that i've painted it, and to internally clear the invalid region:

BeginPaint(hWnd, {out}paintStruct);
try
   //Do my painting
finally
   EndPaint(hWnd, paintStruct);
end;

但是调用BeginPaint也会在PAINTSTRUCT结构内部返回DC.这是我应该绘画的DC.

But calling BeginPaint also returns me a DC inside the PAINTSTRUCT structure. This is the DC that i should be painting on.

我在文档中找不到任何内容,表明BeginPaint()返回的DC与我从GetDC()获得的DC相同.

i cannot find anything in the documentation that says that the DC returned by BeginPaint() is the same DC that i would get from GetDC().

现在特别是在桌面合成"时代,在我从BeginPaint之外获得的DC上绘画是否有效?

Especially now, in the days of Desktop Composition, is it valid to paint on a DC that i obtain outside of BeginPaint?

在绘画周期中,我似乎可以通过两种方式获得DC:

There seem to be 2 ways i can get a DC to paint on during a paint cycle:

  1. dc = GetDC (hWnd);

BeginPaint(& paintStruct);

BeginPaint(&paintStruct);

有第三种方法,但这似乎是我开发的Borland Delphi的一个错误.

There is a 3rd way, but it seems to be a bug with the Borland Delphi that i develop with.

WM_PAINT 处理期间,Delphi认为wParam是DC,并继续在其上绘画. MSDN表示WM_PAINT消息的wParam未使用.

During WM_PAINT processing, Delphi believes that the wParam is a DC, and proceeds to paint on it. Whereas the MSDN says that the wParam of a WM_PAINT message is unused.

我的真正目标>尝试保持持久的GDI +针对HDC的图形对象,这样我就可以使用GDI +的一些性能更好的功能,这些功能依赖于持久的DC.

My real goal is to try to keep a persistent GDI+ Graphics object against an HDC, so that i can use some better performing features of GDI+ that depend on having a persistent DC.

在WM_PAINT消息处理期间,我想在画布上绘制GDI +图像.以下nieve版本非常慢:

During the WM_PAINT message handling i want to draw a GDI+ image to the canvas. The following nieve version is very slow:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);
   Graphics g = new Graphics(ps.hdc);
   g.DrawImage(m_someBitmap, 0, 0);
   g.Destroy();
   EndPaint(h_hwnd, ps);
}

GDI包含性能更快的位图,即CachedBitmap.但是,不加思索地使用它并不会带来性能上的好处:

GDI contains a faster performing bitmap, a CachedBitmap. But using it without thinking gives no performance benefit:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);

   Graphics g = new Graphics(ps.hdc);
   CachedBitmap bm = new CachedBitmap(m_someBitmap, g);
   g.DrawCachedBitmap(m_bm, 0, 0);
   bm.Destroy();
   g.Destroy();
   EndPaint(h_hwnd, ps);
}

性能提升来自一次创建CachedBitmap,因此程序初始化:

The performance gain comes from creating the CachedBitmap once, so on program initialization:

m_graphics = new Graphics(GetDC(m_hwnd));
m_cachedBitmap = new CachedBitmap(b_someBitmap, m_graphcis);

现在是绘画周期:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);
   m_graphics.DrawCachedBitmap(m_cachedBitmap, 0, 0);
   EndPaint(h_hwnd, ps);
}        

除了现在,我相信,只要应用程序正在运行,程序初始化后获得的DC将与我的窗口的DC相同.这意味着它可以通过以下方式生存:

Except now i'm trusting that the DC i obtained after program initializtion will be the same DC for my window as long as the application is running. This means that it survives through:

  • 快速的用户切换
  • 启用/禁用合成
  • 主题切换
  • 禁用主题

在MSDN中,我找不到任何东西可以保证只要一个窗口存在,同一窗口就可以使用相同的DC.

i find nothing in MSDN that guarantees that the same DC will be used for a particular window for as long as the window exists.

注意::我没有使用双缓冲, * 有时候,这意味着您的双重缓冲不好.

Note: i am not using double-buffering, because i want to be a good developer, and do the right thing. * Sometimes that means you double-buffering is bad.

推荐答案

有一些例外,但是通常,每次调用GetDCBeginPaint时,您可能会获得不同的DC.因此,您不应尝试将状态保存在DC中. (如果您必须执行此操作以提高性能,则可以为一类窗口或特定窗口实例创建特殊的DC,但这听起来并不是您真正需要或想要的.)

There are exceptions, but in general, you may get a different DC each time you call GetDC or BeginPaint. Thus you shouldn't try to save state in the DC. (If you must do this for performance, there are special DCs you can create for a class of windows or a particular window instance, but it doesn't sound like that's what you really need or want.)

但是,在大多数情况下,这些DC都是兼容的.它们将代表相同的图形模式,因此即使您获得了不同的DC,兼容的位图也应能正常工作.

Most of the time, however, those DCs will be compatible. They will represent the same graphics mode, so your compatible bitmap should work, even if you get a different DC.

有些Windows消息会告诉您图形模式更改的时间,例如WM_DISPLAYCHANGEWM_PALETTECHANGED.您可以侦听这些内容,然后重新创建缓存的位图.由于这些事件很少见,因此您不必担心此时重新创建缓存的位图对性能的影响.

There are Windows messages that tell you when the graphics mode changes, like WM_DISPLAYCHANGE and WM_PALETTECHANGED. You can listen for these, and recreate your cached bitmap. Since those are rare events, you won't have to worry about the performance impact of recreating your cached bitmap at that point.

您还可以收到有关主题更改之类的通知.那些不会改变图形模式-它们是一个更高层次的概念-因此您缓存的位图仍应与您获得的任何DC兼容.但是,如果您想在主题更改时更改位图,则也可以收听WM_THEMECHANGED.

You can also get notifications for things like theme changes. Those don't change the graphics mode--they're a higher level concept--so your cached bitmap should still be compatible with any DC you get. But if you want to change bitmap when the theme changes, you can listen for WM_THEMECHANGED as well.

这篇关于Win32:窗口在整个生命周期中都具有相同的HDC吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆