你的位置:首页 > ASP.net教程

[ASP.net教程]在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);