Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1382 lines
38 KiB

  1. /**************************************************************************\
  2. * Module Name: softkbdimx.cpp
  3. *
  4. * Copyright (c) 1985 - 2000, Microsoft Corporation
  5. *
  6. * Implement TIP interface for Soft Keyboard Input.
  7. *
  8. * History:
  9. * 28-March-2000 weibz Created
  10. \**************************************************************************/
  11. #include "private.h"
  12. #include "softkbdimx.h"
  13. #include "globals.h"
  14. #include "immxutil.h"
  15. #include "proputil.h"
  16. #include "funcprv.h"
  17. #include "helpers.h"
  18. #include "editcb.h"
  19. #include "dispattr.h"
  20. #include "computil.h"
  21. #include "timsink.h"
  22. #include "ats.h"
  23. #include "lpns.h"
  24. #include "regsvr.h"
  25. #include "softkbdes.h"
  26. #include "mui.h"
  27. #include "regimx.h"
  28. #include "xstring.h"
  29. #include "cregkey.h"
  30. extern REGTIPLANGPROFILE c_rgProf[];
  31. // Implementation of CSoftkbdRegistry.
  32. //+---------------------------------------------------------------------------
  33. //
  34. // ctor
  35. //
  36. //----------------------------------------------------------------------------
  37. CSoftkbdRegistry::CSoftkbdRegistry()
  38. {
  39. extern void DllAddRef(void);
  40. m_fInitialized = FALSE;
  41. DllAddRef( );
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // dtor
  46. //
  47. //----------------------------------------------------------------------------
  48. CSoftkbdRegistry::~CSoftkbdRegistry()
  49. {
  50. extern void DllRelease(void);
  51. if (m_rgLang.Count())
  52. m_rgLang.Clear();
  53. DllRelease();
  54. }
  55. // Generate the Current Lang Profile List from registry.
  56. HRESULT CSoftkbdRegistry::_GenerateCurrentLangProfileList( )
  57. {
  58. HRESULT hr = S_OK;
  59. CComPtr<IEnumTfLanguageProfiles> cpEnumTfLangProf;
  60. if ( m_fInitialized == FALSE)
  61. {
  62. hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL,
  63. CLSCTX_INPROC_SERVER,
  64. IID_ITfInputProcessorProfilesEx, (void**)&m_cpInputProcessorProfiles);
  65. // Load profile name from resource.
  66. LoadStringWrapW(g_hInst, IDS_SFTKBD_STANDARD_PROFILE, m_pwszStandard, 128);
  67. LoadStringWrapW(g_hInst, IDS_SFTKBD_SYMBOL_PROFILE, m_pwszSymbol, 128);
  68. char szFilePath[MAX_PATH];
  69. GetModuleFileName(g_hInst, szFilePath, ARRAYSIZE(szFilePath));
  70. StringCchCopyW(m_pwszIconFile, ARRAYSIZE(m_pwszIconFile), AtoW(szFilePath));
  71. if ( hr == S_OK )
  72. m_fInitialized = TRUE;
  73. }
  74. if (hr == S_OK)
  75. {
  76. LONG lret = ERROR_SUCCESS;
  77. CMyRegKey regkey;
  78. if (m_rgLang.Count())
  79. m_rgLang.Clear();
  80. // Get the Language profile list for all languages.
  81. char szSoftkbdLangProfKey[MAX_PATH];
  82. char szClsidStr[64];
  83. StringCchCopyA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szCTFTIPKey);
  84. CLSIDToStringA(CLSID_SoftkbdIMX, szClsidStr);
  85. StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), szClsidStr);
  86. StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), "\\");
  87. StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szLanguageProfileKey);
  88. lret = regkey.Open(HKEY_LOCAL_MACHINE,
  89. szSoftkbdLangProfKey,
  90. KEY_READ);
  91. if ( ERROR_SUCCESS == lret )
  92. {
  93. char szProfileName[MAX_PATH];
  94. char szLangIdName[MAX_PATH];
  95. DWORD dwIndex = 0;
  96. LANGID langid;
  97. BOOL fStandExist = FALSE;
  98. BOOL fSymExist = FALSE;
  99. TCHAR achClsidStd[CLSID_STRLEN+1];
  100. TCHAR achClsidSym[CLSID_STRLEN+1];
  101. CMyRegKey regLangKey;
  102. ULONG ulCount = 0;
  103. CLSIDToStringA(c_guidProfile, achClsidStd);
  104. CLSIDToStringA(c_guidProfileSym, achClsidSym);
  105. // Enum the subkey for langid.
  106. while ( ERROR_SUCCESS == regkey.EnumKey(dwIndex, szLangIdName, ARRAYSIZE(szLangIdName)))
  107. {
  108. lret = regLangKey.Open(regkey.m_hKey,
  109. szLangIdName,
  110. KEY_READ);
  111. if ( ERROR_SUCCESS == lret )
  112. {
  113. char *pLangStr;
  114. int iLangLen;
  115. DWORD dwProfIndex;
  116. pLangStr = szLangIdName;
  117. if ( (tolower(pLangStr[0]) == '0') && (tolower(pLangStr[1]) == 'x'))
  118. pLangStr += 2;
  119. iLangLen = strlen(pLangStr);
  120. langid = 0;
  121. for ( int i=0; i<iLangLen; i++)
  122. {
  123. WORD wVchar;
  124. char cLower;
  125. cLower = (char)tolower(pLangStr[i]);
  126. wVchar = 0;
  127. if ((cLower <= '9') && (cLower >= '0'))
  128. wVchar = cLower - '0';
  129. if ((cLower <= 'f') && (cLower >= 'a' ))
  130. wVchar = cLower - 'a' + 10;
  131. langid = langid * 16 + wVchar;
  132. }
  133. fStandExist = fSymExist = FALSE;
  134. dwProfIndex = 0;
  135. while (!(fStandExist && fSymExist)
  136. && ERROR_SUCCESS == regLangKey.EnumKey(dwProfIndex, szProfileName, ARRAYSIZE(szProfileName)))
  137. {
  138. if ( !_stricmp(szProfileName, achClsidStd) )
  139. fStandExist = TRUE;
  140. else if ( !_stricmp(szProfileName, achClsidSym) )
  141. fSymExist = TRUE;
  142. dwProfIndex++;
  143. }
  144. if ( fStandExist && fSymExist )
  145. {
  146. LANGID *pLang;
  147. m_rgLang.Append(1);
  148. pLang = m_rgLang.GetPtr(ulCount);
  149. if ( pLang )
  150. {
  151. ulCount ++;
  152. *pLang = langid;
  153. }
  154. }
  155. regLangKey.Close( );
  156. }
  157. dwIndex ++;
  158. }
  159. }
  160. }
  161. return hr;
  162. }
  163. // Add or Remove Language profile
  164. HRESULT CSoftkbdRegistry::_SetSoftkbdTIP(LANGID langid, BOOL fEnable )
  165. {
  166. HRESULT hr = S_OK;
  167. ULONG ulCount;
  168. BOOL fAllLangExist = FALSE;
  169. BOOL fLangExist = FALSE;
  170. LANGID *pLangId = NULL;
  171. hr = _GenerateCurrentLangProfileList( );
  172. if ( hr != S_OK ) return hr;
  173. ulCount = m_rgLang.Count();
  174. if ( langid == 0 || langid == (LANGID)0xffff )
  175. {
  176. // Remove all the Profiles first.
  177. for (ULONG i=0; i<ulCount; i++)
  178. {
  179. pLangId = m_rgLang.GetPtr(i);
  180. if ( pLangId )
  181. {
  182. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  183. *pLangId,
  184. c_guidProfile);
  185. if (S_OK == hr)
  186. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  187. *pLangId,
  188. c_guidProfileSym);
  189. }
  190. }
  191. if ( fEnable && hr == S_OK) // Add this profile for all languages.
  192. {
  193. hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
  194. (LANGID)0xffff,
  195. c_guidProfile,
  196. m_pwszStandard,
  197. wcslen(m_pwszStandard),
  198. m_pwszIconFile,
  199. wcslen(m_pwszIconFile),
  200. 0);
  201. if ( hr == S_OK )
  202. {
  203. // Set DisplayName for MUI supporting
  204. hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
  205. (LANGID)0xffff,
  206. c_guidProfile,
  207. m_pwszIconFile,
  208. wcslen(m_pwszIconFile),
  209. IDS_SFTKBD_STANDARD_PROFILE );
  210. }
  211. if ( hr == S_OK )
  212. {
  213. hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
  214. (LANGID)0xffff,
  215. c_guidProfileSym,
  216. m_pwszSymbol,
  217. wcslen(m_pwszSymbol),
  218. m_pwszIconFile,
  219. wcslen(m_pwszIconFile),
  220. 1);
  221. }
  222. if ( hr == S_OK )
  223. {
  224. // Set DisplayName for MUI supporting
  225. hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
  226. (LANGID)0xffff,
  227. c_guidProfileSym,
  228. m_pwszIconFile,
  229. wcslen(m_pwszIconFile),
  230. IDS_SFTKBD_SYMBOL_PROFILE );
  231. }
  232. }
  233. return hr;
  234. }
  235. // Check to see if this profile is already there
  236. for (ULONG i=0; i<ulCount; i++)
  237. {
  238. if ( fAllLangExist && fLangExist )
  239. break;
  240. pLangId = m_rgLang.GetPtr(i);
  241. if ( pLangId )
  242. {
  243. if ( *pLangId == (LANGID)0xffff)
  244. fAllLangExist = TRUE;
  245. if ( *pLangId == langid )
  246. fLangExist = TRUE;
  247. }
  248. }
  249. if ( fEnable )
  250. {
  251. if ( !fAllLangExist && !fLangExist )
  252. {
  253. hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
  254. langid,
  255. c_guidProfile,
  256. m_pwszStandard,
  257. wcslen(m_pwszStandard),
  258. m_pwszIconFile,
  259. wcslen(m_pwszIconFile),
  260. 0);
  261. if ( hr == S_OK )
  262. {
  263. // Set DisplayName for MUI supporting
  264. hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
  265. langid,
  266. c_guidProfile,
  267. m_pwszIconFile,
  268. wcslen(m_pwszIconFile),
  269. IDS_SFTKBD_STANDARD_PROFILE );
  270. }
  271. if ( hr == S_OK )
  272. {
  273. hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
  274. langid,
  275. c_guidProfileSym,
  276. m_pwszSymbol,
  277. wcslen(m_pwszSymbol),
  278. m_pwszIconFile,
  279. wcslen(m_pwszIconFile),
  280. 1);
  281. }
  282. if ( hr == S_OK )
  283. {
  284. // Set DisplayName for MUI supporting
  285. hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
  286. langid,
  287. c_guidProfileSym,
  288. m_pwszIconFile,
  289. wcslen(m_pwszIconFile),
  290. IDS_SFTKBD_SYMBOL_PROFILE );
  291. }
  292. }
  293. }
  294. else
  295. {
  296. // Remove the specified or all Profiles.
  297. for (ULONG i=0; i<ulCount; i++)
  298. {
  299. pLangId = m_rgLang.GetPtr(i);
  300. if ( pLangId )
  301. {
  302. if ( fAllLangExist )
  303. {
  304. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  305. *pLangId,
  306. c_guidProfile);
  307. if ( S_OK == hr )
  308. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  309. *pLangId,
  310. c_guidProfileSym);
  311. }
  312. else if ( fLangExist )
  313. {
  314. if ( *pLangId == langid )
  315. {
  316. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  317. langid,
  318. c_guidProfile);
  319. if ( S_OK == hr )
  320. hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
  321. langid,
  322. c_guidProfileSym);
  323. }
  324. }
  325. }
  326. }
  327. }
  328. return hr;
  329. }
  330. HRESULT CSoftkbdRegistry::EnableSoftkbd(LANGID langid )
  331. {
  332. return _SetSoftkbdTIP(langid, TRUE);
  333. }
  334. HRESULT CSoftkbdRegistry::DisableSoftkbd(LANGID langid )
  335. {
  336. return _SetSoftkbdTIP(langid, FALSE);
  337. }
  338. //+---------------------------------------------------------------------------
  339. //
  340. // ctor
  341. //
  342. //----------------------------------------------------------------------------
  343. CSoftkbdIMX::CSoftkbdIMX()
  344. {
  345. extern void DllAddRef(void);
  346. _fInitialized = FALSE;
  347. _SoftKbd = NULL;
  348. _CurKbdType = KBDTYPE_NONE;
  349. _CurLayout = NON_LAYOUT;
  350. _tim = NULL;
  351. _dim = NULL;
  352. _pCes = NULL;
  353. DllAddRef();
  354. }
  355. //+---------------------------------------------------------------------------
  356. //
  357. // dtor
  358. //
  359. //----------------------------------------------------------------------------
  360. CSoftkbdIMX::~CSoftkbdIMX()
  361. {
  362. extern void DllRelease(void);
  363. if ( _SoftKbd != NULL )
  364. {
  365. _SoftKbd->DestroySoftKeyboardWindow( );
  366. }
  367. if ( _hOwnerWnd != NULL )
  368. DestroyWindow(_hOwnerWnd);
  369. _fInitialized = FALSE;
  370. if ( _SoftKbd != NULL )
  371. {
  372. if ( _KbdSymbol.pskbdes != NULL )
  373. {
  374. _SoftKbd->UnadviseSoftKeyboardEventSink(_KbdSymbol.dwSkbdESCookie);
  375. _SoftKbd->UnadviseSoftKeyboardEventSink(_dwsftkbdwndesCookie);
  376. delete _psftkbdwndes;
  377. delete _KbdSymbol.pskbdes;
  378. }
  379. }
  380. if ( _pCes != NULL )
  381. {
  382. _fOnOffSave = FALSE;
  383. _pCes->_Unadvise();
  384. SafeReleaseClear(_pCes);
  385. }
  386. SafeRelease(_SoftKbd);
  387. SafeRelease(_pFuncPrv);
  388. DllRelease();
  389. }
  390. //
  391. // Only when GUID_COMPARTMENT_HANDWRITING_OPENCLOSE is set TRUE at the first
  392. // time, this Initiliaze( ) could be called by the compartment event sink.
  393. //
  394. HRESULT CSoftkbdIMX::Initialize( )
  395. {
  396. HRESULT hr;
  397. WCHAR *lpSymXMLResStr = L"IDSKD_SYMLAYOUT";
  398. WCHAR wszModuleFile[MAX_PATH];
  399. CHAR szModuleFile[MAX_PATH];
  400. DWORD dwFileLen;
  401. WNDCLASSEX wndclass;
  402. INT wScreenWidth, wScreenHeight;
  403. INT left, top, width, height;
  404. RECT rcWork;
  405. hr = S_OK;
  406. if ( _fInitialized == TRUE )
  407. {
  408. // Initialization is already done.
  409. return hr;
  410. }
  411. if ( GetClassInfoEx( g_hInst, c_szIMXOwnerWndClass, &wndclass) == 0 )
  412. {
  413. memset(&wndclass, 0, sizeof(wndclass));
  414. wndclass.cbSize = sizeof(wndclass);
  415. wndclass.style = CS_HREDRAW | CS_VREDRAW ;
  416. wndclass.hInstance = g_hInst;
  417. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  418. wndclass.lpfnWndProc = _OwnerWndProc;
  419. wndclass.lpszClassName = c_szIMXOwnerWndClass;
  420. RegisterClassEx(&wndclass);
  421. }
  422. _hOwnerWnd = CreateWindowEx(0, c_szIMXOwnerWndClass, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, 0, g_hInst, 0);
  423. // PerfConsider: use a static ctor instead of ole32/class factory/etc.
  424. hr=CoCreateInstance(CLSID_SoftKbd, NULL, CLSCTX_INPROC_SERVER, IID_ISoftKbd, (void**)&_SoftKbd);
  425. if (FAILED(hr) )
  426. {
  427. // assert(0);
  428. return hr;
  429. }
  430. _SoftKbd->Initialize( );
  431. // initialize Standard soft layout and Symbol Soft Layout.
  432. _KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
  433. _KbdStandard.fStandard = TRUE;
  434. _KbdStandard.dwNumLabels = 0; // for standard, this field is not really used.
  435. _KbdStandard.dwCurLabel = 0;
  436. _KbdStandard.pskbdes = NULL; // standard layout doesn't supply sftkbd event sink.
  437. _KbdStandard.dwSkbdESCookie = 0;
  438. _KbdSymbol.fStandard = FALSE;
  439. _KbdSymbol.dwNumLabels = 2;
  440. _KbdSymbol.dwCurLabel = 0;
  441. dwFileLen = GetModuleFileNameA(g_hInst, szModuleFile, MAX_PATH);
  442. if ( dwFileLen == 0 )
  443. {
  444. hr = E_FAIL;
  445. goto CleanUp;
  446. }
  447. MultiByteToWideChar(CP_ACP, 0, szModuleFile, -1,
  448. wszModuleFile, MAX_PATH);
  449. hr = _SoftKbd->CreateSoftKeyboardLayoutFromResource(wszModuleFile, L"SKDFILE", lpSymXMLResStr,
  450. &(_KbdSymbol.dwSoftKbdLayout) );
  451. CHECKHR(hr);
  452. _KbdSymbol.pskbdes = new CSoftKeyboardEventSink(this, _KbdSymbol.dwSoftKbdLayout);
  453. if ( _KbdSymbol.pskbdes == NULL )
  454. {
  455. hr = E_FAIL;
  456. goto CleanUp;
  457. }
  458. hr = _SoftKbd->AdviseSoftKeyboardEventSink(_KbdSymbol.dwSoftKbdLayout,
  459. IID_ISoftKeyboardEventSink,
  460. _KbdSymbol.pskbdes,
  461. &(_KbdSymbol.dwSkbdESCookie) );
  462. CHECKHR(hr);
  463. _psftkbdwndes = new CSoftKbdWindowEventSink(this);
  464. if ( _psftkbdwndes == NULL )
  465. {
  466. hr=E_FAIL;
  467. goto CleanUp;
  468. }
  469. CHECKHR(_SoftKbd->AdviseSoftKeyboardEventSink(0,IID_ISoftKbdWindowEventSink,_psftkbdwndes, &(_dwsftkbdwndesCookie)) );
  470. _CurLayout = _KbdStandard.dwSoftKbdLayout;
  471. width = 400;
  472. height = 172;
  473. if ( S_OK != GetSoftKBDPosition( &left, &top ) )
  474. {
  475. // the compartment is not initialize.
  476. SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0 );
  477. wScreenWidth = (INT)(rcWork.right - rcWork.left + 1);
  478. wScreenHeight = (INT)(rcWork.bottom - rcWork.top + 1);
  479. left = wScreenWidth - width -2;
  480. top = wScreenHeight - height - 1;
  481. }
  482. CHECKHR(_SoftKbd->CreateSoftKeyboardWindow(_hOwnerWnd,TITLEBAR_GRIPPER_BUTTON, left,top,width,height));
  483. SetSoftKBDPosition(left, top );
  484. if ( hr == S_OK )
  485. {
  486. LOGFONTW lfTextFont;
  487. int iDpi;
  488. int iPoint;
  489. iDpi = 96;
  490. iPoint = 9;
  491. HDC hdc;
  492. hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  493. if (hdc)
  494. {
  495. iDpi = GetDeviceCaps(hdc, LOGPIXELSY);
  496. DeleteDC(hdc);
  497. memset(&lfTextFont, 0, sizeof(LOGFONTW) );
  498. lfTextFont.lfHeight = -iPoint * iDpi / 72;
  499. lfTextFont.lfWeight = 400;
  500. lfTextFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  501. wcsncpy(lfTextFont.lfFaceName, L"Arial", ARRAYSIZE(lfTextFont.lfFaceName));
  502. lfTextFont.lfCharSet = 0;
  503. hr = _SoftKbd->SetSoftKeyboardTextFont(&lfTextFont);
  504. }
  505. }
  506. _fInitialized = TRUE;
  507. // or get the current layout from previous saved one.
  508. CleanUp:
  509. return hr;
  510. }
  511. //+---------------------------------------------------------------------------
  512. //
  513. // OnSetThreadFocus
  514. //
  515. //----------------------------------------------------------------------------
  516. STDAPI CSoftkbdIMX::OnSetThreadFocus()
  517. {
  518. // Restore the ON/OFF status before KillThreadFocus( )
  519. if ( _SoftKbd != NULL )
  520. {
  521. if ( _fOnOffSave )
  522. {
  523. // adjust the window position.
  524. int xWnd, yWnd;
  525. WORD width=0, height=0;
  526. POINT OldPoint;
  527. HRESULT hr;
  528. _SoftKbd->GetSoftKeyboardPosSize(&OldPoint, &width, &height);
  529. hr = GetSoftKBDPosition(&xWnd, &yWnd);
  530. if ( hr == S_OK )
  531. {
  532. if ( (xWnd != OldPoint.x) || (yWnd != OldPoint.y) )
  533. {
  534. POINT NewPoint;
  535. NewPoint.x = xWnd;
  536. NewPoint.y = yWnd;
  537. _SoftKbd->SetSoftKeyboardPosSize(NewPoint, width, height);
  538. }
  539. }
  540. _ShowSoftKBDWindow(TRUE);
  541. }
  542. else
  543. _SoftKbd->ShowSoftKeyboard(FALSE);
  544. }
  545. return S_OK;
  546. }
  547. //+---------------------------------------------------------------------------
  548. //
  549. // OnKillThreadFocus
  550. //
  551. //----------------------------------------------------------------------------
  552. STDAPI CSoftkbdIMX::OnKillThreadFocus()
  553. {
  554. // keep the ON/OFF status so that OnSetThreadFocus( ) can restore it later
  555. _fOnOffSave = GetSoftKBDOnOff( );
  556. if ( _SoftKbd != NULL )
  557. {
  558. _SoftKbd->ShowSoftKeyboard( FALSE );
  559. }
  560. // release all the modifier keys except lock keys. that is , Shift, Alt, Ctrl,
  561. keybd_event((BYTE)VK_SHIFT, (BYTE)KID_LSHFT, (DWORD)KEYEVENTF_KEYUP, 0);
  562. keybd_event((BYTE)VK_MENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
  563. keybd_event((BYTE)VK_LMENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
  564. keybd_event((BYTE)VK_RMENU, (BYTE)KID_RALT, (DWORD)KEYEVENTF_KEYUP, 0);
  565. keybd_event((BYTE)VK_CONTROL, (BYTE)KID_CTRL, (DWORD)KEYEVENTF_KEYUP, 0);
  566. return S_OK;
  567. }
  568. //+---------------------------------------------------------------------------
  569. //
  570. // Activate
  571. //
  572. //----------------------------------------------------------------------------
  573. STDAPI CSoftkbdIMX::Activate(ITfThreadMgr *ptim, TfClientId tid)
  574. {
  575. ITfSource *source;
  576. ITfLangBarItemMgr *plbim = NULL;
  577. HRESULT hr;
  578. Assert(_tim == NULL);
  579. _tim = ptim;
  580. _tim->AddRef();
  581. _tid = tid;
  582. _pProfile = NULL;
  583. if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
  584. {
  585. source->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this, &_dwThreadFocusCookie);
  586. source->Release();
  587. }
  588. //
  589. // Add SoftKeyboard activate button into LangBarItemMgr.
  590. //
  591. if (FAILED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
  592. {
  593. hr = E_FAIL;
  594. goto CleanUp;
  595. }
  596. if (!(_plbi = new CLBarItem(this)))
  597. {
  598. hr = E_OUTOFMEMORY;
  599. goto CleanUp;
  600. }
  601. plbim->AddItem(_plbi);
  602. //
  603. // get language ID.
  604. //
  605. _InitLangID();
  606. if ( (_timActiveLangSink = new CActiveLanguageProfileNotifySink(_AlsCallback, this)) == NULL )
  607. {
  608. Assert(0);
  609. hr = E_FAIL;
  610. goto CleanUp;
  611. }
  612. _timActiveLangSink->_Advise(_tim);
  613. if ( (_timLangSink = new CLanguageProfileNotifySink(_LsCallback, this)) == NULL )
  614. {
  615. Assert(0);
  616. hr = E_FAIL;
  617. goto CleanUp;
  618. }
  619. _timLangSink->_Advise(_pProfile);
  620. _pFuncPrv = new CFunctionProvider(this);
  621. if ( _pFuncPrv != NULL)
  622. _pFuncPrv->_Advise(_tim);
  623. // defaultly, hide the soft keyboard window.
  624. _fOnOffSave = FALSE;
  625. if (!(_pCes = new CCompartmentEventSink(_CompEventSinkCallback, this)))
  626. {
  627. hr = E_OUTOFMEMORY;
  628. CHECKHR(hr);
  629. }
  630. CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE, FALSE));
  631. CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT, FALSE));
  632. #if 0
  633. if (_tim->IsThreadFocus(&fThreadFocus) == S_OK && fThreadFocus)
  634. {
  635. // init any UI
  636. OnSetThreadFocus();
  637. }
  638. #endif
  639. hr = S_OK;
  640. CleanUp:
  641. SafeRelease(plbim);
  642. return hr;
  643. }
  644. //+---------------------------------------------------------------------------
  645. //
  646. // Deactivate
  647. //
  648. //----------------------------------------------------------------------------
  649. STDAPI CSoftkbdIMX::Deactivate()
  650. {
  651. ITfSource *source;
  652. ITfLangBarItemMgr *plbim = NULL;
  653. // BOOL fThreadFocus;
  654. HRESULT hr;
  655. if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
  656. {
  657. source->UnadviseSink(_dwThreadFocusCookie);
  658. source->Release();
  659. }
  660. //
  661. // Clean up SoftKeyboard activate button into LangBarItemMgr.
  662. //
  663. if (SUCCEEDED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
  664. {
  665. plbim->RemoveItem(_plbi);
  666. SafeReleaseClear(_plbi);
  667. SafeReleaseClear(plbim);
  668. }
  669. if ( _timActiveLangSink != NULL )
  670. {
  671. _timActiveLangSink->_Unadvise( );
  672. SafeReleaseClear(_timActiveLangSink);
  673. }
  674. if ( _timLangSink != NULL )
  675. {
  676. _timLangSink->_Unadvise( );
  677. SafeReleaseClear(_timLangSink);
  678. }
  679. if ( _pFuncPrv != NULL )
  680. {
  681. _pFuncPrv->_Unadvise(_tim);
  682. SafeReleaseClear(_pFuncPrv);
  683. }
  684. if ( _pCes != NULL )
  685. {
  686. if ( _SoftKbd != NULL )
  687. _SoftKbd->ShowSoftKeyboard(FALSE);
  688. _fOnOffSave = FALSE;
  689. _pCes->_Unadvise();
  690. SafeReleaseClear(_pCes);
  691. }
  692. SafeReleaseClear(_pProfile);
  693. SafeReleaseClear(_tim);
  694. TFUninitLib_Thread(&_libTLS);
  695. hr = S_OK;
  696. return hr;
  697. }
  698. //+---------------------------------------------------------------------------
  699. //
  700. // GetIC
  701. //
  702. //----------------------------------------------------------------------------
  703. ITfContext *CSoftkbdIMX::GetIC()
  704. {
  705. ITfContext *pic = NULL;
  706. if (!_tim)
  707. {
  708. Assert(0);
  709. return NULL;
  710. }
  711. ITfDocumentMgr *pdim;
  712. if (SUCCEEDED(_tim->GetFocus(&pdim)) && pdim)
  713. {
  714. // otherwise grab the top of the stack
  715. pdim->GetTop(&pic);
  716. pdim->Release();
  717. }
  718. return pic;
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // _OnOffToggle
  723. //
  724. //----------------------------------------------------------------------------
  725. void CSoftkbdIMX::_OnOffToggle( )
  726. {
  727. BOOL fOn = GetSoftKBDOnOff( );
  728. SetSoftKBDOnOff(!fOn);
  729. _UpdateUI();
  730. }
  731. //+---------------------------------------------------------------------------
  732. //
  733. // _EditSessionCallback
  734. //
  735. //----------------------------------------------------------------------------
  736. HRESULT CSoftkbdIMX::_InputKeyLabel(TfEditCookie ec, ITfContext *pic, WCHAR *lpszLabel, UINT nLabLen)
  737. {
  738. HRESULT hr = S_OK;
  739. ITfRange *pRange, *pSelection;
  740. if ( pic )
  741. {
  742. TF_STATUS ts;
  743. hr = pic->GetStatus(&ts);
  744. if ( (S_OK == hr) && (TF_SD_READONLY & ts.dwDynamicFlags) )
  745. {
  746. // Readonly Doc, just return here!
  747. return hr;
  748. }
  749. if (GetSelectionSimple(ec, pic, &pSelection) == S_OK)
  750. {
  751. if (SUCCEEDED(pSelection->Clone(&pRange)))
  752. {
  753. BOOL fInsertOk = FALSE;
  754. hr = pRange->AdjustForInsert(ec, nLabLen, &fInsertOk);
  755. if (S_OK == hr && fInsertOk)
  756. {
  757. SetTextAndProperty(&_libTLS, ec, pic, pRange, lpszLabel, nLabLen, _langid, NULL);
  758. _MySetSelectionSimple(ec, pic, pRange);
  759. }
  760. pRange->Release();
  761. }
  762. pSelection->Release();
  763. }
  764. }
  765. return hr;
  766. }
  767. HRESULT CSoftkbdIMX::_EditSessionCallback(TfEditCookie ec, CEditSession *pes)
  768. {
  769. CSoftkbdIMX *_this;
  770. HRESULT hr;
  771. hr = S_OK;
  772. switch (pes->_state.u)
  773. {
  774. case ESCB_KEYLABEL :
  775. {
  776. WCHAR *lpszLabel;
  777. UINT nLabLen;
  778. lpszLabel = (WCHAR *)(pes->_state.lParam);
  779. if ( lpszLabel == NULL )
  780. {
  781. hr = E_FAIL;
  782. return hr;
  783. }
  784. nLabLen = wcslen(lpszLabel);
  785. _this = (CSoftkbdIMX *)pes->_state.pv;
  786. hr = _this->_InputKeyLabel(ec,
  787. pes->_state.pic,
  788. lpszLabel,
  789. nLabLen);
  790. SafeFreePointer(lpszLabel);
  791. break;
  792. }
  793. default :
  794. break;
  795. }
  796. return hr;
  797. }
  798. //
  799. // Show or Hide the soft keyboard window based on current setting.
  800. //
  801. HRESULT CSoftkbdIMX::_ShowSoftKBDWindow( BOOL fShow )
  802. {
  803. HRESULT hr;
  804. hr = S_OK;
  805. if ( fShow && ( _fInitialized == FALSE ) )
  806. // call the initialize function
  807. // to get the ISoftKbd.
  808. {
  809. Initialize( );
  810. }
  811. if ( _SoftKbd == NULL )
  812. {
  813. hr = E_FAIL;
  814. return hr;
  815. }
  816. if ( fShow ) {
  817. DWORD dwSoftLayout;
  818. if ( _CurKbdType == KBDTYPE_STANDARD )
  819. {
  820. // Standard soft kbd was selected.
  821. WORD prmlangid;
  822. prmlangid = PRIMARYLANGID(_langid);
  823. switch ( prmlangid ) {
  824. case LANG_JAPANESE :
  825. // Lang JPN is activated.
  826. // select the standard layout to J 106-k.
  827. _KbdStandard.dwSoftKbdLayout = SOFTKBD_JPN_STANDARD;
  828. break;
  829. case LANG_AZERI :
  830. case LANG_BELARUSIAN :
  831. case LANG_CHINESE :
  832. case LANG_KOREAN :
  833. case LANG_RUSSIAN :
  834. case LANG_THAI :
  835. case LANG_URDU :
  836. case LANG_UZBEK :
  837. _KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
  838. break;
  839. case LANG_ENGLISH :
  840. if ( SUBLANGID(_langid) != SUBLANG_ENGLISH_US )
  841. _KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
  842. else
  843. _KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
  844. break;
  845. default :
  846. _KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
  847. break;
  848. }
  849. // the current layout is standard layout.
  850. // we need to set the correct standard layout id based on current lang profile.
  851. dwSoftLayout = _KbdStandard.dwSoftKbdLayout;
  852. _CurLayout = dwSoftLayout;
  853. CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
  854. CHECKHR(_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
  855. }
  856. else if ( _CurKbdType == KBDTYPE_SYMBOL)
  857. {
  858. // This is symbol soft keyboard layout
  859. //
  860. DWORD dwCurLabel;
  861. dwSoftLayout = _KbdSymbol.dwSoftKbdLayout;
  862. dwCurLabel = _KbdSymbol.dwCurLabel;
  863. CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
  864. CHECKHR(_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
  865. }
  866. // TIP is ON, so we need to show soft keyboard.
  867. CHECKHR(_SoftKbd->ShowSoftKeyboard(TRUE));
  868. }
  869. else
  870. {
  871. // TIP is going to close.
  872. // close the soft keyboard window also.
  873. CHECKHR(_SoftKbd->ShowSoftKeyboard(FALSE));
  874. }
  875. CleanUp:
  876. return hr;
  877. }
  878. //+---------------------------------------------------------------------------
  879. //
  880. // _CompEventSinkCallback
  881. //
  882. //----------------------------------------------------------------------------
  883. HRESULT CSoftkbdIMX::_CompEventSinkCallback(void *pv, REFGUID rguid)
  884. {
  885. CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
  886. BOOL fOn;
  887. HRESULT hr;
  888. hr = S_OK;
  889. if ( IsEqualGUID(rguid, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE) )
  890. {
  891. fOn = _this->GetSoftKBDOnOff( );
  892. CHECKHR(_this->_ShowSoftKBDWindow(fOn));
  893. //
  894. // Open/Close status was updated, we need to update Langbar button's
  895. // toggle state.
  896. //
  897. _this->_plbi->UpdateToggle();
  898. }
  899. else if ( IsEqualGUID(rguid, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT) )
  900. {
  901. DWORD dwSoftLayout;
  902. if ( _this->_SoftKbd == NULL )
  903. {
  904. hr = E_FAIL;
  905. return hr;
  906. }
  907. dwSoftLayout = _this->GetSoftKBDLayout( );
  908. _this->_CurLayout = dwSoftLayout;
  909. if ( dwSoftLayout == (_this->_KbdStandard).dwSoftKbdLayout )
  910. {
  911. // this is standard layout.
  912. _this->_CurKbdType = KBDTYPE_STANDARD;
  913. CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
  914. CHECKHR(_this->_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
  915. }
  916. else if ( dwSoftLayout == (_this->_KbdSymbol).dwSoftKbdLayout )
  917. {
  918. // this is symbol layout.
  919. DWORD dwCurLabel;
  920. _this->_CurKbdType = KBDTYPE_SYMBOL;
  921. dwCurLabel = (_this->_KbdSymbol).dwCurLabel;
  922. CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
  923. CHECKHR(_this->_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
  924. }
  925. if ( _this->GetSoftKBDOnOff( ) )
  926. CHECKHR(_this->_SoftKbd->ShowSoftKeyboard(TRUE));
  927. }
  928. _this->_UpdateUI();
  929. CleanUp:
  930. return hr;
  931. }
  932. //+---------------------------------------------------------------------------
  933. //
  934. // _UpdateUI
  935. //
  936. //----------------------------------------------------------------------------
  937. void CSoftkbdIMX::_UpdateUI()
  938. {
  939. }
  940. //+---------------------------------------------------------------------------
  941. //
  942. // _MySetSelectionSimple
  943. //
  944. //----------------------------------------------------------------------------
  945. HRESULT CSoftkbdIMX::_MySetSelectionSimple(TfEditCookie ec, ITfContext *pic, ITfRange *range)
  946. {
  947. TF_SELECTION sel;
  948. sel.range = range;
  949. sel.style.ase = TF_AE_NONE;
  950. sel.style.fInterimChar = FALSE;
  951. range->Collapse(ec, TF_ANCHOR_END);
  952. return pic->SetSelection(ec, 1, &sel);
  953. }
  954. HRESULT CSoftkbdIMX::_LsCallback(BOOL fChanged, LANGID langid, BOOL *pfAccept, void *pv)
  955. {
  956. HRESULT hr = S_OK;
  957. GUID guidProfile;
  958. LANGID lang;
  959. TraceMsg(TF_GENERAL, "CSoftkbdIMX::_LsCallback is called, langid=%x fChanged=%d", langid, fChanged);
  960. CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
  961. if (!fChanged)
  962. {
  963. if ( pfAccept )
  964. *pfAccept = TRUE;
  965. return hr;
  966. }
  967. hr = _this->_pProfile->GetActiveLanguageProfile(CLSID_SoftkbdIMX, &lang, &guidProfile);
  968. if ( hr == S_OK )
  969. {
  970. _this->_langid = lang;
  971. if ( IsEqualGUID(guidProfile, c_guidProfile) )
  972. {
  973. // Standard soft kbd is selected.
  974. TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
  975. _this->_CurKbdType = KBDTYPE_STANDARD;
  976. }
  977. else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
  978. {
  979. // This is symbol soft keyboard layout
  980. //
  981. TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
  982. _this->_CurKbdType = KBDTYPE_SYMBOL;
  983. }
  984. if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
  985. _this->_ShowSoftKBDWindow(TRUE);
  986. }
  987. return hr;
  988. }
  989. HRESULT CSoftkbdIMX::_AlsCallback(REFCLSID clsid, REFGUID guidProfile, BOOL fActivated, void *pv)
  990. {
  991. HRESULT hr;
  992. ITfInputProcessorProfiles *pProfile = NULL;
  993. hr = S_OK;
  994. CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
  995. // if this is not for SoftKbdIMX TIP,
  996. // we just ignore it.
  997. if (IsEqualGUID(clsid, CLSID_SoftkbdIMX))
  998. {
  999. // if this is not for our registered profile guid, just ignore it.
  1000. if ( !IsEqualGUID(guidProfile, c_guidProfile) && !IsEqualGUID(guidProfile, c_guidProfileSym) )
  1001. return hr;
  1002. TraceMsg(TF_GENERAL, "CSoftkbdIMX::_AlsCallback is called for this tip fActivated=%d", fActivated);
  1003. if ( fActivated == FALSE )
  1004. {
  1005. if ( _this->GetSoftKBDOnOff( ) )
  1006. {
  1007. if ( _this->_SoftKbd != NULL )
  1008. (_this->_SoftKbd)->ShowSoftKeyboard(FALSE);
  1009. }
  1010. return hr;
  1011. }
  1012. if ( IsEqualGUID(guidProfile, c_guidProfile) )
  1013. {
  1014. // Standard soft kbd is selected.
  1015. TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
  1016. _this->_CurKbdType = KBDTYPE_STANDARD;
  1017. }
  1018. else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
  1019. {
  1020. // This is symbol soft keyboard layout
  1021. //
  1022. TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
  1023. _this->_CurKbdType = KBDTYPE_SYMBOL;
  1024. }
  1025. if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
  1026. _this->_ShowSoftKBDWindow(TRUE);
  1027. }
  1028. else if (IsEqualGUID(clsid, GUID_NULL))
  1029. {
  1030. // This is keyboard layout change without language change.
  1031. if ( _this->GetSoftKBDOnOff( ) && fActivated)
  1032. {
  1033. _this->_ShowSoftKBDWindow(fActivated);
  1034. }
  1035. }
  1036. return hr;
  1037. }