//========================================================================//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)的一个简单的实现.