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

问题描述 投票:0回答:1

我正在使用this answer中的代码,它工作正常!

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

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

[Invalidate()有建议,但我不太清楚如何使用它

我尝试将以下代码放入MouseMoveTabControl事件中,

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);
    }
}

但是那似乎也不起作用。

isNormalisHover变量已经在较早的代码中创建,并且在DrawItem事件中,我具有:

try
{
    if (isHover == false && isNormal == true)
    {
        CloseImage = Properties.Resources.normalImage;

        var tabRect = this.tabControl1.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.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(CloseImage, imageRect.Location);
    }
    else if (isHover == true && isNormal == false)
    {
        CloseImage = Properties.Resources.hoverImage;

        var tabRect = this.tabControl1.GetTabRect(tabControl1.SelectedIndex);
        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.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[tabControl1.SelectedIndex].Text,
                              this.Font, Brushes.Black, tabRect, sf);

        e.Graphics.DrawImage(CloseImage, imageRect.Location);

        isHover = false;
        isNormal = true;
    }
}
catch (Exception) { }

但是它仍然不起作用。

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

c# winforms tabcontrol mousehover close-button
1个回答
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

© www.soinside.com 2019 - 2024. All rights reserved.