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

步骤:

1,寻找窗体的句柄

2,运用windows API: SendMessage或PostMessage

3,目标窗体收到消息

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

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

  1. /// <summary>
  2. /// 获取当前exe文件的是否已经在电脑上运行了一个实例,如果是,则返回那个实例的Process;如果否,就返回null;
  3. /// 如果有窗体,可以通过process.MainWindowHandle获取窗体的句柄,如果没窗体(ShowInTaskbar = false),则句柄为空
  4. /// </summary>
  5. public static Process GetCurrentExeProcess()
  6. {
  7. Process targetProcess = null;
  8.  
  9. Process currentProcess = Process.GetCurrentProcess();
  10. string exeName = string.Format("{0}.exe", currentProcess.ProcessName);
  11. //PTZ.Tracer.AppLog.Info("$$$$$Get Current Process Successfully, current process exe: {0}", exeName);
  12.  
  13. try
  14. {
  15. Process[] aryProcess = Process.GetProcessesByName(currentProcess.ProcessName);
  16.  
  17. //PTZ.Tracer.AppLog.Info("$$$$$Get aryProcess Successfully, aryProcess count: {0}", aryProcess.Count());
  18. foreach (Process process in aryProcess)
  19. {
  20. if (process.Id != currentProcess.Id && process.ProcessName == currentProcess.ProcessName)
  21. {
  22. targetProcess = process;
  23. //PTZ.Tracer.AppLog.Info("$$$$$Get MainWindowHandle Successfully, hWnd: {0}", hWnd);
  24. break;
  25. }
  26. }
  27. }
  28. catch (System.PlatformNotSupportedException pEx)
  29. {
  30. //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", pEx);
  31. }
  32. catch (System.InvalidOperationException iEx)
  33. {
  34. //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", iEx);
  35. }
  36. catch (System.ComponentModel.Win32Exception win32Ex)
  37. {
  38. //PTZ.Tracer.AppLog.Error("$$$$$GetCurrentWindowsInstanceHandle exception:", win32Ex);
  39. }
  40.  
  41. return targetProcess;
  42. }

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

  1. try
  2. {
  3. string wmiQueryString = string.Format("SELECT ProcessId, Handle,ExecutablePath,Name FROM Win32_Process WHERE ProcessId != {0} AND Name = '{1}'", currentProcess.Id, exeName);
  4. using (var searcher = new ManagementObjectSearcher(wmiQueryString))
  5. {
  6. using (var results = searcher.Get())
  7. {
  8. ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
  9. if (mo != null)
  10. {
  11. string s = (string)mo["ExecutablePath"];
  12. string handleStr = (string)mo["Handle"];
  13. string sss = (string)mo["Name"];
  14. Tracing.Trace.Information("¥*¥ManagementObjectSearcher, name: {0} Handle: {1} Path: {2}", sss, handleStr, s);
  15.  
  16. int handle = int.Parse(handleStr);
  17. Process p = Process.GetProcessById(handle);
  18. hWnd = p.MainWindowHandle;
  19. isRunExist = true;
  20. Tracing.Trace.Information("¥*¥ManagementObjectSearcher, hWnd: {0}", hWnd);
  21. }
  22. }
  23. }
  24. }
  25. catch (Exception e)
  26. {
  27. Tracing.Trace.Error("ManagementObjectSearcher exception:", e);
  28. }

2.注册WindowsAPI

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

3.修改App.OnStartup方法

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

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

4.主窗体监听消息:

  1. protected override void OnSourceInitialized(EventArgs e)
  2. {
  3. base.OnSourceInitialized(e);
  4. ((HwndSource)PresentationSource.FromVisual(this)).AddHook(myHook);
  5.  
  6. //HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
  7. //source.AddHook(new HwndSourceHook(myHook));
  8. }
  9.  
  10. private IntPtr myHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  11. {
  12. int m = (int)App.WM_APP;
  13. if (msg == m)
  14. {
  15. System.Windows.MessageBox.Show("haha");
  16. }
  17. return IntPtr.Zero;
  18. }

