すべての更新を実行するまで、フォームの再描画を一時停止できますか?
-
03-07-2019 - |
質問
C#と.Net 2.0を使用して、不規則な形状のフォーム(TransparencyKey、FormBorderStyle = Noneなど)を使用しており、「通常」を許可したいボーダー付きモード。
背景色をLimeからデフォルトに変更します FormBorderStyleをFixedSingleに変更します TransparencyKeyをColour.Noneに変更します
残念ながら、これは画面上で完全に混乱しているように見えます。画像は数ピクセル下にジャンプして、ライムグリーンの形になります。
これは、コードの各行の後にフォームが再描画されることが原因だと思いますが、変更を加えるまでフォームの描画を一時停止し、一度だけフォームを再描画することは可能ですか?
G
解決
新しい回答:新しいウィンドウプロパティを適用している間、WndProcをオーバーライドし、WM_PAINTメッセージをブロックします。
古い回答:WndProcをオーバーライドし、 WM_ERASEBKGND
メッセージをブロックします。
以下のコードの機能の説明:
ウィンドウの領域が無効化されると、Windowsはコントロールに一連のメッセージを送信し、その結果、新しくペイントされたウィジェットが作成されます。このシリーズの初期のメッセージは WM_ERASEBKGND
です。通常、このメッセージに応じて、コントロールはそれ自体を単色で塗りつぶします。後で、 WM_PAINT
メッセージ(通常はOnPaintイベントで消費される)への応答で、実際の描画が行われます。この描画が重要でない場合、ウィジェットが更新されるまでに遅延が発生し、迷惑なちらつきが発生します。
もう一度コードを見ると、明らかに別の問題を解決していました。この新しい例を試してください。 bAllowPaint
フラグが設定されていない場合、フォーム/コントロールの描画をブロックします。
NEW の例:
private const int WM_PAINT = 0x000F;
protected override void WndProc(ref Message m)
{
if ((m.Msg != WM_PAINT) ||
(bAllowPaint && m.Msg == WM_PAINT))
{
base.WndProc(ref m);
}
}
OLD の例:
private const int WM_ERASEBKGND = 0x0014;
protected override void WndProc(ref Message m)
{
if (m.Msg != WM_ERASEBKGND) // ignore WM_ERASEBKGND
{
base.WndProc(ref m);
}
}
他のヒント
Form.DoubleBufferedプロパティを試してください。 「true」に設定します。
また、フォームに子コントロールがある場合は、それらについてもDoubleBufferedをtrueに設定します(そして子の子など)。
最後に、変更の前にSuspendLayoutを呼び出し、その後でResumeLayoutを呼び出します。これは子コントロールの配置にのみ影響することに注意してください。カスタム描画を行う場合は、DoubleBufferedプロパティを使用すると、より大きな価値が得られます。
フォームにかなり大きな影響を及ぼすプロパティを変更しています。 TransparencyKeyとFormBorderStyleでは、ウィンドウスタイルビットを変更する必要があります。 Windowsでは、これらのスタイルビットを変更することはできません。 Windows Formsは、ウィンドウを完全に破棄し、ゼロから再作成することで実装します。きちんとしたトリックですが、それには時間がかかり、スタイルを変更するたびにフォームが再描画されます。不快な視覚効果を引き起こす。
これを試してください: 1. Opacityを0に設定して、フォームを非表示にします 2. BackColorの変更、問題なし 3. FormBorderStyleを変更すると、ウィンドウが再作成されます 4. TransparencyKeyを変更すると、ウィンドウが再作成されます 5.不透明度を1に変更すると、ウィンドウが再作成されて表示されます
例:
this.Opacity = 0;
this.BackColor = Color.FromKnownColor(KnownColor.Control);
this.FormBorderStyle = FormBorderStyle.Sizable;
this.TransparencyKey = Color.Empty;
this.Opacity = 1;
すべてが失敗した場合は、フォームへのすべてのペイントメッセージをブロックすることにより、低レベルのハッキングを試みることができます。
警告:この方法の使用は推奨していませんが、本当にやりたい場合は試してください。過去に私を助けてくれました。
Win32.LockWindowUpdate(this.Handle);
try
{
//make your changes here
}
finally
{
//release the lock
Win32.LockWindowUpdate((IntPtr)0);
}
このコードは、次のサポートコードに依存しています。
public class Win32
{
private Win32() { }
/// <summary>
/// Lock ore relase the wndow for updating.
/// </summary>
[DllImport("user32")]
public static extern int LockWindowUpdate(HWND hwnd);
}
すべての&quot; image&quot;を送信する方法フォームの画面への1ステップでのDoubleBufferの有効化です。
コンストラクターでControlStylesを設定できます
VB.NET:
SetStyle(ControlStyles.DoubleBuffer, True)