在使用 Infragistics、C# 和 WinForms 的 Visual Studio 中,当用户单击表单中的任意位置时如何关闭选项卡?我在同一页面上同时打开了多个表单。当用户单击这些多个表单中的任意位置时,应关闭特定选项卡(假设“DecorDesign”是选项卡名称)。
当选项卡上的焦点丢失时,有什么方法可以关闭选项卡吗?或者这个场景的任何事件处理程序?
这个答案无论有没有 Infragistics 都应该有效。据我了解,您希望收到应用程序中以任何形式发生鼠标单击的通知,当发生这种情况时,您希望能够检查它以确定单击是否专门发生在“选项卡”(或不是)。如所示,为应用程序的主窗体实现
IMessageFilter
应该给出如图所示的预期行为:
public partial class MainForm : Form, IMessageFilter
{
public MainForm()
{
InitializeComponent();
Application.AddMessageFilter(this);
Disposed += (sender, e) =>
{
Application.RemoveMessageFilter(this);
OtherForm.Dispose();
};
ClickAnywhere += (sender, e) =>
{
if (sender is Control clickedOn)
{
switch (clickedOn?.TopLevelControl?.GetType().Name)
{
case nameof(MainForm): richTextBox.SelectionColor = Color.Green; break;
case nameof(OtherForm): richTextBox.SelectionColor = Color.Blue; break;
default: richTextBox.SelectionColor = SystemColors.ControlText; break;
}
string message = $"{clickedOn?.TopLevelControl?.Name}.{clickedOn.Name}{Environment.NewLine}";
richTextBox.AppendText(message);
}
};
buttonShowOther.Click += (sender, e) =>
{
if (!OtherForm.Visible)
{
OtherForm.Show(this); // Pass 'this' to keep child form on top.
OtherForm.Location = new Point(Left + 100, Top + 100);
}
};
}
OtherForm OtherForm = new OtherForm();
IMessageFilter
的实现由单个方法组成,这里将检测单击“事件”(WM_LBUTTONDOWN消息),以便引发通用自定义事件。
public bool PreFilterMessage(ref Message m)
{
if(m.Msg == WM_LBUTTONDOWN && Control.FromHandle(m.HWnd) is Control control)
{
BeginInvoke((MethodInvoker)delegate
{
ClickAnywhere?.Invoke(control, EventArgs.Empty);
});
}
return false;
}
public event EventHandler ClickAnywhere;
private const int WM_LBUTTONDOWN = 0x0201;
}
其他形式的模拟示例
public partial class OtherForm : Form
{
public OtherForm() => InitializeComponent();
protected override void OnFormClosing(FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
base.OnFormClosing(e);
}
}