14

パネルとパネルのパネルがたくさんあるプログラムを作成しています。

これらのパネルには、いくつかのカスタム描画コントロールがあります。

1 つのパネルのサイズ変更機能には、そのパネル内のすべてのコントロールのサイズと位置を調整するコードが含まれています。

プログラムのサイズを変更するとすぐに、このパネルのサイズ変更がアクティブになります。これにより、このパネル内のコンポーネントに多くのちらつきが生じます。

ユーザーが描画したすべてのコントロールは、ダブル バッファリングされます。

誰かがこの問題を解決するのを手伝ってくれますか?

4

8 に答える 8

23

win フォームのサイズ変更中にちらつきをなくすには、サイズ変更中にレイアウトを一時停止します。以下のように、フォームの resizebegin/resizeend メソッドをオーバーライドします。

protected override void OnResizeBegin(EventArgs e) {
    SuspendLayout();
    base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
    ResumeLayout();
    base.OnResizeEnd(e);
}

これにより、コントロールはそのまま (サイズ変更前の状態) のままになり、サイズ変更操作が完了すると強制的に再描画されます。

于 2011-10-13T20:18:01.413 に答える
18

投稿したプロジェクトを見ると、グラデーションで塗りつぶされたグループ ボックスで最初のタブを選択すると、ちらつきがひどくなります。2 番目または 3 番目のタブが表示されている場合、ちらつきはほとんどありません。

  あなたのメインフォーム

明らかに、問題はそのタブ ページに表示されているコントロールに関係しています。グラデーションで塗りつぶされたカスタム グループ ボックス クラスのコードをざっと見ただけで、より具体的な原因がわかります。グループボックス コントロールの 1 つを描画するたびに、多くの非常にコストのかかる処理を行っています。グループボックス コントロールは、フォームのサイズが変更されるたびに再描画する必要があるため、そのコードは信じられないほどの回数実行されます。

さらに、コントロールの背景を「透明」に設定しています。これは、親ウィンドウにコントロールウィンドウ内で最初に自分自身を描画して背景ピクセルを生成するように要求することにより、WinForms で偽造する必要があります。次に、コントロールはその上に自分自身を描画します。これは、コントロールの背景を のような単色でSystemColors.Control塗りつぶすよりも手間がかかります。また、フォームのサイズを変更している間、グループボックスが自分自身をペイントする前に、フォームのピクセルが描画されるのを確認できます。

カスタム グラデーション塗りつぶしグループ ボックス コントロール クラスから私が話している特定のコードは次のとおりです。

protected override void OnPaint(PaintEventArgs e)
{
    if (Visible)
    {
        Graphics gr = e.Graphics;
        Rectangle clipRectangle = new Rectangle(new Point(0, 0), this.Size);
        Size tSize = TextRenderer.MeasureText(Text, this.Font);
        Rectangle r1 = new Rectangle(0, (tSize.Height / 2), Width - 2, Height - tSize.Height / 2 - 2);
        Rectangle r2 = new Rectangle(0, 0, Width, Height);
        Rectangle textRect = new Rectangle(6, 0, tSize.Width, tSize.Height);

        GraphicsPath gp = new GraphicsPath();
        gp.AddRectangle(r2);
        gp.AddRectangle(r1);
        gp.FillMode = FillMode.Alternate;

        gr.FillRectangle(new SolidBrush(Parent.BackColor), clipRectangle);

        LinearGradientBrush gradBrush;
        gradBrush = new LinearGradientBrush(clipRectangle, SystemColors.GradientInactiveCaption, SystemColors.InactiveCaptionText, LinearGradientMode.BackwardDiagonal);
        gr.FillPath(gradBrush, RoundedRectangle.Create(r1, 7));

        Pen borderPen = new Pen(BorderColor);
        gr.DrawPath(borderPen, RoundedRectangle.Create(r1, 7));
        gr.FillRectangle(gradBrush, textRect);
        gr.DrawRectangle(borderPen, textRect);
        gr.DrawString(Text, base.Font, new SolidBrush(ForeColor), 6, 0);
    }

}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
    if (this.BackColor == Color.Transparent)
        base.OnPaintBackground(pevent);
}

コードを確認したので、赤い警告フラグが上がるはずです。大量の GDI+ オブジェクト (ブラシ、ペン、領域など) を作成していますが、どれにも失敗しています! Disposeそのコードのほとんどすべてusingをステートメントでラップする必要があります。それはただのずさんなコーディングです。

