下拉框(ComboBox)在展开时如何捕获鼠标?

7
我正在尝试模拟ComboBox下拉框(或其他下拉框,包括上下文菜单)的行为,即在单击任何其他地方时关闭下拉菜单,即使单击无法聚焦的内容也是如此。
我已经尝试订阅诸如MouseCaptureChanged、LostFocus和Leave之类的事件。我有一个自定义UserControl作为下拉菜单,我只想在用户单击其他地方时将其关闭。
这似乎是许多控件中都可以实现的事情,因此如果没有简单的方法来实现这一点,我会感到惊讶。
到目前为止,我能想到的过于复杂的方法是使用pinvoke和SetCapture()函数,或创建一个MessageFilter。如果这些是唯一的选项,我不确定哪个更好。

3
实现类似于下拉列表的控件的简便方法是使用ToolStripControlHost和ToolStripDropDown。这与ComboBox的工作方式类似。请参阅如何在显示列表项时,拦截窗体上任何位置的鼠标事件以隐藏该列表? - LarsTech
我正在尝试使用ToolStripControlHost。我无法消除弹出窗口顶部的丑陋边框,也无法消除每次打开下拉列表时ComboBox的闪烁。 - Trevor Elliott
3
请确保将ToolStripContorlHost的边距和ToolStripDropDown的填充设置为0。您控件上的闪烁是一个不同的问题 - 您是否尝试使用带有自定义下拉框的ComboBox? - LarsTech
是的。我正在覆盖 OnDropDown 方法,并重置 IntegralHeight 属性以强制其关闭。这样做可以使其不再出现,但仍会闪烁。 - Trevor Elliott
@Moozhe,你是在使用Windows Forms还是WPF? - Dima
尝试使用双缓冲技术来控制你的控件,看看它是否还会闪烁? - Satyajit
2个回答

1

ComboBox由2个控件构成。

  • Base - 非活动状态下可见 (Control)
  • DropDownList - 编辑模式或列表选择模式下可见 (Window or Form)

通常情况下,Base是可见的。当用户单击ComboBox时,Base控件隐藏,DropDownList控件显示。这个切换是在后台完成的,所以对于用户来说,控件似乎只是扩展了。

要捕获的事件是通过DropDownList窗口完成的。如果您在客户端区域的任何地方单击,DropDownList窗口将通过其WndProc(Message% m)方法接收WM_KILLFOCUS事件。然后向父窗口(Base控件)发送一个带有WParam=526318(HIWORD(WParam)=8)的WM_COMMAND(OCM_COMMAND)消息,Base控件知道它应该隐藏DropDownList窗口。

因此,您需要实现额外的DropDown窗口并捕获WM_KILLFOCUS事件。


0

你提到的控件模板在下拉列表中使用弹出窗口作为容器,StaysOpen属性设置为false(我认为这是默认值)。

ComboBox模板示例


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