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〜8ミリ秒かかりました。確かに、それほど驚くべきことではありませんが、30FPS+でリフレッシュするには十分です。

私の場合、パフォーマンスの低下は、再描画ごとにほぼ100回の更新を要求するスレッドから発生し、すべてが遅くなりました。解決策は、更新/再描画を分解し、それらを分離することでした。1つは領域を更新(結合)し、もう1つは描画していない場合、その領域を取得して描画してから空にします。

于 2013-03-20T15:52:59.530 に答える