基本上,我有一个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;
}
}
这是绘图代码:
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");
}
}
如您所见,在某些情况下getTab();返回null,这不是很有用。 还有......可靠的方法吗?
以下是从第二个线程调用以更改标题颜色的方法:
private void SetTabHeader(TabPage page, Color color)
{
TabColors[page] = color;
channelTabs.Invalidate();
}
当然没有交叉线程部分,我会抛出异常。
正如您可能想象的那样,channelTabs是GUI选项卡控件。
感谢任何帮助,谢谢!
- 哦,是的,如果它真的有用: 私人词典TabColors =新词典();
答案 0 :(得分: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
的潜在危险调用。
如果你真的想修复你正在使用的代码,你需要做的是从Invoke返回值,如下所示:
private TabControl getTab()
{
if (this.channelTabs.InvokeRequired)
{
getTabDelegate d = new getTabDelegate(getTab);
return (TabControl)this.Invoke(d);
}
else
{
return channelTabs;
}
}
答案 1 :(得分:0)
你过于复杂 - 你需要使用Invoke来设置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();
}
}
答案 2 :(得分: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;
}
}
而是这样做:
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;
}
}