winform 将untiy程序嵌入到一个panel里

核心脚本

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;namespace SimulationTraining
{public class ExetowinformClass//将应用程序嵌入winform {EventHandler appIdleEvent = null;//这个事件是程序处于空闲时触发 这里用于出发当程序加载完成后要做的事public Form ParentForm = null;string strGUID = "";#region 属性//标识内嵌程序是否已经启动public Process m_AppProcess = null;public bool IsStarted { get { return (this.m_AppProcess != null); } }#endregion 属性public ExetowinformClass(string Titlestr){appIdleEvent = new EventHandler(Application_Idle);strGUID = Titlestr;}//将属性AppFilename指向的应用程序打开并嵌入此容器public IntPtr Start(string FileNameStr, string arg){if (m_AppProcess != null){Stop();}try{ProcessStartInfo info = new ProcessStartInfo(FileNameStr);info.UseShellExecute = true;info.WindowStyle = ProcessWindowStyle.Minimized;info.Arguments = arg;m_AppProcess = System.Diagnostics.Process.Start(info);m_AppProcess.WaitForInputIdle();Application.Idle += appIdleEvent;}catch{if (m_AppProcess != null){if (!m_AppProcess.HasExited) m_AppProcess.Kill();m_AppProcess = null;}}return m_AppProcess.Handle;}//程序加载完成时要做的事  private void Application_Idle(object sender, EventArgs e){if (this.m_AppProcess == null || this.m_AppProcess.HasExited){this.m_AppProcess = null;Application.Idle -= appIdleEvent;return;}//Thread.Sleep(300); //这里加阻塞,时间可以大些Application.DoEvents();if (m_AppProcess.MainWindowHandle == IntPtr.Zero) return;Application.Idle -= appIdleEvent;//EmbedProcess(panel_play);}//将属性AppFilename指向的应用程序关闭public void Stop(){if (m_AppProcess != null){try{if (!m_AppProcess.HasExited)m_AppProcess.Kill();}catch (Exception){}m_AppProcess = null;}}//将指定的程序嵌入指定的控件  这一步会真正嵌入到winform里public void EmbedProcess(Control control){if (m_AppProcess == null || m_AppProcess.MainWindowHandle == IntPtr.Zero || control == null) return;try{//put it into this formShowWindow(m_AppProcess.MainWindowHandle, 0);//先将窗体隐藏,避免闪烁 SetParent(m_AppProcess.MainWindowHandle, control.Handle);}catch (Exception){ }try{//Remove border and whatnotSetWindowLong(new HandleRef(this, m_AppProcess.MainWindowHandle), GWL_STYLE, WS_VISIBLE);SendMessage(m_AppProcess.MainWindowHandle, WM_SETTEXT, IntPtr.Zero, strGUID);}catch (Exception){ }try{//Move the window to overlay it on this windowMoveWindow(m_AppProcess.MainWindowHandle, 0, 0, control.Width, control.Height, true);ShowWindow(m_AppProcess.MainWindowHandle, 3);//窗体显示并最大化}catch (Exception){ }}#region Win32 API[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = true,CallingConvention = CallingConvention.StdCall)]private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);[DllImport("user32.dll", SetLastError = true)]private static extern IntPtr FindWindow(string lpClassname, string lpWindowName);[DllImport("user32.dll", SetLastError = true)]private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]private static extern long GetWindowLong(IntPtr hwnd, int nIndex);[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, int dwNewLong);[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, int dwNewLong);public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong){if (IntPtr.Size == 4){return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);}return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);}[DllImport("user32.dll", SetLastError = true)]private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cy, long wFlags);[DllImport("user32.dll", SetLastError = true)]private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]private static extern bool PostMessage(IntPtr hwnd, uint Msg, uint wParam, uint lParam);[DllImport("user32.dll", SetLastError = true)]private static extern IntPtr GetParent(IntPtr hwnd);[DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);[DllImport("user32.dll", EntryPoint = "SendMessage")]private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);private const int SWP_NOOWNERZORDER = 0x200;private const int SWP_NOREDRAW = 0x8;private const int SWP_NOZORDER = 0x4;private const int SWP_SHOWWINDOW = 0x0040;private const int WS_EX_MDICHILD = 0x40;private const int SWP_FRAMECHANGED = 0x20;private const int SWP_NOACTIVATE = 0x10;private const int SWP_ASYNCWINDOWPOS = 0x40;private const int SWP_NOMOVE = 0x2;private const int SWP_NOSIZE = 0x1;private const int GWL_STYLE = (-16);private const int WS_VISIBLE = 0x10000000;private const int WM_CLOSE = 0x10;private const int WS_CHILD = 0x40000000;private const int SW_HIDE = 0;//{隐藏,并且任务栏也没有最小化图标}private const int SW_SHOWNORMAL = 1;//{用最近的大小和位置显示,激活}private const int SW_NORMAL = 1;//{同 SW_SHOWNORMAL}private const int SW_SHOWMINIMIZED = 2;//{最小化,激活}private const int SW_SHOWMAXIMIZED = 3;//{最大化,激活}private const int SW_MAXIMIZE = 3;//同 SW_SHOWMAXIMIZED}private const int SW_SHOWNOACTIVATE = 4;//{用最近的大小和位置显示,不激活}private const int SW_SHOW = 5;//{同SW_SHOWNORMAL}private const int SW_MINIMIZE = 6;//最小化,不激活private const int SW_SHOWMINNOACTIVE = 7;//同 SW_MINIMIZEprivate const int SW_SHOWNA = 8;//同 SW_SHOWNOACTIVATEprivate const int SW_RESTORE = 9;//同 SW_SHOWNORMALprivate const int SW_SHOWDEFAULT = 10;//同 SW_SHOWNORMALprivate const int SW_MAX = 10;//同 SW_SHOWNORMALconst int WM_SETTEXT = 0x000C;private const int WM_COPYDATA = 0x004A;//接收外部消息#endregion Win32 API}
}

