派生したオーナー描画TabControlのダブルバッファリングの問題?
-
03-07-2019 - |
質問
期待どおりに機能しない場合を除き、ダブルバッファリングを有効にするという明確な目的でTabControlを派生させました。 TabControlコードは次のとおりです。
class DoubleBufferedTabControl : TabControl
{
public DoubleBufferedTabControl() : base()
{
this.DoubleBuffered = true;
this.SetStyle
(
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.SupportsTransparentBackColor,
false
);
}
}
このTabcontrolは、描画モードが「OwnerDrawnFixed」に設定されているため、色を変更できます。カスタム描画方法は次のとおりです。
private void Navigation_PageContent_DrawItem(object sender, DrawItemEventArgs e)
{
//Structure.
Graphics g = e.Graphics;
TabControl t = (TabControl)sender;
TabPage CurrentPage = t.TabPages[e.Index];
//Get the current tab
Rectangle CurrentTabRect = t.GetTabRect(e.Index);
//Get the last tab.
Rectangle LastTab = t.GetTabRect(t.TabPages.Count - 1);
//Main background rectangle.
Rectangle BackgroundRect = new Rectangle(LastTab.Width, t.Bounds.Y - 4, t.Width - (LastTab.Width), t.Height);
//Tab background rectangle.
Rectangle TabBackgroundRect = new Rectangle(0, LastTab.Y + LastTab.Height, LastTab.Width, t.Bounds.Height - (LastTab.Y + LastTab.Height));
//Set anitialiasing for the text.
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
//String format for the text.
StringFormat StringFormat = new StringFormat();
StringFormat.Alignment = StringAlignment.Center;
StringFormat.LineAlignment = StringAlignment.Center;
//Fill the background.
g.FillRectangle(Brushes.LightGray, BackgroundRect);
g.FillRectangle(Brushes.Bisque, TabBackgroundRect);
//Draw the selected tab.
if(e.State == DrawItemState.Selected)
{
g.FillRectangle(Brushes.White, e.Bounds);
Rectangle SelectedTabOutline = new Rectangle(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width, e.Bounds.Height - 4);
g.DrawRectangle(new Pen(Brushes.LightGray, 4f), SelectedTabOutline);
g.DrawString(CurrentPage.Text, new Font("Arial", 12f, FontStyle.Bold, GraphicsUnit.Point), new SolidBrush(Color.FromArgb(70, 70, 70)), CurrentTabRect, StringFormat);
}
else
{
g.FillRectangle(new SolidBrush(Color.FromArgb(230, 230, 230)), e.Bounds);
g.DrawString(CurrentPage.Text, new Font("Arial", 12f, FontStyle.Regular, GraphicsUnit.Point), Brushes.Gray, CurrentTabRect, StringFormat);
}
}
ただし、このコントロールはダブルバッファリングされておらず、サイズを変更してもちらつきます。
アイデアはありますか
解決
ドキュメントを読むと、「このメンバーはこのコントロールには意味がありません」と表示されます。ダブルバッファリングを使用してコントロールを描画する場合は、自分でコントロールを実装する必要があります。コントロールを所有者が描画する場合は、とにかく自分でダブルバッファリングを実装する必要があるという事実に加えて。
他のヒント
まず、 TabControl
コードを取り除くことができます。—バッファリングをオンにしてからすぐにオフにするので、実際には何の役にも立ちません。
問題の一部は、 TabControl
の一部をペイントしようとしていることです。
約90%のソリューションを提供する最も簡単なソリューション(ちらつきが発生する可能性はまだあります)は、これをフォームクラスに追加することです:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
ちらつきのない非常ににしたい場合は、 TabControl
全体を自分で描画し、バックグラウンドペインティングリクエストを無視する必要があります。
編集:これはXP以降でのみ機能することに注意してください。
過去にコントロールのダブルバッファリングに問題がありましたが、ちらつきを止める唯一の方法は、継承されたOnPaintBackgroundメソッドが呼び出されないようにすることでした。 (以下のコードを参照)また、ペイント呼び出し中に背景全体がペイントされるようにする必要があります。
protected override void OnPaintBackground( PaintEventArgs pevent )
{
//do not call base - I don't want the background re-painted!
}
わかりませんが、タブコントロールを含むコントロールをダブルバッファリングしてみてください。
私はかなり見回して、あなたのコードや他に考えられることを試しましたが、ちらつきを取り除く方法がわかりません。残念ながら、私のテストでは、サイズ変更中に通常の(所有者が描画しない)タブコントロールでさえちらつきます。
価値がある場合は、「ドラッグ中にウィンドウの内容を表示」をオフにします。それを修正しますが、私はそれが役に立たないかもしれないことに気付きます。
ダブルバッファリングを無効にしているため、機能しないと思います!
this.DoubleBuffered = true
は、ControlStyles.OptimizedDoubleBufferをtrueに設定します。プログラムの次の行でそのフラグを無効にしているため、実際には何もしていません。 ControlStyles.OptimizedDoubleBuffer(およびおそらくControlStyles.AllPaintingInWmPaint)を削除すると、動作するはずです。