1

フォームをドラッグして、ドラッグされたときに透明にする次のコードがあります。問題は、ちらつき、スムーズにドラッグできないことです。フォームに写真がありますが、それが原因かどうかはわかりません。ちらつきないようにするにはどうすればよいでしょうか。不透明度を削除すると、ドラッグが速く/スムーズになります。

[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, 
    int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();

public void Drag(MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        this.Opacity = 0.9;
        ReleaseCapture();

        SendMessage(Handle, 0xA1, 0x2, 0);
        this.Opacity = 1;
    }
}

private void Body_MouseDown(object sender, MouseEventArgs e)
{       
    Drag(e);
}
4

1 に答える 1

3

Form および Control クラスには、"重い" プロパティが多数あり、基になるネイティブ Windows ウィンドウに大幅な変更を加える必要があります。これらは、ネイティブの CreateWindowEx() 呼び出しに渡されるスタイル フラグに関連付けられているプロパティです。Opacity プロパティは、TransparencyKey プロパティと同様に、デフォルトから変更すると、ウィンドウに別のスタイル フラグ WS_EX_LAYERED が必要になります。

ウィンドウを作成するときにこのスタイルフラグが指定されていることを考えると、これは問題です。Windows は、ウィンドウが SetWindowsLongPtr() で作成された後にそれらを変更することをある程度サポートしていますが、それは常にむらがあります。特に WS_EX_LAYERED の場合、オンにすると内部で多くのことが起こります。これは、「レイヤー」と呼ばれるビデオ アダプターのハードウェア機能を利用して実装されます。レイヤーは、ピクセルがメイン メモリと結合されたビデオ メモリの個別のチャンクです。不透明効果(乗算)と透明キー効果(省略)をサポートするミキサー。

そのため、ウィンドウの作成後に Opacity プロパティをオンザフライで変更するのは非常に困難です。WPFがそれを完全に禁止するほどです。しかし、Winforms はそうではなく、Windows 98 の制限に対処する必要がありました。これにより、ShowInTaskbar、RightToLeft、FormBorderStyle などのプロパティを変更することも困難になりました。これらのプロパティの変更を許可するトリックを使用して、ネイティブ ウィンドウを完全に破棄し、新しいスタイル フラグを使用して再作成します。

問題は解決しましたが、これには顕著な副作用があります。必然的に、見ているウィンドウが消え、新しいウィンドウが作成され、同じ場所にペイントされます。それはあなたが不平を言ったちらつきを引き起こします。また、ウィンドウを破棄すると、多くの内部状態が失われます。Winforms は、新しいウィンドウの場合と同様にその状態を復元するために最善を尽くしますが、「現在移動中です」状態を復元することはできません。モーダル移動ループは既に終了しています。

この問題の回避策は大雑把ですが簡単です。[プロパティ] ウィンドウで [不透明度] プロパティを 99% に設定します。コードを変更して、100 ではなく 99 に戻します。これで、スタイル ビットを変更する必要がなくなるため、これらのアーティファクトが発生しなくなります。

于 2013-01-08T18:52:10.383 に答える