漫谈WinCE输入法的编写(二)
//========================================================================
//TITLE:
// 漫谈WinCE输入法的编写(二)
//AUTHOR:
// norains
//DATE:
// Monday 11-February -2007
//Environment:
// EVC4.0 + Standard SDK
//========================================================================
在上一节中我们了解了CClassFactory和CInputMethod的基本架构功能,现在就让我们来看看具体是如何实现的吧.
首先是CClassFactory的实现:
CClassFactory::CClassFactory(long *plDllCnt,HINSTANCE hInst)
{
//初始化设置为1次
m_lRef = 1;
//Dll的引用次数,该指针指向的是一个外部的变量
m_plDllCnt = plDllCnt;
//保存句柄
m_hInst = hInst;
}
CClassFactory::~CClassFactory()
{
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID *ppv)
{
//返回IUnknown或IClassFactory对象
if (IsEqualIID (riid, IID_IUnknown) || IsEqualIID (riid, IID_IClassFactory))
{
//返回指向对象的指针
*ppv = (LPVOID)this;
//增加计数,以避免返回的时候卸载该对象.
AddRef(); // Increment ref to prevent delete on return.
//情况正常,成功返回
return NOERROR;
}
*ppv = NULL;
//但接口不是调用者所需的,则失败返回.
return (E_NOINTERFACE);
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
ULONG cnt;
cnt = (ULONG)InterlockedIncrement (&m_lRef);
return cnt;
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClassFactory::Release()
{
ULONG cnt;
cnt = (ULONG)InterlockedDecrement (&m_lRef);
if (cnt == 0)
{
delete this;
}
return cnt;
}
//---------------------------------------------------------------------
//Description:
// CreateInstance - Called to have class factory object create other objects
//----------------------------------------------------------------------
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppv)
{
//创建一个指向CInputMethod对象的指针.
CInputMethod *pInputMethod;
HRESULT hr;
if (pUnkOuter)
{
return (CLASS_E_NOAGGREGATION);
}
if (IsEqualIID (riid, IID_IUnknown) || IsEqualIID (riid, IID_IInputMethod) || IsEqualIID (riid, IID_IInputMethod2))
{
// 创建一个输入法对象
pInputMethod = new CInputMethod(m_plDllCnt,m_hInst);
if (!pInputMethod)
{
//内存分配失败
return E_OUTOFMEMORY;
}
//查看该输入法对象的接口是否支持是我们所需要的
hr = pInputMethod->QueryInterface (riid, ppv);
//如果不是我们所需的接口方法,那么下面这个函数将会删除刚刚创建的对象
pInputMethod->Release ();
return hr;
}
return E_NOINTERFACE;
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
if (fLock)
{
InterlockedIncrement (m_plDllCnt);
}
else
{
InterlockedDecrement (m_plDllCnt);
}
return NOERROR;
}
然后我们来看看CInputMethod类的实现
CInputMethod::CInputMethod(long *plDllCnt, HINSTANCE hInst)
{
//获取输入法窗口的实例
m_pIMWnd = CIMWnd::GetInstance();
m_hInst = hInst;
m_plDllCnt = plDllCnt;
//增加一次计数
(*m_plDllCnt)++;
m_lRef = 1; // Set ref count to 1 on create.
}
CInputMethod::~CInputMethod()
{
//销毁时减少一次计数
(*m_plDllCnt)--;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to create the windows and image list for the input method (IM).
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::Select(HWND hWndSip)
{
//初始化输入法界面窗口
if(m_pIMWnd->Initialize(m_hInst,hWndSip) == FALSE)
{
return E_FAIL;
}
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to select the input method (IM) out of the software-based
//input panel window and to destroy the IM windows.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::Deselect()
{
//销毁输入法界面窗口
m_pIMWnd->DestroyWindow();
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to perform any initialization before the software-based
//input panel window is displayed
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::Showing()
{
//显示输入法界面窗口
m_pIMWnd->ShowWindow(TRUE);
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to perform any saving routines before the software-based
//input panel is hidden.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::Hiding()
{
//隐藏输入法界面窗口
m_pIMWnd->ShowWindow(FALSE);
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to return information about the current input
//method (IM) to the operating system.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::GetInfo(IMINFO *pimi)
{
pimi->cbSize = sizeof (IMINFO);
pimi->hImageNarrow = 0;
pimi->hImageWide = 0;
pimi->iNarrow = 0;
pimi->iWide = 0;
pimi->fdwFlags = SIPF_DOCKED;
pimi->rcSipRect.left = 0;
pimi->rcSipRect.top = 0;
pimi->rcSipRect.right = SIP_WND_WIDTH;
pimi->rcSipRect.bottom = SIP_WND_HEIGHT;
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented for the IM to receive information about the size,
//placement, and docked status of the software-based input panel.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::ReceiveSipInfo(SIPINFO *psi)
{
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to receive a pointer to an IIMCallback interface.
//An input method (IM) uses the IIMCallback interface to send keystrokes to applications
//and to change the icons on the Input Panel button.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::RegisterCallback(IIMCallback *pIMCallback)
{
//发送一条自定义消息传递回调函数的地址给输入法界面窗口
HWND hWnd = m_pIMWnd->GetWindow();
SendMessage(hWnd,MYMSG_REGCALLBACK,(WPARAM)pIMCallback,0);
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to send data from the current
//input method (IM) to the current application.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::GetImData(DWORD dwSize, void *pvImData)
{
return S_OK;
}
//-------------------------------------------------------------------------------------------
//Description:
// This method is implemented to respond to an application's request to
//set input method (IM)-specific data within the IM.
//----------------------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::SetImData(DWORD dwSize, void *pvImData)
{
return S_OK;
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP CInputMethod::QueryInterface(REFIID riid, LPVOID *ppv)
{
//如果当前的接口符合要求,则返回一个接口对象
if (IsEqualIID (riid, IID_IUnknown) || IsEqualIID (riid, IID_IInputMethod) || IsEqualIID (riid, IID_IInputMethod2))
{
*ppv = (IInputMethod *)this;
AddRef();
return NOERROR;
}
*ppv = NULL;
return (E_NOINTERFACE);
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CInputMethod::AddRef()
{
ULONG cnt;
cnt = (ULONG)InterlockedIncrement (&m_lRef);
return cnt;
}
//---------------------------------------------------------------------
//Description:
// Increment object ref count
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CInputMethod::Release()
{
ULONG cnt;
cnt = (ULONG)InterlockedDecrement (&m_lRef);
if (cnt == 0)
{
delete this;
return 0;
}
return cnt;
}
//---------------------------------------------------------------------
//Description:
// The SIP Control Panel applet is asking for a configuration dialog box to be displayed.
//----------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CInputMethod::UserOptionsDlg(HWND hwndParent)
{
//显示设置窗口
m_pIMWnd->ShowUserOptionsDlg(hwndParent,m_hInst);
return S_OK;
}
CInputMethod和CClassFactory的实现我们暂时就先说到这里,下一章我们将会讨论输入法界面窗口(CIMWnd)的一个简单的实现.