这几天,在公司里很是清闲,OJT(On Job Training)的日子确实还是挺自在的。唯一让人纠结的是,给你一片日文文档让你看。这下可把我害苦了,缺胳膊掉腿儿的中国字,我哪里看得懂啊??
所以这几天,总是Google Translate陪伴着我。可是每次总不能老是打开IE输入网址去翻译吧?太过于繁琐的工作,还是写个小工具吧!终究是因为自己比较懒而已。
打开Visual Studio 2010,公司可都是正版啊!建立个项目,程序本省很简单。与那里就是拖个WebBrowse控件,将Google Translate网址加进去就可以了。可谁知,接憧而至的麻烦不是这个~~而是下面这些:
1.实现最小化到托盘(这点notifyIcon控件可以轻松实现)
2.托盘菜单控制(这点ContextMenu控件也可以轻松实现)
3.禁止程序重复启动,即多次点击exe文件,只允许在系统里保留一个(这个就稍微麻烦点了,但是Google一下也不难解决)
4.多次点击运行exe文件后,将已经最小化到托盘的窗体激活到桌面上(这就是难点所在了)
前面都相对简单就不讲了,着重讲一下第3,4点。之所以不容易,是因为我Baidu,Google了一天都没有找到真正的解决方案,最后自己各种测试才成功的。
重点是这个:
获取后台窗体句柄时要使用 User32.dll中的FindWindow函数而非.Net框架中Process.GetProcessesByName(XXX).如果采用后者,程序在前台和隐藏后获取的窗体句柄是不同的两个值,我也不清楚为什么??
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.Threading; using System.Diagnostics; using System.Runtime.InteropServices; using System.Reflection; namespace GTranslate { //static class Program //{ // /// <summary> // /// The main entry point for the application. // /// </summary> // //[STAThread] // //static void Main() // //{ // // Application.EnableVisualStyles(); // // Application.SetCompatibleTextRenderingDefault(false); // // Application.Run(new Main()); // //} // private const int WS_SHOWSTATE = 9;//用当前的大小和位置显示一个窗口,不改变活动窗口 // [STAThread] // static void Main() // { // bool createdNew; // //系统能够识别有名称的互斥,因此可以使用它禁止应用程序启动两次 // //第二个参数可以设置为产品的名称:Application.ProductName // //每次启动应用程序,都会验证名称为SingletonWinAppMutex的互斥是否存在 // Mutex mutex = new Mutex(false, "GTranslate", out createdNew); // //如果已运行,则在前端显示 // //createdNew == false,说明程序已运行 // if (!createdNew) // { // Process instance = GetExistProcess(); // if (instance != null) // { // //MessageBox.Show("程序已经运行,进程名字:"+instance.ProcessName, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); // SetForegroud(instance); // Application.Exit(); // //Environment.Exit(0); // return; // } // } // Application.EnableVisualStyles(); // Application.SetCompatibleTextRenderingDefault(false); // Application.Run(new Main()); // } // /* // * 查看程序是否已经运行 // */ // private static Process GetExistProcess() // { // Process currentProcess = Process.GetCurrentProcess(); // foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName)) // { // //MessageBox.Show(currentProcess.ProcessName.ToString()); // if ((process.Id != currentProcess.Id) && (Assembly.GetExecutingAssembly().Location == currentProcess.MainModule.FileName)) // { // return process; // } // } // return null; // } // private static void SetForegroud(Process instance) // { // IntPtr mainFormHandle = instance.MainWindowHandle; // if (mainFormHandle != IntPtr.Zero) // { // //PostMessage(mainFormHandle); // //instance.CloseMainWindow(); // ShowWindowAsync(mainFormHandle, WS_SHOWSTATE); // ShowWindow(mainFormHandle, WS_SHOWSTATE); // //Control.FromHandle(mainFormHandle).Show(); // SwitchToThisWindow(instance.MainWindowHandle, true); // MessageBox.Show(mainFormHandle.ToString() + instance.MainWindowTitle); // SetForegroundWindow(mainFormHandle); // } // } // [DllImport("User32.dll")] // private static extern bool SetForegroundWindow(IntPtr hWnd); // [DllImport("User32.dll")] // private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); // [DllImport("user32.dll ", SetLastError = true)] // static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); // [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)] // private static extern int ShowWindow(IntPtr hwnd, int nCmdShow); //} static class Program { [DllImport("User32.dll")] private static extern bool ShowWindowAsync(int hWnd, int cmdShow); [DllImport("User32.dll", EntryPoint = "FindWindow")] private static extern int FindWindow(string lpClassName, string lpWindowName); [DllImport("User32")] static extern int SetForegroundWindow(int hwnd); private const int SW_NORMAL = 1; //正常弹出窗体 [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Process currentProcess = Process.GetCurrentProcess(); //判断程序是否已经启动 Mutex mutex = new Mutex(false, "GTranslate"); bool Running = !mutex.WaitOne(0, false); if (!Running) { Application.Run(new Main()); } else { //MessageBox.Show("程序已经运行" + Process.GetProcessesByName(currentProcess.ProcessName)[0].MainWindowTitle, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); int WINDOW_HANDLER = FindWindow(null, "Google Translate V 1.0 BY: Z.A.CHEN"); //程序标题或类名二选1 if (WINDOW_HANDLER > 0) { //MessageBox.Show(WINDOW_HANDLER.ToString()); ShowWindowAsync(WINDOW_HANDLER, SW_NORMAL); SetForegroundWindow(WINDOW_HANDLER); } Environment.Exit(0); } } } } |
上面,注释掉的就是不行的方法,没注释掉的就是正常使用的方法。可以防止多次运行程序,并且第二次运行时,激活已在托盘的原程序。
如有其它什么问题,可以联系me[at]chenzhiguo.cn