zoukankan      html  css  js  c++  java
  • C# WPF 窗体传递消息

     对于存在窗体的WPF程序(或者说,起码在任务栏上有个图标,即ShowInTaskbar = true),互相传递消息是很容易的。

    步骤:

    1,寻找窗体的句柄

    2,运用windows API: SendMessage或PostMessage

    3,目标窗体收到消息

    这里的代码,展示了一个APP不希望多开所以在启动时检查是否存在一个已经运行的进程。如果进程已经存在,则给对方发送消息并结束自身。

    1.判断/获取已经运行的实例

           /// <summary>
            /// 获取当前exe文件的是否已经在电脑上运行了一个实例,如果是,则返回那个实例的Process;如果否,就返回null;
            /// 如果有窗体,可以通过process.MainWindowHandle获取窗体的句柄,如果没窗体(ShowInTaskbar = false),则句柄为空
            /// </summary>
            public static Process GetCurrentExeProcess()
            {
                Process targetProcess = null;
    
                Process currentProcess = Process.GetCurrentProcess();
                string exeName = string.Format("{0}.exe", currentProcess.ProcessName);
                //PTZ.Tracer.AppLog.Info("$$$$$Get Current Process Successfully, current process exe: {0}", exeName);
    
                try
                {
                    Process[] aryProcess = Process.GetProcessesByName(currentProcess.ProcessName);
    
                    //PTZ.Tracer.AppLog.Info("$$$$$Get aryProcess Successfully, aryProcess count: {0}", aryProcess.Count());
                    foreach (Process process in aryProcess)
                    {
                        if (process.Id != currentProcess.Id && process.ProcessName == currentProcess.ProcessName)
                        {
                            targetProcess = process;
                            //PTZ.Tracer.AppLog.Info("$$$$$Get MainWindowHandle Successfully, hWnd: {0}", hWnd);
                            break;
                        }
                    }
                }
                catch (System.PlatformNotSupportedException pEx)
                {
                    //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", pEx);
                }
                catch (System.InvalidOperationException iEx)
                {
                    //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", iEx);
                }
                catch (System.ComponentModel.Win32Exception win32Ex)
                {
                    //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", win32Ex);
                }
    
                return targetProcess;
            }

    但是这个方法在某些奇怪权限设置的电脑上会遭遇UnauthorizedException,所以,如果只是想获取窗体句柄的话,还可以将上述方法的Try & Catch部分换成下面的代码:

                try
                {
                    string wmiQueryString = string.Format("SELECT ProcessId, Handle,ExecutablePath,Name FROM Win32_Process WHERE ProcessId != {0} AND Name = '{1}'", currentProcess.Id, exeName);
                    using (var searcher = new ManagementObjectSearcher(wmiQueryString))
                    {
                        using (var results = searcher.Get())
                        {
                            ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
                            if (mo != null)
                            {
                                string s = (string)mo["ExecutablePath"];
                                string handleStr = (string)mo["Handle"];
                                string sss = (string)mo["Name"];
                                Tracing.Trace.Information("¥*¥ManagementObjectSearcher, name: {0} Handle: {1} Path: {2}", sss, handleStr, s);
    
                                int handle = int.Parse(handleStr);
                                Process p = Process.GetProcessById(handle);
                                hWnd = p.MainWindowHandle;
                                isRunExist = true;
                                Tracing.Trace.Information("¥*¥ManagementObjectSearcher, hWnd: {0}", hWnd);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Tracing.Trace.Error("ManagementObjectSearcher exception:", e);
                }

    2.注册WindowsAPI

            #region Dll Imports
    
            [DllImport("user32.dll")]
            static extern IntPtr PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
    
            public const uint WM_APP = 0x9112;////0x8001~0xBFFF,随意#endregion Dll Imports

    3.修改App.OnStartup方法

    当程序启动,就需要检测实例。如已有实例运行,则发送消息;如没有,则继续正常运行。所以我们需要修改Appxaml.cs的OnStartup方法:

    
    
    protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
    
                Process targetProcess = SingleExeHelper.GetCurrentExeProcess();
    
                if (targetProcess!=null)//Software has been running...
                {
    //currentHandle通过targetProcess.MainWindowHandle得到
                    PostMessage(currentHandle,WM_APP, IntPtr.Zero, IntPtr.Zero);
                    Environment.Exit(0);//Software has been running, close this
                }
                else
                {
                    //do nothing
                }
            }
    
    
    
     

    4.主窗体监听消息:

           protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                ((HwndSource)PresentationSource.FromVisual(this)).AddHook(myHook);
    
                //HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
                //source.AddHook(new HwndSourceHook(myHook));
            }
    
            private IntPtr myHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                int m = (int)App.WM_APP;
                if (msg == m)
                {
                    System.Windows.MessageBox.Show("haha");
                }
                return IntPtr.Zero;
            }
  • 相关阅读:
    PHP程序员应当如何保持与时俱进?
    使用validator-api来验证spring-boot的参数
    运维不仅仅是懂Linux就行,还需要知道这些……
    Let's Encrypt: 为CentOS/RHEL 7下的nginx安装https支持-具体案例
    少年,是时候换种更优雅的方式部署你的php代码了
    为什么大多数培训机构还停留在只教ssh框架?
    设置spring-boot的logging
    ElasticSearch 429 Too Many Requests circuit_breaking_exception
    LINUX下永久添加静态路由
    Kafka集群管理和监控方案之Kafka Manager
  • 原文地址:https://www.cnblogs.com/AlvinLiang/p/6171088.html
Copyright © 2011-2022 走看看