在WinForms中,如何使控件不接受鼠标事件

3
我有一个按钮,当鼠标移入时,会弹出一个小表单,在鼠标离开按钮时,该小表单会消失。我需要这个表单不接受任何鼠标事件,也就是对鼠标“无形的”。
问题在于,表单会在鼠标下方弹出,从而触发按钮的“鼠标离开”事件。我知道还有其他方法可以解决这个问题,但我需要当鼠标离开原始按钮时隐藏表单,并且需要表单出现在鼠标下方。
那么,如何使弹出窗口表单对鼠标事件不可见,以免触发按钮的“鼠标离开”事件呢?
弹出窗口的类型为“表单”。以下是触发显示和隐藏表单的mouseEnter和mouseLeave代码:
private void btnPatientSearch_MouseEnter(object sender, EventArgs e)
        {
                _currentPatientInfo = new PatientInfo()
                {
                    MdiParent = this.MdiParent
                };
                _currentPatientInfo.Show();
                _currentPatientInfo.Location = new Point(181, 9);
            }
        }

        private void btnPatientSearch_MouseLeave(object sender, EventArgs e)
        {
            if (_currentPatientInfo == null) return;
            _currentPatientInfo.Hide();
            _currentPatientInfo = null;
        }

如果你只需要关闭/隐藏表单,为什么还需要为按钮编写mouseleave事件呢? - HappyLee
@Hans Passant - 我尝试过了,但是即使鼠标离开按钮后,按钮仍然保留鼠标控制权。如果我使用按钮的“capture”属性,我如何仍然使用mouseleave事件? - Tyler Jones
@HappyLee 我需要当鼠标离开按钮时,表单自动隐藏。我不希望用户必须关闭表单。类似于工具提示的想法。 - Tyler Jones
4
专注于创建易用的用户界面。你们一直做的都没有任何意义,当然你们要确保这个表格永远不会重叠在按钮上方。听起来很强烈的是这需要成为一个工具提示。 - Hans Passant
感谢大家的有益评论! - Tyler Jones
显示剩余13条评论
1个回答

1
从以下的表单类继承你的弹出式表单。这段代码使用了一些p/invokes并且没有经过测试,但是它应该可以工作。
public class PopupForm : Form
{
  private const int WS_BORDER = 0x00800000;
  private const int WS_POPUP = unchecked((int)0x80000000);

  private const int WS_EX_TOPMOST = 0x00000008;
  private const int WS_EX_NOACTIVATE = 0x08000000;

  private const int WM_MOUSEACTIVATE = 0x0021;
  private const int MA_NOACTIVATEANDEAT = 4;

  private static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1);

  private const int SWP_NOSIZE = 0x0001;
  private const int SWP_NOMOVE = 0x0002;
  private const int SWP_NOACTIVATE = 0x0010;

  [DllImport("user32.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
    int X, int Y, int cx, int cy, int uFlags);

  public PopupForm()
  {
    SetStyle(ControlStyles.Selectable, false);
    FormBorderStyle = FormBorderStyle.None;
    StartPosition = FormStartPosition.Manual;
    ShowInTaskbar = false;
    Visible = false;
  }

  protected override CreateParams CreateParams
  {
    get
    {
      CreateParams cp = base.CreateParams;
      cp.Style |= WS_POPUP | WS_BORDER;
      cp.ExStyle |= WS_EX_TOPMOST | WS_EX_NOACTIVATE;
      return cp;
    }
  }

  protected override bool ShowWithoutActivation
  {
    get { return true; }
  }

  protected override void WndProc(ref Message m)
  {
    if (m.Msg == WM_MOUSEACTIVATE)
    {
      OnClick(EventArgs.Empty);
      m.Result = (IntPtr)MA_NOACTIVATEANDEAT;
    }
    else
      base.WndProc(ref m);
  }

  public new void Show()
  {
    Windows.SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0,
      SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
    base.Show();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接