XNA中的中文輸入(三)

來源:互聯網
上載者:User

      XNA中的中文輸入(三)

僅供個人學習使用,請勿轉載,勿用於任何商業用途。

 

     把前兩部分的代碼移植到XNA Game中,最大的問題在於無法訪問底層的WinForm視窗,自然也就無法獲得視窗訊息。網上有一些通過window handle建立一個NativeWindow,然後重載NativeWindow WndProc的方法來獲得windos訊息。不幸的是把之前的代碼添加在這樣的構架中,不會有任何作用。順便說一下,Game把WinForm封裝到內部實在是一種不太好的策略。因此,我們不得不直接調用API hook視窗訊息。

         首先,聲明以下函數:

 

代碼

[DllImport("user32.dll",CharSet = CharSet.Unicode)]
static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  

         建立一個靜態類來完成所有訊息捕獲任務:

 

代碼

public static class InputCaputure
{
    delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    static bool initialized;
    static IntPtr prevWndProc;
    static WndProc hookProcDelegate;
    static IntPtr hIMC;

     public static void Initialize(GameWindow window)
    {
        if (initialized)
            throw new InvalidOperationException("InputCaputure.Initialize can only be called once!");

        hookProcDelegate = new WndProc(HookProc);
        prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC, (int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
        hIMC = ImmGetContext(window.Handle);
        initialized = true;
    }

    static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
        switch (msg)
        {             
            case WindowMessage.ImeSetContext:
                {
                    //add code here
                    return (IntPtr)1;
                }

            case WindowMessage.ImeStartCompostition:
                //add code here

                return (IntPtr)0;

            case ............

            default:
                return CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
        }
    }
}

 

         好了,現在把之前的代碼搬到HookProc中,它將捕獲並處理所有我們關心的訊息,之後,再把所有訊息傳遞給Game。

         移植完所有代碼之後,你會發現幾個問題。首先,雖然成功啟用了IME視窗,但IME似乎接收不到任何按鍵訊息,添加以下代碼:

 

case WM_GETDLGCODE:
    return (IntPtr)DLGC_WANTALLKEYS;  

 

         其次,系統預設的IME視窗不會顯示了。很好,這正是我們希望的效果。此外,在IME啟用的狀態下,一直按著鍵盤鍵盤,會導致遊戲被卡住。這是hook視窗訊息得到的bug嗎?不是,做個實驗,wow也會這樣。最後,如果在全螢幕模式下,還會出現一些問題,這主要是看是否在正確的位置,調用了Initialize。

         通過這三篇文章的,你應該已經能夠為遊戲編寫一個最基本的中文輸入系統了。最後還有一些函數是你應該留意的:

1. 除了在捕獲WM_IME_ENDCOMPOSITION用ImmGetCompositionString獲得合成的字串外,捕獲WM_IME_CHAR和WM_CHAR也能獲得同樣的效果。

2. GetKeyboardLayout可以獲得與當前鍵盤配置相關的訊息。

3. ImmGetIMEFileName可以獲得當前IME的標識名稱。

4. ImmSetConversionStatus可以切換半形全形狀態。

5. 用WM_CHAR處理普通輸入,而不要用Xna中的Keyboard。因為XNA中的Keyboard本來就不是為輸入字元設計的,你根本無法獲得Caps Lock等狀態,因此,即使是普通英文輸入,也非常麻煩。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.