C# WPF 窗体传递消息的更多相关文章

  1. C# WPF 无窗体传递消息

    WPF如果存在窗体(或至少,在任务栏有图标显示),互相传递消息是很容易的. 寻找目标窗体句柄->WindowsAPI SendMessage/PostMessage->目标窗体AddHoo ...

  2. WPF自学入门(八)WPF窗体之间的交互

    今天我们一起来看一下WPF窗体之间的交互-窗体之间的传值.有两个窗体,一个是父窗体,一个是子窗体.要将父窗体的文本框中的值传递给子窗体中的控件.我们该怎么实现? 接下来我们一起来实现窗体之间的传值,在 ...

  3. javascript跨域传递消息 / 服务器实时推送总结

    参考文档,下面有转载[非常好的两篇文章]: http://www.cnblogs.com/loveis715/p/4592246.html [跨源的各种方法总结] http://kb.cnblogs. ...

  4. C# WPF QQ新消息托盘悬浮窗效果实现

    原文:C# WPF QQ新消息托盘悬浮窗效果实现 今天在做一个项目的时候需要这么一个效果,但是网上找了一会发现并没有现成的给我参考(复制),但是呢,我千(到)辛(处)万(抄)苦(袭)想(复)破(制)头 ...

  5. Android消息传递之组件间传递消息

    前言: 上篇学习总结了Android通过Handler消息机制实现了工作线程与UI线程之间的通信,今天来学习一下如何实现组件之间的通信.本文依然是为学习EventBus做铺垫,有对比才能进步,今天主要 ...

  6. WinForm 与WPF 窗体之间的想到调用

    先放置一个容器控件,并设计 好WinForm(或WPF)窗口 winform 调用 wpf ElementHost el = new ElementHost(); el.Dock = DockStyl ...

  7. 关于WinForm引用WPF窗体---在Winform窗体中使用WPF控件

    项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...

  8. WPF处理Windows消息

    WPF中处理消息首先要获取窗口句柄,创建HwndSource对象 通过HwndSource对象添加消息处理回调函数. HwndSource类: 实现其自己的窗口过程. 创建窗口之后使用 AddHook ...

  9. 关于WinForm引用WPF窗体

    项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...

随机推荐

  1. (函数即服务)Faas的现状与未来

    刚看到jolestar一位从法律转行程序员的前辈写了一篇Faas现状与未来的文章,里面很多观点都很有启发,或许正如他说的那样,由于Faas能较好的解决资源利用率和开发效率问题,2018年Faas将变得 ...

  2. 看看 SDWebImage内部基本实现过程

    一.实现流程 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 ...

  3. PCB SQL SERVER 发送邮件(异步改同步)

    采用SQL SERVER发送邮件是队列方式(异步)发送邮件,所以在我们执行发送邮件后,无法立即获取到邮件是否发送成功了,而在PCB行业实际应用中是需要立即获取发送邮件是否成功的状态来决定下一步逻辑该如 ...

  4. js的45个技巧

    JavaScript是一个绝冠全球的编程语言,可用于Web开发.移动应用开发(PhoneGap.Appcelerator).服务器端开发(Node.js和Wakanda)等等.JavaScript还是 ...

  5. 如何自学编程,零基础适合学习Java或者Web前端吗,非科班的能学java吗?

    很多人都会选择自学Java或者前端,相信有在校的大学生,有正在上班想转行的,也有已经在自学的.下面通过几个问题我来给大家分析学习编程的难易程度. 编程是什么? 通俗的理解,编程就是编写程序,哪什么是程 ...

  6. P1968 美元汇率

    题目背景 此处省略maxint+1个数 题目描述 在以后的若干天里戴维将学习美元与德国马克的汇率.编写程序帮助戴维何时应买或卖马克或美元,使他从100美元开始,最后能获得最高可能的价值. 输入输出格式 ...

  7. SAS学习笔记之《SAS编程与数据挖掘商业案例》(5)SAS宏语言、SQL过程

    SAS学习笔记之<SAS编程与数据挖掘商业案例>(5)SAS宏语言.SQL过程 1. 一个SAS程序可能包含一个或几个语言成分: DATA步或PROC步 全程语句 SAS组件语言(SCL) ...

  8. Java_Web三大框架之Hibernate+jsp+selvect+HQL查询数据

    俗话说:"好记性不如烂笔头".本人学习Hibernate也有一个星期了,对Hibernate也有一个初步的了解.下面对Hibernate显示数据做个笔记,使用租房系统的Hibern ...

  9. HDU_1079_思维题

    Calendar Game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  10. 四次挥手与tcp标志位

    鉴于tcp的标志位可以同时置位,在相应端无数据传输时,四次握手可以用三次报文完成.