zoukankan      html  css  js  c++  java
  • 在Winform中屏蔽UnityWebPlayer的右键以及自带Logo解决方案整理

            根据项目的需要,对已经完成的Unity三维模型以及游戏要使用Winform进行包装,也就是使用Winform做一层外壳。因此在展示Unity的时候使用到了UnityWebPlayer这个插件,对于此插件就不多说了,无论是想把Unity嵌在网页中还是winform中都要使用到。

            网上很多资料是在Web中使用Unity的,很自然的把Unity发布成Web类型,在此如何在Web中使用Unity也就不多说了,重点是解决在winform中使用Unity出现的插件自带的右键问题以及Logo问题。

          一、winform中使用Unity

         在winform中使用Unity,同样是像网页形式把做好的Unity发布成Web类型,然后直接使用文件格式为.unity3d的文件。把Unity文件的路径赋值给UnityWebplayer的src属性即可,对于动态赋值,从网上找到如下方法:

    /// <summary>
            /// 实例化UnitywebPlayer控件并添加到界面上
            /// </summary>
            /// <param name="panel">承载unity的控件</param>
            /// <param name="unityfileServerpath">服务端路径</param>
            public void BindUnity(Panel panel,string unityfileServerpath)
            {
                if (panel.Controls.Count > 0)
                {
                    panel.Controls[0].Dispose();
                }
                panel.Controls.Clear();
                ///指定空的Unity3D,用来做外壳
                string unityfilepath = Application.StartupPath + unityfileServerpath;//"/U3D/LoadAsset.unity3d";
                unityex = new UnityWebPlayerEx();
                ((System.ComponentModel.ISupportInitialize)(unityex)).BeginInit();
                this.Controls.Add(unityex);
                ((System.ComponentModel.ISupportInitialize)(unityex)).EndInit();
                unityex.src = unityfilepath;
                AxHost.State state = unityex.OcxState;
                unityex.Dispose();
                unityex = new UnityWebPlayerEx();
                ((System.ComponentModel.ISupportInitialize)(unityex)).BeginInit();
                this.SuspendLayout();
                unityex.Dock = DockStyle.Fill;
                unityex.Name = "Unityex";
                unityex.OcxState = state;
                unityex.TabIndex = 0;
                unityex.DisableContextMenu = true;
                unityex.OnExternalCall += new AxUnityWebPlayerAXLib._DUnityWebPlayerAXEvents_OnExternalCallEventHandler(unityex_OnExternalCall);
                panel.Controls.Add(unityex);
                ((System.ComponentModel.ISupportInitialize)(unityex)).EndInit();
                this.ResumeLayout(false);
            }

             二、屏蔽UnityWebPlayer控件的右键问题

             实现的代码如下:

    class UnityWebPlayerEx : AxUnityWebPlayerAXLib.AxUnityWebPlayer
        {
            #region MyRegion
            //private const int WM_RBUTTONDOWN = 0x204;
    
            //private const int WM_RBUTTONUP = 0x205;
    
            //private const int WM_RBUTTONBLCLK = 0x206;
    
            //public override bool PreProcessMessage(ref Message msg)
            //{
            //    switch (msg.Msg)
            //    {
            //        case 0x204://鼠标右键按下消息                  
    
            //            this.SendMessage("ThiredViewCamera", "RightMouseButtonDown", null); 
            //            this.SendMessage("FirstViewCamera", "RightMouseButtonDown", null); 
            //            this.SendMessage("Main Camera", "RightMouseButtonDown", null);
            //            this.Focus();
            //            return true;
    
            //        case 0x205://鼠标右键抬起消息                  
    
            //            this.SendMessage("ThiredViewCamera", "RightMouseButtonUp", null); 
            //            this.SendMessage("FirstViewCamera", "RightMouseButtonUp", null); 
            //            this.SendMessage("Main Camera", "RightMouseButtonUp", null);
            //            return true;
            //        case 0x206://鼠标右键点击消息                  
            //            return true;
            //    }
            //    return base.PreProcessMessage(ref msg);
            //}  
            #endregion
    
            public UnityWebPlayerEx()
            {
                
            }
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
    
            [DllImport("user32")]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
            private const int WM_PARENTNOTIFY = 0x210;
    
            protected override void WndProc(ref Message m)
            {
                _menuHided = false;
                switch (m.Msg)
                {
                    case WM_PARENTNOTIFY:
                        HideContextMenu(m);
                        break;
                }
                base.WndProc(ref m);
            }
    
            /// <summary>
            /// 是否隐藏右键菜单,默认还是要显示的,new出来后要设置一下
            /// </summary>
            public bool DisableContextMenu{ get; set; }
    
            private bool _menuHided { get; set; }
    
            private void HideContextMenu(Message m)
            {
                if (_menuHided) return;
                if (DisableContextMenu == false) return;
                if (m.ToString().Contains("WM_RBUTTONDOWN"))
                {
                    if (_menuHided == false)
                    {
                        new Thread(() =>
                        {
                            while (_menuHided == false)
                            {
                                HideContextMenu();
                            }
                        }).Start();
                    }
                }
            }
            private void HideContextMenu()
            {
                //Unity.ContextSubmenu 为右键快键菜单的Form
                IntPtr handle = FindWindow("Unity.ContextSubmenu", null);
                if (handle != IntPtr.Zero)
                {
                    //把快捷菜单Form移到左上角并设置其大小为0
                    MoveWindow(handle, 0, 0, 10, 10, true); 
                    MoveWindow(handle, 0, 0, 0, 0, true);
                    _menuHided = true;
                }
            }
        }
    View Code


            需要注意的是在关闭使用的窗体的时候需要释放Unitywebplayer所占用的资源,否则在第二次进来的点击的第一次右键还是会弹出快捷菜单。

            三、遮住unitywebplayer的Logo

            在网上找了很多资料,基本都是网页形式通过修改param参数来更换Logo的,但是winform中直接使用Unity文件,也就没有使用到其一起发布的js文件,所以此方式的可能性不大。一开始也还是抱着可行的态度尝试了使用C#调用js的方式,然并没有解决。在网上是在找不到方法的时候想到了一种“投机取巧”的方法:先遮住UnityWebPlayer,等加载完成后在显示出来。于是在初始化UnityWebPlayer的时候先在其上边添加一个遮挡物,遮挡物可以自定义,比如使用Panel或者自定义一个用户控件,把界面做得好看些。

    //实例化遮挡物
                shadeuc = new ShadeUC();
                shadeuc.Name = "shadeuc1";
                shadeuc.Dock = DockStyle.Fill;
                //把遮罩层添加到界面
                this.splitContainerEx1.Panel1.Controls.Add(shadeuc);
                //遮罩层置顶以遮住底层
                shadeuc.BringToFront();


           接下来的一个问题是何时移除遮挡物,根据自己的项目我是在UnityWebPlayer的OnExternalCall事件中接收到Unity返回的消息时移除的,这种方式得到的效果还可以。还有一种不是太靠谱的方式是使用计时器,自定义一个时长移除遮挡物。

    this.splitContainerEx1.Panel1.Controls.Remove(shadeuc);

          

  • 相关阅读:
    mybatis批量插入、批量更新和批量删除
    MySQL本地密码过期处理及永不过期设置
    Intellij IDEA安装与使用,完整详细。
    深入浅出mybatis之useGeneratedKeys参数用法
    springmvc_learn
    Mac下,MySQL数据库中文乱码的解决方法
    springmvc整合mybatis实现商品列表查询
    sql server 数据库导出表里所有数据成insert 语句
    推荐几个bootstrap 后端UI框架
    50个极好的bootstrap框架
  • 原文地址:https://www.cnblogs.com/fengshen/p/Unity3D.html
Copyright © 2011-2022 走看看