关于CEGUI的中文输入与显示

来源:互联网 发布:淘宝扫码领取粮票 编辑:程序博客网 时间:2024/04/29 04:27

项目终于进行到中文的输入和显示了,貌似这是个老话题,同样还是先求助于前辈,很多方案,照着做了一下,很好用,整理一个版本,希望能方便到更多需要用到这个功能的朋友。

感谢腾讯网友襄樊石开和Azure。

中文的显示:

中文的显示很简单,因为CEGUI本来就支持utf-8,只是他默认的demo里没有带中文字体,自己根据.ttf文件创建一个就是了。

Step1: 在控制面板里找到一种.ttf格式的字体,我用了自己喜欢的微软雅黑,文件名为MSYH.TTF,将其拷贝至datafiles文件下的font里。

Step2: 在font文件夹下新建一个记事本文件,另存为msyh.font,里面输入

view plaincopy to clipboardprint?
<?xml version="1.0" ?> 
<Font Name="MSYH" Filename="MSYH.TTF" Type="FreeType" Size="10" NativeHorzRes="800" NativeVertRes="600" AutoScaled="true" />   
<?xml version="1.0" ?>
<Font Name="MSYH" Filename="MSYH.TTF" Type="FreeType" Size="10" NativeHorzRes="800" NativeVertRes="600" AutoScaled="true" />  

Step3: 以CEGUI自带的FontDemo为例,如下修改源码:

在static const char *FontList [] = {}里添加项 "MSYH"(就是字体名,.font文件里定义的)

view plaincopy to clipboardprint?
static struct 
{  
    utf8 *Language;  
    utf8 *Text;  
} LangList [] 
static struct
{
    utf8 *Language;
    utf8 *Text;
} LangList []

的最后加上

view plaincopy to clipboardprint?
{  
    (utf8 *)"MSYH. Chinese",  
    (utf8 *)"简体中文测试,微软雅黑/n",   

{
    (utf8 *)"MSYH. Chinese",
    (utf8 *)"简体中文测试,微软雅黑/n",
}

Step4: 将FontDemo对应的FontDemo.layout文件用记事本打开,另存为utf-8。

OK,现在看看你的成就吧,呵呵。

中文的输入:

中文的输入比较复杂,涉及到一些底层的东西,这里拿来主义,不进行深究,只简单的完成功能。

需要修改CEGUISampleHelper里的Win32AppHelper.h和Win32AppHelper.cpp,下面直接贴上修改后的源文件,可以直接将原文件覆盖掉重新编译。

view plaincopy to clipboardprint?
/*********************************************************************** 
    filename:   Win32AppHelper.h 
    created:    17/10/2004 
    author:     Paul D Turner 
*************************************************************************/ 
/*************************************************************************** 
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 
 * 
 *   Permission is hereby granted, free of charge, to any person obtaining 
 *   a copy of this software and associated documentation files (the 
 *   "Software"), to deal in the Software without restriction, including 
 *   without limitation the rights to use, copy, modify, merge, publish, 
 *   distribute, sublicense, and/or sell copies of the Software, and to 
 *   permit persons to whom the Software is furnished to do so, subject to 
 *   the following conditions: 
 * 
 *   The above copyright notice and this permission notice shall be 
 *   included in all copies or substantial portions of the Software. 
 * 
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 *   OTHER DEALINGS IN THE SOFTWARE. 
 ***************************************************************************/ 
#ifndef _Win32AppHelper_h_  
#define _Win32AppHelper_h_  
 
#if defined( __WIN32__ ) || defined( _WIN32 )  
#   define WIN32_LEAN_AND_MEAN  
#   include <windows.h>  
 
// 这个是新加的  
#include "imm.h"  
#include <dinput.h>  
 
// undefine Microsoft macro evilness  
#   undef min  
#   undef max  
#endif  
 
#if defined(_WIN32)  
#  pragma comment(lib, "dinput8.lib")  
#  pragma comment(lib, "dxguid.lib")  
#  pragma comment(lib, "imm32.lib")  
#endif  
 
#include "CEGUIString.h"  
 
/*! 
/brief 
    All static utility class containing helper / common functions used for the Win32 apps 
*/ 
class Win32AppHelper  
{  
public:  
    struct DirectInputState  
    {  
        DirectInputState() : directInput(0), keyboardDevice(0)  
        {}  
 
        LPDIRECTINPUT8 directInput;  
        LPDIRECTINPUTDEVICE8 keyboardDevice ;  
    };  
 
    static HWND createApplicationWindow(int width, int height);  
    static void mouseEnters(void);  
    static void mouseLeaves(void);  
    static bool initialiseDirectInput(HWND window, Win32AppHelper::DirectInputState& dis);  
    static void cleanupDirectInput(Win32AppHelper::DirectInputState& dis);  
    static void doDirectInputEvents(const Win32AppHelper::DirectInputState& dis);  
    static bool doWin32Events(bool& idle);  
      
    /////// 中文输入注入字符 (Added by Azure)  
    static bool ChnInjectChar(CEGUI::utf32 code_point);  
    ///////  
 
    /////// 虚拟按键转扫描码 (Added by Azure)  
    static UINT VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam);  
 
 
    /////// 获得输入框的坐标 (Added by Azure)  
    static bool getFocusedInputBoxCoord(POINT& point, float& height);  
 
    ////// 输入法跟随 (Added by Azure)  
    static bool IMEFollow(HWND hWnd);  
 
    static LRESULT CALLBACK wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
 
    /************************************************************************* 
        Constants 
    *************************************************************************/ 
    // name of the application, used for class and window creation  
    static const TCHAR  APPLICATION_NAME[];  
 
    // error strings displayed during initialisation  
    static const TCHAR  REGISTER_CLASS_ERROR[];  
    static const TCHAR  CREATE_WINDOW_ERROR[];  
 
    // other error strings used  
    static const TCHAR  CREATE_D3D_ERROR[];  
    static const TCHAR  CREATE_DEVICE_ERROR[];  
 
private:  
    static bool d_mouseInWindow;  
};  
 
