对于存在窗体的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();//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;
}

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. [luogu_U15116]珈百璃堕落的开始

    https://www.zybuluo.com/ysner/note/1239458 题面 给定\(n\)个二元组\((x,y)\),问有多少种方案,使得选出其中几个后,\(\sum x=\sum y ...

  2. JSP-Runoob:JSP 点击量统计

    ylbtech-JSP-Runoob:JSP 点击量统计 1.返回顶部 1. JSP 点击量统计 有时候我们需要知道某个页面被访问的次数,这时我们就需要在页面上添加页面统计器,页面访问的统计一般在用户 ...

  3. 为什么要使用XHTML?

    XHTML 是什么? XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup Language). XHTML 的目标是取代 HTML. XHTML 与 HTML ...

  4. 56. EditorGridPanel和渲染器renderer的使用

    转自:https://blog.csdn.net/chenkangwan/article/details/4748716?utm_source=blogxgwz6 1. 在EditorGriddPan ...

  5. jsp jquery js 的基本路径获取

    引子:js中需要当前页面的基础路径,获取不到request,可以通过如下方法来解决!   1.jsp基础路径,在jsp头部加上,获取基础路径http://localhost:8080/project/ ...

  6. 2017北京国庆刷题Day1 morning T2

    T2火柴棒 (stick) Time Limit:1000ms   Memory Limit:128MB 题目描述 众所周知的是,火柴棒可以拼成各种各样的数字.具体可以看下图: 通过2根火柴棒可以拼出 ...

  7. codevs1005生日礼物(dfs)

    1005 生日礼物  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 9月12日是小松的朋友小寒的生日.小松知道小寒特别 ...

  8. Unity基本操作

    主要内容: C#学习 Unity项目 打砖块:BreakBricks Unity操作 Unity操作: 调试 碰撞体 触发器 视角 键盘视角平移 光照贴图 游戏对象Gameobject 访问对象 实体 ...

  9. mysql select 操作优先级

    单表查询操作 select filed1,filed2... form table where ... group by ... having .... order by ... limit ... ...

  10. 【洛谷4219】[BJOI2014]大融合(线段树分治)

    题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...