Win32:没有一个窗口具有相同的裂为其整个一生?
-
20-09-2019 - |
题
我允许使用直流之外的一个油漆循环?是我的窗口的DC保证是有效的永远?
我试图找出多久我控制的设备上下文(直流)是有效的。
我知道,我可以叫:
GetDC(hWnd);
要获得设备的背景下我控制的窗口,但是允许的?
当窗户发送我一个WM_PAINT消息,我应该呼叫 BeginPaint/EndPaint 要正确地确认我已经画,并为内部清除无效的区域:
BeginPaint(hWnd, {out}paintStruct);
try
//Do my painting
finally
EndPaint(hWnd, paintStruct);
end;
但呼吁BeginPaint也返回我一直流内PAINTSTRUCT结构。这是DC我 应该 是的绘画上。
我找不到任何东西在文件中说,DC返回的BeginPaint()是相同的直流电,我会得到从GetDC().
尤其是现在,在桌面上组成,它是有效的画上一直流,我获得外部的BeginPaint?
似乎有2种方式我可以一直上的油漆过的油漆周期:
dc= GetDC(hWnd);
BeginPaint(&paintStruct);
有一个第3方式,但它似乎是一个错误Borland德尔菲,我的发展。
在 WM_PAINT 处理,Delphi认为,包含一直流,并进行油漆。而MSDN说,包含一个WM_PAINT消息是未使用。
为什么
我的真正目标 是要尽量保持一个持久的GDI+形对象的 对一个裂,所以,我可以用一些更好的执行功能的GDI+那取决于具有持久性。
在WM_PAINT消息处理我想画一个GDI+图像的画布上。下雪山的版本是非常缓慢:
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.但是,使用它没有思想没有给出性能的好处:
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一次,所以在程序初始化:
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我后获得程序initializtion将是相同的DC为我的窗口,只要应用程序正在运行。这意味着它的生存通过:
- 快用户的开关
- 组成启用/停用
- 主题交换
- 主题是禁止
我什么也找不到在MSDN,保证同DC将用于一个特别窗口,只要的窗口存在。
注: 我不是采用双缓冲, 因为我想要的是一个很好的开发,做正确的事情.有时那意味着你的双缓冲坏。
解决方案
也有例外,但在一般情况下,你可能会得到不同的DC你每次呼叫 GetDC
或 BeginPaint
.因此你不应该试图保存的状态的直流电。(如果你必须做这个的性能、有特殊DCs你可以创建一类的窗户或一个特别窗口的实例,但它不像,你真的需要或不想要的。)
大部分时间,但是,这些DCs将是兼容的。他们将代表相同的图形方式,因此兼容位应工作,甚至如果你得到一个不同的。
有窗户的消息告诉你当形模式的变化,喜欢 WM_DISPLAYCHANGE
和 WM_PALETTECHANGED
.你可以听听这些,并重缓存图。由于这些都是罕见的事件,您不必担心,有关性能的影响的重建你的缓位在这一点上。
你还可以得到通知,如主题的变化。那些不改变形模式--他们是较高级别的概念--所以你的缓位仍然应该是兼容的任何DC你得到的。但如果你想改变位当主题的变化,可以监听 WM_THEMECHANGED
为好。
其他提示
只有这样,我知道的可能(或不可能)来做什么你要找的是建立窗口 CS_OWNDC 类风格。
什么,不会被分配一个独特的设备方面为每个窗口的类。
编辑
从联MSDN文章:
一个装置上下文中是一个特殊的设置 值应用的使用 图在客户区,他们的 窗户。该系统需要一个装置 下文对每个窗口在显示器上 但允许一些灵活性,在怎样的 系统存储和把那设备 上下文。
如果没有设备方面的风格是 明确给出的,该系统的假设 每一个窗口使用的一个装置上下文 从一个游泳池的情况下 维持通过系统。在这样 情况中,每个窗口,必须检索和 初始化装置的上下文之前 绘画和免费的后画。
为了避免检索装置的上下文 每次它需要油漆内 窗口,一个应用程序可以指定 CS_OWNDC式的窗口类。这类式的指示系统 创建一个私人的设备上下文, 是,分配一个独特的设备 下文对每一窗口的类。该应用程序需要的只是检索的 下一次,然后使用它的所有 随后的绘画。
Windows95/98/Me:虽然 CS_OWNDC式是方便,使用它 小心,因为每个装置的上下文 使用的一个重要部分64K GDI 堆。
也许这个例子将说明使用的CS_OWNDC更好:
#include <windows.h>
static TCHAR ClassName[] = TEXT("BitmapWindow");
static TCHAR WindowTitle[] = TEXT("Bitmap Window");
HDC m_hDC;
HWND m_hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static PAINTSTRUCT ps;
switch (msg)
{
case WM_PAINT:
{
BeginPaint(hWnd, &ps);
if (ps.hdc == m_hDC)
MessageBox(NULL, L"ps.hdc == m_hDC", WindowTitle, MB_OK);
else
MessageBox(NULL, L"ps.hdc != m_hDC", WindowTitle, MB_OK);
if (ps.hdc == GetDC(hWnd))
MessageBox(NULL, L"ps.hdc == GetDC(hWnd)", WindowTitle, MB_OK);
else
MessageBox(NULL, L"ps.hdc != GetDC(hWnd)", WindowTitle, MB_OK);
RECT r;
SetRect(&r, 10, 10, 50, 50);
FillRect(m_hDC, &r, (HBRUSH) GetStockObject( BLACK_BRUSH ));
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wcex;
wcex.cbClsExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wcex.hIconSm = NULL;
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = ClassName;
wcex.lpszMenuName = NULL;
wcex.style = CS_OWNDC;
if (!RegisterClassEx(&wcex))
return 0;
DWORD dwExStyle = 0;
DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
m_hWnd = CreateWindowEx(dwExStyle, ClassName, WindowTitle, dwStyle, 0, 0, 300, 300, NULL, NULL, hInstance, NULL);
if (!m_hWnd)
return 0;
m_hDC = GetDC(m_hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
该CS_OWNDC标志 不 要混淆CS_CLASSDC标志,其中:
分配一个装置上下文中可以共享通过所有的窗户类。因为窗口类别处理具体的,能够对多线程的一个应用程序,以创建一个窗口的同类。它也可能是对的线以尝试使用的设备方面同时进行。当发生这种情况,该系统允许只有一线成功地完成了其绘图操作。
如果一切都失败只是 重建 该CachedBitmap.
当你建造一个CachedBitmap对象,就必须通过该地址的图象的要构造。如果关联的屏幕与图形象具有其位深度改变后的缓位是构建,然后DrawCachedBitmap方法会失败,应该重新构建的高速缓存图。或者,也可以显示改变通知消息,并重建的高速缓存位。
我不是说CS_OWNDC是完美的解决方案,但它 是 一步步走向一个更好的解决方案。
编辑
样品的程序似乎保留相同的DC在屏幕决议/位深度的改变测试与CS_OWNDC标志,但是,当这标志已被删除,直流是不同的(窗口7 64位的最终)(应该 工作同过differn操作系统版本...虽然它不会伤害到试验)。
Edit2
这个例子不叫GetUpdateRect检查窗户的需要绘期间WM_PAINT.这是一个错误。
你可以画到哪窗口dc高兴你。他们都是有效的。一个窗口并不只是一直流,可以代表它的时间。所以你每次呼叫GetDC和BeginPaint境内这样做,你会得到一个新的、独特的直流电,尽管如此表示同样显示区域。只是ReleaseDC(或EndPaint)当你完成后他们。在Windows3.1设备情况下是有限的,或者非常昂贵的系统资源,因此应鼓励永远不会抓住他们,但对它们进行检索,从GetDC缓存。现在它完全可以接受的创造dc在窗口的设立和高速缓存这对生活的窗口。
唯一的"问题",在处理 WM_PAINT
, dc返回的BeginPaint会被剪辑无效rect,并保存一个不会。
我不是明白你正在尝试实现与gdiplus.通常,如果对象是...选择成直流长的一段时间,直流是一个存储器,直流电,没有一个窗口。
每次GetDC是叫你会得到一个新的裂代表一个独特的设备方面有其自己的国家。因此,对象背景的颜色,案文的模式等等。设置在一个DC不会影响该国的另一个DC检索的通过不同的称呼来GetDC或BeginPaint.
该系统不能随意无效HDCs检索到通过客户,并且实际上做了大量工作的背景,以确保HDCs检索之前,显示方式开关、继续的功能。甚至改变位深度,这在技术上使dc是不相容的,将不会以任何方式阻止应用程序继续使用一个跳到位图传送.
这就是说,这是明智的,看着至少对于窗口,释放任何缓存DCs和设备位图,并重新创造他们。