#endif  // end of guard _Win32AppHelper_h_ 
/***********************************************************************
    filename:   Win32AppHelper.h
    created:    17/10/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifndef _Win32AppHelper_h_
#define _Win32AppHelper_h_

#if defined( __WIN32__ ) || defined( _WIN32 )
#   define WIN32_LEAN_AND_MEAN
#   include <windows.h>

// 这个是新加的
#include "imm.h"
#include <dinput.h>

// undefine Microsoft macro evilness
#   undef min
#   undef max
#endif

#if defined(_WIN32)
#  pragma comment(lib, "dinput8.lib")
#  pragma comment(lib, "dxguid.lib")
#  pragma comment(lib, "imm32.lib")
#endif

#include "CEGUIString.h"

/*!
/brief
    All static utility class containing helper / common functions used for the Win32 apps
*/
class Win32AppHelper
{
public:
    struct DirectInputState
    {
        DirectInputState() : directInput(0), keyboardDevice(0)
        {}

        LPDIRECTINPUT8 directInput;
        LPDIRECTINPUTDEVICE8 keyboardDevice ;
    };

    static HWND createApplicationWindow(int width, int height);
    static void mouseEnters(void);
    static void mouseLeaves(void);
    static bool initialiseDirectInput(HWND window, Win32AppHelper::DirectInputState& dis);
    static void cleanupDirectInput(Win32AppHelper::DirectInputState& dis);
    static void doDirectInputEvents(const Win32AppHelper::DirectInputState& dis);
    static bool doWin32Events(bool& idle);
 
 /////// 中文输入注入字符 (Added by Azure)
 static bool ChnInjectChar(CEGUI::utf32 code_point);
    ///////

 /////// 虚拟按键转扫描码 (Added by Azure)
 static UINT VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam);


 /////// 获得输入框的坐标 (Added by Azure)
 static bool getFocusedInputBoxCoord(POINT& point, float& height);

 ////// 输入法跟随 (Added by Azure)
 static bool IMEFollow(HWND hWnd);

 static LRESULT CALLBACK wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

    /*************************************************************************
        Constants
    *************************************************************************/
    // name of the application, used for class and window creation
    static const TCHAR  APPLICATION_NAME[];

    // error strings displayed during initialisation
    static const TCHAR  REGISTER_CLASS_ERROR[];
    static const TCHAR  CREATE_WINDOW_ERROR[];

    // other error strings used
    static const TCHAR  CREATE_D3D_ERROR[];
    static const TCHAR  CREATE_DEVICE_ERROR[];

private:
    static bool d_mouseInWindow;
};

#endif  // end of guard _Win32AppHelper_h_ 

view plaincopy to clipboardprint?
/*********************************************************************** 
    filename:   Win32AppHelper.cpp 
    created:    17/10/2004 
    author:     Paul D Turner 
*************************************************************************/ 
/*************************************************************************** 
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 
 * 
 *   Permission is hereby granted, free of charge, to any person obtaining 
 *   a copy of this software and associated documentation files (the 
 *   "Software"), to deal in the Software without restriction, including 
 *   without limitation the rights to use, copy, modify, merge, publish, 
 *   distribute, sublicense, and/or sell copies of the Software, and to 
 *   permit persons to whom the Software is furnished to do so, subject to 
 *   the following conditions: 
 * 
 *   The above copyright notice and this permission notice shall be 
 *   included in all copies or substantial portions of the Software. 
 * 
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 *   OTHER DEALINGS IN THE SOFTWARE. 
 ***************************************************************************/ 
