C# 如何防止拖动已禁用的窗体?

C# 如何防止拖动已禁用的窗体?,c#,.net,winforms,C#,.net,Winforms,以下代码按预期工作,但如果在禁用时“拖动”表单–当记事本退出时–表单将处于新位置。如何防止这种情况 Enabled = false; Process p = Process.Start("notepad"); p.WaitForExit(); Enabled = true; 您可以尝试从另一个名为showDialog的表单运行Process start Form2 frm2 =new Form2(); frm2.ShowDialog() 在Form2加载事件中,将 Process p = P

以下代码按预期工作,但如果在禁用时“拖动”表单–当记事本退出时–表单将处于新位置。如何防止这种情况

Enabled = false;
Process p = Process.Start("notepad");
p.WaitForExit();
Enabled = true;

您可以尝试从另一个名为showDialog的表单运行Process start

Form2 frm2 =new Form2();
frm2.ShowDialog()

在Form2加载事件中,将

Process p = Process.Start("notepad");
p.WaitForExit();
this.DialogResult=DialogResult.OK;
必须检查所有可能不完美的语法

您甚至可以将Form2.Visible设置为false,这样用户就不会看到它

编辑正如HomeToast建议的那样,这非常有效,只要你不介意隐藏表单,如果你想让表单可见,我会同意我的第一个建议

在这个选项中,我们将使用Visible=false作为主窗体,而不是Enable=false 如果没有要拖动的窗体,则用户无法拖动它

this.Visible = false;
Process p = Process.Start("notepad");
p.WaitForExit();
this.Visible = true;

您可以尝试从另一个名为showDialog的表单运行Process start

Form2 frm2 =new Form2();
frm2.ShowDialog()

在Form2加载事件中,将

Process p = Process.Start("notepad");
p.WaitForExit();
this.DialogResult=DialogResult.OK;
必须检查所有可能不完美的语法

您甚至可以将Form2.Visible设置为false,这样用户就不会看到它

编辑正如HomeToast建议的那样,这非常有效,只要你不介意隐藏表单,如果你想让表单可见,我会同意我的第一个建议

在这个选项中,我们将使用Visible=false作为主窗体,而不是Enable=false 如果没有要拖动的窗体,则用户无法拖动它

this.Visible = false;
Process p = Process.Start("notepad");
p.WaitForExit();
this.Visible = true;

好的,我重新解释这个问题。问题是您正在UI线程上调用WaitForExit()。这会阻止它泵送消息循环和处理输入事件。它们将被放入消息队列中。一旦进程退出,您的方法将返回,UI线程将再次开始泵送消息。并查找缓冲的鼠标消息,因为窗口不再被禁用而执行这些消息

在UI线程上运行的代码的一般规则是,它不应该阻塞。很多事情都会出错,这只是一个例子。处理Process类很容易,它有一个在流程退出时激发的事件。因此,您不需要使用WaitForExit()。使您的代码如下所示:

        this.Enabled = false;
        var prc = System.Diagnostics.Process.Start("notepad.exe");
        prc.EnableRaisingEvents = true;
        prc.SynchronizingObject = this;
        prc.Exited += delegate { 
            this.Enabled = true;
            this.Activate();
        };

请注意,Activate()调用是将窗口放回前台所必需的。这可能并不总是有效。

好的,我重新设置问题。问题是您正在UI线程上调用WaitForExit()。这会阻止它泵送消息循环和处理输入事件。它们将被放入消息队列中。一旦进程退出,您的方法将返回,UI线程将再次开始泵送消息。并查找缓冲的鼠标消息,因为窗口不再被禁用而执行这些消息

在UI线程上运行的代码的一般规则是,它不应该阻塞。很多事情都会出错,这只是一个例子。处理Process类很容易,它有一个在流程退出时激发的事件。因此,您不需要使用WaitForExit()。使您的代码如下所示:

        this.Enabled = false;
        var prc = System.Diagnostics.Process.Start("notepad.exe");
        prc.EnableRaisingEvents = true;
        prc.SynchronizingObject = this;
        prc.Exited += delegate { 
            this.Enabled = true;
            this.Activate();
        };


请注意,Activate()调用是将窗口放回前台所必需的。这可能并不总是有效。

这个问题/答案可能会帮助您:@MAV谢谢。但我想知道是否有一些简单的方法,比如某种类型的“完全”禁用表单(或者一些简单的事件刷新)。@ispiro,据我所知,捕获WndProc消息并过滤掉MAV链接问题中的“移动”命令是最直接的。我也不知道你会想盲目地刷新表单消息队列。很难猜测你是如何在表单被禁用时拖动窗口的。“存在”也很难理解,应该是“退出”吗?“改进你的问题!”汉帕桑看我的回答,我们在那里进行了一些讨论,他说的是,我想这是一种错误。如果在禁用的情况下拖动Form1,或者在启用Form.ShowDialog返回到第一个表单时,或者在Form2返回dialogresult时拖动Form.ShowDialog,则第一个表单也会移动到您尝试拖动它的位置。奇怪但真实。这个问题/答案可能会帮助你:@MAV谢谢。但我想知道是否有一些简单的方法,比如某种类型的“完全”禁用表单(或者一些简单的事件刷新)。@ispiro,据我所知,捕获WndProc消息并过滤掉MAV链接问题中的“移动”命令是最直接的。我也不知道你会想盲目地刷新表单消息队列。很难猜测你是如何在表单被禁用时拖动窗口的。“存在”也很难理解,应该是“退出”吗?“改进你的问题!”汉帕桑看我的回答,我们在那里进行了一些讨论,他说的是,我想这是一种错误。如果在禁用的情况下拖动Form1,或者在启用Form.ShowDialog返回到第一个表单时,或者在Form2返回dialogresult时拖动Form.ShowDialog,则第一个表单也会移动到您尝试拖动它的位置。奇怪但却是真的。我测试了这个,它可以工作,除了当你关闭记事本时,它会按预期关闭Form2,但Form1似乎会最小化。实际上我从来没有想过,我本想隐藏Form2,但你建议隐藏Form1,然后用户可以修改它。我将添加这一点作为编辑,尽管@hometoos值得称赞。不是我的主意,你在编辑之前的最后一句话是:“你甚至可以将Form2.Visible设置为false,这样用户就永远看不到它了。”但是谢谢你的回答。这个想法很好。不幸的是,它不起作用。它似乎对您起作用(并最小化原始表单)的原因是Visual Studio以某种方式干扰了它。尝试以下操作:开始调试后–最小化所有->显示正在运行的表单->(打开