#include "priv.h" #include #include "langicon.h" using namespace DirectUI; #include "logon.h" extern LogonFrame* g_plf; typedef struct { HKL dwHkl; HICON hIcon; } LAYOUTINFO, *PLAYOUTINFO; typedef struct { HKL hklLast; UINT uLangs; PLAYOUTINFO pLayoutInfo; } USERLAYOUTINFO, *PUSERLAYOUTINFO; HICON CreateLangIdIcon( WORD LangId); int CreateIconList( PLAYOUTINFO pLayoutInfo, HKL hkl, UINT uLangs); HICON GetIconFromHkl( PLAYOUTINFO pLayoutInfo, HKL hkl, UINT uLangs); USERLAYOUTINFO UserLayoutInfo[2] = {0}; typedef BOOL (WINAPI *LPFNIMMGETIMEFILENAME)(HKL, LPTSTR, UINT); LPFNIMMGETIMEFILENAME pfnImmGetImeFileName = NULL; TCHAR szImm32DLL[] = TEXT("imm32.dll"); typedef UINT (WINAPI *PFNEXTRACTICONEXW)(LPCWSTR lpszFile, int nIconIndex, HICON FAR *phiconLarge, HICON FAR *phiconSmall, UINT nIcons); /***************************************************************************\ * FUNCTION: CreateLangIdIcon * * PURPOSE: Create an icon that displays the first two letters of the * supplied language ID. * * RETURNS: Icon that shows displays Language ID. * * HISTORY: * * 04-17-98 ShanXu Borrowed from internat.exe * \***************************************************************************/ HICON CreateLangIdIcon( WORD langID ) { HBITMAP hbmColour = NULL; HBITMAP hbmMono; HBITMAP hbmOld; HICON hicon = NULL; ICONINFO ii; RECT rc; DWORD rgbText; DWORD rgbBk = 0; HDC hdc = NULL; HDC hdcScreen; LOGFONT lf; HFONT hfont; HFONT hfontOld; TCHAR szData[20]; UINT cxSmIcon, cySmIcon; // due to the font we create, these should not be smaller than 16 x 16 cxSmIcon = GetSystemMetrics(SM_CXSMICON); if (cxSmIcon < 16) { cxSmIcon = 16; } cySmIcon = GetSystemMetrics(SM_CYSMICON); if (cySmIcon < 16) { cySmIcon = 16; } // // Get the indicator by using the first 2 characters of the // abbreviated language name. // if (GetLocaleInfo( MAKELCID(langID, SORT_DEFAULT), LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, szData, sizeof(szData) / sizeof(szData[0]) )) { // // Only use the first two characters. // szData[2] = TEXT('\0'); } else { // // Id wasn't found. Use question marks. // szData[0] = TEXT('?'); szData[1] = TEXT('?'); szData[2] = TEXT('\0'); } if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0)) { if ((hfont = CreateFontIndirect(&lf)) != NULL) { hdcScreen = GetDC(NULL); if ( hdcScreen ) { hdc = CreateCompatibleDC(hdcScreen); hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon); ReleaseDC(NULL, hdcScreen); } if (hbmColour && hdc) { hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL); if (hbmMono) { hbmOld = (HBITMAP)SelectObject(hdc, hbmColour); rc.left = 0; rc.top = 0; rc.right = cxSmIcon; rc.bottom = cySmIcon; rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); ExtTextOut( hdc, rc.left, rc.top, ETO_OPAQUE, &rc, TEXT(""), 0, NULL ); SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); hfontOld = (HFONT)SelectObject(hdc, hfont); DrawText( hdc, szData, 2, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); #ifdef USE_MIRRORING { DWORD dwLayout; GetProcessDefaultLayout(&dwLayout); if (dwLayout & LAYOUT_RTL) { // MirrorBitmapInDC(hdc, hbmColour); } } #endif SelectObject(hdc, hbmMono); PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS); SelectObject(hdc, hbmOld); ii.fIcon = TRUE; ii.xHotspot = 0; ii.yHotspot = 0; ii.hbmColor = hbmColour; ii.hbmMask = hbmMono; hicon = CreateIconIndirect(&ii); DeleteObject(hbmMono); SelectObject(hdc, hfontOld); } DeleteObject(hbmColour); DeleteDC(hdc); } DeleteObject(hfont); } } return (hicon); } /***************************************************************************\ * FUNCTION: CreateIconList * * PURPOSE: Create the table that contains the relationship between an hkl * and an icon. * * RETURNS: Index of the current hkl in the table. * * HISTORY: * * 04-17-98 ShanXu Created * \***************************************************************************/ int CreateIconList( PLAYOUTINFO pLayoutInfo, HKL hklCur, UINT uLangs) { HKL *pLanguages; UINT uCount; int nCurIndex = -1; pLanguages = (HKL *)LocalAlloc(LPTR, uLangs * sizeof(HKL)); if (!pLanguages) { return -1; } GetKeyboardLayoutList(uLangs, (HKL *)pLanguages); for (uCount = 0; uCount < uLangs; uCount++) { pLayoutInfo[uCount].dwHkl = pLanguages[uCount]; if (pLanguages[uCount] == hklCur) { nCurIndex = uCount; } if ((HIWORD(pLanguages[uCount]) & 0xf000) == 0xe000) { WCHAR szIMEFile[32]; // assume long filename up to 32 byte if (!pfnImmGetImeFileName) { HMODULE hMod; hMod = GetModuleHandle(szImm32DLL); if (hMod) { pfnImmGetImeFileName = (LPFNIMMGETIMEFILENAME) GetProcAddress( hMod, "ImmGetIMEFileNameW"); } } if (pfnImmGetImeFileName && (*pfnImmGetImeFileName) (pLanguages[uCount], szIMEFile, sizeof(szIMEFile) )) { HINSTANCE hInstShell32; PFNEXTRACTICONEXW pfnExtractIconExW; hInstShell32 = LoadLibrary (TEXT("shell32.dll")); if (hInstShell32) { pfnExtractIconExW = (PFNEXTRACTICONEXW) GetProcAddress (hInstShell32, "ExtractIconExW"); if (pfnExtractIconExW) { // // First one of the file. // pfnExtractIconExW( szIMEFile, 0, NULL, &pLayoutInfo[uCount].hIcon, 1); } FreeLibrary (hInstShell32); } continue; } } // // for non-ime layout // pLayoutInfo[uCount].hIcon = CreateLangIdIcon(LOWORD(pLanguages[uCount])); } LocalFree(pLanguages); return nCurIndex; } /***************************************************************************\ * FUNCTION: GetIconFromHkl * * PURPOSE: Find the icon in our table that has a matching hkl * with the supplied hkl. Create the table if it does not * exist. * * RETURNS: Icon of the macthing hkl. * * HISTORY: * * 04-17-98 ShanXu Created * \***************************************************************************/ HICON GetIconFromHkl( PLAYOUTINFO pLayoutInfo, HKL hkl, UINT uLangs) { UINT uCount; int nIndex = -1; if (pLayoutInfo[0].dwHkl == 0) { // // Icon/hkl list no exsists yet. Create it. // nIndex = CreateIconList(pLayoutInfo, hkl, uLangs); } else { // // Find the icon with a matching hkl // for (uCount = 0; uCount < uLangs; uCount++) { if (pLayoutInfo[uCount].dwHkl == hkl) { nIndex = uCount; break; } } } if (nIndex == -1) { return NULL; } return ( pLayoutInfo[nIndex].hIcon); } /***************************************************************************\ * FUNCTION: DisplayLanguageIcon * * PURPOSE: Displays the icon of the currently selected hkl in the window. * * RETURNS: TRUE - The icon is displayed. * FALSE - No icon displayed. * * HISTORY: * * 04-17-98 ShanXu Created * \***************************************************************************/ BOOL DisplayLanguageIcon( LAYOUT_USER LayoutUser, HKL hkl) { HICON hIconLayout; UINT uLangs; PLAYOUTINFO pLayout; uLangs = GetKeyboardLayoutList(0, NULL); if (uLangs < 2) { return FALSE; } pLayout = UserLayoutInfo[LayoutUser].pLayoutInfo; if (!pLayout) { pLayout = (PLAYOUTINFO)LocalAlloc(LPTR, uLangs * sizeof(LAYOUTINFO)); if (!pLayout) { return FALSE; } UserLayoutInfo[LayoutUser].uLangs = uLangs; UserLayoutInfo[LayoutUser].pLayoutInfo = pLayout; } hIconLayout = GetIconFromHkl( pLayout, hkl, uLangs); if (!hIconLayout) { return FALSE; } LogonAccount::SetKeyboardIcon(hIconLayout); UserLayoutInfo[LayoutUser].hklLast = hkl; return TRUE; } /***************************************************************************\ * FUNCTION: FreeLayoutInfo * * PURPOSE: Delete the icon/hkl table and destroy all icons. * * RETURNS: - * * HISTORY: * * 04-17-98 ShanXu Created * \***************************************************************************/ void FreeLayoutInfo( LAYOUT_USER LayoutUser) { UINT uLangs; UINT uCount; PLAYOUTINFO pLayoutInfo; pLayoutInfo = UserLayoutInfo[LayoutUser].pLayoutInfo; if (!pLayoutInfo) { return; } uLangs = UserLayoutInfo[LayoutUser].uLangs; for (uCount = 0; uCount < uLangs; uCount++) { DestroyIcon (pLayoutInfo[uCount].hIcon); } LocalFree(pLayoutInfo); UserLayoutInfo[LayoutUser].pLayoutInfo = NULL; UserLayoutInfo[LayoutUser].uLangs = 0; return; } /***************************************************************************\ * FUNCTION: LayoutCheckHandler * * PURPOSE: Handle layout check. Set appropriate icon if there is * a change in keyboard layout. * * RETURNS: - * * HISTORY: * * 04-22-98 ShanXu Created * \***************************************************************************/ void LayoutCheckHandler( LAYOUT_USER LayoutUser) { HKL hklCurrent; hklCurrent = GetKeyboardLayout(0); if (hklCurrent != UserLayoutInfo[LayoutUser].hklLast) { DisplayLanguageIcon( LayoutUser, hklCurrent); } }