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.

483 lines
12 KiB

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