漫谈WinCE输入法的编写(五)--以DLL替代CIMWnd

本文介绍了一种使用 DLL 替代 CIMWnd 类实现在 Windows CE 中输入法的方法,通过这种方式,可以更灵活地更新输入法组件。文章详细介绍了 DLL 的编写过程及如何与 CInputMethod 类接口配合使用。
//========================================================================
//TITLE:
// 漫谈WinCE输入法的编写(五)--以DLL替代CIMWnd
//AUTHOR:
// norains
//DATE:
// Friday 12-October-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
之前的一系列文章(恩,好久以前的文章),輸入法的功能實現都是在CIMWnd中,而本文则是以外部的DLL为替代CIMWnd.以DLL替代CIMWnd类有什么好处呢?恩,这个~其实我也说不上,不过嘛,知道一种新方式,有多一种选择,毕竟不是一件坏事,不是么?何况,这个方法,以我个人观点,还更为灵活些.更换输入法部件时,只需要更新dll即可.

我们首先来回顾一下之前一系列文章中定义的CIMWnd接口功能:
class CIMWnd
{
public:
//获取窗口句柄
HWND GetWindow();;
//显示输入法的设置窗口
void ShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst = NULL);
//显示输入法界面
void ShowWindow(BOOL bShow);
//销毁输入法界面
void DestroyWindow();
//初始化窗口,hWndSip是输入法管理器的句柄
BOOL Initialize(HINSTANCE hInst, HWND hWndSip);

...

}

也就是说,为了和CInputMethod(漫谈WinCE输入法的编写(二))衔接起来,我们在dll中也必须实现这五个功能接口.我们新建一个名为DllWnd工程的DLL工程,并且为了避免和系统的函数重复从而导致出现获取函数入口失败,我们将这五个功能接口分别添上IM前缀:
//The interface
//获取窗口句柄
HWND IMGetWindow();
//显示输入法的设置窗口
void IMShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst);
//显示输入法界面
void IMShowWindow(BOOL bShow);
//销毁输入法界面
void IMDestroyWindow();
//初始化窗口
BOOL IMInitialize(HINSTANCE hInstSip, HWND hWndSip);


下面是一个完整的DllWnd代码,其功能是实现一个输入法窗口的创建,并且当点击该窗口时会输出一串测试字符.

#include
"sip.h"
#include
"resource.h"

//===================================================================
#defineMYMSG_REGCALLBACK(WM_USER+100)
//Description:
//Themessageisusingforregisteringtheinputmethodcallbackfunction
//
//Parameters:
//pImCallback=(IIMCallback*)wParam
//0=lParam

//=====================================================================




//====================================================================
//Macrodefine
#defineWINDOW_CLASSTEXT("IMWND_Class")
#defineWINDOW_TITLETEXT("IMWND_Title")

//Thetaskbarheight
#defineTASKBAR_HEIGHT_AUTOHIDE5
#defineTASKBAR_HEIGHT26

#defineIMG_IMWND_WIDTH370
#defineIMG_IMWND_HEIGHT206

#defineSCREEN_WIDTH800
#defineSCREEN_HEIGHT480



//==================================================================
//ForwardDeclare

//------------------------------------------------------------------------
//Theinterface

HWNDIMGetWindow();
voidIMShowUserOptionsDlg(HWNDhWndParent,HINSTANCEhInst);
voidIMShowWindow(BOOLbShow);
voidIMDestroyWindow();
BOOLIMInitialize(HINSTANCEhInstSip,HWNDhWndSip);

//------------------------------------------------------------------------


