目前最通用的客户端调用3D的方式,就是WPF程序通过Process启动Unity3D的exe进程,直接上代码:

 //开启3D进程
internal void Create3DProcess(string processUri)
{
if (string.IsNullOrWhiteSpace(processUri) || !File.Exists(processUri))
{
return;
//throw new Exception("Unable to find Unity window,File was not exit");
}
var handle = Panel.Handle;
this.Dispatcher.InvokeAsync(() =>
{
try
{ //判断当前要启动的进程是否还在启动,如果还在启动,先关闭进程再创建进程
CheckProcessByName(processUri); if (process != null)
{
process.Close();
} process = new Process();
process.StartInfo.Arguments = "-parentHWND " + handle.ToInt32() + " " + Environment.CommandLine + " " + Unity3DProcessArges.Replace("AutoWidth",Panel.Width.ToString()).Replace("AutoHeight",Panel.Height.ToString());
process.StartInfo.FileName = processUri;
process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(processUri);
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.WaitForInputIdle();
EnumChildWindows(handle, WindowEnum, IntPtr.Zero);
}
catch (Exception ex)
{
LogHelper.Error(ex.ToString());
}
}); } [DllImport("user32.dll")]
public static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);

启动进程后,在做WPF应用上的交互,比如点击了WPF上的一个按钮,当前的鼠标的焦点会被WPF程序捕获到,如果3D程序进程没有做键盘或者鼠标焦点的获取,就会出现键盘和鼠标事件无法触发!

大概的解决思路:在WPF程序上,获取鼠标滑动的窗体的句柄,判断当前鼠标停留的窗体的句柄如果跟3D程序的窗体句柄一样,则激活3D窗体程序(需要用到user32的API),直接上代码:

 1    private IntPtr unityHWND = IntPtr.Zero; //3D窗体的句柄
2 /// <summary>
3 /// 发送消息,触发激活当前窗体
4 /// </summary>
5 internal void ActiveWindows()
6 {
7
8 if (unityHWND!=IntPtr.Zero)
9 {
10 SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
11 }
12 }
13
14 /// <summary>
15 /// 解除激活窗体
16 /// </summary>
17 internal void UnActiveWindows()
18 {
19 if (unityHWND!=IntPtr.Zero)
20 {
21 SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
22 }
23 }
24
25
26 //检测窗体句柄
27 private void CheckWindowsActive()
28 {
29 actionTime = new DispatcherTimer();
30 actionTime.Interval = new TimeSpan(TimeSpan.TicksPerMillisecond * 300);
31 actionTime.Tick += ActionTime_Tick;
32 actionTime.Start();
33 }
34
35 IntPtr lastIntprt = IntPtr.Zero; //获取上一次的鼠标指向的句柄,为了指向相同的位置,避免重复给窗体发送消息
36 private void ActionTime_Tick(object sender, EventArgs e)
37 {
38 try
39 {
40 POINT pOINT;
41 bool isSuccess = GetCursorPos(out pOINT);
42 var intptr = WindowFromPoint(pOINT);
43 if (isSuccess && unityHWND != IntPtr.Zero && lastIntprt != intptr)//判断当前句柄跟上一次的句柄是否一样,如果一样就不再触发
44 {
45 if (intptr == unityHWND)
46 {
47 ActiveWindows();
48 }
49 else
50 {
51 UnActiveWindows();
52 }
53
54 }
55 lastIntprt = intptr;
56
57 }
58 catch (Exception ex)
59 {
60 LogHelper.Error(ex.ToString());
61 }
62 }
63
64 [DllImport("user32.dll", CharSet = CharSet.Auto)]
65 public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
66
67 [DllImport("user32.dll", CharSet = CharSet.Auto)]
68 public static extern bool GetCursorPos(out POINT pt);
69
70 [DllImport("user32.dll")]
71 public static extern IntPtr WindowFromPoint(POINT Point);
72
73 public struct POINT
74 {
75 public int X;
76 public int Y;
77 public POINT(int x, int y)
78 {
79 this.X = x;
80 this.Y = y;
81 }
82 }

