我有一个分层窗口,通常以这种方式绘制:
private void SelectBitmap(Bitmap bitmap)
{
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr hOldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
hOldBitmap = SelectObject(memDc, hBitmap);
POINT sourceLocation = new POINT(0, 0);
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
SIZE newSize = new SIZE(bitmap.Width, bitmap.Height);
POINT newLocation = new POINT(Location.X, Location.Y);
UpdateLayeredWindow(Handle, screenDc,
ref newLocation, ref newSize,
memDc,
ref sourceLocation, 0,
ref blend,
ULW_ALPHA);
}
finally
{
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
SelectObject(memDc, hOldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
}
然而,这显然会在每次调用时重绘整个窗口。大窗户的性能消耗很大。 (甚至在我的顶级PC上,这让我想知道人们如何在Win2K中处理它)
If I read the Microsoft paper on the layered window, it says:UpdateLayeredWindow始终更新整个窗口。要更新窗口的一部分,请使用传统的WM_PAINT并使用SetLayeredWindowAttributes设置混合值。
我只是无法理解上述内容。 WM_PAINT如何访问分层窗口位图并在窗口上仅重绘部分窗口位图?根据我的理解,分层窗口只是禁用WM_PAINT消息并期望用户自己绘制窗口。显然没有办法将WM_PAINT绑定到完成的自定义绘图。
我错过了一些非常明显的东西吗?
答案 0 :(得分:1)
经过长时间的分析,我发现它并不是真正的分层窗口更新是瓶颈。刷新整个屏幕,上面的SelectBitmap方法,在1920 * 1200上花了大约6-8ms。当然,不是很惊人,但足以刷新30 FPS +。
在我的情况下,性能消耗来自某个线程要求每次重绘几乎一百次刷新,使一切都迟钝。解决方案是分解刷新/重绘并将它们分开。一个人会更新(联合)一个区域而另一个人在没有绘图的情况下会占用该区域,绘制它然后清空它。