voidOnDestroy(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
voidOnPaint(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
voidOnRegCallback(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
voidOnLButtonUp(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
//---------------------------------------------------------------------
//Theglobalmember
HWNDg_hWnd=NULL;//输入法功能窗口
HWNDg_hWndSip=NULL;//IM父窗口
HMODULEg_hInst=NULL;//dll的实例句柄
HINSTANCEg_hInstSip=NULL;//sipdll的实例句柄
IIMCallback*g_pIMCallback;//回调函数指针


//-------------------------------------------------------------------
//Description:
//TheDLLMAIN
//
//------------------------------------------------------------------
BOOLAPIENTRYDllMain(HANDLEhModule,
DWORDul_reason_for_call,
LPVOIDlpReserved
)
{
switch(ul_reason_for_call)
{
caseDLL_PROCESS_ATTACH:
{
g_hInst
=(HMODULE)hModule;
break;
}
}

returnTRUE;
}



//-------------------------------------------------------------------
//Description:
//Getthewindowhandle
//
//------------------------------------------------------------------
HWNDIMGetWindow()
{
returng_hWnd;
}


//-------------------------------------------------------------------
//Description:
//Showtheuseroptionsdialog
//
//------------------------------------------------------------------
voidIMShowUserOptionsDlg(HWNDhWndParent,HINSTANCEhInst)
{
MessageBox(NULL,TEXT(
"控制面板可以調出的輸入法設置"),TEXT("設置"),MB_OK);
}


//-------------------------------------------------------------------
//Description:
//Showthewindow
//
//------------------------------------------------------------------
voidIMShowWindow(BOOLbShow)
{
if(bShow==TRUE)
{
::ShowWindow(g_hWnd,SW_SHOW);
}
else
{
::ShowWindow(g_hWnd,SW_HIDE);
}
}


//-------------------------------------------------------------------
//Description:
//Destroythewindow
//
//------------------------------------------------------------------
voidIMDestroyWindow()
{
::DestroyWindow(g_hWnd);
}


//-------------------------------------------------------------------
//Description:
//Initializethewindow
//
//------------------------------------------------------------------
BOOLIMInitialize(HINSTANCEhInstSip,HWNDhWndSip)
{
g_hInstSip
=hInstSip;
g_hWndSip
=hWndSip;




UnregisterClass(WINDOW_CLASS,g_hInst);

WNDCLASSwc
={0};
wc.style
=CS_VREDRAW|CS_HREDRAW;;
wc.lpfnWndProc
=WndProc;
wc.cbClsExtra
=0;
wc.cbWndExtra
=0;
wc.hInstance
=g_hInst;
wc.hIcon
=NULL;
wc.hCursor
=NULL;
wc.hbrBackground
=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName
=NULL;
wc.lpszClassName
=WINDOW_CLASS;
if(RegisterClass(&wc)==0)
{
returnFALSE;
}




//Setthewindowareatosuitwiththeimage
RECTrcClientWnd={0};
GetClientRect(hWndSip,
&rcClientWnd);
RECTrcSipWnd
={0};
GetWindowRect(hWndSip,
&rcSipWnd);
//Itmaybetheframefortheparentwindow,sowemustholdit.
intiWidth=(rcSipWnd.right-rcSipWnd.left)-(rcClientWnd.right-rcClientWnd.left)+IMG_IMWND_WIDTH;
intiHeight=(rcSipWnd.bottom-rcSipWnd.top)-(rcClientWnd.bottom-rcClientWnd.top)+IMG_IMWND_HEIGHT;
rcSipWnd.left
=SCREEN_WIDTH-iWidth;
rcSipWnd.top
=SCREEN_HEIGHT-iHeight-TASKBAR_HEIGHT;
SetWindowPos(hWndSip,hWndSip,rcSipWnd.left,rcSipWnd.top,iWidth,iHeight,NULL);

//CreateSIPwindow.
g_hWnd=CreateWindowEx(0,
WINDOW_CLASS,
WINDOW_TITLE,
WS_CHILD
|WS_BORDER,
rcClientWnd.left,
rcClientWnd.top,
IMG_IMWND_WIDTH,
//rcWnd.right-rcWnd.left,
IMG_IMWND_HEIGHT,//rcWnd.bottom-rcWnd.top,
hWndSip,
NULL,
g_hInst,
NULL
);






if(IsWindow(g_hWnd)==FALSE)
{
returnFALSE;
}



returnTRUE;
}



//-------------------------------------------------------------------
//Description:
//Thewindowprocess
//
//------------------------------------------------------------------
LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
switch(wMsg)
{
caseWM_PAINT:
OnPaint(hWnd,wMsg,wParam,lParam);
return0;
caseMYMSG_REGCALLBACK:
OnRegCallback(hWnd,wMsg,wParam,lParam);
return0;
caseWM_ERASEBKGND:
//Donothinginordernottoflashthewindow
return0;
caseWM_LBUTTONUP:
OnLButtonUp(hWnd,wMsg,wParam,lParam);
return0;

}
returnDefWindowProc(hWnd,wMsg,wParam,lParam);
}



//-------------------------------------------------------------------
//Description:
//OnmessageWM_PAINT
//
//------------------------------------------------------------------
voidOnPaint(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{

PAINTSTRUCTps;
HDChdc
=BeginPaint(hWnd,&ps);
//CreateaDCthatmatchesthedevice
HBITMAPhBitmap=CreateCompatibleBitmap(hdc,IMG_IMWND_WIDTH,IMG_IMWND_HEIGHT);
HDChdcMem
=CreateCompatibleDC(hdc);
//Selectthebitmapintotothecompatibledevicecontext
HGDIOBJhOldSel=SelectObject(hdcMem,hBitmap);

//CreateaDCthatmatchesthedevice
HDChdcBmp=CreateCompatibleDC(hdc);
//Loadthebitmap
HANDLEhBmp=LoadImage(g_hInst,MAKEINTRESOURCE(IDB_PANNEL),IMAGE_BITMAP,0,0,0);
//Selectthebitmapintotothecompatibledevicecontext
HGDIOBJhOldBmpSel=SelectObject(hdcBmp,hBmp);
//CopythebitmapimagetothememoryDC.
BitBlt(hdcMem,0,0,IMG_IMWND_WIDTH,IMG_IMWND_HEIGHT,hdcBmp,0,0,SRCCOPY);


//Drawtothescreen
BitBlt(hdc,0,0,IMG_IMWND_WIDTH,IMG_IMWND_HEIGHT,hdcMem,0,0,SRCCOPY);

//RestoreoriginalbitmapselectionanddestroythememoryDC
SelectObject(hdcBmp,hOldBmpSel);
SelectObject(hdcMem,hOldSel);
DeleteObject(hBitmap);
DeleteDC(hdcBmp);
DeleteDC(hdcMem);
EndPaint(hWnd,
&ps);
}

//-------------------------------------------------------------------
//Description:
//OnmessageMYMSG_REGCALLBACK
//
//------------------------------------------------------------------
voidOnRegCallback(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
g_pIMCallback
=(IIMCallback*)wParam;

}

//-------------------------------------------------------------------
//Description:
//OnmessageWM_LBUTTONUP
//
//------------------------------------------------------------------
voidOnLButtonUp(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
if(g_pIMCallback!=NULL)
{
g_pIMCallback
->SendString(TEXT("輸入法測試程序"),8);
}
}


当然,上部接口CInputMethod也需要更改.为了方便和CIMWnd契合,我们设置两个宏定义:IMWND_FROM_CODE和IMWND_FROM_DLL.

IMWND_FROM_CODE定义时,我们采用CIMWnd作为功能实现窗口;而IMWND_FROM_DLL则是采用上文所说的dllwnd.dll.


///////////////////////////////////////////////////////////////////////
//InputMethod.h:interfacefortheCInputMethodclass.
//
//////////////////////////////////////////////////////////////////////

#ifndefIMPUTMETHOD_H
#defineIMPUTMETHOD_H

#include
"stdafx.h"
#include
"sip.h"
#include
"IMWnd.h"


//-----------------------------------------------------------------
classCInputMethod:publicIInputMethod
{
public:

//IUnknownmethods
STDMETHODIMP_(ULONG)Release(THIS);
STDMETHODIMP_(ULONG)AddRef(THIS);
STDMETHODIMPQueryInterface(THIS_REFIIDriid,LPVOID
*ppv);

//IInputMethod
HRESULTSTDMETHODCALLTYPESetImData(DWORDdwSize,void*pvImData);
HRESULTSTDMETHODCALLTYPEGetImData(DWORDdwSize,
void*pvImData);
HRESULTSTDMETHODCALLTYPERegisterCallback(IIMCallback
*pIMCallback);
HRESULTSTDMETHODCALLTYPEReceiveSipInfo(SIPINFO
*psi);
HRESULTSTDMETHODCALLTYPEGetInfo(IMINFO
*pimi);
HRESULTSTDMETHODCALLTYPEHiding();
HRESULTSTDMETHODCALLTYPEShowing();
HRESULTSTDMETHODCALLTYPEDeselect();
HRESULTSTDMETHODCALLTYPESelect(HWNDhWndSip);
HRESULTSTDMETHODCALLTYPEUserOptionsDlg(HWNDhwndParent);
CInputMethod(
long*plDllCnt,HINSTANCEhInst);
virtual~CInputMethod();

protected:

HINSTANCEm_hInst;
//Thedllinstance
long*m_plDllCnt;//pointtotheGlobalDLLreferencecount
longm_lRef;




#ifdefIMWND_FROM_CODE
CIMWnd
*m_pIMWnd;//Theinputmethodwindowpointer
#defineGETINSTANCE()(m_pIMWnd=CIMWnd::GetInstance())
#defineGETWINDOW()(m_pIMWnd->GetWindow())
#defineSHOWUSEROPTIONSDLG(x,y)(m_pIMWnd->ShowUserOptionsDlg(x,y))
#defineSHOWWINDOW(x)(m_pIMWnd->ShowWindow(x))
#defineDESTROYWINDOW()(m_pIMWnd->DestroyWindow())
#defineINITIALIZE(x,y)(m_pIMWnd->Initialize(x,y))
#endif//#ifdefIMWND_FROM_CODE



#ifdefIMWND_FROM_DLL

BOOLm_bLoadLib;

//Idon'tneedgetinstancefromthedll.
#defineGETINSTANCE()

typedefHWND(WINAPI
*DLL_GETWINDOW)(void);
typedef
void(WINAPI*DLL_SHOWUSEROPTIONSDLG)(HWND,HINSTANCE=NULL);
typedef
void(WINAPI*DLL_SHOWWINDOW)(BOOL);
typedef
void(WINAPI*DLL_DESTROYWINDOW)(void);
typedefBOOL(WINAPI
*DLL_INITIALIZE)(HINSTANCE,HWND);


DLL_GETWINDOWGETWINDOW;
DLL_SHOWUSEROPTIONSDLGSHOWUSEROPTIONSDLG;
DLL_SHOWWINDOWSHOWWINDOW;
DLL_DESTROYWINDOWDESTROYWINDOW;
DLL_INITIALIZEINITIALIZE;

#endif//#ifdefIMWND_FROM_DLL
};

//--------------------------------------------------------------------------------
#endif//IMPUTMETHOD_H



//////////////////////////////////////////////////////////////////////
//InputMethod.cpp:implementationoftheCInputMethodclass.
//
//////////////////////////////////////////////////////////////////////
#include"InputMethod.h"

//--------------------------------------------------------------------
//Macrodefine
#defineSIP_WND_WIDTH200
#defineSIP_WND_HEIGHT180

#defineIMWND_DLL_PATHTEXT("window/dllwnd.dll")
//----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
//Construction/Destruction
//////////////////////////////////////////////////////////////////////

CInputMethod::CInputMethod(
long*plDllCnt,HINSTANCEhInst)
{
GETINSTANCE();
m_hInst
=hInst;
m_plDllCnt
=plDllCnt;
(
*m_plDllCnt)++;
m_lRef
=1;//Setrefcountto1oncreate.


#ifdefIMWND_FROM_DLL

GETWINDOW
=NULL;
SHOWUSEROPTIONSDLG
=NULL;
SHOWWINDOW
=NULL;
DESTROYWINDOW
=NULL;
INITIALIZE
=NULL;

HINSTANCEhInstDll;
hInstDll
=LoadLibrary(IMWND_DLL_PATH);
if(hInstDll!=NULL)
{
GETWINDOW
=(DLL_GETWINDOW)GetProcAddress(hInstDll,TEXT("IMGetWindow"));
SHOWUSEROPTIONSDLG
=(DLL_SHOWUSEROPTIONSDLG)GetProcAddress(hInstDll,TEXT("IMShowUserOptionsDlg"));
SHOWWINDOW
=(DLL_SHOWWINDOW)GetProcAddress(hInstDll,TEXT("IMShowWindow"));
DESTROYWINDOW
=(DLL_DESTROYWINDOW)GetProcAddress(hInstDll,TEXT("IMDestroyWindow"));
INITIALIZE
=(DLL_INITIALIZE)GetProcAddress(hInstDll,TEXT("IMInitialize"));
}

if(GETWINDOW==NULL||
SHOWUSEROPTIONSDLG
==NULL||
SHOWWINDOW
==NULL||
DESTROYWINDOW
==NULL||
INITIALIZE
==NULL)
{
m_bLoadLib
=FALSE;
}
else
{
m_bLoadLib
=TRUE;
}

#endif

}

CInputMethod::
~CInputMethod()
{
(
*m_plDllCnt)--;
}


//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtocreatethewindowsandimagelistfortheinputmethod(IM).
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::Select(HWNDhWndSip)
{

if(INITIALIZE(m_hInst,hWndSip)==FALSE)
{
returnE_FAIL;
}

SHOWWINDOW(TRUE);


returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtoselecttheinputmethod(IM)outofthesoftware-based
//inputpanelwindowandtodestroytheIMwindows.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::Deselect()
{
DESTROYWINDOW();
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtoperformanyinitializationbeforethesoftware-based
//inputpanelwindowisdisplayed
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::Showing()
{
SHOWWINDOW(TRUE);
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtoperformanysavingroutinesbeforethesoftware-based
//inputpanelishidden.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::Hiding()
{
SHOWWINDOW(FALSE);

returnS_OK;
}


//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtoreturninformationaboutthecurrentinput
//method(IM)totheoperatingsystem.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::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;
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//ThismethodisimplementedfortheIMtoreceiveinformationaboutthesize,
//placement,anddockedstatusofthesoftware-basedinputpanel.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::ReceiveSipInfo(SIPINFO*psi)
{
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//ThismethodisimplementedtoreceiveapointertoanIIMCallbackinterface.
//Aninputmethod(IM)usestheIIMCallbackinterfacetosendkeystrokestoapplications
//andtochangetheiconsontheInputPanelbutton.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::RegisterCallback(IIMCallback*pIMCallback)
{

//TelltheIMwindowtoregisterthecallback
HWNDhWnd=GETWINDOW();
SendMessage(hWnd,MYMSG_REGCALLBACK,(WPARAM)pIMCallback,
0);
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtosenddatafromthecurrent
//inputmethod(IM)tothecurrentapplication.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::GetImData(DWORDdwSize,void*pvImData)
{
returnS_OK;
}

//-------------------------------------------------------------------------------------------
//Description:
//Thismethodisimplementedtorespondtoanapplication'srequestto
//setinputmethod(IM)-specificdatawithintheIM.
//----------------------------------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::SetImData(DWORDdwSize,void*pvImData)
{
returnS_OK;
}

//---------------------------------------------------------------------
//Description:
//Incrementobjectrefcount
//----------------------------------------------------------------------
STDMETHODIMPCInputMethod::QueryInterface(REFIIDriid,LPVOID*ppv)
{


#ifdefIMWND_FROM_DLL
if(m_bLoadLib==FALSE)
{
returnE_NOINTERFACE;
}
#endif//#ifdefIMWND_FROM_DLL


//IfcallerwantsourIUnknownorIID_IInputMethod2object,
//returnapointertotheobject.
if(IsEqualIID(riid,IID_IUnknown)||IsEqualIID(riid,IID_IInputMethod)||IsEqualIID(riid,IID_IInputMethod2))
{
//Returnptrtoobject.
*ppv=(IInputMethod*)this;
AddRef();
//Incrementreftopreventdeleteonreturn.
returnNOERROR;
}
*ppv=NULL;
return(E_NOINTERFACE);

}


//---------------------------------------------------------------------
//Description:
//Incrementobjectrefcount
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG)CInputMethod::AddRef()
{

ULONGcnt;
cnt
=(ULONG)InterlockedIncrement(&m_lRef);
returncnt;
}

//---------------------------------------------------------------------
//Description:
//Incrementobjectrefcount
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG)CInputMethod::Release()
{
ULONGcnt;

cnt
=(ULONG)InterlockedDecrement(&m_lRef);
if(cnt==0)
{
delete
this;
return0;
}
returncnt;
}


//---------------------------------------------------------------------
//Description:
//TheSIPControlPanelappletisaskingforaconfigurationdialogboxtobedisplayed.
//----------------------------------------------------------------------
HRESULTSTDMETHODCALLTYPECInputMethod::UserOptionsDlg(HWNDhwndParent)
{

SHOWUSEROPTIONSDLG(hwndParent,m_hInst);
returnS_OK;
}


OK,编译完毕,大功告成!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值