#ifdef HAVE_CONFIG_H  
#   include "config.h"  
#endif  
 
#if defined(CEGUI_SAMPLES_USE_DIRECTX_8) || defined(CEGUI_SAMPLES_USE_DIRECTX_9)  
 
#include "Win32AppHelper.h"  
#include "../../../RendererModules/directx9GUIRenderer/d3d9renderer.h"  
#include "CEGUI.h"  
#include <TCHAR.H>  
 
 
/************************************************************************* 
    Static Data Definitions 
*************************************************************************/ 
// name of the application, used for class and window creation  
const TCHAR Win32AppHelper::APPLICATION_NAME[]      = _TEXT("Crazy Eddie's GUI Mk-2 - Sample Application");  
 
// error strings displayed during initialisation  
const TCHAR Win32AppHelper::REGISTER_CLASS_ERROR[]  = _TEXT("Failed to register window class.");  
const TCHAR Win32AppHelper::CREATE_WINDOW_ERROR[]   = _TEXT("Failed to create window.");  
 
// other error strings used  
const TCHAR Win32AppHelper::CREATE_D3D_ERROR[]      = _TEXT("Failed to create main Direct3D object.");  
const TCHAR Win32AppHelper::CREATE_DEVICE_ERROR[]   = _TEXT("Failed to create Direct3D Device object.");  
 
// variable for tracking Win32 cursor  
bool Win32AppHelper::d_mouseInWindow = false;  
 
 
/************************************************************************* 
    Create main application window. 
*************************************************************************/ 
HWND Win32AppHelper::createApplicationWindow(int width, int height)  
{  
    WNDCLASS    wndClass;       // structure used to register window class  
 
    // Initialise WNDCLASS structure.  
    wndClass.style          = 0;  
    wndClass.lpfnWndProc    = wndProc;  
    wndClass.cbClsExtra     = 0;  
    wndClass.cbWndExtra     = 0;  
    wndClass.hInstance      = GetModuleHandle(0);  
    wndClass.hIcon          = LoadIcon(0, IDI_WINLOGO);  
    wndClass.hCursor        = LoadCursor(0, IDC_ARROW);  
    wndClass.hbrBackground  = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));  
    wndClass.lpszMenuName   = 0;  
    wndClass.lpszClassName  = APPLICATION_NAME;  
 
    HWND window = 0;  
 
    // register class.  Report error & exit upon failure  
    if (RegisterClass(&wndClass))  
    {  
        // create new window  
        window = CreateWindow(APPLICATION_NAME, APPLICATION_NAME, WS_OVERLAPPEDWINDOW,  
                              0, 0, width, height, 0, 0, GetModuleHandle(0), 0);  
    }  
    else 
    {  
        MessageBox(0, REGISTER_CLASS_ERROR, APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    }  
 
    return window;  
}  
 
//寻找到有输入焦点的EditBox的左上坐标  
bool Win32AppHelper::getFocusedInputBoxCoord(POINT& point, float& height)  
{  
    //遍历所有窗口  
    CEGUI::WindowManager::WindowIterator wit = CEGUI::WindowManager::getSingleton().getIterator();  
    while(!wit.isAtEnd())  
    {  
        const CEGUI::Window* widget = (*wit)->getActiveChild();  
        //如果是EditBox或者MultiLineEditBox  
        if(widget)  
        {  
            CEGUI::String windowType = widget->getType();  
            if(windowType == "TaharezLook/Editbox") //根据具体的scheme来修改  
            {  
                const CEGUI::UVector2& winPos = widget->getPosition();  
                height = widget->getPixelRect().getHeight();  
                      
                CEGUI::Vector2 winPos1 = CEGUI::CoordConverter::windowToScreen(*widget, winPos);  
 
                point.x = winPos1.d_x;  
                point.y = winPos1.d_y;  
                return true;  
            }  
        }  
        wit++;  
    }  
 
    return false;  
}  
 
bool Win32AppHelper::IMEFollow(HWND hWnd)  
{  
    //判断输入法是否打开  
    if (!ImmIsIME(GetKeyboardLayout(0)))  
        return false;  
      
    //获得输入框左上坐标  
    bool result;  
    POINT point;  
    float height;  
    result = getFocusedInputBoxCoord(point, height);  
    if(!result)  
        return false;  
      
    //获得客户区的坐标  
    RECT rect;  
    GetClientRect(hWnd, &rect);  
    point.x+=rect.left;  
    point.y+=rect.top;  
 
    //设置输入法位置  
    HIMC hImc = ImmGetContext(hWnd);  
    if(hImc==NULL) return false;  
    COMPOSITIONFORM form;  
    ImmGetCompositionWindow(hImc, &form);  
    form.ptCurrentPos.x = point.x;  
    form.ptCurrentPos.y = point.y + height;  
    ImmSetCompositionWindow(hImc, &form);  
 
    return true;      
}  
 
