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.

278 lines
7.4 KiB

  1. //
  2. // APITHK.C
  3. //
  4. // This file has API thunks that allow comctl32 to load and run on
  5. // multiple versions of NT or Win95. Since this component needs
  6. // to load on the base-level NT 4.0 and Win95, any calls to system
  7. // APIs introduced in later OS versions must be done via GetProcAddress.
  8. //
  9. // Also, any code that may need to access data structures that are
  10. // post-4.0 specific can be added here.
  11. //
  12. // NOTE: this file does *not* use the standard precompiled header,
  13. // so it can set _WIN32_WINNT to a later version.
  14. //
  15. #include "ctlspriv.h" // Don't use precompiled header here
  16. typedef BOOL (* PFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlags);
  17. /*----------------------------------------------------------
  18. Purpose: Thunk for NT 5's AnimateWindow.
  19. Returns:
  20. Cond: --
  21. */
  22. BOOL
  23. NT5_AnimateWindow(
  24. IN HWND hwnd,
  25. IN DWORD dwTime,
  26. IN DWORD dwFlags)
  27. {
  28. BOOL bRet = FALSE;
  29. static PFNANIMATEWINDOW pfn = NULL;
  30. if (NULL == pfn)
  31. {
  32. HMODULE hmod = GetModuleHandle(TEXT("USER32"));
  33. if (hmod)
  34. pfn = (PFNANIMATEWINDOW)GetProcAddress(hmod, "AnimateWindow");
  35. }
  36. if (pfn)
  37. bRet = pfn(hwnd, dwTime, dwFlags);
  38. return bRet;
  39. }
  40. /*----------------------------------------------------------
  41. Purpose: Shows the tooltip. On NT4/Win95, this is a standard
  42. show window. On NT5/Memphis, this slides the tooltip
  43. bubble from an invisible point.
  44. Returns: --
  45. Cond: --
  46. */
  47. #define CMS_TOOLTIP 135
  48. void SlideAnimate(HWND hwnd, LPCRECT prc)
  49. {
  50. DWORD dwPos, dwFlags;
  51. dwPos = GetMessagePos();
  52. if (GET_Y_LPARAM(dwPos) > prc->top + (prc->bottom - prc->top) / 2)
  53. {
  54. dwFlags = AW_VER_NEGATIVE;
  55. }
  56. else
  57. {
  58. dwFlags = AW_VER_POSITIVE;
  59. }
  60. AnimateWindow(hwnd, CMS_TOOLTIP, dwFlags | AW_SLIDE);
  61. }
  62. STDAPI_(void) CoolTooltipBubble(IN HWND hwnd, IN LPCRECT prc, BOOL fAllowFade, BOOL fAllowAnimate)
  63. {
  64. ASSERT(prc);
  65. if (g_bRunOnNT5 || g_bRunOnMemphis)
  66. {
  67. #ifdef WINNT
  68. BOOL fAnimate = TRUE;
  69. SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &fAnimate, 0);
  70. #else
  71. // Memphis doesn't support the tooltip SPI's, so we piggyback
  72. // off of SPI_GETSCREENREADER instead. Note that we want to
  73. // animate if SPI_GETSCREENREADER is >off<, so we need to do some
  74. // flippery. Fortunately, the compiler will optimize all this out.
  75. BOOL fScreenRead = FALSE;
  76. BOOL fAnimate;
  77. SystemParametersInfo(SPI_GETSCREENREADER, 0, &fScreenRead, 0);
  78. fAnimate = !fScreenRead;
  79. #endif
  80. if (fAnimate)
  81. {
  82. fAnimate = FALSE;
  83. #ifdef WINNT
  84. SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fAnimate, 0);
  85. #endif // WINNT
  86. if (fAnimate && fAllowFade)
  87. {
  88. AnimateWindow(hwnd, CMS_TOOLTIP, AW_BLEND);
  89. }
  90. else if (fAllowAnimate)
  91. {
  92. SlideAnimate(hwnd, prc);
  93. }
  94. else
  95. goto UseSetWindowPos;
  96. }
  97. else
  98. goto UseSetWindowPos;
  99. }
  100. else
  101. {
  102. UseSetWindowPos:
  103. SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  104. SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
  105. }
  106. }
  107. /*----------------------------------------------------------
  108. Purpose: Get the COLOR_HOTLIGHT system color index from NT5 or Memphis.
  109. Get COLOR_HIGHLIGHT from NT4 or Win95, where COLOR_HOTLIGHT is not defined.
  110. Returns: --
  111. Cond: --
  112. */
  113. int GetCOLOR_HOTLIGHT()
  114. {
  115. return (g_bRunOnNT5 || g_bRunOnMemphis) ? COLOR_HOTLIGHT : COLOR_HIGHLIGHT;
  116. }
  117. STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes)
  118. {
  119. if (g_bRunOnNT5 || g_bRunOnMemphis)
  120. {
  121. HCURSOR hcur = LoadCursor(NULL, IDC_HAND); // from USER, system supplied
  122. if (hcur)
  123. return hcur;
  124. }
  125. return LoadCursor(HINST_THISDLL, MAKEINTRESOURCE(IDC_HAND_INTERNAL));
  126. }
  127. typedef BOOL (*PFNQUEUEUSERWORKITEM)(LPTHREAD_START_ROUTINE Function,
  128. PVOID Context, BOOL PreferIo);
  129. STDAPI_(BOOL) NT5_QueueUserWorkItem(LPTHREAD_START_ROUTINE Function,
  130. PVOID Context, BOOL PreferIo)
  131. {
  132. BOOL bRet = FALSE;
  133. static PFNQUEUEUSERWORKITEM pfn = (PFNQUEUEUSERWORKITEM)-1;
  134. if ((PFNQUEUEUSERWORKITEM)-1 == pfn)
  135. {
  136. HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
  137. if (hmod)
  138. pfn = (PFNQUEUEUSERWORKITEM)GetProcAddress(hmod, "QueueUserWorkItem");
  139. else
  140. pfn = NULL;
  141. }
  142. if (pfn)
  143. bRet = pfn( Function, Context, PreferIo);
  144. return bRet;
  145. }
  146. //
  147. // Here's how CAL_ITWODIGITYEARMAX works.
  148. //
  149. // If a two-digit year is input from the user, we put it into the range
  150. // (N-99) ... N. for example, if the maximum value is 2029, then all
  151. // two-digit numbers will be coerced into the range 1930 through 2029.
  152. //
  153. // Win95 and NT4 don't have GetCalendarInfo, but they do have
  154. // EnumCalendarInfo, so you'd think we could avoid the GetProcAddress
  155. // by enumerating the one calendar we care about.
  156. //
  157. // Unfortunately, Win98 has a bug where EnumCalendarInfo can't enumerate
  158. // the maximum two-digit year value! What a lamer!
  159. //
  160. // So we're stuck with GetProcAddress.
  161. //
  162. // But wait, Win98 exports GetCalendarInfoW but doesn't implement it!
  163. // Double lame!
  164. //
  165. // So we have to use the Ansi version exclusively. Fortunately, we
  166. // are only interested in numbers (so far) so there is no loss of amenity.
  167. //
  168. // First, here's the dummy function that emulates GetCalendarInfoA
  169. // on Win95 and NT4.
  170. //
  171. STDAPI_(int)
  172. Emulate_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
  173. LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
  174. {
  175. //
  176. // In the absence of the API, we go straight for the information
  177. // in the registry.
  178. //
  179. BOOL fSuccess = FALSE;
  180. HKEY hkey;
  181. ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
  182. ASSERT(pszBuf == NULL);
  183. ASSERT(cchBuf == 0);
  184. if (RegOpenKeyExA(HKEY_CURRENT_USER,
  185. "Control Panel\\International\\Calendars\\TwoDigitYearMax",
  186. 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  187. {
  188. char szKey[16];
  189. char szBuf[64];
  190. DWORD dwSize;
  191. wsprintfA(szKey, "%d", calid);
  192. dwSize = sizeof(szBuf);
  193. if (RegQueryValueExA(hkey, szKey, 0, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
  194. {
  195. *pdwOut = StrToIntA(szBuf);
  196. fSuccess = TRUE;
  197. }
  198. RegCloseKey(hkey);
  199. }
  200. return fSuccess;
  201. }
  202. typedef int (CALLBACK *GETCALENDARINFOA)(LCID, CALID, CALTYPE, LPSTR, int, LPDWORD);
  203. GETCALENDARINFOA _GetCalendarInfoA;
  204. STDAPI_(int)
  205. NT5_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
  206. LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
  207. {
  208. // This is the only function our emulator supports
  209. ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
  210. ASSERT(pszBuf == NULL);
  211. ASSERT(cchBuf == 0);
  212. if (_GetCalendarInfoA == NULL)
  213. {
  214. HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
  215. //
  216. // Must keep in a local to avoid thread races.
  217. //
  218. GETCALENDARINFOA pfn = NULL;
  219. if (hmod)
  220. pfn = (GETCALENDARINFOA)
  221. GetProcAddress(hmod, "GetCalendarInfoA");
  222. //
  223. // If function is not available, then use our fallback
  224. //
  225. if (pfn == NULL)
  226. pfn = Emulate_GetCalendarInfoA;
  227. ASSERT(pfn != NULL);
  228. _GetCalendarInfoA = pfn;
  229. }
  230. return _GetCalendarInfoA(lcid, calid, cal, pszBuf, cchBuf, pdwOut);
  231. }