最近在写一款软件数组
软件是用来接收其余程序传递过来的命令行,并造成列表并发
大概的最终效果就像下图同样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
作完这些咱们想要的效果就彻底实现了,每次咱们的程序被运行都只会有一个窗口,而且全部的数据会汇总在这里
以上文章都乃小生的我的看法,可能会有小的错误或者更好的方法来实现.也但愿你们能评论出来让我学习
另外,但愿有会自绘列表中带有按钮的大大们,能够指导一下小生