C# 交叉螺纹制表符绘图
基本上,我有一个TabControl。 我自己为标题绘制文本,以便在需要时对标题进行着色。 更改颜色的调用位于与TabControl不同的线程上,因此我将委托等用于跨线程操作。 不幸的是,我的方法并不完全可靠 以下是交叉螺纹部分:C# 交叉螺纹制表符绘图,c#,C#,基本上,我有一个TabControl。 我自己为标题绘制文本,以便在需要时对标题进行着色。 更改颜色的调用位于与TabControl不同的线程上,因此我将委托等用于跨线程操作。 不幸的是,我的方法并不完全可靠 以下是交叉螺纹部分: delegate TabControl getTabDelegate(); private TabControl getTab() { if (this.channelTabs.InvokeRequired) { getTabDeleg
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=新字典() 您的所有绘图都需要在UI线程中完成,因此我要做的是修改
channelTabs\u DrawItem(对象发送器,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;
}
}
您将事情复杂化了—您需要对SetTabHeader函数使用Invoke,而不是绘图事件或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();
}
}
private void SetTabHeader(TabPage页面,颜色)
{
if(this.invokererequired){
调用(新操作(SetTabHeader)、页面、颜色);
}否则{
TabColors[页面]=颜色;
channelTabs.Invalidate();
}
}
由于此原因,它正在失败
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;
}
}
所有可能的重复似乎是如何修改属性,我试图检索控件并引出它的相同问题。您正在从非GUI线程修改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;
}
}