C# 显示任何进程,如模式窗口
C# 显示任何进程,如模式窗口,c#,.net,vb.net,C#,.net,Vb.net,MessageBox.Show显示一个窗口,在MessageBox窗口未关闭之前,单击主应用程序仍将使MessageBox窗口具有焦点,并使MessageBox窗口闪烁。TaskDialogAPI和的行为相同 如何为不同的进程(如process.Start(“notepad.exe”)?好的,这里有一个可行的解决方案: 使用以下代码启动流程: Process p = new Process("cmd"); p.Start(); p.WaitForExit(); 现在,在激活应用程序的事件处理程
MessageBox.Show
显示一个窗口,在MessageBox
窗口未关闭之前,单击主应用程序仍将使MessageBox
窗口具有焦点,并使MessageBox
窗口闪烁。TaskDialog
API和的行为相同
如何为不同的进程(如
process.Start(“notepad.exe”)
?好的,这里有一个可行的解决方案:
使用以下代码启动流程:
Process p = new Process("cmd");
p.Start();
p.WaitForExit();
现在,在激活应用程序的事件处理程序(active)中,再次将焦点设置在流程上。您可以使用process.HasExited来验证您的进程是否仍在运行
注意:我还没有测试过它,但我认为它应该能让你接近它。看这里:
简而言之,您可以使用“process.WaitForExit();”暂停执行,直到进程退出,但我认为这不会闪烁窗口或自动聚焦到该进程
如果你想要更丰富的用户界面,你必须这样做:
while (!process.HasExited)
{
//update UI
}
为了将焦点转移到另一个流程,您应该开始了
编辑:
有关闪烁窗口的更多信息。好的,这是我想到的,不是最好或最优雅的方式,也不包含任何错误处理,但我认为它是有效的 我在代码中所做的是创建一个带有面板控件的虚拟表单(Form2),并将EXE的父级分配给面板的句柄(InPtr)。我已经删除了窗体的边框,使它看起来尽可能的刷新,但是在EXE加载和正在调用的SetParent方法之间仍然有一个明显的闪烁 表格1代码 表格2代码
这个黑客可能会成功。但是在使用这个之前一定要问自己两次
private void DoEvil()
{
var windowField = typeof(Control).GetField("window", BindingFlags.Instance |
BindingFlags.NonPublic);
Form notepad = new Form();
NativeWindow window = (NativeWindow)windowField.GetValue(notepad);
var process = Process.Start("notepad.exe");
process.EnableRaisingEvents = true;
while (process.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(1);
}
window.AssignHandle(process.MainWindowHandle);
Control.CheckForIllegalCrossThreadCalls = false;
EventHandler handler = (s, ev) => notepad.DialogResult = DialogResult.OK;
process.Exited += handler;
notepad.ShowDialog(this);
process.Exited -= handler;
Control.CheckForIllegalCrossThreadCalls = true;
}
警告:不要在家里、办公室或任何地方尝试此操作:p据我所知,这是不可能的,因为您启动的流程可以是任何内容,并且并不总是代表窗口。但是,您可以使用Process.WaitForExit和Process.HasExited来确定进程是否仍在运行(并且您可以阻止应用程序执行任何操作,直到调用的进程停止)。您尝试过类似的方法吗?@MPatel会阻止GUI线程,因为
WaitForExit()
只会使线程休眠。而不是MessageBox提供的行为。单击主应用程序将不会发生任何事情。的确,但它不会模仿flash行为。我希望最终我得到了它,请检查我的新答案。在发布答案之前,你应该阅读原始帖子下方的评论……。感谢你的努力,但这太疯狂了。:)(尝试调整/移动子窗口的大小)。一定有一些简单的事情。。。类似于ShowDialog的功能works@Zuck,同意,但我还不知道是什么,在哪里。找到它的那一刻,我将更新代码。我正试图理解dotPeek/Reflector/JustDecompile中的ShowDialog函数。在任何代码进入生产之前,我都会对其进行三次提问=pBtw,即使在我关上它们之后,邪恶的记事本还是神秘地出现了。记事本启示录!说真的,我建议大家不要使用这个代码。对我来说,它不是这样的,也许你应该检查一下,你只需要调用一次这个邪恶的代码。不管怎样,我玩得很开心,喜欢你的问题+1。你介意我问一下为什么会有这种奇怪的要求吗?我不是在用这个命令运行记事本,一些CMD/K命令。我正在考虑为此制作一个表单,以便将CMD输出重定向到表单。但是我没有完全理解你的代码。
public partial class Form2 : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
private readonly BackgroundWorker worker = new BackgroundWorker();
private IntPtr mainHandle;
private IntPtr processHandle;
private Panel panel;
public Form2()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
FormBorderStyle = FormBorderStyle.None;
StartPosition = FormStartPosition.CenterParent;
AddPanel();
}
private void AddPanel()
{
panel = new Panel {Dock = DockStyle.Fill};
mainHandle = panel.Handle;
Controls.Add(panel);
}
private void Form2_Load(object sender, EventArgs e)
{
worker.RunWorkerAsync();
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Invoke((MethodInvoker) Close);
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
var process = Process.Start("cmd.exe", "/k echo echo");
if (process != null)
{
while (process.MainWindowHandle == IntPtr.Zero)
{
// Add some sort of timeout here, infintite loops are bad!!!
}
processHandle = process.MainWindowHandle;
// Get the size of the EXE window and apply it to this form.
var size = GetSize(processHandle);
Invoke((MethodInvoker) delegate { Size = new Size(size.Width, size.Height);});
// Hook the parent of the EXE window to this form
SetHandle(processHandle);
// Make sure the windows is positions at location x = 0, y = 0 of this form
SetWindowPos(processHandle, IntPtr.Zero, 0, 0, size.Width, size.Height, SetWindowPosFlags.SWP_ASYNCWINDOWPOS);
// wait for the EXE to terminate
process.WaitForExit();
// Unhook the closed process window
SetParent(processHandle, IntPtr.Zero);
}
}
private void SetHandle(IntPtr ptr)
{
if (ptr != IntPtr.Zero)
SetParent(processHandle, mainHandle);
}
private static Size GetSize(IntPtr hWnd)
{
RECT pRect;
var size = new Size();
GetWindowRect(hWnd, out pRect);
size.Width = pRect.Right - pRect.Left;
size.Height = pRect.Bottom - pRect.Top;
return size;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[Flags]
private enum SetWindowPosFlags : uint
{
SWP_ASYNCWINDOWPOS = 0x4000,
SWP_DEFERERASE = 0x2000,
SWP_DRAWFRAME = 0x0020,
SWP_FRAMECHANGED = 0x0020,
SWP_HIDEWINDOW = 0x0080,
SWP_NOACTIVATE = 0x0010,
SWP_NOCOPYBITS = 0x0100,
SWP_NOMOVE = 0x0002,
SWP_NOOWNERZORDER = 0x0200,
SWP_NOREDRAW = 0x0008,
SWP_NOREPOSITION = 0x0200,
SWP_NOSENDCHANGING = 0x0400,
SWP_NOSIZE = 0x0001,
SWP_NOZORDER = 0x0004,
SWP_SHOWWINDOW = 0x0040,
}
}
private void DoEvil()
{
var windowField = typeof(Control).GetField("window", BindingFlags.Instance |
BindingFlags.NonPublic);
Form notepad = new Form();
NativeWindow window = (NativeWindow)windowField.GetValue(notepad);
var process = Process.Start("notepad.exe");
process.EnableRaisingEvents = true;
while (process.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(1);
}
window.AssignHandle(process.MainWindowHandle);
Control.CheckForIllegalCrossThreadCalls = false;
EventHandler handler = (s, ev) => notepad.DialogResult = DialogResult.OK;
process.Exited += handler;
notepad.ShowDialog(this);
process.Exited -= handler;
Control.CheckForIllegalCrossThreadCalls = true;
}