Source code of Windows XP (NT5)
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.

488 lines
12 KiB

  1. #include "msgina.h"
  2. #include <shellapi.h>
  3. typedef struct
  4. {
  5. HKL dwHkl;
  6. HICON hIcon;
  7. } LAYOUTINFO, *PLAYOUTINFO;
  8. typedef struct
  9. {
  10. HKL hklLast;
  11. PLAYOUTINFO pLayoutInfo;
  12. } USERLAYOUTINFO, *PUSERLAYOUTINFO;
  13. HICON
  14. CreateLangIdIcon(
  15. WORD LangId);
  16. int
  17. CreateIconList(
  18. PLAYOUTINFO pLayoutInfo,
  19. HKL hkl,
  20. UINT uLangs);
  21. HICON
  22. GetIconFromHkl(
  23. PLAYOUTINFO pLayoutInfo,
  24. HKL hkl,
  25. UINT uLangs);
  26. USERLAYOUTINFO UserLayoutInfo[2];
  27. typedef BOOL (WINAPI *LPFNIMMGETIMEFILENAME)(HKL, LPTSTR, UINT);
  28. LPFNIMMGETIMEFILENAME pfnImmGetImeFileName = NULL;
  29. TCHAR szImm32DLL[] = TEXT("imm32.dll");
  30. typedef UINT (WINAPI *PFNEXTRACTICONEXW)(LPCWSTR lpszFile, int nIconIndex, HICON FAR *phiconLarge, HICON FAR *phiconSmall, UINT nIcons);
  31. /***************************************************************************\
  32. * FUNCTION: CreateLangIdIcon
  33. *
  34. * PURPOSE: Create an icon that displays the first two letters of the
  35. * supplied language ID.
  36. *
  37. * RETURNS: Icon that shows displays Language ID.
  38. *
  39. * HISTORY:
  40. *
  41. * 04-17-98 ShanXu Borrowed from internat.exe
  42. *
  43. \***************************************************************************/
  44. HICON
  45. CreateLangIdIcon(
  46. WORD langID
  47. )
  48. {
  49. HBITMAP hbmColour = NULL;
  50. HBITMAP hbmMono;
  51. HBITMAP hbmOld;
  52. HICON hicon = NULL;
  53. ICONINFO ii;
  54. RECT rc;
  55. DWORD rgbText;
  56. DWORD rgbBk = 0;
  57. HDC hdc = NULL;
  58. HDC hdcScreen;
  59. LOGFONT lf;
  60. HFONT hfont;
  61. HFONT hfontOld;
  62. TCHAR szData[20];
  63. UINT cxSmIcon, cySmIcon;
  64. cxSmIcon = GetSystemMetrics(SM_CXSMICON);
  65. cySmIcon = GetSystemMetrics(SM_CYSMICON);
  66. //
  67. // Get the indicator by using the first 2 characters of the
  68. // abbreviated language name.
  69. //
  70. if (GetLocaleInfo( MAKELCID(langID, SORT_DEFAULT),
  71. LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
  72. szData,
  73. sizeof(szData) / sizeof(szData[0]) ))
  74. {
  75. //
  76. // Only use the first two characters.
  77. //
  78. szData[2] = TEXT('\0');
  79. }
  80. else
  81. {
  82. //
  83. // Id wasn't found. Use question marks.
  84. //
  85. szData[0] = TEXT('?');
  86. szData[1] = TEXT('?');
  87. szData[2] = TEXT('\0');
  88. }
  89. if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
  90. {
  91. #if (1) //DSIE: Bug 351507
  92. if (hdcScreen = GetDC(NULL))
  93. {
  94. double dScaleY = GetDeviceCaps(hdcScreen, LOGPIXELSY) / 96.0f;
  95. lf.lfHeight = (int) (lf.lfHeight * dScaleY); // Scale the height based on the system DPI.
  96. ReleaseDC(NULL, hdcScreen);
  97. }
  98. #endif
  99. if ((hfont = CreateFontIndirect(&lf)))
  100. {
  101. hdcScreen = GetDC(NULL);
  102. if ( hdcScreen )
  103. {
  104. hdc = CreateCompatibleDC(hdcScreen);
  105. hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon);
  106. ReleaseDC(NULL, hdcScreen);
  107. }
  108. if (hbmColour && hdc)
  109. {
  110. hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL);
  111. if (hbmMono)
  112. {
  113. hbmOld = SelectObject(hdc, hbmColour);
  114. rc.left = 0;
  115. rc.top = 0;
  116. rc.right = cxSmIcon;
  117. rc.bottom = cySmIcon;
  118. rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  119. rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  120. ExtTextOut( hdc,
  121. rc.left,
  122. rc.top,
  123. ETO_OPAQUE,
  124. &rc,
  125. TEXT(""),
  126. 0,
  127. NULL );
  128. SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
  129. hfontOld = SelectObject(hdc, hfont);
  130. DrawText( hdc,
  131. szData,
  132. 2,
  133. &rc,
  134. DT_CENTER | DT_VCENTER | DT_SINGLELINE );
  135. #ifdef USE_MIRRORING
  136. {
  137. DWORD dwLayout;
  138. GetProcessDefaultLayout(&dwLayout);
  139. if (dwLayout & LAYOUT_RTL)
  140. {
  141. MirrorBitmapInDC(hdc, hbmColour);
  142. }
  143. }
  144. #endif
  145. SelectObject(hdc, hbmMono);
  146. PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS);
  147. SelectObject(hdc, hbmOld);
  148. ii.fIcon = TRUE;
  149. ii.xHotspot = 0;
  150. ii.yHotspot = 0;
  151. ii.hbmColor = hbmColour;
  152. ii.hbmMask = hbmMono;
  153. hicon = CreateIconIndirect(&ii);
  154. DeleteObject(hbmMono);
  155. SelectObject(hdc, hfontOld);
  156. }
  157. DeleteObject(hbmColour);
  158. DeleteDC(hdc);
  159. }
  160. DeleteObject(hfont);
  161. }
  162. }
  163. return (hicon);
  164. }
  165. /***************************************************************************\
  166. * FUNCTION: CreateIconList
  167. *
  168. * PURPOSE: Create the table that contains the relationship between an hkl
  169. * and an icon.
  170. *
  171. * RETURNS: Index of the current hkl in the table.
  172. *
  173. * HISTORY:
  174. *
  175. * 04-17-98 ShanXu Created
  176. *
  177. \***************************************************************************/
  178. int
  179. CreateIconList(
  180. PLAYOUTINFO pLayoutInfo,
  181. HKL hklCur,
  182. UINT uLangs)
  183. {
  184. HKL *pLanguages;
  185. UINT uCount;
  186. int nCurIndex = -1;
  187. pLanguages = (HKL *)LocalAlloc(LPTR, uLangs * sizeof(HKL));
  188. if (!pLanguages)
  189. {
  190. return -1;
  191. }
  192. GetKeyboardLayoutList(uLangs, (HKL *)pLanguages);
  193. for (uCount = 0; uCount < uLangs; uCount++)
  194. {
  195. pLayoutInfo[uCount].dwHkl = pLanguages[uCount];
  196. if (pLanguages[uCount] == hklCur)
  197. {
  198. nCurIndex = uCount;
  199. }
  200. if ((HIWORD(pLanguages[uCount]) & 0xf000) == 0xe000)
  201. {
  202. WCHAR szIMEFile[32]; // assume long filename up to 32 byte
  203. if (!pfnImmGetImeFileName)
  204. {
  205. HMODULE hMod;
  206. hMod = GetModuleHandle(szImm32DLL);
  207. if (hMod)
  208. {
  209. pfnImmGetImeFileName = (LPFNIMMGETIMEFILENAME)
  210. GetProcAddress(
  211. hMod,
  212. "ImmGetIMEFileNameW");
  213. }
  214. }
  215. if (pfnImmGetImeFileName &&
  216. (*pfnImmGetImeFileName) (pLanguages[uCount],
  217. szIMEFile,
  218. sizeof(szIMEFile) ))
  219. {
  220. HINSTANCE hInstShell32;
  221. PFNEXTRACTICONEXW pfnExtractIconExW;
  222. hInstShell32 = LoadLibrary (TEXT("shell32.dll"));
  223. if (hInstShell32)
  224. {
  225. pfnExtractIconExW = (PFNEXTRACTICONEXW) GetProcAddress (hInstShell32,
  226. "ExtractIconExW");
  227. if (pfnExtractIconExW)
  228. {
  229. //
  230. // First one of the file.
  231. //
  232. pfnExtractIconExW(
  233. szIMEFile,
  234. 0,
  235. NULL,
  236. &pLayoutInfo[uCount].hIcon,
  237. 1);
  238. }
  239. FreeLibrary (hInstShell32);
  240. }
  241. continue;
  242. }
  243. }
  244. //
  245. // for non-ime layout
  246. //
  247. pLayoutInfo[uCount].hIcon = CreateLangIdIcon(LOWORD(pLanguages[uCount]));
  248. }
  249. LocalFree(pLanguages);
  250. return nCurIndex;
  251. }
  252. /***************************************************************************\
  253. * FUNCTION: GetIconFromHkl
  254. *
  255. * PURPOSE: Find the icon in our table that has a matching hkl
  256. * with the supplied hkl. Create the table if it does not
  257. * exist.
  258. *
  259. * RETURNS: Icon of the macthing hkl.
  260. *
  261. * HISTORY:
  262. *
  263. * 04-17-98 ShanXu Created
  264. *
  265. \***************************************************************************/
  266. HICON
  267. GetIconFromHkl(
  268. PLAYOUTINFO pLayoutInfo,
  269. HKL hkl,
  270. UINT uLangs)
  271. {
  272. UINT uCount;
  273. int nIndex = -1;
  274. if (pLayoutInfo[0].dwHkl == 0)
  275. {
  276. //
  277. // Icon/hkl list no exsists yet. Create it.
  278. //
  279. nIndex = CreateIconList(pLayoutInfo, hkl, uLangs);
  280. }
  281. else
  282. {
  283. //
  284. // Find the icon with a matching hkl
  285. //
  286. for (uCount = 0; uCount < uLangs; uCount++)
  287. {
  288. if (pLayoutInfo[uCount].dwHkl == hkl)
  289. {
  290. nIndex = uCount;
  291. break;
  292. }
  293. }
  294. }
  295. if (nIndex == -1)
  296. {
  297. return NULL;
  298. }
  299. return ( pLayoutInfo[nIndex].hIcon);
  300. }
  301. /***************************************************************************\
  302. * FUNCTION: DisplayLanguageIcon
  303. *
  304. * PURPOSE: Displays the icon of the currently selected hkl in the
  305. * dlg window.
  306. *
  307. * RETURNS: TRUE - The icon is displayed.
  308. * FALSE - No icon displayed.
  309. *
  310. * HISTORY:
  311. *
  312. * 04-17-98 ShanXu Created
  313. *
  314. \***************************************************************************/
  315. BOOL
  316. DisplayLanguageIcon(
  317. HWND hwnd,
  318. LAYOUT_USER LayoutUser,
  319. HKL hkl)
  320. {
  321. HICON hIconLayout;
  322. UINT uLangs;
  323. PLAYOUTINFO pLayout;
  324. uLangs = GetKeyboardLayoutList(0, NULL);
  325. if (uLangs < 2)
  326. {
  327. return FALSE;
  328. }
  329. pLayout = UserLayoutInfo[LayoutUser].pLayoutInfo;
  330. if (!pLayout)
  331. {
  332. pLayout = (PLAYOUTINFO)LocalAlloc(LPTR, uLangs * sizeof(LAYOUTINFO));
  333. if (!pLayout)
  334. {
  335. return FALSE;
  336. }
  337. UserLayoutInfo[LayoutUser].pLayoutInfo = pLayout;
  338. }
  339. hIconLayout = GetIconFromHkl(
  340. pLayout,
  341. hkl,
  342. uLangs);
  343. if (!hIconLayout)
  344. {
  345. return FALSE;
  346. }
  347. SendMessage(
  348. GetDlgItem(hwnd, IDD_KBLAYOUT_ICON),
  349. STM_SETICON,
  350. (WPARAM)hIconLayout,
  351. 0 );
  352. UserLayoutInfo[LayoutUser].hklLast = hkl;
  353. SetTimer(hwnd, TIMER_MYLANGUAGECHECK, 500, NULL);
  354. return TRUE;
  355. }
  356. /***************************************************************************\
  357. * FUNCTION: FreeLayoutInfo
  358. *
  359. * PURPOSE: Delete the icon/hkl table and destroy all icons.
  360. *
  361. * RETURNS: -
  362. *
  363. * HISTORY:
  364. *
  365. * 04-17-98 ShanXu Created
  366. *
  367. \***************************************************************************/
  368. void
  369. FreeLayoutInfo(
  370. LAYOUT_USER LayoutUser)
  371. {
  372. UINT uLangs;
  373. UINT uCount;
  374. PLAYOUTINFO pLayoutInfo;
  375. pLayoutInfo = UserLayoutInfo[LayoutUser].pLayoutInfo;
  376. if (!pLayoutInfo)
  377. {
  378. return;
  379. }
  380. uLangs = GetKeyboardLayoutList(0, NULL);
  381. for (uCount = 0; uCount < uLangs; uCount++)
  382. {
  383. DestroyIcon (pLayoutInfo[uCount].hIcon);
  384. }
  385. LocalFree(pLayoutInfo);
  386. UserLayoutInfo[LayoutUser].pLayoutInfo = NULL;
  387. return;
  388. }
  389. /***************************************************************************\
  390. * FUNCTION: LayoutCheckHandler
  391. *
  392. * PURPOSE: Handle layout check. Set appropriate icon if there is
  393. * a change in keyboard layout.
  394. *
  395. * RETURNS: -
  396. *
  397. * HISTORY:
  398. *
  399. * 04-22-98 ShanXu Created
  400. *
  401. \***************************************************************************/
  402. void
  403. LayoutCheckHandler(
  404. HWND hwnd,
  405. LAYOUT_USER LayoutUser)
  406. {
  407. HKL hklCurrent;
  408. KillTimer(hwnd, TIMER_MYLANGUAGECHECK);
  409. hklCurrent = GetKeyboardLayout(0);
  410. if (hklCurrent != UserLayoutInfo[LayoutUser].hklLast)
  411. {
  412. DisplayLanguageIcon(
  413. hwnd,
  414. LayoutUser,
  415. hklCurrent);
  416. }else{
  417. SetTimer(hwnd, TIMER_MYLANGUAGECHECK, 500, NULL);
  418. }
  419. }