2016-06-30 4 views
1

私のプログラムの1つに最近機能を追加し、非常に奇妙なことに気付きました。この機能では、私が使用しているタブコントロールに新しいタブを追加する必要がありました。これは、タブコントロールのタブをナビゲートするために矢印を必要とする既定のサイズで、フォーム上に表示できる内容を超えてタブを押しました。C#.net 4.0 tabControl1_DrawItemイベントは常に発生します

enter image description here

私が発見した問題は、タブコントロール上のこれらの矢印が存在する場合だけで座ったときに、tabControl1_DrawItemイベントはプログラムが遅くなると、約15%〜20%のCPUを使用することを引き起こして数ミリ秒ごとに発射されたということですフォームロードイベントの後には何もしません。

フォームサイズを大きくして矢印が存在しないようにすると、フォームが移動されたとき、または別のタブが選択されたときにのみイベントが発生します。

私はこれを一日中検索し、デバッグして答えを見つけましたが、回避策は言えますが、ここではできません。だから私は2つの質問があると思う。矢印が存在する場合、イベントは絶え間なく発火するのですが、アプリケーションのユーザーがフォームのサイズを変更してこれを起こさないようにできないので、これを防ぐことはできません。

これは私がイベントで持っているコードです。

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e) 
{ 
Platform.Log(LogLevel.Debug, "DrawItem event is being called."); 
//Draw the tabs on the tab conrol 
e.DrawBackground(); 
using (Brush br = new SolidBrush(TabColors[tabControl1.TabPages[e.Index]])) 
{ 
    e.Graphics.FillRectangle(br, e.Bounds); 
    SizeF sz = e.Graphics.MeasureString(tabControl1.TabPages[e.Index].Text, e.Font); 
    e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, e.Font, DGVBrushForeColor, e.Bounds.Left + (e.Bounds.Width - sz.Width)/2, e.Bounds.Top + (e.Bounds.Height - sz.Height)/2 + 1); 

    Rectangle rect = e.Bounds; 
    rect.Offset(0, 1); 
    rect.Inflate(0, -1); 
    e.Graphics.DrawRectangle(DGVPenBackColor, rect); 
    e.DrawFocusRectangle(); 
} 

//To Fill the blank portion of the end of the tab control 
SolidBrush fillbrush = new SolidBrush(BACK_COLOR); 
//draw rectangle behind the tabs 
Rectangle lasttabrect = tabControl1.GetTabRect(tabControl1.TabPages.Count - 1); 
Rectangle background = new Rectangle(); 
background.Location = new Point(lasttabrect.Right, 0); 

//pad the rectangle to cover the 1 pixel line between the top of the tabpage and the start of the tabs 
background.Size = new Size(tabControl1.Right - background.Left, lasttabrect.Height + 1); 
e.Graphics.FillRectangle(fillbrush, background); 
} 
+0

矢印が存在する場合、イベントは絶えず発火しないので、問題を複製するコードを表示します。 – LarsTech

+0

@LarsTech Testingは私の場合、矢印が存在すればそれが起こることを示しています。もし存在しなければ、それは起こるときだけ起こります。 – Jake

+0

あなたが投稿したコードは問題を重複しません。問題は他のどこかから来ている。 – LarsTech

答えて

1

答えはHans Passantのおかげです。私はこのコードを私のアプリケーションのstackoverflowでここに実装しました。

public Form1() 
    { 
     InitializeComponent(); 

     int style = NativeWinAPI.GetWindowLong(this.Handle, NativeWinAPI.GWL_EXSTYLE); 
     style |= NativeWinAPI.WS_EX_COMPOSITED; 
     NativeWinAPI.SetWindowLong(this.Handle, NativeWinAPI.GWL_EXSTYLE, style); 
    } 

    internal static class NativeWinAPI 
    { 
     internal static readonly int GWL_EXSTYLE = -20; 
     internal static readonly int WS_EX_COMPOSITED = 0x02000000; 

     [DllImport("user32")] 
     internal static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

     [DllImport("user32")] 
     internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 
    } 

これは、タブナビゲーション矢印が存在する場合、常に描画イベントが発生する問題を引き起こしています。問題を解決するために、タブコントロールのMultilineプロパティをtrueに設定しました。これにより、ナビゲーション矢印が表示されなくなり、複数のタブ行が表示されます。

このコードがなければ、問題は発生しませんが、タブはHansが呼び出すように「WS_EX_COMPOSITED hack」なしで常に狂っていることに注意してください。このハックを使用してすべてをダブルバッファリングすることで、すべてがうまく動作するようになり、このアプリケーションでは今のところそこにとどまっています。

関連する問題