0

我有一个通常以这种方式绘制的分层窗口:

    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 中处理它)

如果我阅读了有关分层窗口的 Microsoft 论文,它说:UpdateLayeredWindow 总是更新整个窗口。要更新窗口的一部分,请使用传统的 WM_PAINT 并使用 SetLayeredWindowAttributes 设置混合值。

我只是无法理解上面的内容。WM_PAINT 应该如何访问分层窗口位图并仅在窗口上重绘它的一部分?据我了解,分层窗口只是禁用 WM_PAINT 消息并期望用户自己绘制窗口。显然没有办法将 WM_PAINT 绑定到完成的自定义绘图。

我错过了一些非常明显的东西吗?

4

1 回答 1

1

经过长时间的分析,我发现瓶颈并不是分层窗口更新。刷新整个屏幕,上面的 SelectBitmap 方法,在 1920*1200 上大约需要 6-8ms。当然,不是很神奇,但足以以 30 FPS+ 刷新。

就我而言,性能消耗来自于某个线程要求每次重绘近百次刷新,这使得一切都变得迟缓。解决方案是分解刷新/重绘并将它们分开。一个会更新(联合)一个区域,另一个会在不绘制时获取该区域,绘制它然后清空它。

于 2013-03-20T15:52:59.530 回答