// 虚键转扫描码  
UINT Win32AppHelper::VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam)  
{  
    if(HIWORD(lParam) & 0x0F00)   
    {   
        UINT scancode = MapVirtualKey(wParam, 0);   
        return scancode | 0x80;   
    }   
    else   
    {   
        return HIWORD(lParam) & 0x00FF;   
    }   
}  
 
// 中文字符输入  
bool Win32AppHelper::ChnInjectChar(CEGUI::utf32 code_point)  
{  
#ifndef UNICODE  
    static char     s_tempChar[3]  = "";  
    static wchar_t  s_tempWchar[2] = L"";  
    static bool s_flag = false;  
    unsigned char  uch  = (unsigned char)code_point;  
    if( uch >= 0xA1 )  
    {  
        if( !s_flag )  
        {  
            s_tempChar[0] = (char)uch; //第一个字节  
            s_flag = true;  
            return true;  
        }  
        else if( uch >= 0xA1 )  
        {  
            s_tempChar[1] = (char)uch; //第二个字节  
            s_flag = false;  
            MultiByteToWideChar( 0, 0, s_tempChar, 2, s_tempWchar, 1); //转成宽字节  
            s_tempWchar[1] = L'/0';  
            CEGUI::utf32 code = (CEGUI::utf32)s_tempWchar[0];  
            return CEGUI::System::getSingleton().injectChar( code );  
        }  
        else 
        {  
            return CEGUI::System::getSingleton().injectChar(code_point);  
        }  
    }  
    else 
    {  
        s_flag = false;  
        return CEGUI::System::getSingleton().injectChar(code_point);  
    }  
#else  
    return CEGUI::System::getSingleton().injectChar(code_point );  
#endif  
}  
 
 
/************************************************************************* 
    Win32 'Window Procedure' function 
*************************************************************************/ 
LRESULT CALLBACK Win32AppHelper::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    switch(message)  
    {  
    case WM_CHAR:  
        // 不要这个  
        //CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);  
        // 改用自己的注入  
        ChnInjectChar((CEGUI::utf32)wParam);  
        break;  
 
    case WM_MOUSELEAVE:  
        mouseLeaves();  
        break;  
 
    case WM_NCMOUSEMOVE:  
        mouseLeaves();  
        break;  
 
    case WM_MOUSEMOVE:  
        mouseEnters();  
 
        CEGUI::System::getSingleton().injectMousePosition((float)(LOWORD(lParam)), (float)(HIWORD(lParam)));  
        break;  
 
    case WM_LBUTTONDOWN:  
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton);  
        break;  
 
    case WM_LBUTTONUP:  
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton);  
        break;  
 
    case WM_RBUTTONDOWN:  
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton);  
        break;  
 
    case WM_RBUTTONUP:  
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton);  
        break;  
 
    case WM_MBUTTONDOWN:  
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton);  
        break;  
 
    case WM_MBUTTONUP:  
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton);  
        break;  
 
    case 0x020A: // WM_MOUSEWHEEL:  
        CEGUI::System::getSingleton().injectMouseWheelChange(static_cast<float>((short)HIWORD(wParam)) / static_cast<float>(120));  
        break;  
 
    case WM_DESTROY:  
        PostQuitMessage(0);  
        break;  
 
    case WM_SIZE:  
        // TODO: Notify about new size  
        {  
            //if(CEGUI::System::getSingletonPtr())  
            //{  
            //  RECT rect;  
            //  GetClientRect(hWnd, &rect);  
            //  CEGUI::DirectX9Renderer* dx9render = static_cast<CEGUI::DirectX9Renderer*>(CEGUI::System::getSingletonPtr()->getRenderer());  
            //  dx9render->setDisplaySize(CEGUI::Size(rect.right-rect.left, rect.bottom-rect.top));  
            //}  
        }  
        break;  
 
    case WM_PAINT:  
        {  
            HDC         hDC;  
            PAINTSTRUCT ps;  
 
            hDC = BeginPaint(hWnd, &ps);  
            EndPaint(hWnd, &ps);  
            break;  
        }  
 
    case WM_KEYDOWN:  
        {  
            //输入法跟随  
            IMEFollow(hWnd);  
              
            //输入法状态时,输入不传递到UI系统中去。  
            UINT vk = (UINT)ImmGetVirtualKey(hWnd);   
            if(vk == wParam)  
                break;  
              
            CEGUI::System::getSingleton().injectKeyDown((CEGUI::utf32)(VirtualKeyToScanCode(wParam, lParam)));  
        }  
        break;  
 
    case WM_KEYUP:  
        CEGUI::System::getSingleton().injectKeyUp((CEGUI::utf32)(VirtualKeyToScanCode(wParam, lParam)));  
        break;  
 
    default:  
        return(DefWindowProc(hWnd, message, wParam, lParam));  
        break;  
    }  
 
    return 0;  
}  
 
