Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
680 views
in Technique[技术] by (71.8m points)

winforms - Close button for TabPages of Right To Left TabControl c#

I want to add a close button to TabPages of a TabControl. I try this code and it works fine with a Left To Right TabControl:

private Point _imageLocation = new Point(13, 5);
private Point _imgHitArea = new Point(13, 2);

this.tabControl2.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;

tabControl2.DrawItem += TabControl2_DrawItem;

private void TabControl2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
    try
    {
        Image img = new Bitmap(GestionP.Properties.Resources.Close);
        Rectangle r = e.Bounds;
        r = this.tabControl2.GetTabRect(e.Index);
        r.Offset(2, 2);
        Brush TitleBrush = new SolidBrush(Color.Black);
        Font f = this.Font;
        string title = this.tabControl2.TabPages[e.Index].Text;
        e.Graphics.DrawString(title, f, TitleBrush, new PointF(r.X, r.Y));

        if (tabControl2.SelectedIndex >= 1)
        {
            e.Graphics.DrawImage(img, new Point(r.X + (this.tabControl2.GetTabRect(e.Index).Width - _imageLocation.X), _imageLocation.Y));
        }

    }
        catch (Exception) { }
}

    private void tabControl2_MouseClick(object sender, MouseEventArgs e)
    {
        TabControl tc = (TabControl)sender;
        Point p = e.Location;
        int _tabWidth = 0;
        _tabWidth = this.tabControl2.GetTabRect(tc.SelectedIndex).Width - (_imgHitArea.X);
        Rectangle r = this.tabControl2.GetTabRect(tc.SelectedIndex);
        r.Offset(_tabWidth, _imgHitArea.Y);
        r.Width = 16;
        r.Height = 16;
        if (tabControl2.SelectedIndex >= 1)
        {
            if (r.Contains(p))
            {
                TabPage TabP = (TabPage)tc.TabPages[tc.SelectedIndex];
                tc.TabPages.Remove(TabP);

            }
        }
    }

But when I set the property RightToLeftLayout = true and RightToLeft = true it doesn't work, TabPage titles don't appear and also close button.

So how to fix the code in a way that accepts RightToLeft property?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can create a function to translate coordinates of a rectangle to RTL coordinates in a container:

public static Rectangle GetRTLCoordinates(Rectangle container, Rectangle drawRectangle)
{
    return new Rectangle(
        container.Width - drawRectangle.Width - drawRectangle.X,
        drawRectangle.Y,
        drawRectangle.Width,
        drawRectangle.Height);
}

And when painting in RTL mode, calculate coordinates this way:

tabRect = GetRTLCoordinates(this.tabControl2.ClientRectangle, tabRect);

Also you should draw your strings using an StringFormat and set it to use StringFormatFlags.DirectionRightToLeft when you are in RTL mode and draw string in the translated rectangle using the string format:

e.Graphics.DrawString(this.tabControl2.TabPages[e.Index].Text, 
                      this.Font, Brushes.Black, tabRect, sf);

You can encapsulate all codes in a CustomTabControl inheriting TabControl.

Screenshot

enter image description here enter image description here

The whole code could be:

I suppose you have a close image somewhere like Properties.Default.Close and assign it to this.CloseImage. Here is the image I used: enter image description here

I also set the this.tabControl2.Padding = new Point(10, 3); to provide additional free space for drawing the image.

Also you can simply add your criteria of not closing first tab.

Image CloseImage;

private void Form1_Load(object sender, EventArgs e)
{
    this.tabControl2.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;
    tabControl2.DrawItem += TabControl2_DrawItem;
    tabControl2.MouseClick += tabControl2_MouseClick;
    CloseImage = Properties.Resources.Close;
    this.tabControl2.Padding = new Point(10, 3);
}


private void TabControl2_DrawItem(object sender, 
                                  System.Windows.Forms.DrawItemEventArgs e)
{
    try
    {
        var tabRect = this.tabControl2.GetTabRect(e.Index);
        tabRect.Inflate(-2, -2);
        var imageRect = new Rectangle(tabRect.Right - CloseImage.Width,
                                 tabRect.Top + (tabRect.Height - CloseImage.Height) / 2,
                                 CloseImage.Width,
                                 CloseImage.Height);

        var sf = new StringFormat(StringFormat.GenericDefault);
        if (this.tabControl2.RightToLeft == System.Windows.Forms.RightToLeft.Yes &&
            this.tabControl2.RightToLeftLayout == true)
        {
            tabRect = GetRTLCoordinates(this.tabControl2.ClientRectangle, tabRect);
            imageRect = GetRTLCoordinates(this.tabControl2.ClientRectangle, imageRect);
            sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
        }

        e.Graphics.DrawString(this.tabControl2.TabPages[e.Index].Text,
                              this.Font, Brushes.Black, tabRect, sf);
        e.Graphics.DrawImage(CloseImage, imageRect.Location);

    }
    catch (Exception) { }
}

private void tabControl2_MouseClick(object sender, MouseEventArgs e)
{

    for (var i = 0; i < this.tabControl2.TabPages.Count; i++)
    {
        var tabRect = this.tabControl2.GetTabRect(i);
        tabRect.Inflate(-2, -2);
        var imageRect = new Rectangle(tabRect.Right - CloseImage.Width,
                                 tabRect.Top + (tabRect.Height - CloseImage.Height) / 2,
                                 CloseImage.Width,
                                 CloseImage.Height);
        if (imageRect.Contains(e.Location))
        {
            this.tabControl2.TabPages.RemoveAt(i);
            break;
        }
    }
}

public static Rectangle GetRTLCoordinates(Rectangle container, Rectangle drawRectangle)
{
    return new Rectangle(
        container.Width - drawRectangle.Width - drawRectangle.X,
        drawRectangle.Y,
        drawRectangle.Width,
        drawRectangle.Height);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...