windows-nt/Source/XPSP1/NT/shell/ext/logondui/langicon.cpp
2020-09-26 16:20:57 +08:00

484 lines
12 KiB
C++

#include "priv.h"
#include <shellapi.h>
#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);
}
}