// 鼠标进入区域  
void Win32AppHelper::mouseEnters(void)  
{  
    if (!d_mouseInWindow)  
    {  
        d_mouseInWindow = true;  
        ShowCursor(false);  
    }  
}  
 
// 鼠标离开区域  
void Win32AppHelper::mouseLeaves(void)  
{  
    if (d_mouseInWindow)  
    {  
        d_mouseInWindow = false;  
        ShowCursor(true);  
    }  
}  
 
// 初始化Direct Input,没用上  
bool Win32AppHelper::initialiseDirectInput(HWND window, Win32AppHelper::DirectInputState& dis)  
{  
    //if (SUCCEEDED(DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dis.directInput, 0)))  
    //{  
    //    if (SUCCEEDED(dis.directInput->CreateDevice(GUID_SysKeyboard, &dis.keyboardDevice, 0)))  
    //    {  
    //        if (SUCCEEDED(dis.keyboardDevice->SetDataFormat(&c_dfDIKeyboard)))  
    //        {  
    //            if (SUCCEEDED(dis.keyboardDevice->SetCooperativeLevel(window, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE)))  
    //            {  
    //                DIPROPDWORD inputProp;  
    //                // the header  
    //                inputProp.diph.dwSize       = sizeof(DIPROPDWORD);  
    //                inputProp.diph.dwHeaderSize = sizeof(DIPROPHEADER);  
    //                inputProp.diph.dwObj        = 0;  
    //                inputProp.diph.dwHow        = DIPH_DEVICE;  
    //                inputProp.dwData            = 16;  
 
    //                if (SUCCEEDED(dis.keyboardDevice->SetProperty(DIPROP_BUFFERSIZE, &inputProp.diph)))  
    //                {  
    //                    dis.keyboardDevice->Acquire();  
    //                    return true;  
    //                }  
    //                else  
    //                {  
    //                    MessageBox(0, _TEXT("Failed to set buffer size for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    //                }  
 
    //            }  
    //            else  
    //            {  
    //                MessageBox(0, _TEXT("Failed to set co-operative level for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    //            }  
 
    //        }  
    //        else  
    //        {  
    //            MessageBox(0, _TEXT("Failed to set data format for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    //        }  
 
    //        dis.keyboardDevice->Release();  
    //        dis.keyboardDevice = 0;  
    //    }  
    //    else  
    //    {  
    //        MessageBox(0, _TEXT("Failed to create DirectInput keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    //    }  
 
    //    dis.directInput->Release();  
    //    dis.directInput = 0;  
    //}  
    //else  
    //{  
    //    MessageBox(0, _TEXT("Failed to create main DirectInput object."), APPLICATION_NAME, MB_ICONERROR|MB_OK);  
    //}  
 
    return true;  
}  
 
 
// 清楚Direct Input,没用上  
void Win32AppHelper::cleanupDirectInput(Win32AppHelper::DirectInputState& dis)  
{  
    //if (dis.keyboardDevice)  
    //{  
    //    dis.keyboardDevice->Unacquire();  
    //    dis.keyboardDevice->Release();  
    //    dis.keyboardDevice = 0;  
    //}  
 
    //if (dis.directInput)  
    //{  
    //    dis.directInput->Release();  
    //    dis.directInput = 0;  
    //}  
}  
 
// 处理Direct Input事件,没用上  
void Win32AppHelper::doDirectInputEvents(const Win32AppHelper::DirectInputState& dis)  
{  
    //// handle direct input based inputs  
    //DIDEVICEOBJECTDATA devDat;  
    //DWORD itemCount = 1;  
 
    //HRESULT res = dis.keyboardDevice->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &devDat, &itemCount, 0);  
 
    //if (SUCCEEDED(res))  
    //{  
    //    if (itemCount > 0)  
    //    {  
    //        if (LOBYTE(devDat.dwData) & 0x80)  
    //        {  
    //            // force quit on ESCAPE key  
    //            if (devDat.dwOfs == CEGUI::Key::Escape)  
    //            {  
    //                PostQuitMessage(0);  
    //            }  
    //            else  
    //            {  
    //                CEGUI::System::getSingleton().injectKeyDown(devDat.dwOfs);  
    //            }  
 
    //        }  
    //        else  
    //        {  
    //            CEGUI::System::getSingleton().injectKeyUp(devDat.dwOfs);  
    //        }  
 
    //    }  
    //}  
    //else  
    //{  
    //    // try to re-acquire device if that was the cause of the error.  
    //    if ((res == DIERR_NOTACQUIRED) || (res == DIERR_INPUTLOST))  
    //    {  
    //        dis.keyboardDevice->Acquire();  
    //    }  
 
    //}  
 
}  
 
