自定义控件在最小化时不会获得MouseLeave事件

时间:2016-05-24 04:42:10

标签: c# .net winforms controls

我有一个继承自System.Windows.Forms.Control的自定义控件,我在MouseEnter和MouseLeave事件上更改了BackColor属性。我用它来创建一个自定义按钮类。一切都很好,除了一个按钮,其点击处理程序最小化包含所有按钮的主窗体。当通过单击此按钮最小化表单时,该按钮的MouseLeave事件永远不会触发(MouseUp,Click,其他人仍然会这样做)。

当我将应用程序恢复到正常窗口状态时,问题就开始了。如果我将鼠标放在我的自定义最小化按钮上,则没有MouseEnter事件。如果我离开按钮(没有点击),那么我终于得到一个MouseLeave。它基本上似乎是因为原始MouseLeave在主窗体最小化时从未触发过,所以它并不认为MouseEnter应该是可能的。因此,在你再次进入和退出之前,一切都基本上已经破裂了。

我尝试让我的点击处理程序手动调用OnMouseLeave并且没有改变任何内容,但我没有在EventArgs参数中特别指定任何内容,如果它是关键部分。

关于我缺少什么才能让它发挥作用的任何想法?

编辑:这是完整的项目:

https://dl.dropboxusercontent.com/u/32742882/Button.zip

事实证明,问题与最小化至notifyIcon有关,并未显示正常的最小化。

编辑:添加代码......

public class IconButton : Control
{
  public bool pressed;

  static readonly public bool boundingBox = false;
  static readonly Color darkGray = Color.FromArgb(255, 112, 112, 112);
  static readonly Color mediumGray = Color.FromArgb(255, 145, 145, 145);
  static readonly Color lightGray = Color.FromArgb(255, 178, 178, 178);
  static readonly Color hoverColor = Color.FromArgb(255, 209, 226, 242);
  static readonly Color backgroundColor =  boundingBox ? Color.FromArgb(255, 227, 227, 227) : SystemColors.Control;
  static readonly Color pressColor = Color.FromArgb(255, 180, 212, 244);
  static readonly Color enabledTextColor = Color.Black;
  static readonly Color disabledTextColor = mediumGray;

  public IconButton()
  {
    this.BackColor = backgroundColor;
    this.DoubleBuffered = true;
    this.Margin = new Padding(2);
  }

  protected override void OnMouseEnter(EventArgs e)
  {
    if (Enabled)
    {
      this.BackColor = hoverColor;
    }
    base.OnMouseEnter(e);
  }

  protected override void OnMouseLeave(EventArgs e)
  {
    this.BackColor = backgroundColor;
    base.OnMouseLeave(e);
  }

  protected override void OnMouseDown(MouseEventArgs e)
  {
    if (Enabled)
    {
      this.BackColor = pressColor;
    }
    base.OnMouseDown(e);
  }

  protected override void OnMouseUp(MouseEventArgs e)
  {
    if (Enabled)
    {
      if (this.ClientRectangle.Contains(e.Location))
      {
        this.BackColor = hoverColor;
      }
      else
      {
        this.BackColor = backgroundColor;
      }
    }
    base.OnMouseUp(e);
  }
}

最终编辑:

所以问题与直接在MainForm_SizeChanged处理程序中调用ShowInTaskbar = false有关。这似乎阻止了事件处理的轨道并导致问题。所以相反,我现在这行延迟250毫秒,一切似乎都很好。我打算提出如何使这个更干净的建议......

    private void Form1_SizeChanged(object sender, EventArgs e)
    {
        if (WindowState == FormWindowState.Minimized)
        {
            notifyIcon.Visible = true;

            notifyIcon.BalloonTipText = "We got minimized";
            notifyIcon.Text = "Minimized";

            notifyIcon.ShowBalloonTip(1000);

            TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();

            Task.Delay(250).ContinueWith(_ => {
                this.ShowInTaskbar = false;
            }, CancellationToken.None, TaskContinuationOptions.None, scheduler);
        }
        else if (WindowState == FormWindowState.Normal)
        {
            ShowInTaskbar = true;
            notifyIcon.Visible = false;
        }
    }

2 个答案:

答案 0 :(得分:1)

因为您将ShowInTaskbar设置为false,所以意图实际上是隐藏表单,而不是最小化它。为此,您需要intercept the minimizing event,因此请尝试将代码更改为以下内容:

private void ToggleView() {
  if (this.Visible) {
    this.Hide();
    notifyIcon.Visible = true;
    notifyIcon.BalloonTipText = "We got minimized";
    notifyIcon.Text = "Minimized";
    notifyIcon.ShowBalloonTip(1000);
  } else {
    this.Show();
    notifyIcon.Visible = false;
  }
}

protected override void WndProc(ref Message m) {
  const int WM_SYSCOMMAND = 0x0112;
  const int SC_MINIMIZE = 0xf020;

  if (m.Msg == WM_SYSCOMMAND) {
    if (m.WParam.ToInt32() == SC_MINIMIZE) {
      m.Result = IntPtr.Zero;
      ToggleView();
      return;
    }
  }
  base.WndProc(ref m);
}

public void button_click(object sender, EventArgs e) {
  ToggleView();
}

private void notifyIcon_MouseClick(object sender, MouseEventArgs e) {
  ToggleView();
}

请注意,我删除了Form1_SizeChanged事件。

答案 1 :(得分:-1)

private void Form1_Resize ( object sender , EventArgs e )
{
    if ( WindowState == FormWindowState.Minimized )
    {
        // code on minimized
    }
    else if(WindowsState == FormWindowState.Maximized) 
    {
        // code on maximized
    }
}