【问题标题】:Using Graphics.DrawImage to create custom tabs in C#使用 Graphics.DrawImage 在 C# 中创建自定义选项卡
【发布时间】:2014-10-12 17:28:18
【问题描述】:

我有一个项目,您可以在其中添加和删除选项卡(如网络浏览器)。到目前为止,我有这个:

//Button to add a new tab page
    private void cb_addPage_Click(object sender, EventArgs e)
    {
        string title = "TabPage " + (tabControl1.TabCount + 1).ToString() + "   ";
        TabPage myTabPage = new TabPage(title);
        tabControl1.TabPages.Add(myTabPage);
        tabControl1.SelectedTab = myTabPage;
    }


//Form1_Load
    private void Form1_Load(object sender, EventArgs e)
    {
        tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
        cb_addPage.Top = tabControl1.Top;
        cb_addPage.Left = tabControl1.Right - cb_addPage.Width;
        foreach (TabPage tp in tabControl1.TabPages) tp.Text += "   ";
    }

    Rectangle closeX = Rectangle.Empty;

//Sets background and places the X button on each tab
    private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
    {
        Size xSize = new Size(15, 15);
        TabPage tp = tabControl1.TabPages[e.Index];
        e.DrawBackground();
        using (SolidBrush brush = new SolidBrush(e.ForeColor))
            e.Graphics.DrawString(tp.Text + "   ", e.Font, brush,
                                  e.Bounds.X + 3, e.Bounds.Y + 4);

        if (e.State == DrawItemState.Selected)
        {
            closeX = new Rectangle(e.Bounds.Right - xSize.Width - 3, 
                           e.Bounds.Top + 5, xSize.Width, xSize.Height);
            e.Graphics.DrawImage(imageList1.Images[0], closeX, 
                         new Rectangle(0,0,16,16), GraphicsUnit.Pixel );
        }

    }

//Removes current tab (from X button)
    private void tabControl1_MouseClick(object sender, MouseEventArgs e)
    {
        if (closeX.Contains(e.Location))
            tabControl1.TabPages.Remove(tabControl1.SelectedTab);
    }

所以这一切就是让您使用按钮添加选项卡,并且在每个单独的选项卡上都有一个 X 按钮来删除选项卡。

我使用Graphics.DrawImage 来显示自定义X 按钮(位于imageList 中)。但是我将如何使用Graphics.DrawImage 制作自定义标签。

总而言之,我想要标签,但我希望它们是我制作的自定义图像,这样看起来会更好。 - 谢谢