// 处理Win32事件  
bool Win32AppHelper::doWin32Events(bool& idle)  
{  
    MSG msg;  
 
    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))  
    {  
 
        if (msg.message == WM_QUIT)  
        {  
            return false;  
        }  
 
        TranslateMessage(&msg);  
        DispatchMessage(&msg);  
 
        idle = false;  
    }  
    else 
    {  
        idle = true;  
    }  
 
    return true;  
}  
 
#endif 
/***********************************************************************
    filename:   Win32AppHelper.cpp
    created:    17/10/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#if defined(CEGUI_SAMPLES_USE_DIRECTX_8) || defined(CEGUI_SAMPLES_USE_DIRECTX_9)

#include "Win32AppHelper.h"
#include "../../../RendererModules/directx9GUIRenderer/d3d9renderer.h"
#include "CEGUI.h"
#include <TCHAR.H>


/*************************************************************************
    Static Data Definitions
*************************************************************************/
// name of the application, used for class and window creation
const TCHAR Win32AppHelper::APPLICATION_NAME[]      = _TEXT("Crazy Eddie's GUI Mk-2 - Sample Application");

// error strings displayed during initialisation
const TCHAR Win32AppHelper::REGISTER_CLASS_ERROR[]  = _TEXT("Failed to register window class.");
const TCHAR Win32AppHelper::CREATE_WINDOW_ERROR[]   = _TEXT("Failed to create window.");

// other error strings used
const TCHAR Win32AppHelper::CREATE_D3D_ERROR[]      = _TEXT("Failed to create main Direct3D object.");
const TCHAR Win32AppHelper::CREATE_DEVICE_ERROR[]   = _TEXT("Failed to create Direct3D Device object.");

// variable for tracking Win32 cursor
bool Win32AppHelper::d_mouseInWindow = false;


/*************************************************************************
    Create main application window.
*************************************************************************/
HWND Win32AppHelper::createApplicationWindow(int width, int height)
{
    WNDCLASS    wndClass;       // structure used to register window class

    // Initialise WNDCLASS structure.
    wndClass.style          = 0;
    wndClass.lpfnWndProc    = wndProc;
    wndClass.cbClsExtra     = 0;
    wndClass.cbWndExtra     = 0;
    wndClass.hInstance      = GetModuleHandle(0);
    wndClass.hIcon          = LoadIcon(0, IDI_WINLOGO);
    wndClass.hCursor        = LoadCursor(0, IDC_ARROW);
    wndClass.hbrBackground  = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    wndClass.lpszMenuName   = 0;
    wndClass.lpszClassName  = APPLICATION_NAME;

    HWND window = 0;

    // register class.  Report error & exit upon failure
    if (RegisterClass(&wndClass))
    {
        // create new window
        window = CreateWindow(APPLICATION_NAME, APPLICATION_NAME, WS_OVERLAPPEDWINDOW,
                              0, 0, width, height, 0, 0, GetModuleHandle(0), 0);
    }
    else
    {
        MessageBox(0, REGISTER_CLASS_ERROR, APPLICATION_NAME, MB_ICONERROR|MB_OK);
    }

    return window;
}

//寻找到有输入焦点的EditBox的左上坐标
bool Win32AppHelper::getFocusedInputBoxCoord(POINT& point, float& height)
{
 //遍历所有窗口
 CEGUI::WindowManager::WindowIterator wit = CEGUI::WindowManager::getSingleton().getIterator();
 while(!wit.isAtEnd())
 {
  const CEGUI::Window* widget = (*wit)->getActiveChild();
  //如果是EditBox或者MultiLineEditBox
  if(widget)
  {
   CEGUI::String windowType = widget->getType();
   if(windowType == "TaharezLook/Editbox") //根据具体的scheme来修改
   {
    const CEGUI::UVector2& winPos = widget->getPosition();
    height = widget->getPixelRect().getHeight();
     
    CEGUI::Vector2 winPos1 = CEGUI::CoordConverter::windowToScreen(*widget, winPos);

    point.x = winPos1.d_x;
    point.y = winPos1.d_y;
    return true;
   }
  }
  wit++;
 }

 return false;
}

