我有一个自定义控件(自定义ComboBox)。它工作得很好,当我按下“箭头按钮”它部署,如果我再按它它也部署,但如果它已部署,我按我的形式任何地方 - 它关闭但是,当我试图打开它 - 我必须按两次“箭头按钮”。所以当我点击我的组合框外面时,我需要检测这个时刻。
打开ComboBox的代码(在ButtonClick中调用)
private void OpenComboBox()
{
if (drop_flag)
{
...
popup.Show(this);
}
else
{
drop_flag = true;
}
}
关闭事件
private void popup_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
drop_flag = false;
}
所以,我想要这样的东西
private ClickedOutsideControl()
{
dropflag = true;
}
答案 0 :(得分:0)
不是那么容易。使用基本的.net,你总是需要通过绑定点击事件来拦截点击来控制/引用。例如,如果你有一个MDI Parent(Mainwindow,你可以拦截它的点击次数)。
另一种方法(使用windows api)是挂钩inso系统事件请参阅以下stackoverflow帖子Global mouse event handler。
但如果你真的需要这个,你应该三思而行。
答案 1 :(得分:0)
在表单中,您可以使用消息过滤器预处理发送到控件的消息。这是我失败的尝试,以实现所需的功能:
public partial class frmAutoCloseDropDown : Form, IMessageFilter
{
int _lastMsg;
public frmAutoCloseDropDown()
{
InitializeComponent();
Application.AddMessageFilter(this);
}
// THIS ATTEMPT DOES NOT WORK!
public bool PreFilterMessage(ref Message m)
{
const int WM_LBUTTONDOWN = 0x0201;
if (m.Msg!= _lastMsg) {
_lastMsg = m.Msg;
}
if (m.Msg == WM_LBUTTONDOWN) {
// You would have to do this recursively if the combo-boxes were nested inside other controls.
foreach (ComboBox cbo in Controls.OfType<ComboBox>()) {
cbo.DroppedDown = false;
}
}
return false;
}
// Note: Dispose is created inside *.Designer.cs and you have to move it manually to *.cs
protected override void Dispose(bool disposing)
{
if (disposing) {
Application.RemoveMessageFilter(this);
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
}
为什么不起作用?可能是因为cbo.DroppedDown = false
生成的发送到表单以关闭下拉列表的新消息被附加到消息队列中,并且仅在鼠标左键单击处理后 。这意味着即使使用PreFilterMessage
来关闭下拉菜单,也来不及了。
可能的解决方案是将WM_LBUTTONDOWN重新发送到右侧的ComboBox。您将必须解释消息的参数以获取鼠标坐标,并查看它们所指向的组合框以获取其HWnd。我这样做的尝试还表明,行为也取决于下拉样式。它还具有关闭刚打开的溺水的不良效果。如果您单击下拉列表本身来选择一个条目,会发生什么?
也许您可以做到,但是代码往往变得非常复杂。这不值得付出努力。