作者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
推 yeahhey:先感謝你!!我有個問題是 他這樣會有焦點變化嗎? 07/29 00:47
→ yeahhey:start後的瞬間 焦點還是會被啟動的程式奪去 在還回? 07/29 00:48
→ yeahhey:我原本想找看看有沒有函示可以直接設定不要搶走焦點= = 07/29 00:50
→ yeahhey:但最後也是找到你這邊提到的ShowWindowCommands! 07/29 00:52
→ TeemingVoid:一旦呼叫 Process.Start(),focus 就會被新視窗搶走, 07/29 01:00
推 yeahhey:會問有沒有焦點變化 主要是擔心某個使用中全螢幕的視窗 07/29 01:00
→ TeemingVoid:ShowWindow(..., Hide); 的作用在於隱藏新的視窗, 07/29 01:01
→ yeahhey:會因為focus改變而縮小或是瞬間縮小又切回來 07/29 01:01
→ TeemingVoid:這樣 focus 自然釋出。 07/29 01:02
→ yeahhey:因為Process.Start()會搶focus,我現在改用CreateProcess 07/29 01:03
→ yeahhey:外部程式的作法除了process,另外查到shellExecute 07/29 01:04
→ yeahhey:跟CreateProcess~~ shellExecute跟CreateProcess可以直接 07/29 01:04
→ TeemingVoid:我猜你這樣的結果可能一樣,視窗焦點還是會被搶走 :) 07/29 01:05
→ yeahhey:設定ShowWindowCommands(與啟動同一行指令下設定) 07/29 01:05
→ yeahhey:你這樣一講我也覺得 那兩種內部運作應該也跟你的一樣= = 07/29 01:06
→ yeahhey:我開個youtube測測看會不會跳掉好了= = 07/29 01:07
→ TeemingVoid:以前我曾用過 Sendkeys.Send("+{Tab}"); // Alt + Tab 07/29 01:07
→ TeemingVoid:但是效果並不好... 07/29 01:08
推 yeahhey:youtube全螢幕看起來沒影響..kmp全螢幕會突然跳出 07/29 01:10
→ TeemingVoid:隱藏視窗自然釋出焦點,比較自然,你再試試囉!晚安!^^ 07/29 01:10
→ yeahhey:跳出最下排的程式縮圖= =..所以內部運作應該跟寫法你一樣! 07/29 01:11
→ yeahhey:嗯嗯感謝你~~ 07/29 01:11