imedllhost09.cpp
上传用户:qiandli
上传日期:2021-02-22
资源大小:103k
文件大小:12k
源码类别:

输入法编程

开发平台:

Visual Basic

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <imm.h>
  5. #include <tchar.h>
  6. #pragma comment(lib,"imm32.lib")
  7. //窗口类名
  8. #define CLSNAME_UI _T("DLLISUI") //UI
  9. #define CS_INPUTSTAR (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS)
  10. #pragma data_seg("mysechx")
  11. DWORD CallBackData1=0;
  12. DWORD CallBackData2=0;
  13. DWORD CallBackData3=0;
  14. DWORD OnloadDllWhenExit=0;    // 当输入法退出时是否卸载客户DLL  0-是,1-否
  15. DWORD LoadNextWhenActive=0;    // 当本输入法激活时,是否自动打开下一个输入法 0-否,1-是
  16. char g_IMEDLLString[802]="";
  17. #pragma data_seg()
  18. typedef DWORD (CALLBACK * RUNDLLHOSTCALLBACK)(DWORD calldata1, DWORD calldata2,DWORD calldata3);
  19. HMODULE CilentDLL=NULL;
  20. RUNDLLHOSTCALLBACK RunDllCallBackX=NULL;
  21. // 先定义好各种函数
  22. BOOL ImeClass_Register(HINSTANCE hInstance);
  23. void ImeClass_Unregister(HINSTANCE hInstance);
  24. LRESULT WINAPI UIWndProc(HWND hUIWnd,UINT message,WPARAM wParam,LPARAM lParam);
  25. BOOL MyGenerateMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam);
  26. void MyLoadCilentDLLFun()
  27. {
  28. if (CilentDLL==NULL)
  29. {
  30.   if (lstrlen(g_IMEDLLString)>0)
  31.   {
  32.   CilentDLL=LoadLibrary(g_IMEDLLString);   // 在输入法加载时同时加载客户DLL
  33.   if (CilentDLL!=NULL)
  34.   {
  35.   // 如果存在,则调用客户DLL指定名称的回调函数
  36.   RunDllCallBackX=(RUNDLLHOSTCALLBACK)GetProcAddress(CilentDLL,"RunDllHostCallBack");
  37.   if (RunDllCallBackX!=NULL)
  38.   {
  39.   RunDllCallBackX(CallBackData1,CallBackData2,CallBackData3);
  40.   }
  41.   }
  42.   }
  43. }
  44. }
  45. BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
  46. {
  47.    switch(fdwReason)
  48.     {
  49.       case DLL_PROCESS_ATTACH:
  50.   if(!ImeClass_Register(hinstDLL)) return FALSE;   // DLL加载时注册必须的UI基本窗口类
  51.   MyLoadCilentDLLFun();
  52.   break;
  53.   case DLL_THREAD_ATTACH:
  54.  break;
  55.   case DLL_THREAD_DETACH:
  56.  break;
  57.       case DLL_PROCESS_DETACH:
  58.   ImeClass_Unregister(hinstDLL);  // DLL退出时注销注册的窗口类
  59.   if (CilentDLL!=NULL && OnloadDllWhenExit==0)
  60.   {
  61.   FreeLibrary(CilentDLL);    // 输入法退出时卸载客户DLL
  62.   }
  63.         break;
  64.       default:
  65.         break;
  66.     }
  67. return true;
  68. }
  69. int WINAPI IMESetPubString(LPCTSTR tmpStr,DWORD UnloadDLL,DWORD loadNextIme,DWORD DllData1,DWORD DllData2,DWORD DllData3)
  70. {
  71. CallBackData1=DllData1;
  72. CallBackData2=DllData2;
  73. CallBackData3=DllData3;
  74. OnloadDllWhenExit=UnloadDLL;
  75. LoadNextWhenActive=loadNextIme;
  76. memset(g_IMEDLLString,0,802);
  77. if (lstrlen(tmpStr)>800)
  78. {
  79. lstrcpyn(g_IMEDLLString,tmpStr,800);
  80. }
  81. else
  82. {
  83. lstrcpy(g_IMEDLLString,tmpStr);
  84. }
  85. return 1;
  86. }
  87. int WINAPI IMEClearPubString()
  88. {
  89. CallBackData1=0;
  90. CallBackData2=0;
  91. CallBackData3=0;
  92. OnloadDllWhenExit=0;
  93. LoadNextWhenActive=0;
  94. memset(g_IMEDLLString,0,802);
  95. return 1;
  96. }
  97. //************************************************************
  98. // 基本输入法窗口UI类注册
  99. //************************************************************
  100. BOOL ImeClass_Register(HINSTANCE hInstance)
  101. {
  102.     WNDCLASSEX wc;
  103.     //
  104.     // register class of UI window.
  105.     //
  106.     wc.cbSize         = sizeof(WNDCLASSEX);
  107.     wc.style          = CS_INPUTSTAR | CS_IME;
  108.     wc.lpfnWndProc    = UIWndProc;
  109.     wc.cbClsExtra     = 0;
  110.     wc.cbWndExtra     = 2 * sizeof(LONG);
  111.     wc.hInstance      = hInstance;
  112.     wc.hCursor        = LoadCursor( NULL, IDC_ARROW );
  113.     wc.hIcon          = NULL;
  114.     wc.lpszMenuName   = (LPTSTR)NULL;
  115.     wc.lpszClassName  = CLSNAME_UI;
  116.     wc.hbrBackground  = NULL;
  117.     wc.hIconSm        = NULL;
  118.     if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  119.         return FALSE;
  120. return TRUE;
  121. }
  122. //**************************************************************
  123. // 注销注册的窗口类
  124. //**************************************************************
  125. void ImeClass_Unregister(HINSTANCE hInstance)
  126. {
  127. UnregisterClass(CLSNAME_UI,hInstance);
  128. }
  129. // ------------------------------------
  130. DWORD WINAPI ImeConversionList(HIMC hIMC,LPCTSTR lpSource,LPCANDIDATELIST lpCandList,DWORD dwBufLen,UINT uFlag)
  131. {
  132.     return 0;
  133. }
  134. BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData)
  135. {
  136.     switch (dwMode) {
  137.     case IME_CONFIG_GENERAL:
  138.         MessageBox(NULL,"Windows标准输入法扩展服务 V1.0  ","关于输入法扩展",48);
  139.         break;
  140.     default:
  141.         return (FALSE);
  142.         break;
  143.     }
  144.     return (TRUE);
  145. }
  146. BOOL WINAPI ImeDestroy(UINT uForce)
  147. {
  148.     if (uForce) {
  149.         return (FALSE);
  150.     }
  151.     return (TRUE);
  152. }
  153. LRESULT WINAPI ImeEscape(HIMC hIMC,UINT uSubFunc,LPVOID lpData)
  154. {
  155. return FALSE;
  156. }
  157. BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption)
  158. {
  159. // 输入法初始化过程
  160.     lpIMEInfo->dwPrivateDataSize = 0; //系统根据它为INPUTCONTEXT.hPrivate分配空间
  161.     lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | 
  162.                              IME_PROP_IGNORE_UPKEYS |
  163.  IME_PROP_END_UNLOAD; 
  164.     lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE |
  165. IME_CMODE_NATIVE;
  166.     lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE;
  167.     lpIMEInfo->fdwUICaps = UI_CAP_2700;
  168. lpIMEInfo->fdwSCSCaps = 0;
  169.     lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;
  170.     _tcscpy(lpszUIClass,CLSNAME_UI);  // 注意该输入法基本窗口类必须注册,否则输入法不能正常运行
  171.     return TRUE;
  172. }
  173. /*
  174. 系统调用这个接口来判断IME是否处理当前键盘输入
  175. HIMC hIMC:输入上下文
  176. UINT uKey:键值
  177. LPARAM lKeyData: unknown
  178. CONST LPBYTE lpbKeyState:键盘状态,包含256键的状态
  179. return : TRUE-IME处理,FALSE-系统处理
  180. 系统则调用ImeToAsciiEx,否则直接将键盘消息发到应用程序
  181. */
  182. BOOL WINAPI ImeProcessKey(HIMC hIMC,UINT uKey,LPARAM lKeyData,CONST LPBYTE lpbKeyState)
  183. {
  184. return FALSE;
  185. }
  186. /**********************************************************************/
  187. /* ImeSelect()                                                        */
  188. /* Return Value:                                                      */
  189. /*      TRUE - successful, FALSE - failure                            */
  190. /**********************************************************************/
  191. BOOL WINAPI ImeSelect(HIMC hIMC,BOOL fSelect)
  192. {
  193. MyLoadCilentDLLFun();   // 在切换输入法时判断是否需要加载客户DLL
  194.     if (!hIMC) {
  195.         return (FALSE);
  196.     }
  197. if (fSelect==TRUE && LoadNextWhenActive!=0)
  198. {
  199. //ActivateKeyboardLayout((HKL)HKL_NEXT,0);  // 不要在该接口中使用此函数切换到下一个输入法,否则函数返回时输入法又会切换回去
  200. MyGenerateMessage(hIMC,WM_INPUTLANGCHANGEREQUEST,1,(LPARAM)HKL_NEXT);
  201. }
  202.     return TRUE;
  203. }
  204. /*
  205. 使一个输入上下文激活或者失活,并通知输入法最新的输入上下文,可以在此做一些初始化工作
  206. HIMC hIMC :输入上下文
  207. BOOL fFlag : TRUE if activated, FALSE if deactivated. 
  208. Returns TRUE if successful, FALSE otherwise. 
  209. */
  210. BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag)
  211. {
  212. //通过IME消息来实现窗口状态变化
  213.     return TRUE;
  214. }
  215. /*
  216. Causes the IME to arrange the composition string structure with the given data.
  217. This function causes the IME to send the WM_IME_COMPOSITION message. 
  218. Returns TRUE if successful, FALSE otherwise.
  219. */
  220. BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwComp, LPCVOID lpRead, DWORD dwRead)
  221. {
  222.     return FALSE;
  223. }
  224. /*
  225. 应用程序调用这个接口来进行输入上下文的转换,输入法程序在这个接口中转换用户的输入
  226. UINT uVKey:键值,如果在ImeInquire接口中为fdwProperty设置了属性IME_PROP_KBD_CHAR_FIRST,则高字节是输入键值
  227. UINT uScanCode:按键的扫描码,有时两个键有同样的键值,这时需要使用uScanCode来区分
  228. CONST LPBYTE lpbKeyState:键盘状态,包含256键的状态
  229. LPDWORD lpdwTransKey:消息缓冲区,用来保存IME要发给应用程序的消息,第一个双字是缓冲区可以容纳的最大消息条数
  230. UINT fuState:Active menu flag(come from msdn)
  231. HIMC hIMC:输入上下文
  232. return : 返回保存在消息缓冲区lpdwTransKey中的消息个数
  233. */
  234. UINT WINAPI ImeToAsciiEx (UINT uVKey,UINT uScanCode,CONST LPBYTE lpbKeyState,LPDWORD lpdwTransKey,UINT fuState,HIMC hIMC)
  235. {
  236.     return 0;
  237. }
  238. //由应用程序发给输入法的消息,输入法可以在此响应用程序的请求
  239. //return : TRUE-正确响应了请求,FALSE-无响应
  240. BOOL WINAPI NotifyIME(HIMC hIMC,DWORD dwAction,DWORD dwIndex,DWORD dwValue)
  241. {
  242.     BOOL bRet = FALSE;
  243.     switch(dwAction)
  244.     {
  245. case NI_OPENCANDIDATE:
  246. break;
  247. case NI_CLOSECANDIDATE:
  248. break;
  249. case NI_SELECTCANDIDATESTR:
  250. break;
  251. case NI_CHANGECANDIDATELIST:
  252. break;
  253. case NI_SETCANDIDATE_PAGESTART:
  254. break;
  255. case NI_SETCANDIDATE_PAGESIZE:
  256. break;
  257. case NI_CONTEXTUPDATED:
  258. switch (dwValue)
  259. {
  260. case IMC_SETCONVERSIONMODE:
  261. break;
  262. case IMC_SETSENTENCEMODE:
  263. break;
  264. case IMC_SETCANDIDATEPOS:
  265. break;
  266. case IMC_SETCOMPOSITIONFONT:
  267. break;
  268. case IMC_SETCOMPOSITIONWINDOW:
  269. break;
  270. case IMC_SETOPENSTATUS:
  271. break;
  272. default:
  273. break;
  274. }
  275. break;
  276. case NI_COMPOSITIONSTR:
  277. switch (dwIndex)
  278. {
  279. case CPS_COMPLETE:
  280. break;
  281. case CPS_CONVERT:
  282. break;
  283. case CPS_REVERT:
  284. break;
  285. case CPS_CANCEL:
  286. break;
  287. default:
  288. break;
  289. }
  290. break;
  291. default:
  292. break;
  293.     }
  294.     return bRet;
  295. }
  296. /**********************************************************************/
  297. /* ImeRegsisterWord                                                   */
  298. /* Return Value:                                                      */
  299. /*      TRUE - successful, FALSE - failure                            */
  300. /**********************************************************************/
  301. BOOL WINAPI ImeRegisterWord(
  302.     LPCTSTR lpszReading,
  303.     DWORD   dwStyle,
  304.     LPCTSTR lpszString)
  305. {
  306.     return (FALSE);
  307. }
  308. /**********************************************************************/
  309. /* ImeUnregsisterWord                                                 */
  310. /* Return Value:                                                      */
  311. /*      TRUE - successful, FALSE - failure                            */
  312. /**********************************************************************/
  313. BOOL WINAPI ImeUnregisterWord(
  314.     LPCTSTR lpszReading,
  315.     DWORD   dwStyle,
  316.     LPCTSTR lpszString)
  317. {
  318.     return (FALSE);
  319. }
  320. /**********************************************************************/
  321. /* ImeGetRegsisterWordStyle                                           */
  322. /* Return Value:                                                      */
  323. /*      number of styles copied/required                              */
  324. /**********************************************************************/
  325. UINT WINAPI ImeGetRegisterWordStyle(
  326.     UINT       nItem,
  327.     LPSTYLEBUF lpStyleBuf)
  328. {
  329.     return (FALSE);
  330. }
  331. /**********************************************************************/
  332. /* ImeEnumRegisterWord                                                */
  333. /* Return Value:                                                      */
  334. /*      the last value return by the callback function                */
  335. /**********************************************************************/
  336. UINT WINAPI ImeEnumRegisterWord(
  337.     REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,
  338.     LPCTSTR              lpszReading,
  339.     DWORD                dwStyle,
  340.     LPCTSTR              lpszString,
  341.     LPVOID               lpData)
  342. {
  343.     return (FALSE);
  344. }
  345. /**********************************************************************/
  346. /*                                                                    */
  347. /* UIWndProc()                                                        */
  348. /*                                                                    */
  349. /* 输入法界面窗口的窗口处理过程                                       */
  350. /*                                                                    */
  351. /**********************************************************************/
  352. LRESULT WINAPI UIWndProc(HWND hUIWnd,UINT message,WPARAM wParam,LPARAM lParam)
  353. {
  354.     return 0;
  355. }
  356. LRESULT WINAPI StatusWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
  357. {
  358. // 输入法状态条的窗口处理过程
  359. return 0;
  360. }
  361. LRESULT WINAPI CompWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
  362. {
  363. // 输入法显示候选字的窗口的的窗口处理过程
  364. return 0;
  365. }
  366. LRESULT WINAPI CandWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
  367. {
  368. // 输入法编码窗口的窗口处理过程
  369. return 0;
  370. }
  371. //*****************************************************************
  372. // 向HIMC发送消息
  373. // 利用此函数直接向输入法所属窗口发送消息
  374. //*****************************************************************
  375. BOOL MyGenerateMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam)
  376. {
  377. BOOL bRet=FALSE;
  378.     LPINPUTCONTEXT lpIMC= ImmLockIMC(hIMC);
  379. if(lpIMC == NULL)
  380. return FALSE;    
  381.     if (IsWindow(lpIMC->hWnd))
  382.     {
  383. PostMessage(lpIMC->hWnd,msg,wParam,lParam);
  384. bRet=TRUE;
  385.     }
  386. ImmUnlockIMC(hIMC); 
  387. return bRet;
  388. }