Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 交叉螺纹制表符绘图_C# - Fatal编程技术网

C# 交叉螺纹制表符绘图

C# 交叉螺纹制表符绘图,c#,C#,基本上,我有一个TabControl。 我自己为标题绘制文本,以便在需要时对标题进行着色。 更改颜色的调用位于与TabControl不同的线程上,因此我将委托等用于跨线程操作。 不幸的是,我的方法并不完全可靠 以下是交叉螺纹部分: delegate TabControl getTabDelegate(); private TabControl getTab() { if (this.channelTabs.InvokeRequired) { getTabDeleg

基本上,我有一个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=新字典()

您的所有绘图都需要在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; 
    } 
}