XNA中的中文输入(三)

      XNA中的中文输入(三)

仅供个人学习使用,请勿转载,勿用于任何商业用途。

 

     把前两部分的代码移植到XNA Game中,最大的问题在于无法访问底层的WinForm窗口,自然也就无法获得窗口消息。网上有一些通过window handle创建一个NativeWindow,然后重载NativeWindow WndProc的方法来获得windos消息。不幸的是把之前的代码添加在这样的构架中,不会有任何作用。顺便说一下,GameWinForm封装到内部实在是一种不太好的策略。因此,我们不得不直接调用API hook窗口消息。

         首先,声明以下函数:

 

ExpandedBlockStart.gif 代码
[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);

  

         创建一个静态类来完成所有消息捕获任务:

 

ExpandedBlockStart.gif 代码
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_ENDCOMPOSITIONImmGetCompositionString获得合成的字符串外,捕获WM_IME_CHARWM_CHAR也能获得同样的效果。

2. GetKeyboardLayout可以获得与当前键盘布局相关的消息。

3. ImmGetIMEFileName可以获得当前输入法的标识名称。

4. ImmSetConversionStatus可以切换半角全角状态。

5. WM_CHAR处理普通输入,而不要用Xna中的Keyboard。因为XNA中的Keyboard本来就不是为输入字符设计的,你根本无法获得Caps Lock等状态,因此,即使是普通英文输入,也非常麻烦。

 

转载于:https://www.cnblogs.com/clayman/archive/2009/12/18/1626819.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值