//========================================================================
//TITLE:
// 漫谈WinCE输入法的编写(三)
//AUTHOR:
// norains
//DATE:
// Friday 2-March -2007
//Environment:
// EVC4.0 + Standard SDK
//========================================================================
这次就让我们来看看一个简单的输入法界面窗口的实现.如果以类的观点来看,输入法界面窗口和普通的应用程序的窗口没有什么不同,可能也是唯一最大的差异就是输入法窗口不能也不应该发送PostQuiteMessage,否则将导致输入法管理器的退出.
闲话不表,直接来看看一个最简单的输入法窗口架构:
// IMWnd.h
// *************************************************************
// The input method window class
class CIMWnd
... {
public:
//获取对象实例
static CIMWnd * GetInstance();
//显示输入法的设置窗口
void ShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst = NULL);
//显示输入法界面
void ShowWindow(BOOL bShow);
//销毁输入法界面
void DestroyWindow();
//初始化窗口,hWndSip是输入法管理器的句柄
BOOL Initialize(HINSTANCE hInst, HWND hWndSip);
//析构函数
virtual ~CIMWnd();
protected:
//构造函数
CIMWnd();
//注册回调函数
void OnRegCallback(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
//窗口过程
static LRESULT WndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
//指向对象的指针
static CIMWnd *m_pInstance;
//输入法窗口句柄
HWND m_hWnd;
//DLL实例
HINSTANCE m_hInst;
//输入法管理器窗口句柄
HWND m_hWndSip;
//保存对外回调函数的指针
IIMCallback *m_pIMCallback; //Pointer to the callback function
} ;
// IMWnd.cpp
// *************************************************************
// Initialize
CIMWnd * CIMWnd::m_pInstance = NULL;
// ----------------------------------------------------------------------
// Description:
// Get the object instance
// ----------------------------------------------------------------------
CIMWnd * CIMWnd::GetInstance()
... {
if(m_pInstance == NULL)
...{
m_pInstance = new CIMWnd();
}
return m_pInstance;
}
// ----------------------------------------------------------------------------
// Decription:
// On message MSG_USEROPTIONSDLG
// -----------------------------------------------------------------------------
void CIMWnd::ShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst)
... {
CSettingDlg *pSettingDlg;
pSettingDlg = CSettingDlg::GetInstance();
if(hInst == NULL)
...{
pSettingDlg->ShowDlg(m_hInst,hWndParent,&m_iTimeFresh);
}
else
...{
pSettingDlg->ShowDlg(hInst,hWndParent,&m_iTimeFresh);
}
}
// ----------------------------------------------------------------------
// Description:
// Show the window
// ----------------------------------------------------------------------
void CIMWnd::ShowWindow(BOOL bShow)
... {
if(bShow == TRUE)
...{
::ShowWindow(m_hWnd,SW_SHOW);
}
else
...{
::ShowWindow(m_hWnd,SW_HIDE);
}
}
// ----------------------------------------------------------------------
// Description:
// Destroy the window
// ----------------------------------------------------------------------
void CIMWnd::DestroyWindow()
... {
::DestroyWindow(m_hWnd);
UnregisterClass(WINDOW_CLASS,m_hInst);
}
// ----------------------------------------------------------------------
// Description:
// Initialize
// ----------------------------------------------------------------------
BOOL CIMWnd::Initialize(HINSTANCE hInst, HWND hWndSip)
... {
m_hInst = hInst;
m_hWndSip = hWndSip;
WNDCLASS wc;
wc.style = CS_VREDRAW | CS_HREDRAW;;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = WINDOW_CLASS;
if(RegisterClass(&wc) == 0)
...{
return FALSE;
}
// Create SIP window.
m_hWnd = CreateWindowEx(0,
WINDOW_CLASS,
WINDOW_TITLE,
WS_CHILD | WS_BORDER ,
CW_USERDEFAULT,
CW_USERDEFAULT,
CW_USERDEFAULT,
CW_USERDEFAULT,
hWndSip,
NULL,
m_hInst,
NULL
);
if(IsWindow(m_hWnd)==FALSE)
...{
return FALSE;
}
return TRUE;
}
CIMWnd:: ~ CIMWnd()
... {
DeleteCriticalSection(&m_CriticalForWaitFresh);
if(m_pInstance != NULL)
...{
delete m_pInstance;
m_pInstance = NULL;
}
}
CIMWnd::CIMWnd()
... {
m_pIMCallback = NULL;
m_hWnd = NULL;
m_hInst = NULL;
m_hWndSip = NULL;
}
// ----------------------------------------------------------------------------
// Decription:
// On message MYMSG_REGCALLBACK
// -----------------------------------------------------------------------------
void CIMWnd::OnRegCallback(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
... {
m_pIMCallback = (IIMCallback *)wParam;
}
// ----------------------------------------------------------------------
// Description:
// Window process
// ----------------------------------------------------------------------
LRESULT CIMWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
... {
switch(wMsg)
...{
...
case MYMSG_REGCALLBACK:
m_pInstance->OnRegCallback(hWnd,wMsg,wParam,lParam);
return 0;
...
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
这里需要注意的是m_pIMCallback指针,它保存的是输入法管理器传回来的函数地址,我们可以通过这个回调函数来像外发送字符.例如:m_pIMCallback->SendString(TEXT(","),1);
MYMSG_REGCALLBACK是自定义的消息,用来通知输入法窗口来保存函数地址.该消息的发送是在CInputMethod类的RegisterCallback()函数中.
一个简单的输入法架构基本上已经完成,在下一章中将介绍一些输入法的调试技巧和需要注意的问题.