【问题讨论】:

    标签: c# tabs


    【解决方案1】:

    你的问题不是很清楚。可能您想在每个选项卡上显示不同的文本。您可以使用TextRenderer 这样做:

    const TextFormatFlags flags = TextFormatFlags.PreserveGraphicsClipping |
        TextFormatFlags.VerticalCenter;
    
    TextRenderer.DrawText(e.Graphics, tp.Text, tp.Font, e.Bounds, tp.ForeColor, flags);
    

    要么在文本前添加一些空格以便为 X 留出空间,要么为文本定义新的坐标

    const int XCrossWidth = 20;
    Rectangle textRect = new Rectangle(e.Bounds.Left + XCrossWidth,  e.Bounds.Top,
                                       e.Width - XCrossWidth, e.Height);
    

    并用这个替换TextRenderer.DrawText(...)中的e.Bounds


    更新

    因此,您希望在标签上显示自定义图像。我假设您已将这些图像放在imageList1 中。你怎么知道它们中的哪一个显示在哪个 TabPage 上?

    您可以创建自己的标签页类并使用这个类来代替TabPage

    public TabPageEx : TabPage
    {
        public int ImageIndex { get; set }
    }
    

    现在将属性设置为适当的图像索引。

    TabPageEx myTabPage = new TabPageEx(title);
    myTabPage.ImageIndex = 3; // As an example.
    tabControl1.TabPages.Add(myTabPage);
    

    然后你就可以画出图片了

    TabPageEx tp = (TabPageEx)tabControl1.TabPages[e.Index];
    
    ...
    
    Rectangle imageRect = new Rectangle(e.Bounds.Left + 20,  0, 16, 16);
    e.Graphics.DrawImage(imageList1.Images[tp.ImageIndex], imageRect);
    

    【讨论】:

    • 编辑总结结束。
    【解决方案2】:

    如果您想在文本之外显示图像,例如 webbrowsers favicon,您可以使用修改后的代码:

    private void tabControl3_DrawItem(object sender, DrawItemEventArgs e)
    {
        Size xSize = new Size(16,16);
        Point imgLoc = new Point(e.Bounds.X +  4, e.Bounds.Y + 4);
        TabPage tp = tabControl3.TabPages[e.Index];
        e.DrawBackground();
        e.Graphics.DrawImage(imageList1.Images[tp.ImageIndex], new Rectangle(imgLoc, xSize), 
                                new Rectangle(Point.Empty, xSize), GraphicsUnit.Pixel);
    
        using (SolidBrush brush = new SolidBrush(e.ForeColor))
        {
            e.Graphics.DrawString(tp.Text + "   ", e.Font, brush, 
                                  e.Bounds.X + 23, e.Bounds.Y + 4);
            if (e.State == DrawItemState.Selected)
            {
                closeX = new Rectangle(e.Bounds.Right - xSize.Width - 3, 
                             e.Bounds.Top + 5, xSize.Width, xSize.Height);
                e.Graphics.DrawImage(imageList1.Images[0], closeX, 
                           new Rectangle(Point.Empty, xSize), GraphicsUnit.Pixel);
    
            }
        }
    }
    

    您需要确保:

    • 您拥有想要在图像列表的每个选项卡中显示的图像。
    • 你知道 ech one 的索引。
    • 您必须在创建页面时设置它,但您可以随时更改它。
    • 最好在索引 0 处设置一个默认图标,并将 imageindex 设置为 0,以便您不知道正确的索引。

    通常您还必须将 Tab 控制点设置为 Imagelist。但既然我们都是自己画的,这并不重要。

    您可以使用更复杂的DrawString 格式,用于绘制关闭按钮。在这里,您不只是使用点来确定要绘制的位置;相反,这种格式使用两个矩形来确定源和目标。这有效地导致了将图像缩放到新尺寸的选项。

    但是,如果您的图片一开始就具有正确的尺寸,您将获得最佳质量。请注意每个TabPage的文字决定了tab的宽度;要使其更高,您需要选择更大的字体大小。

    【讨论】:

    • 嗯,好吧,我有一张 135 x 30 的图片(如图所示):gyazo.com/ac4bb80e71797cc2fc571fb5cadecfb7。 (忽略上面的文字,这是为了测试)。但这是图像,我想知道是否可以用该图像替换每个选项卡的选项卡。另外你会把e.Graphics.DrawImage(imageList2.Images[e.Index], Point.Empty );放在哪里?我不能 100% 确定它在我的代码中的位置。
    • 嗯,30 像素对于高度来说有点多。但是你真的想为每个标签显示这些图像吗? - 如果所有图片都只显示文字,您也可以更改字体以匹配您图片中的字体;这会容易得多,当然也很灵活。背景也很容易为文本创建
    • 好吧,我打算用它来做一个测试。我可以快速创建一个 80 x 15 或其他的东西
    • 字体看起来像 Verdana。如果您将 Tab 控件的字体更改为 Verdana 12-15 磅,您只需要添加一个 FillRectangle..
    • 哦,对了,我的最终目标是在选项卡中显示页面上的内容(如网络浏览器),但我会在之后尝试弄清楚,但如果字体和文本发挥这么大的作用,现在值得尝试吗?如果是这样,是否必须在选项卡上显示一个文本框,然后将其链接到页面的某个字符串?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多