自定义TabPage选项卡,例如Microsoft Dynamics CRM 2015中的“流程流箭头" [英] Customize TabPage tabs like Process Flow Arrows in Microsoft Dynamics CRM 2015

查看:130
本文介绍了自定义TabPage选项卡,例如Microsoft Dynamics CRM 2015中的“流程流箭头"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望Windows窗体应用程序中的TabControl看起来像这样: https://technet.microsoft.com/en-us/library/dn531164.aspx

I want my TabControl in a Windows Forms app to look something like this: https://technet.microsoft.com/en-us/library/dn531164.aspx

我有一个具有处理流程的应用程序,每个TabPage都是一个处理阶段,我想用这些漂亮的箭头来表示.我知道OnPaint和System.Drawing,但是我无法使这些选项卡看起来不错.

I have an app that has process flow and each TabPage is a process phase that I want to represent with these nice looking arrows. I know about OnPaint and System.Drawing, but I cannot make those tabs look decent.

我试图处理TabControl.DrawItem事件并绘制箭头,但对外观不满意.

I tried to handle TabControl.DrawItem event and to draw an arrow, but I am not satisfied with the look.

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    Rectangle rect = e.Bounds;

    int offset = 10;
    Point p1 = e.Bounds.Location;
    Point p2 = new Point(e.Bounds.X + e.Bounds.Width - offset, e.Bounds.Y);
    Point p3 = new Point(e.Bounds.X + e.Bounds.Width, e.Bounds.Y + (e.Bounds.Height / 2));
    Point p4 = new Point(p2.X, e.Bounds.Bottom);
    Point p5 = new Point(e.Bounds.X, e.Bounds.Y+e.Bounds.Height);
    Point p6 = new Point(e.Bounds.X + offset, p3.Y);

    GraphicsPath path = new GraphicsPath();

    path.AddLine(p1, p2);
    path.AddLine(p2, p3);
    path.AddLine(p3, p4);
    path.AddLine(p4, p5);
    path.AddLine(p5, p6);
    path.AddLine(p6, p1);
    e.Graphics.FillPath(Brushes.Black, path);
};

还有其他方法可以使该工作按所述进行吗?

Is there any other approach to make this work as described?

推荐答案

有时候我会发疯,为了娱乐而挑战:-)

Sometimes I go crazy and pick up a challenge just for fun :-)

这是结果:

我用Panel tp覆盖了TabControl tabControl1. (请选择更好的名字!)请注意,这必须发生得很晚,否则TabControl会弹出顶部.

I overlay the TabControl tabControl1 with a Panel tp. (Do pick better names!) Note that this must happen rather late or else the TabControl will pop to the top.

我在Shown事件中称他们为定单:

I call them to order in the Shown event:

private void Form1_Shown(object sender, EventArgs e)
{
    tp.BringToFront();
    tabControl1.SendToBack();
}

您可能可以在设计器中创建Panel以避免这些动作.

You probably could create the Panel in the designer to avoid these motions..

除了Panel外,我还需要一个List<GraphicsPath>,用于绘图和精确的命中测试..:

In addition to the Panel I need a List<GraphicsPath> which is used both for drawing and for precise hit testing..:

Panel tp = null;
List<GraphicsPath> tabAreas = new List<GraphicsPath>();

您可以调用此函数来准备PanelList:

You can call this function to prepare both the Panel and the List:

void makeTabPanel(TabControl tab)
{
    tp = new Panel();
    tp.Size = new Size(tab.Width, tab.ItemSize.Height);
    tp.Paint += tp_Paint;
    tp.MouseClick += tp_MouseClick;
    tp.Location =  tab.Location;
    tab.Parent.Controls.Add(tp);

    int tabs = tabControl1.TabPages.Count;
    float w = tabControl1.Width / tabs;
    float h = tp.Size.Height;
    float y0 = 0;    float y1 = h / 2f;    float y2 = h;
    float d = 5;          //  <--- this is the gap
    float e = 8;          //  <- this is the extrusion
    float w1 = w - d;
    tabAreas = new List<GraphicsPath>();
    for (int t = 0; t < tabs; t++)
    {
        int t1 = t + 1;
        float e1 = t == 0 ? 0 : e;    // corrections for start and end..
        float e2 = t == tabs - 1 ? 0 : e;
        float e3 = t == tabs - 1 ? d : 0;
        List<PointF> points = new List<PointF>();
        points.Add(new PointF(t * w, y0));
        points.Add(new PointF(t1 * w - d + e3, y0));
        points.Add(new PointF(t1 * w -d + e2 + e3, y1));
        points.Add(new PointF(t1 * w- d + e3, y2));
        points.Add(new PointF(t * w, y2));
        points.Add(new PointF(t * w + e1, y1));
        GraphicsPath gp = new GraphicsPath(FillMode.Alternate);
        gp.AddPolygon(points.ToArray());
        tabAreas.Add(gp);
    }
}

在此之后,实际事件非常简单:

After this the actual events are rather simple:

void tp_MouseClick(object sender, MouseEventArgs e)
{
    for (int t = 0; t < tabAreas.Count; t++)
    {
        if (tabAreas[t].IsVisible(e.Location) )
           { tabControl1.SelectedIndex = t; break;}
    }
    tp.Invalidate();
}

void tp_Paint(object sender, PaintEventArgs e)
{
    StringFormat fmt = new StringFormat() 
      { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.Clear(Color.White);   // **
    float w = tp.Width / tabAreas.Count;
    Size sz = new System.Drawing.Size( (int)w, e.ClipRectangle.Height);
    for (int t = 0; t < tabAreas.Count; t++)
    {
        Rectangle rect = new Rectangle((int)(t * w ), 0, sz.Width, sz.Height);            
        bool selected = tabControl1.SelectedIndex == t ;
        Brush brush = selected ?  Brushes.DarkGoldenrod : Brushes.DarkGray;   // **
        e.Graphics.FillPath(brush, tabAreas[t]);

        e.Graphics.DrawString(tabControl1.TabPages[t].Text,
                tabControl1.Font, Brushes.White, rect, fmt);
    }
}

在这里选择颜色(**)

Pick your colors here (**)

更新:使用Lars建议的TextRenderer也是一样. (至少;-)

Update: Using TextRenderer as Lars suggests works just as well. (At least ;-)

TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter ;
TextRenderer.DrawText(e.Graphics, tabControl1.TabPages[t].Text,
    tabControl1.Font, rect, Color.White, flags);

这篇关于自定义TabPage选项卡,例如Microsoft Dynamics CRM 2015中的“流程流箭头"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