0

我正在使用此答案中的代码,并且运行良好!

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

我已经画了图像,我只需要在悬停时更改图像,并在停止悬停时将其更改回来。

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

我尝试将以下代码放入MouseMove事件中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);
    }
}

但这似乎也不起作用。

变量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) { }

但它仍然无法正常工作。

如果我的问题不清楚,我深表歉意:)

4

1 回答 1

1

您的代码中有几个问题:

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

于 2020-05-17T07:01:38.840 回答