[C#] Winform 同一支App裡面不同的視窗有不同的Process (2)
2017-06-14
接續上篇 Winform 同一支App裡面不同的視窗有不同的Process (1) ,我們繼續實作
接下來我們要製作一個PrcessAgent 來啟動 FormA , FormB ,因為他必須是一個MdiChild 所以我將它設定繼承Form ,當然如果你設計是要放在tabcontrol 裡面 可能你可以繼承usercontrol 等物件
ProcessAgent :
using System; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; namespace MutiProcessWindows { public partial class ProcessAgent : Form { #region Win32 API //https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms633541(v=vs.85).aspx [DllImport("user32.dll", SetLastError = true)] private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent); //https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms633534(v=vs.85).aspx [DllImport("user32.dll", SetLastError = true)] private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint); //https://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)] private static extern long SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong); #endregion #region Const //請參考 https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms633591(v=vs.85).aspx private const int GWL_STYLE = -16; private const int WS_VISIBLE = 0x10000000; #endregion public Process MProcess { get; set; } public ProcessAgent(string param) { //初始化Process ,並且設定執行自己exe 但是有帶參數 //param 可傳入 -forma, -formb MProcess = new Process() { SynchronizingObject = this, StartInfo = new ProcessStartInfo() { FileName = Application.ExecutablePath, Arguments = param } }; //啟動 MProcess.Start(); InitializeComponent(); } private void ProcessAgent_Load(object sender, EventArgs e) { //https://msdn.microsoft.com/zh-tw/library/system.diagnostics.process.waitforinputidle(v=vs.110).aspx //讓 Process 元件等候相關聯處理序進入閒置狀態。 MProcess.WaitForInputIdle(); while (!MProcess.HasExited && MProcess.MainWindowHandle == IntPtr.Zero) { Application.DoEvents(); Thread.Sleep(100); } //取得或設定是否應該在處理序終止時引發事件 MProcess.EnableRaisingEvents = true; //設定裡面的視窗被關掉時,此中介曾的ProceeAgent 所以要處理的 MProcess.Exited += M_Process_Exited; var handle = MProcess.MainWindowHandle; //將發動的handle 爸爸設成此中介層 SetParent(handle, this.Handle); //設定該發動handle(視窗) 顯示樣式 SetWindowLong(handle, GWL_STYLE, WS_VISIBLE); //移動至相關位置 MoveWindow(handle, 0, 0, (this.MdiParent as Form).Width, (this.MdiParent as Form).Height, true); } private void M_Process_Exited(object sender, EventArgs e) { //當然就是把自己關掉 this.Close(); } } }
這裡面我都寫上註解跟加上參考的網址,基本上流程是爸爸(Form1) 產生一個新的ProcssAgent(Form),但是這Form 只是一個中介層,他將啟動自己因為帶參數的關係所以用一個Process 啟動了FormA 之後呼叫Win32 把FormA handler的爸爸設成自己(ProcessAgent),因為 Prorcess隸屬於Form1的並且設定為Mdi Child 而做到此效果,Form1 呼叫 FormA 的 Code :
var processAgent = new ProcessAgent("-forma"); processAgent.MdiParent = this; processAgent.Show();
之後我故意在FormA 裡面製作一個Exception ,按下結束後回復到只有Form1的狀態,並非整個程式都被結束,大致上這案例寫到這邊結束,如果有不懂的下面有原始碼提供。
這邊因為專案要用到所以那時候參考的文件很多,這邊因為遺失所以都沒有整理起來參考到那些大大的,但是可以確定的是蹂躪哥幫我很多忙
這邊是他的網站 : http://larrynung.github.io/2013/11/06/bf1439a5-abbc-4b6e-896a-0b115119f3e7/ 這篇給我幫助也很大,很值得參考一下。
soruce : https://github.com/donma/MutiProcessWindows