使用方法:

//伪代码unityExeManager = new ExetowinformClass("");//参数是窗口的标题名unityExeManager.Start(exeFullPath, "");//参数2 启动参数
//我用了一个timer和ProcessBar,Untiy程序以最小化启动,等进度条wiform的processBar执行完成后,再将unity嵌入panel,并最大化Unity,这么做是为了不让用户看到madewithunity
//等timer执行完毕后嵌入panelunityExeManager.EmbedProcess(panel_play);//如果不需要进度条,那么可以直接在ExetowinformClass的Application_Idle方法里,取消注释//EmbedProcess(panel_play);来自动嵌入,注意这里panel_play只是演示用的参数,取消注释后需要稍微修改一下代码才能正确执行

//这一部分是timer的代码,仅供参考

  private void timer_UnityLoad_Tick(object sender, EventArgs e)//itmer事件{progressBar_UnityLoad.Value += 1;//timer每0.1秒执行一次,一秒钟为进度条填充10个单位,我们希望他能执行5-7秒if (progressBar_UnityLoad.Value == progressBar_UnityLoad.Maximum){panel_progressBar.Visible = false;//隐藏进度条面板GameApp.Interface.SendEvent(new OnEmbedExe_unityManager(playPanel));timer_UnityLoad.Stop();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1551916.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【有啥问啥】卡尔曼滤波(Kalman Filter):从噪声中提取信号的利器

卡尔曼滤波(Kalman Filter):从噪声中提取信号的利器 什么是卡尔曼滤波? 卡尔曼滤波(Kalman Filter)是一种高效的递归滤波器,专为处理包含噪声的线性动态系统而设计。它能够从一系列不完全且含…

网盘能否作为FTP替代产品?企业该如何进行FTP国产化替代?

近年来,信创的概念引入和高效实践落地让更多的行业企业自发性地进行国产化替代,目前信创国产化替代还多发生在操作系统和应用层面,软件工具等目前还在下一阶段规划,但很多企业未雨绸缪,已经在做调研和尝试。 FTP作为世…

大屏娱乐体验新标杆:海信发布全新一代AI电视

在金秋送爽的9月29日,海信以一场盛大的“BIG PLAN百吋风暴”秋季新品发布会,正式揭开了AI电视新时代的序幕。 作为本场发布会上最耀眼的明星,海信AI电视E7N系列凭借无与伦比的AI画质技术和极致性能,引领大屏娱乐体验迈入全新境界&…

仿真设计|基于51单片机的多模式音乐跑马灯

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现(protues8.7) 程序(Keil5) 全部内容 资料获取 具体实现功能 1、16个发光二极管做跑马灯,跑马灯有10种模式。 2、按键可以切换跑马灯模式&#xff0…

Java笔试02

在网络操作系统中,TCP和UDP是传输层中两个非常重要的协议。TCP提供的是面向连接的、可靠的端到端通信机制,因此TCP协议在注重数据安全的场景下获得了极为广泛的应用。 TCP采用了确认和重发机制来确保数据的可靠传输。 相较于UDP,TCP的优势在…

.NET CORE程序发布IIS后报错误 500.19

发布IIS后浏览时报错误500.19,同时配置文件web.config的路径中也存在问号“?”。 可能原因:没有安装运行时