bool Win32AppHelper::IMEFollow(HWND hWnd)
{
 //判断输入法是否打开
 if (!ImmIsIME(GetKeyboardLayout(0)))
  return false;
 
 //获得输入框左上坐标
 bool result;
 POINT point;
 float height;
 result = getFocusedInputBoxCoord(point, height);
 if(!result)
  return false;
 
 //获得客户区的坐标
 RECT rect;
 GetClientRect(hWnd, &rect);
 point.x+=rect.left;
 point.y+=rect.top;

 //设置输入法位置
 HIMC hImc = ImmGetContext(hWnd);
 if(hImc==NULL) return false;
 COMPOSITIONFORM form;
 ImmGetCompositionWindow(hImc, &form);
 form.ptCurrentPos.x = point.x;
 form.ptCurrentPos.y = point.y + height;
 ImmSetCompositionWindow(hImc, &form);

 return true; 
}

// 虚键转扫描码
UINT Win32AppHelper::VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam)
{
 if(HIWORD(lParam) & 0x0F00)
 {
  UINT scancode = MapVirtualKey(wParam, 0);
  return scancode | 0x80;
 }
 else
 {
  return HIWORD(lParam) & 0x00FF;
 }
}

// 中文字符输入
bool Win32AppHelper::ChnInjectChar(CEGUI::utf32 code_point)
{
#ifndef UNICODE
 static char     s_tempChar[3]  = "";
 static wchar_t  s_tempWchar[2] = L"";
 static bool s_flag = false;
 unsigned char  uch  = (unsigned char)code_point;
 if( uch >= 0xA1 )
 {
  if( !s_flag )
  {
   s_tempChar[0] = (char)uch; //第一个字节
   s_flag = true;
   return true;
  }
  else if( uch >= 0xA1 )
  {
   s_tempChar[1] = (char)uch; //第二个字节
   s_flag = false;
   MultiByteToWideChar( 0, 0, s_tempChar, 2, s_tempWchar, 1); //转成宽字节
   s_tempWchar[1] = L'/0';
   CEGUI::utf32 code = (CEGUI::utf32)s_tempWchar[0];
   return CEGUI::System::getSingleton().injectChar( code );
  }
  else
  {
   return CEGUI::System::getSingleton().injectChar(code_point);
  }
 }
 else
 {
  s_flag = false;
  return CEGUI::System::getSingleton().injectChar(code_point);
 }
#else
 return CEGUI::System::getSingleton().injectChar(code_point );
#endif
}


/*************************************************************************
    Win32 'Window Procedure' function
*************************************************************************/
LRESULT CALLBACK Win32AppHelper::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_CHAR:
        // 不要这个
  //CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
        // 改用自己的注入
  ChnInjectChar((CEGUI::utf32)wParam);
  break;

    case WM_MOUSELEAVE:
        mouseLeaves();
        break;

    case WM_NCMOUSEMOVE:
        mouseLeaves();
        break;

    case WM_MOUSEMOVE:
        mouseEnters();

        CEGUI::System::getSingleton().injectMousePosition((float)(LOWORD(lParam)), (float)(HIWORD(lParam)));
        break;

    case WM_LBUTTONDOWN:
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton);
        break;

    case WM_LBUTTONUP:
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton);
        break;

    case WM_RBUTTONDOWN:
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton);
        break;

    case WM_RBUTTONUP:
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton);
        break;

    case WM_MBUTTONDOWN:
        CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton);
        break;

    case WM_MBUTTONUP:
        CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton);
        break;

    case 0x020A: // WM_MOUSEWHEEL:
        CEGUI::System::getSingleton().injectMouseWheelChange(static_cast<float>((short)HIWORD(wParam)) / static_cast<float>(120));
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    case WM_SIZE:
        // TODO: Notify about new size
  {
   //if(CEGUI::System::getSingletonPtr())
   //{
   // RECT rect;
   // GetClientRect(hWnd, &rect);
   // CEGUI::DirectX9Renderer* dx9render = static_cast<CEGUI::DirectX9Renderer*>(CEGUI::System::getSingletonPtr()->getRenderer());
   // dx9render->setDisplaySize(CEGUI::Size(rect.right-rect.left, rect.bottom-rect.top));
   //}
  }
  break;

    case WM_PAINT:
        {
            HDC         hDC;
            PAINTSTRUCT ps;

            hDC = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        }

 case WM_KEYDOWN:
  {
   //输入法跟随
   IMEFollow(hWnd);
   
   //输入法状态时,输入不传递到UI系统中去。
   UINT vk = (UINT)ImmGetVirtualKey(hWnd);
   if(vk == wParam)
    break;
   
   CEGUI::System::getSingleton().injectKeyDown((CEGUI::utf32)(VirtualKeyToScanCode(wParam, lParam)));
  }
  break;

 case WM_KEYUP:
  CEGUI::System::getSingleton().injectKeyUp((CEGUI::utf32)(VirtualKeyToScanCode(wParam, lParam)));
  break;

    default:
        return(DefWindowProc(hWnd, message, wParam, lParam));
        break;
    }

    return 0;
}