WPF嵌入Unity3D之后,unity3D程序的键盘和鼠标事件无法触发(3D程序的焦点无法激活)的解决方案的更多相关文章

  1. WPF之路-键盘与鼠标事件 - 简书

    原文:WPF之路-键盘与鼠标事件 - 简书 键盘事件 事件类型分为以下几个类型 生命周期事件:在元素加载与卸载的时候发生 鼠标事件:鼠标动作 键盘事件:键盘动作 手写笔事件:适用于win7以上的系统 ...

  2. winform中键盘和鼠标事件的捕捉和重写(转)

    在 编写winform应用程序时,有时需要无论在哪个控件获取焦点时,对某一个键盘输入或者鼠标事件都进行同样的操作.比如编写一个处理图片的应用程序时, 希望无论当前哪个控件获得焦点,当用户按上.下.左. ...

  3. winform中键盘和鼠标事件的捕捉和重写

    在编写winform应用程序时,有时需要无论在哪个控件获取焦点时,对某一个键盘输入或者鼠标事件都进行同样的操作.比如编写一个处理图片的应用程序时,希望无论当前哪个控件获得焦点,当用户按上.下.左.右键 ...

  4. cocos2d-x 键盘和鼠标事件

    出了菜单可以响应用户事件外,cocos2d中的层(Layer)也可以响应事件.层能够自动响应窗口事件,这些事件主要是键盘和鼠标事件,cocos2d中事件处理是通过Pyglet的事件处理完成的. 1.键 ...

  5. 第六章 Windows应用程序对键盘与鼠标的响应 P121 6-8

    基于键盘与鼠标应用的程序设计 一.实验目的 1.掌握键盘与鼠标在应用程序中的消息响应机制.   二.实验内容及步骤 实验任务 1.熟悉键盘的消息响应: 2.熟悉鼠标的消息响应: 实验内容 设计一个窗口 ...

  6. Selenium2+python自动化12-操作元素(键盘和鼠标事件)

    前言 在前面的几篇中重点介绍了一些元素的到位方法,到位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...

  7. 自动化测试-8.selenium操作元素之键盘和鼠标事件

    前言 在前面的几篇中重点介绍了一些元素的定位方法,定位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...

  8. tkinter 对键盘和鼠标事件的处理

    鼠标事件 <ButtonPress-n> <Button-n> <n> 鼠标按钮n被按下,n为1左键,2中键,3右键 <ButtonRelease-n> ...

  9. C# 采用钩子捕获键盘和鼠标事件-验证是否处于无人操作状态

    原文地址:https://www.cnblogs.com/gc2013/p/4036414.html 全局抽象类定义 using System; using System.Collections.Ge ...

随机推荐

  1. 使用gitlab runner进行CI(三):使用sonarqube做c++的静态检查

    目录 1. gitlab-ci.yml的配置 1.1 几个基本概念 1.2 使用CI进行代码检查demo 2. Sonarqube安装和配置 2.1 Sonarqube安装 2.2 数据库配置 2.3 ...

  2. MacOS下Java与JDK关系与相关路径

    MacOS下Java与JDK关系与相关路径 macOS下的Java与JDK的路径曾经困扰过我一段时间,今天稍有些忘记,故记下笔记,整理一下.Java与JDK的关系不在本文笔记之内,Javaer常识. ...

  3. res目录下的结构

    目录 res目录下的结构 drawable开头的文件夹 mipmap开头的文件夹 values开头的文件夹 layout文件夹 使用res目录下的资源 res目录下的结构 如果你展开res目录看一下, ...

  4. PublishFolderCleaner 让你的 dotnet 应用发布文件夹更加整洁

    大家都知道,在 dotnet 发布时,将会在输出的 publish 文件夹包含所需的依赖.在 .NET Core 开始,引入了 AppHost 的概念,即使是单个程序集,也需要独立的 Exe 可执行文 ...

  5. Kali Linux修改root密码

    今天在官网下载了一个Kali虚拟机的压缩包, 解压缩后直接在VM中打开,点了好多次打开发现都打不开,查了一下说是没有关闭共享虚拟机,于是操作了一番: 编辑→首选项→共享虚拟机→选择禁用. 操作完之后果 ...

  6. 【Java虚拟机3】类加载器

    前言 Java虚拟机设计团队有意把类加载阶段中的"通过一个类的全限定名来获取描述该类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类. ...

  7. 【UE4 调试】C++ 几种编译方法和小技巧

    编译方法 Visual Studio 2019 编译 默认编译 UnrealVS 快速编译 Editor 编译 一般 vs 编译完后,Editor会跟着热编译(有声音) 如果发现编译后代码没更新到Ed ...

  8. [Beta]the Agiles Scrum Meeting 11

    会议时间:2020.5.26 21:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 帮助解决技术问题 tq 完成评测机新增评测指标 评测部分增加更多评测指标 wjx ...

  9. 2021.8.15考试总结[NOIP模拟40]

    T1 送花 线段树.枚举右端点,线段树记录左端点对应的值. 每次对当前颜色上上次出现的位置到上次出现的位置区间减,上次出现的位置到当前位置区间加. $code:$ 1 #include<bits ...

  10. 万维网www与HTTP协议

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105901440 学习课程:<2019王道考研计算机网络> 学习目的 ...