1. 程式人生 > >在Winform中遮蔽UnityWebPlayer的右鍵以及自帶Logo解決方案整理

在Winform中遮蔽UnityWebPlayer的右鍵以及自帶Logo解決方案整理

文章寫的非常好, 完美解決問題:https://www.cnblogs.com/fengshen/p/Unity3D.html

根據專案的需要,對已經完成的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;
            }
        }
    }

        需要注意的是在關閉使用的窗體的時候需要釋放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);