// 鼠标进入区域
void Win32AppHelper::mouseEnters(void)
{
    if (!d_mouseInWindow)
    {
        d_mouseInWindow = true;
        ShowCursor(false);
    }
}

// 鼠标离开区域
void Win32AppHelper::mouseLeaves(void)
{
    if (d_mouseInWindow)
    {
        d_mouseInWindow = false;
        ShowCursor(true);
    }
}

// 初始化Direct Input,没用上
bool Win32AppHelper::initialiseDirectInput(HWND window, Win32AppHelper::DirectInputState& dis)
{
    //if (SUCCEEDED(DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dis.directInput, 0)))
    //{
    //    if (SUCCEEDED(dis.directInput->CreateDevice(GUID_SysKeyboard, &dis.keyboardDevice, 0)))
    //    {
    //        if (SUCCEEDED(dis.keyboardDevice->SetDataFormat(&c_dfDIKeyboard)))
    //        {
    //            if (SUCCEEDED(dis.keyboardDevice->SetCooperativeLevel(window, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE)))
    //            {
    //                DIPROPDWORD inputProp;
    //                // the header
    //                inputProp.diph.dwSize       = sizeof(DIPROPDWORD);
    //                inputProp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    //                inputProp.diph.dwObj        = 0;
    //                inputProp.diph.dwHow        = DIPH_DEVICE;
    //                inputProp.dwData            = 16;

    //                if (SUCCEEDED(dis.keyboardDevice->SetProperty(DIPROP_BUFFERSIZE, &inputProp.diph)))
    //                {
    //                    dis.keyboardDevice->Acquire();
    //                    return true;
    //                }
    //                else
    //                {
    //                    MessageBox(0, _TEXT("Failed to set buffer size for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);
    //                }

    //            }
    //            else
    //            {
    //                MessageBox(0, _TEXT("Failed to set co-operative level for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);
    //            }

    //        }
    //        else
    //        {
    //            MessageBox(0, _TEXT("Failed to set data format for keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);
    //        }

    //        dis.keyboardDevice->Release();
    //        dis.keyboardDevice = 0;
    //    }
    //    else
    //    {
    //        MessageBox(0, _TEXT("Failed to create DirectInput keyboard device."), APPLICATION_NAME, MB_ICONERROR|MB_OK);
    //    }

    //    dis.directInput->Release();
    //    dis.directInput = 0;
    //}
    //else
    //{
    //    MessageBox(0, _TEXT("Failed to create main DirectInput object."), APPLICATION_NAME, MB_ICONERROR|MB_OK);
    //}

    return true;
}


// 清楚Direct Input,没用上
void Win32AppHelper::cleanupDirectInput(Win32AppHelper::DirectInputState& dis)
{
    //if (dis.keyboardDevice)
    //{
    //    dis.keyboardDevice->Unacquire();
    //    dis.keyboardDevice->Release();
    //    dis.keyboardDevice = 0;
    //}

    //if (dis.directInput)
    //{
    //    dis.directInput->Release();
    //    dis.directInput = 0;
    //}
}

// 处理Direct Input事件,没用上
void Win32AppHelper::doDirectInputEvents(const Win32AppHelper::DirectInputState& dis)
{
    //// handle direct input based inputs
    //DIDEVICEOBJECTDATA devDat;
    //DWORD itemCount = 1;

    //HRESULT res = dis.keyboardDevice->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &devDat, &itemCount, 0);

    //if (SUCCEEDED(res))
    //{
    //    if (itemCount > 0)
    //    {
    //        if (LOBYTE(devDat.dwData) & 0x80)
    //        {
    //            // force quit on ESCAPE key
    //            if (devDat.dwOfs == CEGUI::Key::Escape)
    //            {
    //                PostQuitMessage(0);
    //            }
    //            else
    //            {
    //                CEGUI::System::getSingleton().injectKeyDown(devDat.dwOfs);
    //            }

    //        }
    //        else
    //        {
    //            CEGUI::System::getSingleton().injectKeyUp(devDat.dwOfs);
    //        }

    //    }
    //}
    //else
    //{
    //    // try to re-acquire device if that was the cause of the error.
    //    if ((res == DIERR_NOTACQUIRED) || (res == DIERR_INPUTLOST))
    //    {
    //        dis.keyboardDevice->Acquire();
    //    }

    //}

}

// 处理Win32事件
bool Win32AppHelper::doWin32Events(bool& idle)
{
    MSG msg;

    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {

        if (msg.message == WM_QUIT)
        {
            return false;
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);

        idle = false;
    }
    else
    {
        idle = true;
    }

    return true;
}

#endif 


这里仅仅需要注意的是Win32AppHelper.h需要包含"imm.h"和"imm32.lib"。

最后上图:


 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/naugthyLeo/archive/2009/05/25/4215687.aspx