|
|
//
// APITHK.C
//
// This file has API thunks that allow comctl32 to load and run on
// multiple versions of NT or Win95. Since this component needs
// to load on the base-level NT 4.0 and Win95, any calls to system
// APIs introduced in later OS versions must be done via GetProcAddress.
//
// Also, any code that may need to access data structures that are
// post-4.0 specific can be added here.
//
// NOTE: this file does *not* use the standard precompiled header,
// so it can set _WIN32_WINNT to a later version.
//
#include "ctlspriv.h" // Don't use precompiled header here
typedef BOOL (* PFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlags);
/*----------------------------------------------------------
Purpose: Thunk for NT 5's AnimateWindow.
Returns: Cond: -- */ BOOL NT5_AnimateWindow( IN HWND hwnd, IN DWORD dwTime, IN DWORD dwFlags) { BOOL bRet = FALSE; static PFNANIMATEWINDOW pfn = NULL;
if (NULL == pfn) { HMODULE hmod = GetModuleHandle(TEXT("USER32")); if (hmod) pfn = (PFNANIMATEWINDOW)GetProcAddress(hmod, "AnimateWindow"); }
if (pfn) bRet = pfn(hwnd, dwTime, dwFlags);
return bRet; }
/*----------------------------------------------------------
Purpose: Shows the tooltip. On NT4/Win95, this is a standard show window. On NT5/Memphis, this slides the tooltip bubble from an invisible point.
Returns: -- Cond: -- */
#define CMS_TOOLTIP 135
void SlideAnimate(HWND hwnd, LPCRECT prc) { DWORD dwPos, dwFlags;
dwPos = GetMessagePos(); if (GET_Y_LPARAM(dwPos) > prc->top + (prc->bottom - prc->top) / 2) { dwFlags = AW_VER_NEGATIVE; } else { dwFlags = AW_VER_POSITIVE; }
AnimateWindow(hwnd, CMS_TOOLTIP, dwFlags | AW_SLIDE); }
STDAPI_(void) CoolTooltipBubble(IN HWND hwnd, IN LPCRECT prc, BOOL fAllowFade, BOOL fAllowAnimate) { ASSERT(prc);
if (g_bRunOnNT5 || g_bRunOnMemphis) { BOOL fAnimate = TRUE; SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &fAnimate, 0); if (fAnimate) { fAnimate = FALSE; SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fAnimate, 0); if (fAnimate && fAllowFade) { AnimateWindow(hwnd, CMS_TOOLTIP, AW_BLEND); } else if (fAllowAnimate) { SlideAnimate(hwnd, prc); } else goto UseSetWindowPos; } else goto UseSetWindowPos; } else { UseSetWindowPos: SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER); } }
/*----------------------------------------------------------
Purpose: Get the COLOR_HOTLIGHT system color index from NT5 or Memphis. Get COLOR_HIGHLIGHT from NT4 or Win95, where COLOR_HOTLIGHT is not defined.
Returns: -- Cond: -- */ int GetCOLOR_HOTLIGHT() { return (g_bRunOnNT5 || g_bRunOnMemphis) ? COLOR_HOTLIGHT : COLOR_HIGHLIGHT; }
STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes) { if (g_bRunOnNT5 || g_bRunOnMemphis) { HCURSOR hcur = LoadCursor(NULL, IDC_HAND); // from USER, system supplied
if (hcur) return hcur; }
return LoadCursor(HINST_THISDLL, MAKEINTRESOURCE(IDC_HAND_INTERNAL)); }
typedef BOOL (*PFNQUEUEUSERWORKITEM)(LPTHREAD_START_ROUTINE Function, PVOID Context, BOOL PreferIo);
STDAPI_(BOOL) NT5_QueueUserWorkItem(LPTHREAD_START_ROUTINE Function, PVOID Context, BOOL PreferIo) { BOOL bRet = FALSE; static PFNQUEUEUSERWORKITEM pfn = (PFNQUEUEUSERWORKITEM)-1;
if ((PFNQUEUEUSERWORKITEM)-1 == pfn) { HMODULE hmod = GetModuleHandle(TEXT("KERNEL32")); if (hmod) pfn = (PFNQUEUEUSERWORKITEM)GetProcAddress(hmod, "QueueUserWorkItem"); else pfn = NULL; }
if (pfn) bRet = pfn( Function, Context, PreferIo);
return bRet; }
//
// Here's how CAL_ITWODIGITYEARMAX works.
//
// If a two-digit year is input from the user, we put it into the range
// (N-99) ... N. for example, if the maximum value is 2029, then all
// two-digit numbers will be coerced into the range 1930 through 2029.
//
// Win95 and NT4 don't have GetCalendarInfo, but they do have
// EnumCalendarInfo, so you'd think we could avoid the GetProcAddress
// by enumerating the one calendar we care about.
//
// Unfortunately, Win98 has a bug where EnumCalendarInfo can't enumerate
// the maximum two-digit year value! What a lamer!
//
// So we're stuck with GetProcAddress.
//
// But wait, Win98 exports GetCalendarInfoW but doesn't implement it!
// Double lame!
//
// So we have to use the Ansi version exclusively. Fortunately, we
// are only interested in numbers (so far) so there is no loss of amenity.
//
// First, here's the dummy function that emulates GetCalendarInfoA
// on Win95 and NT4.
//
STDAPI_(int) Emulate_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal, LPSTR pszBuf, int cchBuf, LPDWORD pdwOut) { //
// In the absence of the API, we go straight for the information
// in the registry.
//
BOOL fSuccess = FALSE; HKEY hkey;
ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX); ASSERT(pszBuf == NULL); ASSERT(cchBuf == 0);
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Control Panel\\International\\Calendars\\TwoDigitYearMax", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { char szKey[16]; char szBuf[64]; DWORD dwSize;
if (SUCCEEDED(StringCchPrintfA(szKey, ARRAYSIZE(szKey), "%d", calid))) { dwSize = sizeof(szBuf); if (RegQueryValueExA(hkey, szKey, 0, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS) { *pdwOut = StrToIntA(szBuf); fSuccess = TRUE; } }
RegCloseKey(hkey); } return fSuccess;
}
typedef int (CALLBACK *GETCALENDARINFOA)(LCID, CALID, CALTYPE, LPSTR, int, LPDWORD);
GETCALENDARINFOA _GetCalendarInfoA;
STDAPI_(int) NT5_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal, LPSTR pszBuf, int cchBuf, LPDWORD pdwOut) { // This is the only function our emulator supports
ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX); ASSERT(pszBuf == NULL); ASSERT(cchBuf == 0);
if (_GetCalendarInfoA == NULL) { HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
//
// Must keep in a local to avoid thread races.
//
GETCALENDARINFOA pfn = NULL;
if (hmod) pfn = (GETCALENDARINFOA) GetProcAddress(hmod, "GetCalendarInfoA");
//
// If function is not available, then use our fallback
//
if (pfn == NULL) pfn = Emulate_GetCalendarInfoA;
ASSERT(pfn != NULL); _GetCalendarInfoA = pfn; }
return _GetCalendarInfoA(lcid, calid, cal, pszBuf, cchBuf, pdwOut); }
|