最近在寫一款軟件數組
軟件是用來接收其餘程序傳遞過來的命令行,並造成列表併發
大概的最終效果就像下圖同樣ide
本來爲了程序美觀是打算用listbox自繪列表,字和圖片都繪製好了發現本身不會繪製按鈕學習
因此最終採用了datagridview控件,這個直接就能夠插入按鈕,就省去了那些問題,不過界面美觀就一直是遺憾了(但願有界面方面的大牛能夠指導我!)測試
由於程序啓動的方式是被其餘程序啓動併發送的有命令行ui
因此,若是有多條消息默認狀況下會被打開多個程序,所以開始了以下的各類解決方法spa
1.命令行的讀取命令行
這個相對就比較簡單了,修改Program的Main方法code
[STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1(args)); }
這樣就實現了獲取命令行,命令行中間用空格隔開,最終程序獲得args文本數組orm
窗口新增獲取數組的初始化方法
public Form1(string[] args) { InitializeComponent(); try { //這裏是將args插入列表的操做 } catch (Exception) { } }
固然這些都是十分簡單的,網上隨手查閱就能找到
接下來是程序禁止重複運行,由於咱們想把列表顯示在一個窗口中,而不是每一個窗口都顯示一條數據
因此程序是不能夠被重複運行的.Program.cs新增代碼以下
#region 防止重複運行 public static Process RunningInstance() { Process current = Process.GetCurrentProcess(); Process[] processes = Process.GetProcessesByName(current.ProcessName); foreach (Process process in processes) { if (process.Id != current.Id) { if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName) { return process; } } } return null; } public static void HandleRunningInstance(Process instance) { ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); SetForegroundWindow(instance.MainWindowHandle); } [DllImport("User32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); [DllImport("User32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); private const int WS_SHOWNORMAL = 1; #endregion
新增以後再Main方法作判斷,而且若是已經存在打開的窗口的話,就激活打開的窗口
static void Main(string[] args) { Process instance = RunningInstance(); if (instance == null) { System.Windows.Forms.Application.EnableVisualStyles(); System.Windows.Forms.Application.DoEvents(); System.Windows.Forms.Application.Run(new Form1(args)); } else { HandleRunningInstance(instance); } }
作完這些,程序已經不能被重複運行了,再測試,新的問題又來了...程序沒有被屢次打開,可是一樣的,列表永遠只會有一條數據,不會被更新
新運行的程序收到的命令行沒能告知到舊的窗口,所以須要傳遞值到舊的窗口,這個方法也有不少,最終我採用的是SendMessage
新增代碼以下
#region 發送消息 const int WM_COPYDATA = 0x004A; [DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage(IntPtr hWnd, int msg, uint wParam, ref COPYDATASTRUCT lParam); [DllImport("User32.dll", EntryPoint = "FindWindow")] private static extern int FindWindow(string lpClassName, string lpWindowName); public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } #endregion
而後再封裝一個方法
static void Send(string[] args) { int WINDOW_HANDLER = FindWindow(null, @"這裏要改爲你的窗口標題,Form1的Text"); if (WINDOW_HANDLER != 0) { StringBuilder sb = new StringBuilder(); foreach (string item in args) { sb.Append(item + " "); } byte[] sarr = System.Text.Encoding.Default.GetBytes(sb.ToString()); int len = sarr.Length; COPYDATASTRUCT cds; cds.dwData = (IntPtr)100; cds.lpData = sb.ToString(); cds.cbData = len + 1; int sendRet = SendMessage((IntPtr)WINDOW_HANDLER, WM_COPYDATA, 0, ref cds); if (sendRet != 0) { MessageBox.Show("傳遞參數失敗!"); } } else{ MessageBox.Show("沒有發現舊窗口!"); } }
接下來從新改動一下Main方法
static void Main(string[] args) { Process instance = RunningInstance(); //若是不存在舊窗口 if (instance == null) { System.Windows.Forms.Application.EnableVisualStyles(); System.Windows.Forms.Application.DoEvents(); System.Windows.Forms.Application.Run(new Form1(args)); } else { //若是存在先激活 HandleRunningInstance(instance); //若是收到的有參數就傳遞,沒有就忽略 if (args.Length>0) { Send(args); } } }
這樣,發送參數的部分就完成了.還剩下最後一步,Form中接收傳遞過來的參數
在Form中新增以下代碼
#region 接收消息 protected override void DefWndProc(ref System.Windows.Forms.Message m) { const int WM_COPYDATA = 0x004A; switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT mystr = new COPYDATASTRUCT(); Type mytype = mystr.GetType(); mystr = (COPYDATASTRUCT)m.GetLParam(mytype); string[] s = mystr.lpData.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries); if (s.Length>0) { //這裏寫收到參數的狀況操做 //mystr.lpData爲實際收到的文本,能夠直接操做,我這裏分割爲數組來區分標題,網址等了 } break; default: base.DefWndProc(ref m); break; } } public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } #endregion
作完這些咱們想要的效果就徹底實現了,每次咱們的程序被運行都只會有一個窗口,而且全部的數據會彙總在這裏
以上文章都乃小生的我的看法,可能會有小的錯誤或者更好的方法來實現.也但願你們能評論出來讓我學習
另外,但願有會自繪列表中帶有按鈕的大大們,能夠指導一下小生