我希望我能足够清楚地解释这一点。我有我的主表单 (A),它使用 form.Show() 打开 1 个子表单 (B),使用 form.Show() 打开第二个子表单 (C)。现在我希望子表单 B 使用 form.ShowDialog() 打开表单 (D)。当我这样做时,它也会阻止 A 型和 C 型。有没有办法打开模式对话框并仅阻止打开它的表单?
使用多个 GUI 线程是一件棘手的事情,如果这是您这样做的唯一动机,我建议您不要这样做。
更合适的方法是使用Show()
代替ShowDialog()
,并禁用所有者表单,直到弹出表单返回。无外乎四点考虑:
When ShowDialog(owner)
使用时,弹出窗体保留在其所有者的顶部。当你使用时也是如此Show(owner)
。或者,您可以设置Owner
明确属性,具有相同的效果。
-
如果您设置所有者表单的Enabled
财产给false
,窗体显示禁用状态(子控件“变灰”),而当ShowDialog
使用时,所有者表单仍然被禁用,但不显示禁用状态。
你打电话时ShowDialog
,所有者窗体在 Win32 代码中被禁用 - 它WS_DISABLED
样式位已设置。这会导致它失去获得焦点的能力并在单击时发出“叮”声,但不会使其自身绘制为灰色。
当您设置表单的Enabled
财产给false
,设置了一个附加标志(在框架中,而不是底层 Win32 子系统),某些控件在绘制自身时会检查该标志。该标志告诉控件将自己绘制为禁用状态。
所以要模拟会发生什么ShowDialog
,我们应该设置本机WS_DISABLED
直接样式位,而不是设置表单的Enabled
财产给false
。这是通过一点点互操作来完成的:
const int GWL_STYLE = -16;
const int WS_DISABLED = 0x08000000;
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
void SetNativeEnabled(bool enabled){
SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) &
~WS_DISABLED | (enabled ? 0 : WS_DISABLED));
}
The ShowDialog()
在对话框关闭之前,调用不会返回。这很方便,因为您可以暂停所有者表单中的逻辑,直到对话框完成其任务。这Show()
call 必然不会有这样的行为。因此,如果您要使用Show()
代替ShowDialog()
,您需要将逻辑分为两部分。对话框关闭后应运行的代码(其中包括重新启用所有者表单)应由Closed
事件处理程序。
当表单显示为对话框时,设置其DialogResult
属性会自动关闭它。每当按钮带有DialogResult
财产以外的财产None
被点击。显示的表格Show
不会像这样自动关闭,因此我们必须在单击其关闭按钮之一时显式关闭它。但请注意,DialogResult
属性仍然可以通过按钮进行适当设置。
实现这四件事,你的代码会变成这样:
class FormB : Form{
void Foo(){
SetNativeEnabled(false); // defined above
FormD f = new FormD();
f.Closed += (s, e)=>{
switch(f.DialogResult){
case DialogResult.OK:
// Do OK logic
break;
case DialogResult.Cancel:
// Do Cancel logic
break;
}
SetNativeEnabled(true);
};
f.Show(this);
// function Foo returns now, as soon as FormD is shown
}
}
class FormD : Form{
public FormD(){
Button btnOK = new Button();
btnOK.DialogResult = DialogResult.OK;
btnOK.Text = "OK";
btnOK.Click += (s, e)=>Close();
btnOK.Parent = this;
Button btnCancel = new Button();
btnCancel.DialogResult = DialogResult.Cancel;
btnCancel.Text = "Cancel";
btnCancel.Click += (s, e)=>Close();
btnCancel.Parent = this;
AcceptButton = btnOK;
CancelButton = btnCancel;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)