作者TeemingVoid (TeemingVoid)
看板C_Sharp
标题Re: [问题] process.start 外部程式 视窗焦点
时间Mon Jul 29 00:30:38 2013
※ 引述《yeahhey (神秘人)》之铭言:
: 大家好
: 小弟最近在用process.StartInfo来启动外部程式
: 功能上想要达到
: buttom_click後,可以依序把多个外部程式启动完(利用来处理资料的外部程式)
: (例如:先A,A结束後再B,B结束在C...)
: 这些执行序的视窗,目前程式都设定缩到最小
: 现在问题是
: ...
一开始其实看不懂你在写什麽 :p (抱歉),後来才发现原来是指 A 程式结束後,
接下来要启动 B 程式时,最前景视窗会失去视窗焦点(focus)。
请这样试试看合不合你的需要:
1. 新建一个 Windows Form 专案,名称(例如)叫: StartOneByOne
2. 在 Form1 摆一个 Button,Button1 滑鼠点两下,准备写 Click 事件。
3. using 以下 namespace:
using System.Diagnostics;
using System.Runtime.InteropServices;
4. 在 Click 事件前,贴入下列 Windows API 宣告:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
enum ShowWindowCommands : int
{
/// <summary>
/// Hides the window and activates another window.
/// </summary>
Hide = 0,
/// <summary>
/// Activates and displays a window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when displaying the window
/// for the first time.
/// </summary>
Normal = 1,
/// <summary>
/// Activates the window and displays it as a minimized window.
/// </summary>
ShowMinimized = 2,
/// <summary>
/// Maximizes the specified window.
/// </summary>
Maximize = 3, // is this the right value?
/// <summary>
/// Activates the window and displays it as a maximized window.
/// </summary>
ShowMaximized = 3,
/// <summary>
/// Displays a window in its most recent size and position. This value
/// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except
/// the window is not activated.
/// </summary>
ShowNoActivate = 4,
/// <summary>
/// Activates the window and displays it in its current size and
/// position.
/// </summary>
Show = 5,
/// <summary>
/// Minimizes the specified window and activates the next top-level
/// window in the Z order.
/// </summary>
Minimize = 6,
/// <summary>
/// Displays the window as a minimized window. This value is similar to
/// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the
/// window is not activated.
/// </summary>
ShowMinNoActive = 7,
/// <summary>
/// Displays the window in its current size and position. This value is
/// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the
/// window is not activated.
/// </summary>
ShowNA = 8,
/// <summary>
/// Activates and displays the window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when restoring a minimized
/// window.
/// </summary>
Restore = 9,
/// <summary>
/// Sets the show state based on the SW_* value specified in the
/// STARTUPINFO structure passed to the CreateProcess function by the
/// program that started the application.
/// </summary>
ShowDefault = 10,
/// <summary>
/// <b>Windows 2000/XP:</b> Minimizes a window, even if the thread
/// that owns the window is not responding. This flag should only be
/// used when minimizing windows from a different thread.
/// </summary>
ForceMinimize = 11
}
5. 按钮的 Click 事件处理函式则类似这样:
private void button1_Click(object sender, EventArgs e)
{
// testLab.exe 是我另外写的测试程式,它五秒後会自动结束
string[] Programs = new string[] { @"c:\temp\testLab.exe",
@"notepad.exe" };
foreach (string sProgram in Programs)
{
ProcessStartInfo psi = new ProcessStartInfo(sProgram);
// 一开始是极小化
psi.WindowStyle = ProcessWindowStyle.Minimized;
Process p = Process.Start(psi);
// 等待程式确实 run 起来...
while (p.MainWindowHandle == IntPtr.Zero)
{
System.Threading.Thread.Sleep(100);
p.Refresh();
}
// 测试後,发现主视窗也要极小化。
ShowWindow(this.Handle, ShowWindowCommands.Minimize);
// 隐藏工作视窗,这样 focus 自然释出
ShowWindow(p.MainWindowHandle, ShowWindowCommands.Hide);
// 重新将工作视窗设为极小化
ShowWindow(p.MainWindowHandle, ShowWindowCommands.Minimize);
// p.WaitForExit();
while (!p.HasExited)
{
System.Threading.Thread.Sleep(100);
Application.DoEvents();
}
}
}
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.170.128.145
1F:推 yeahhey:先感谢你!!我有个问题是 他这样会有焦点变化吗? 07/29 00:47
2F:→ yeahhey:start後的瞬间 焦点还是会被启动的程式夺去 在还回? 07/29 00:48
3F:→ yeahhey:我原本想找看看有没有函示可以直接设定不要抢走焦点= = 07/29 00:50
4F:→ yeahhey:但最後也是找到你这边提到的ShowWindowCommands! 07/29 00:52
5F:→ TeemingVoid:一旦呼叫 Process.Start(),focus 就会被新视窗抢走, 07/29 01:00
6F:推 yeahhey:会问有没有焦点变化 主要是担心某个使用中全萤幕的视窗 07/29 01:00
7F:→ TeemingVoid:ShowWindow(..., Hide); 的作用在於隐藏新的视窗, 07/29 01:01
8F:→ yeahhey:会因为focus改变而缩小或是瞬间缩小又切回来 07/29 01:01
9F:→ TeemingVoid:这样 focus 自然释出。 07/29 01:02
10F:→ yeahhey:因为Process.Start()会抢focus,我现在改用CreateProcess 07/29 01:03
11F:→ yeahhey:外部程式的作法除了process,另外查到shellExecute 07/29 01:04
12F:→ yeahhey:跟CreateProcess~~ shellExecute跟CreateProcess可以直接 07/29 01:04
13F:→ TeemingVoid:我猜你这样的结果可能一样,视窗焦点还是会被抢走 :) 07/29 01:05
14F:→ yeahhey:设定ShowWindowCommands(与启动同一行指令下设定) 07/29 01:05
15F:→ yeahhey:你这样一讲我也觉得 那两种内部运作应该也跟你的一样= = 07/29 01:06
16F:→ yeahhey:我开个youtube测测看会不会跳掉好了= = 07/29 01:07
17F:→ TeemingVoid:以前我曾用过 Sendkeys.Send("+{Tab}"); // Alt + Tab 07/29 01:07
18F:→ TeemingVoid:但是效果并不好... 07/29 01:08
19F:推 yeahhey:youtube全萤幕看起来没影响..kmp全萤幕会突然跳出 07/29 01:10
20F:→ TeemingVoid:隐藏视窗自然释出焦点,比较自然,你再试试罗!晚安!^^ 07/29 01:10
21F:→ yeahhey:跳出最下排的程式缩图= =..所以内部运作应该跟写法你一样! 07/29 01:11
22F:→ yeahhey:嗯嗯感谢你~~ 07/29 01:11