无人机之编队控制篇

无人机编队控制是指无人机集群在执行任务过程中,如何形成并保持一定的几何构型,以适应平台性能、战场环境、战术任务等要求的控制技术。以下是对无人机编队控制的详细解析: 一、无人机编队控制的主要任务 无人机编队控制主要解决两个问题&a…

Linux 线程同步

前言 上一期我们介绍了线程互斥,并通过加锁解决了多线程并发访问下的数据不一致问题!本期我们来介绍一下同步问题! 目录 前言 一、线程同步 • 线程同步的引入 • 同步的概念 理解同步和饥饿问题 • 条件变量 理解条件变量 • 同步…

系列一、初始ElasticSearch

前言: 最近公司的业务有用到ElasticSearch,虽然说之前业余时间也自学过ElasticSearch技术,但是在公司实际的业务中开发中没有用过,再加上时间比较久远了,很多东西都忘记了,基于此我决定系统的重新学习一下这…

个人项目简单https服务配置

1.SSL简介 SSL证书是一种数字证书,由受信任的证书颁发机构(CA)颁发,用于在互联网通信中建立加密链接。SSL代表“安全套接层”,是用于在互联网上创建加密链接的协议。SSL证书的主要目的是确保数据传输的安全性和隐私性…

鸿蒙NEXT开发环境搭建(基于最新api12稳定版)

注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

PMP--三模--解题--51-60

文章目录 14.敏捷--每日站会--内容--• 上次站会以来我都完成了什么?• 从现在到下一次站会,我计划完成什么?• 我的障碍(或风险或问题)是什么?--每日站会能够同步与协调相关的活动。14.敏捷--Scrum板 Scru…

【Ubuntu】VMware中虚拟网卡与服务器网卡的绑定

文章目录 服务器网卡和VMware中虚拟网卡的绑定1.在本机上查看需要的网卡名称2.服务器本机设置固定ip3.打开VMware后,将虚拟网卡与本机真实网卡进行绑定。4.给routeOS分配4张网卡,如图所示:5.ubuntu1和ubuntu2只需分配vmnet0和vmnet8即可&…

《More Effective C++》的学习

引用与指针 没有所谓的null reference reference一定需要代表某个对象,所以C要求reference必须有初值。 QString &s; 使用reference可能比使用pointer更高效。 因为reference一定是有效的,而指针可能为空(需要多加一个判断&#xff0…

【PyTorch】图像目标检测

图像目标检测是什么 Object Detection 判断图像中目标的位置 目标检测两要素 分类:分类向量 [p0, …, pn]回归:回归边界框 [x1, y1, x2, y2] 模型如何完成目标检测 将3D张量映射到两个张量 分类张量:shape为 [N, c1]边界框张量&#xf…

索尼MDR-M1:超宽频的音频盛宴,打造沉浸式音乐体验

在音乐的世界里,每一次技术的突破都意味着全新的听觉体验。 索尼,作为音频技术的先锋,再次以其最新力作——MDR-M1封闭式监听耳机,引领了音乐界的新潮流。 这款耳机以其超宽频播放和卓越的隔音性能,为音乐爱好者和专…

深蕾半导体参加2024年度上海设计100+全球竞赛展览WDCC

展览介绍 WDCC2024 上海于2010年加入联合国教科文组织“创意城市网络”,定名为“设计之都”。“上海设计100”全球竞赛,遴选推广优秀设计案例,将“设计之都”的规划和愿景具体呈现。 ——展出时间、地点见文末—— 深蕾参展 深圳前海深蕾…

初识Linux · 进程等待

目录 前言: 进程等待是什么 为什么需要进程等待 进程等待都在做什么 前言: 通过上文的学习,我们了解了进程终止,知道终止是在干什么,终止的三种情况,以及有了退出码,错误码的概念&#xff…

Python | Leetcode Python题解之第448题找到所有数组中消失的数字

题目&#xff1a; 题解&#xff1a; class Solution:def findDisappearedNumbers(self, nums: List[int]) -> List[int]:n len(nums)for num in nums:x (num - 1) % nnums[x] nret [i 1 for i, num in enumerate(nums) if num < n]return ret

【RocketMQ】秒杀设计与实现

&#x1f3af; 导读&#xff1a;本文档详细探讨了高并发场景下的秒杀系统设计与优化策略&#xff0c;特别是如何在短时间内处理大量请求。文档分析了系统性能指标如QPS&#xff08;每秒查询率&#xff09;和TPS&#xff08;每秒事务数&#xff09;&#xff0c;并通过实例讲解了…