如何在鼠标悬停时更改TabControl关闭按钮图像?

时间:2020-05-17 01:43:16

标签: c# winforms tabcontrol mousehover close-button

我正在使用this answer中的代码,并且运行良好!

但是,现在我需要添加一个悬停图像,因为没有一个图像会感到很沉闷。

我已经绘制了图像,我只需要在悬停时更改图像,然后在停止悬停时将其更改回即可。

Invalidate()有一些建议,但我不太了解如何使用它

我尝试将以下代码放入MouseMove的{​​{1}}事件中,

TabControl

但这似乎也不起作用。

变量for (var i = 0; i < this.tabControl1.TabPages.Count; i++) { var tabRect = this.tabControl1.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)) { isHover = true; isNormal = false; Invalidate(tabRect); } else { isNormal = true; isHover = false; Invalidate(tabRect); } } isNormal已经在较早的代码中创建,并且在isHover事件内部,我具有:

DrawItem

但是它仍然无法正常工作。

如果我的问题不清楚,我很抱歉:)

1 个答案:

答案 0 :(得分:1)

您的代码中存在几个问题:

  1. 用于绘制所有选项卡的图像与CloseImage相同,即使将鼠标悬停在一个选项卡上时,其绘制方式也不同于其他选项卡。 解决方案:将每个TabPage的图片存储在其Tag属性中。
  2. 您正在为所有标签使用单个isHoverisNormal字段。这和 1 一样。 (顺便说一句,没有理由使用两个标志,一个标志就足够了,它更简单且更不容易出错)。
  3. 您在使用isHover = false;isNormal = true;进行绘图后将其重置,但是可以通过其他触发器再次重新绘制表单,并且图像将恢复正常。
  4. 您正在使用Invalidate形式的tabRect方法,但是tabRect相对于TabControl的坐标。 解决方案:使用tabControl1.Invalidate(tabRect)

以下是对代码进行的一些更改(带有注释),它们可以正常工作:

Image NormalImage = Properties.Resources.normalImage;
Image HoverImage = Properties.Resources.hoverImage;

private void Form1_Load(object sender, EventArgs e)
{
    this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;
    tabControl1.DrawItem += TabControl1_DrawItem;
    tabControl1.MouseClick += TabControl1_MouseClick;
    this.tabControl1.Padding = new Point(10, 3);
    this.tabControl1.MouseMove += TabControl1_MouseMove;

    // Store the image for each tab page in its Tag
    foreach (TabPage tabPage in tabControl1.TabPages)
    {
        tabPage.Tag = NormalImage;
    }
}

private void TabControl1_MouseMove(object sender, MouseEventArgs e)
{
    // Select the image to draw for each tab
    for (var i = 0; i < this.tabControl1.TabPages.Count; i++)
    {
        var tabRect = this.tabControl1.GetTabRect(i);
        tabRect.Inflate(-2, -2);
        var imageRect = new Rectangle(tabRect.Right - NormalImage.Width,
                                    tabRect.Top + (tabRect.Height - NormalImage.Height) / 2,
                                    NormalImage.Width,
                                    NormalImage.Height);

        // Find what image needs to be drawn
        Image imageToDraw = imageRect.Contains(e.Location) ? HoverImage : NormalImage;

        // Update the image and invalidate only if the image has change to avoid flicker
        // Invalidate using the tabControl1
        if(tabControl1.TabPages[i].Tag != imageToDraw)
        {
            tabControl1.TabPages[i].Tag = imageToDraw;
            tabControl1.Invalidate(tabRect);
        }
    }
}

private void TabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    try
    {
        // Get the image to draw from the TabPages Tag propery.
        Image image = (Image)this.tabControl1.TabPages[e.Index].Tag;

        var tabRect = this.tabControl1.GetTabRect(e.Index);
        tabRect.Inflate(-2, -2);
        var imageRect = new Rectangle(tabRect.Right - image.Width,
                                    tabRect.Top + (tabRect.Height - image.Height) / 2,
                                    image.Width,
                                    image.Height);

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

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

        e.Graphics.DrawImage(image, imageRect.Location);
    }
    catch (Exception) { }
}

我希望添加一个tabControl1.MouseLeave事件以将所有TabPage标签重置为NormalImage