2012-03-14 17 views
0

基本的に、私はTabControlを持っています。 私はヘッダーのテキストを自分で描いていますので、必要に応じて色を付けることができます。 色を変更する呼び出しは、TabControlとは異なるスレッド上にあります。そのため、代理人などをクロススレッド操作に使用しています。 不幸にも、私の方法は正確に信頼できるものではありません。ここでクロススレッドタブの描画

は、クロススレッド一部です:

delegate TabControl getTabDelegate(); 
private TabControl getTab() 
{ 
    if (this.channelTabs.InvokeRequired) 
    { 
     getTabDelegate d = new getTabDelegate(getTab); 
     this.Invoke(d); 
     return null; 
    } 
    else 
    { 
     return channelTabs; 
    } 
} 

、ここでは、描画コードです:あなたは、いくつかの例getTab()で、見ることができるように

private void channelTabs_DrawItem(object sender, DrawItemEventArgs e) 
{ 
    try 
    { 
     TabControl ct = getTab(); 
     using (Brush br = new SolidBrush(TabColors[ct.TabPages[e.Index]])) 
     { 
      e.Graphics.FillRectangle(br, e.Bounds); 
      SizeF sz = e.Graphics.MeasureString(ct.TabPages[e.Index].Text, e.Font); 
      e.Graphics.DrawString(ct.TabPages[e.Index].Text, e.Font, Brushes.Black, 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(Pens.DarkGray, rect); 
      e.DrawFocusRectangle(); 
     } 
    } 
    catch(Exception err) 
    { 
     MessageBox.Show(err.Message, "1"); 
    } 
} 

。正確には役に立たないnullを返します。 これを行うには信頼性の高い方法がありますか?もちろん、私がスローされた例外が取得、

private void SetTabHeader(TabPage page, Color color) 
{ 
    TabColors[page] = color; 
    channelTabs.Invalidate(); 
} 

クロススレッド一部なし:ここ

は、ヘッダーの色を変更するために、第2のスレッドから呼び出されるメソッドです。

おそらく想像しているように、channelTabsはGUIタブコントロールです。

助けてください、ありがとう!

- ああ、実際に役立っている場合: プライベート辞書TabColors =新しい辞書();

+0

可能複製(HTTP ://stackoverflow.com/questions/661561/how-to-update-gui-from-another-thread-in-c) –

+0

プロパティを変更する方法のように見えるすべて、私はコントロールを取得しようとしていますそれには – CokaCola

+0

それは同じ問題です。 GUI以外のスレッドからGUIを変更しています。 –

答えて

0

図面のすべてが、とにかく私はどうなるのか、UIスレッドで実行する必要があるとしているので、同じようchannelTabs_DrawItem(object sender, DrawItemEventArgs e)を変更することです:

channelTabs_DrawItem(object sender, DrawItemEventArgs e) 
{ 
    if(this.InvokeRequired) 
    { 
     this.BeginInvoke(() => channelTabs_DrawItem(sender,e)); 
     return; 
    } 
    TabControl ct = channelTabs; 
    ... 

あなたは常に正しいで実行されていることを確認しますましたInvokeへの潜在的に危険な呼び出しの使用を回避します。 あなたは本当にあなたが使用しているコードを修正したい場合は、何をする必要がそうのような呼び出しから値を返すことです:

private TabControl getTab() 
{ 
    if (this.channelTabs.InvokeRequired) 
    { 
     getTabDelegate d = new getTabDelegate(getTab); 
     return (TabControl)this.Invoke(d); 
    } 
    else 
    { 
     return channelTabs; 
    } 
} 
+0

ありがとう、私は他のクロススレッドコールにも同様の方法を使用しました。 – CokaCola

0

あなたは物事を過度に複雑されている - あなたはSetTabHeader機能の呼び出しを使用している必要があります、ではない描画イベントまたはgetTab。これらは、あなたが別のスレッドからInvalidateを呼び出すのと同じように何もしない限り、当然UIスレッドから呼び出されます。

private void SetTabHeader(TabPage page, Color color) 
{ 
    if(this.InvokeRequired) { 
     this.Invoke(new Action<TabPage,Color>(SetTabHeader),page,color); 
    } else { 
     TabColors[page] = color; 
     channelTabs.Invalidate(); 
    } 
} 
0

それはこれのために失敗している...

delegate TabControl getTabDelegate(); 
private TabControl getTab() 
{ 
    if (this.channelTabs.InvokeRequired) 
    { 
     getTabDelegate d = new getTabDelegate(getTab); 
     this.Invoke(d); 
     return null; // <-- The return from your invoke is ignored 
    } 
    else 
    { 
     return channelTabs; 
    } 
} 

代わりにこれを行う:[?C#で別のスレッドからGUIを更新する方法]

delegate TabControl getTabDelegate(); 
private TabControl getTab() 
{ 
    if (this.channelTabs.InvokeRequired) 
    { 
     getTabDelegate d = new getTabDelegate(getTab); 
     return this.Invoke(d); // Don't lose the return value from the invoked call 
     //return null; 
    } 
    else 
    { 
     return channelTabs; 
    } 
}