そのすべての作業を行うには、いくらかの費用がかかります。コンピューターがコントロールのレンダリングに多くの時間を費やさなければならない場合、他のことが遅れます。サイズ変更に追いつくために緊張しているため、ちらつきが見られます。これは、コンピューターに過負荷をかける他のもの (pi の値の計算など) と同じです。ここで行っているように、カスタム描画コントロールをできるだけ多く使用すると、非常に簡単に行うことができます。Win32 では透過性が難しく、多くのカスタム 3D ペインティングも同様です。これにより、UI のルックアンドフィールがユーザーにとって不格好になります。ネイティブ コントロールからの急ぎを理解できないもう 1 つの理由。

実際には次の 3 つのオプションしかありません。

  1. ちらつきに対処します。(同意します、これは良い選択肢ではありません。)
  2. 標準の組み込みコントロールなど、さまざまなコントロールを使用します。確かに、派手なグラデーション効果はないかもしれませんが、ユーザーが Windows テーマをカスタマイズしている場合、半分の時間は壊れて見えます。また、暗い灰色の背景に黒いテキストを読むのはかなり困難です。
  3. カスタム コントロール内の描画コードを変更して、作業を減らします。視覚効果をまったく犠牲にしない単純な「最適化」でうまくいくかもしれませんが、これはありそうもないことだと思います。これは、速度と見栄えのトレードオフです。何もしない方が常に高速です。
于 2011-01-14T14:19:31.740 に答える
3

このコードを使用してフォームのサイズを変更すると、ちらつきがなくなりました。ありがとう。

VB.NET

Public Class Form1

Public Sub New()
    Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.SupportsTransparentBackColor, True)
End Sub

Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    Me.Update()
End Sub

End Class

C#

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Resize += Form1_Resize;
        this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
    }

    private void Form1_Resize(object sender, System.EventArgs e)
    {
        this.Update();
    }

}
于 2011-06-25T18:30:52.853 に答える
3

だから私はこの同じ問題に遭遇しました - 透明な背景を持つ私のコントロールは34回のように再描画されました、そして私にとってうまくいったのは:

コントロールを含むフォームで

protected override void OnResize(EventArgs e)
    {
        myControl.Visible = false;
        base.OnResize(e);
        myControl.Visible = true;
    }

コントロールでも同じです:

protected override void OnResize(EventArgs e)
    {
        this.Visible = false;
        base.OnResize(e);
        this.Visible = true;
    }

これにより、再描画の量が 4 に減り、コントロールのサイズが変更されたときのちらつきが効果的に除去されました。

于 2011-12-15T22:49:52.227 に答える
1

おそらく、 Form.ResizeBeginイベントとForm.ResizeEndイベントを使用するのが良い解決策になるでしょう。

ResizeBeginでメインパネルの可視性をfalseに設定し、ResizeEndでメインパネルの可視性をtrueに設定します。

このようにして、誰かがフォームのサイズを変更している間、パネルが再描画されることはありません。

于 2011-01-14T12:11:49.210 に答える
1

ResizeBegin と ResizeEnd にフックするのは正しい考えですが、メイン パネルの可視性を隠す代わりに、ResizeEnd までサイズ変更の計算を遅らせます。この場合、ResizeBegin または Resize にフックする必要さえありません。すべてのロジックは ResizeEnd に入ります。

これには 2 つの理由があります。1 つ目は、パネルが非表示になっている場合でも、サイズ変更操作にはまだコストがかかる可能性が高いため、サイズ変更の計算が遅れない限り、フォームの応答性が低下することです。2 つ目は、サイズ変更中にペインの内容を非表示にすると、ユーザーが不快に感じる可能性があることです。

于 2011-05-10T23:32:33.537 に答える
0

私も同じ問題を抱えていました。

丸みを帯びたコーナーを使用しているため、これが起こっていると思われます。CornerRadius プロパティを 0 に設定すると、ちらつきがなくなりました。

これまでのところ、次の回避策しか見つかりませんでした。最高のものではありませんが、ちらつきを止めます。

private void Form_ResizeBegin(object sender, EventArgs e)
{
  rectangleShape.CornerRadius = 0;
}

private void Form_ResizeEnd(object sender, EventArgs e)
{
  rectangleShape.CornerRadius = 15;
}
于 2014-10-09T20:34:13.487 に答える