如何创建一个非模态形式,但阻塞



听起来很奇怪,但这只是我的爱好。我想要一个(自定义)消息框弹出一个YesNo按钮,理想情况下应该阻止代码。但是我应该能够单击父窗体,这样我就可以取消消息框,而不必特别单击消息框按钮(相当于在消息框上单击No).

像这样:

     void Foo()
     {
         CustomMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
         //block the code here, but user should be able to click on form, so that its equivalent to have clicked No;
         //if clicked No, return;
         //delete.
     }

所以我认为的解决方案是使自定义消息框非模态-这样用户就可以点击表单,但我不能阻止代码。我怎么能做到呢?

它看起来像这样:

 void Foo()
 {
     NonModalMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
     //block thread till user clicks on form or messagebox buttons.
     //unblock when user clicks.
     //if No, return;
     //delete.
 }

编辑:我知道这不是一个标准的做法,我知道非模态形式不会阻塞,而模态形式。所以请不要建议满足于情态动词或非情态动词的行为。我的问题是,是否有任何方法来模拟上下文菜单的行为与windows窗体。

您可以很容易地解决这个问题。创建并使用一个模态对话框,但是覆盖对话框的WndProc并处理WM_MOUSEDOWN事件。检查鼠标的位置,如果它在父窗口上,但不在对话框本身上,则直接关闭对话框。

基本上你不能在一个'阻塞'调用中轻松做到这一点。您可以轻松地将执行删除所需的信息或执行操作的委托传递给表单。当它们单击Ok时,您只需执行操作即可。如果它们激活了父窗体,那么只需关闭子窗体。

您希望用户能够单击背景窗口来取消对话框?为背景窗口添加一个处理程序,这样当用户单击它时,您就可以检查是否显示非模态窗口,如果显示,则关闭它。

听起来很简单,但是您需要小心处理背景窗口和子窗口上的每一个可能的点击。这听起来像一个棘手的问题,我不想下去。

也许你可以检测非模态对话框是否失去焦点并自动关闭它。我可以看到这种行为对于一个简单的"确认删除"对话框来说是有意义的,但是作为用户,我的第一反应是按ESC键关闭对话框。

另一种处理方法是在调用ShowDialog时手动启用父窗体,从这里

[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool enable);
internal static DialogResult ShowDialogSpecial(this Form formToBeShown, Form parent)
{
    parent.BeginInvoke(new Action(() => EnableWindow(parent.Handle, true)));
    formToBeShown.ShowDialog(parent);
    return formToBeShown.DialogResult;
}

只需从任何父表单调用扩展方法,像这样:

var f = new Form();
f.ShowDialogSpecial(this);
//blocks but parent window will be active.

当然你需要处理父窗体上的点击来关闭子窗体。

你可以这样做:

public void ShowMe() {
    Show();
    while (!_receivedDeactivateEvent)
        Application.DoEvents();
}

我不确定我会推荐它,虽然——我不确定它会有多稳定,我也不确定它是否会按照你想要的方式行事,如果你点击父窗体上的删除按钮,而"对话框"是向上的(它会先关闭第一个对话框,还是离开它?

一个更简单的方法:设置表单的"TopMost"属性为True。然后它就像阻塞了

相关内容

  • 没有找到相关文章

最新更新