WPF嵌入Unity3D之后,unity3D程序的键盘和鼠标事件无法触发(3D程序的焦点无法激活)的解决方案
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了WPF嵌入Unity3D之后,unity3D程序的键盘和鼠标事件无法触发(3D程序的焦点无法激活)的解决方案,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3208字,纯文字阅读大概需要5分钟。
内容图文
目前最通用的客户端调用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")] publicstaticexternbool 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> 5internalvoid ActiveWindows() 6 { 7 8if (unityHWND!=IntPtr.Zero) 9 { 10 SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero); 11 } 12 } 1314///<summary>15/// 解除激活窗体 16///</summary>17internalvoid UnActiveWindows() 18 { 19if (unityHWND!=IntPtr.Zero) 20 { 21 SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero); 22 } 23 } 242526//检测窗体句柄27privatevoid CheckWindowsActive() 28 { 29 actionTime = new DispatcherTimer(); 30 actionTime.Interval = new TimeSpan(TimeSpan.TicksPerMillisecond * 300); 31 actionTime.Tick += ActionTime_Tick; 32 actionTime.Start(); 33 } 3435 IntPtr lastIntprt = IntPtr.Zero; //获取上一次的鼠标指向的句柄,为了指向相同的位置,避免重复给窗体发送消息36privatevoid ActionTime_Tick(object sender, EventArgs e) 37 { 38try39 { 40 POINT pOINT; 41bool isSuccess = GetCursorPos(out pOINT); 42var intptr = WindowFromPoint(pOINT); 43if (isSuccess && unityHWND != IntPtr.Zero && lastIntprt != intptr)//判断当前句柄跟上一次的句柄是否一样,如果一样就不再触发44 { 45if (intptr == unityHWND) 46 { 47 ActiveWindows(); 48 } 49else50 { 51 UnActiveWindows(); 52 } 5354 } 55 lastIntprt = intptr; 5657 } 58catch (Exception ex) 59 { 60 LogHelper.Error(ex.ToString()); 61 } 62 } 6364 [DllImport("user32.dll", CharSet = CharSet.Auto)] 65publicstaticextern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 6667 [DllImport("user32.dll", CharSet = CharSet.Auto)] 68publicstaticexternbool GetCursorPos(out POINT pt); 6970 [DllImport("user32.dll")] 71publicstaticextern IntPtr WindowFromPoint(POINT Point); 7273publicstruct POINT 74 { 75publicint X; 76publicint Y; 77public POINT(int x, int y) 78 { 79this.X = x; 80this.Y = y; 81 } 82 }
原文:https://www.cnblogs.com/xiao-wu/p/14876639.html
内容总结
以上是互联网集市为您收集整理的WPF嵌入Unity3D之后,unity3D程序的键盘和鼠标事件无法触发(3D程序的焦点无法激活)的解决方案全部内容,希望文章能够帮你解决WPF嵌入Unity3D之后,unity3D程序的键盘和鼠标事件无法触发(3D程序的焦点无法激活)的解决方案所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。