简体   繁体   English

如何仅重绘分层窗口的某个区域?

[英]How to redraw only a region of a layered window?

I have a layered window which is normally drawn this way: 我有一个通常以这种方式绘制的分层窗口:

    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);
        }
    }

However, this obviously redraw the whole window every time it's called. 但是,这显然会在每次调用时重新绘制整个窗口。 It's quite a performance drain on large window. 大窗口上的性能消耗很大。 (even on my top of the line PC, which make me wonder how people could handle that in Win2K) (即使在我的高端PC上,这也使我想知道人们如何在Win2K中处理它)

If I read the Microsoft paper on the layered window, it says : UpdateLayeredWindow always updates the entire window. 如果我在分层窗口上阅读了Microsoft的论文,它说 :UpdateLayeredWindow总是更新整个窗口。 To update part of a window, use the traditional WM_PAINT and set the blend value using SetLayeredWindowAttributes. 要更新部分窗口,请使用传统的WM_PAINT并使用SetLayeredWindowAttributes设置混合值。

I just can't understand the above. 我只是无法理解以上内容。 How is WM_PAINT supposed to access the layered window bitmap and redraw only part of it on the window? WM_PAINT应该如何访问分层的窗口位图并仅在窗口上重绘部分位图? From what I understood, layered windows simply disable the WM_PAINT message and expect the user to draw the window by himself. 据我了解,分层窗口只是禁用WM_PAINT消息,并希望用户自己绘制窗口。 There's obviously no way to bind the WM_PAINT to the custom drawing done. 很显然,没有办法将WM_PAINT绑定到完成的自定义工程图上。

Am I missing something very obvious? 我是否缺少一些显而易见的东西?

After long profiling, I found out it wasn't really the layered window update that was bottleneck. 经过长时间的分析,我发现瓶颈并不是真正的分层窗口更新。 Refreshing the whole screen, the SelectBitmap method above, on a 1920*1200 was taking about 6-8ms. 刷新整个屏幕,上面的SelectBitmap方法在1920 * 1200上耗时约6-8ms。 Sure, not very amazing, but plenty enough to refresh at 30 FPS+. 当然,不是很惊人,但足以以30 FPS +的速度刷新。

In my case, the performance drains was coming from some thread asking for refresh almost a hundred time per redraw, making everything sluggish. 以我为例,性能消耗来自某个线程,要求每次重绘刷新将近一百次,从而使所有操作都变得缓慢。 The solution was to break down the refresh/redraw and separate them. 解决方案是分解刷新/重画并将它们分开。 One would update (union) a region and the other, when not drawing, would take that region, draw it and then empty it. 一个将更新(联合)一个区域,而另一个在不绘制时将占据该区域,绘制该区域,然后将其清空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM