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.

370 lines
12 KiB

  1. /*
  2. * RESIMAGE.CPP
  3. *
  4. * Implementation of the Results Image control for OLE 2.0 UI dialogs.
  5. * We need a separate control for dialogs in order to control the repaints
  6. * properly and to provide a clean message interface for the dialog
  7. * implementations.
  8. *
  9. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  10. */
  11. #include "precomp.h"
  12. #include "resimage.h"
  13. #include "uiclass.h"
  14. OLEDBGDATA
  15. //Reference counter indicating how many times fResultImageInitialize has been
  16. //successfully called
  17. static UINT uRegistered = 0;
  18. //Bitmap and image dimensions for result images.
  19. static HBITMAP hBmpResults = NULL;
  20. static UINT cxBmpResult;
  21. static UINT cyBmpResult;
  22. /*
  23. * FResultImageInitialize
  24. *
  25. * Purpose:
  26. * Attempts to load result bitmaps for the current display driver
  27. * for use in OLE 2.0 UI dialogs. Also registers the ResultImage
  28. * control class.
  29. *
  30. * Parameters:
  31. * hInst HINSTANCE instance of the DLL.
  32. *
  33. * hPrevInst HINSTANCE of the previous instance. Used to
  34. * determine whether to register window classes or not.
  35. *
  36. * Return Value:
  37. * BOOL TRUE if all initialization succeeded, FALSE otherwise.
  38. */
  39. #pragma code_seg(".text$initseg")
  40. BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst)
  41. {
  42. int cx, iBmp;
  43. HDC hDC;
  44. BITMAP bm;
  45. WNDCLASS wc;
  46. /*
  47. * Determine the aspect ratio of the display we're currently
  48. * running on and load the appropriate bitmap into the global
  49. * hBmpResults (used from the ResultImage control only).
  50. *
  51. * By retrieving the logical Y extent of the display driver, you
  52. * only have limited possibilities:
  53. * LOGPIXELSY Display
  54. * ----------------------------------------
  55. * 48 CGA (unsupported)
  56. * 72 EGA
  57. * 96 VGA
  58. * 120 8514/a (i.e. HiRes VGA)
  59. */
  60. hDC=GetDC(NULL);
  61. if (NULL==hDC)
  62. return FALSE;
  63. cx=GetDeviceCaps(hDC, LOGPIXELSY);
  64. ReleaseDC(NULL, hDC);
  65. /*
  66. * Instead of single comparisons, check ranges instead, so in case
  67. * we get something funky, we'll act reasonable.
  68. */
  69. if (72 >=cx) iBmp=IDB_RESULTSEGA;
  70. if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA;
  71. if (120 <=cx) iBmp=IDB_RESULTSHIRESVGA;
  72. if (NULL == hBmpResults)
  73. {
  74. hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp));
  75. if (NULL==hBmpResults)
  76. {
  77. //On error, fail loading the DLL
  78. OleDbgOut1(TEXT("FResultImageInitialize: Failed LoadBitmap.\r\n"));
  79. return FALSE;
  80. }
  81. OleDbgOut4(TEXT("FResultImageInitialize: Loaded hBmpResults\r\n"));
  82. // Now that we have the bitmap, calculate image dimensions
  83. GetObject(hBmpResults, sizeof(BITMAP), &bm);
  84. cxBmpResult = bm.bmWidth/CIMAGESX;
  85. cyBmpResult = bm.bmHeight;
  86. }
  87. // Only register class if we're the first instance
  88. if (hPrevInst)
  89. uRegistered++;
  90. else
  91. {
  92. // Static flag fRegistered guards against calling this function more
  93. // than once in the same instance
  94. if (0 == uRegistered)
  95. {
  96. wc.lpfnWndProc =ResultImageWndProc;
  97. wc.cbClsExtra =0;
  98. wc.cbWndExtra =CBRESULTIMAGEWNDEXTRA;
  99. wc.hInstance =hInst;
  100. wc.hIcon =NULL;
  101. wc.hCursor =LoadCursor(NULL, IDC_ARROW);
  102. wc.hbrBackground =NULL;
  103. wc.lpszMenuName =NULL;
  104. wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
  105. wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE1);
  106. uRegistered = RegisterClass(&wc) ? 1 : 0;
  107. wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE2);
  108. uRegistered = RegisterClass(&wc) ? 1 : 0;
  109. wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE3);
  110. uRegistered = RegisterClass(&wc) ? 1 : 0;
  111. }
  112. else
  113. uRegistered++;
  114. }
  115. return (uRegistered > 0);
  116. }
  117. #pragma code_seg()
  118. /*
  119. * ResultImageUninitialize
  120. *
  121. * Purpose:
  122. * Cleans up anything done in FResultImageInitialize, such as freeing
  123. * the bitmaps. Call from WEP.
  124. *
  125. * Parameters:
  126. * None
  127. *
  128. * Return Value:
  129. * None
  130. */
  131. void ResultImageUninitialize(void)
  132. {
  133. --uRegistered;
  134. if (0 == uRegistered)
  135. {
  136. if (NULL != hBmpResults)
  137. {
  138. DeleteObject(hBmpResults);
  139. hBmpResults = NULL;
  140. }
  141. }
  142. }
  143. /*
  144. * ResultImageWndProc
  145. *
  146. * Purpose:
  147. * Window Procedure for the ResultImage custom control. Only handles
  148. * WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap.
  149. *
  150. * Parameters:
  151. * Standard
  152. *
  153. * Return Value:
  154. * Standard
  155. */
  156. LRESULT CALLBACK ResultImageWndProc(HWND hWnd, UINT iMsg,
  157. WPARAM wParam, LPARAM lParam)
  158. {
  159. UINT iBmp;
  160. PAINTSTRUCT ps;
  161. HDC hDC;
  162. //Handle standard Windows messages.
  163. switch (iMsg)
  164. {
  165. case WM_CREATE:
  166. SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE);
  167. return (LRESULT)0;
  168. case WM_PAINT:
  169. iBmp = GetWindowWord(hWnd, RIWW_IMAGEINDEX);
  170. hDC = BeginPaint(hWnd, &ps);
  171. RECT rc;
  172. UINT x, y;
  173. HDC hDCDlg;
  174. HBRUSH hBr;
  175. LOGBRUSH lb;
  176. HWND hDlg;
  177. /*
  178. * Our job before using TransparentBlt is to figure out
  179. * where to position the result image. We place it centered
  180. * on this control, so get our rect's center and subtract
  181. * half of the image dimensions.
  182. */
  183. GetClientRect(hWnd, &rc);
  184. x = (rc.right+rc.left-cxBmpResult)/2;
  185. y = (rc.bottom+rc.top-cyBmpResult)/2;
  186. // Get the backgroup color the dialog is using.
  187. hDlg=GetParent(hWnd);
  188. hDCDlg=GetDC(hDlg);
  189. if (hDCDlg)
  190. {
  191. //hDCDlg might be NULL in low-memory situations.
  192. hBr = (HBRUSH)SendMessage(hDlg,
  193. WM_CTLCOLORDLG,
  194. (WPARAM)hDCDlg,
  195. (LPARAM)hDlg);
  196. ReleaseDC(hDlg, hDCDlg);
  197. GetObject(hBr, sizeof(LOGBRUSH), &lb);
  198. SetBkColor(hDC, lb.lbColor);
  199. }
  200. if (RESULTIMAGE_NONE != iBmp)
  201. {
  202. TransparentBlt(hDC, x, y, hBmpResults, iBmp*cxBmpResult, 0,
  203. cxBmpResult, cyBmpResult, RGBTRANSPARENT);
  204. }
  205. else
  206. {
  207. FillRect(hDC, &rc, hBr);
  208. }
  209. EndPaint(hWnd, &ps);
  210. break;
  211. case RIM_IMAGESET:
  212. // wParam contains the new index.
  213. iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
  214. // Validate the index before changing it and repainting
  215. if (RESULTIMAGE_NONE==wParam ||
  216. ((RESULTIMAGE_MAX >= wParam)))
  217. {
  218. SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam);
  219. InvalidateRect(hWnd, NULL, FALSE);
  220. UpdateWindow(hWnd);
  221. }
  222. // Return the previous index.
  223. return (LRESULT)iBmp;
  224. case RIM_IMAGEGET:
  225. // Return the current index.
  226. iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
  227. return (LRESULT)iBmp;
  228. default:
  229. return DefWindowProc(hWnd, iMsg, wParam, lParam);
  230. }
  231. return (LRESULT)0;
  232. }
  233. /*
  234. * TransparentBlt
  235. *
  236. * Purpose:
  237. * Given a DC, a bitmap, and a color to assume as transparent in that
  238. * bitmap, BitBlts the bitmap to the DC letting the existing background
  239. * show in place of the transparent color.
  240. *
  241. * Parameters:
  242. * hDC HDC on which to draw.
  243. * x, y UINT location at which to draw the bitmap
  244. * hBmp HBITMIP to draw from
  245. * xOrg, yOrg UINT coordinates from which to draw the bitamp
  246. * cx, cy UINT dimensions of the bitmap to Blt.
  247. * cr COLORREF to consider as transparent.
  248. *
  249. * Return Value:
  250. * None
  251. */
  252. void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg,
  253. UINT cx, UINT cy, COLORREF cr)
  254. {
  255. if (hBmp)
  256. {
  257. // Get three intermediate DC's
  258. HDC hDCSrc = CreateCompatibleDC(hDC);
  259. if (hDCSrc)
  260. {
  261. HDC hDCMid = CreateCompatibleDC(hDC);
  262. if (hDCMid)
  263. {
  264. HDC hMemDC = CreateCompatibleDC(hDC);
  265. if (hMemDC)
  266. {
  267. SelectObject(hDCSrc, hBmp);
  268. // Create a monochrome bitmap for masking
  269. HBITMAP hBmpMono = CreateCompatibleBitmap(hDCMid, cx, cy);
  270. if (hBmpMono)
  271. {
  272. SelectObject(hDCMid, hBmpMono);
  273. // Create a middle bitmap
  274. HBITMAP hBmpT = CreateCompatibleBitmap(hDC, cx, cy);
  275. if (hBmpT)
  276. {
  277. SelectObject(hMemDC, hBmpT);
  278. // Create a monochrome mask where we have 0's in the image, 1's elsewhere.
  279. COLORREF crBack = SetBkColor(hDCSrc, cr);
  280. BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
  281. SetBkColor(hDCSrc, crBack);
  282. // Put the unmodified image in the temporary bitmap
  283. BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
  284. // Create an select a brush of the background color
  285. HBRUSH hBr = CreateSolidBrush(GetBkColor(hDC));
  286. if (hBr)
  287. {
  288. HBRUSH hBrT = (HBRUSH)SelectObject(hMemDC, hBr);
  289. // Force conversion of the monochrome to stay black and white.
  290. COLORREF crText = SetTextColor(hMemDC, 0L);
  291. crBack = SetBkColor(hMemDC, RGB(255, 255, 255));
  292. /*
  293. * Where the monochrome mask is 1, Blt the brush; where the mono mask
  294. * is 0, leave the destination untouches. This results in painting
  295. * around the image with the background brush. We do this first
  296. * in the temporary bitmap, then put the whole thing to the screen.
  297. */
  298. BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax);
  299. BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY);
  300. SetTextColor(hMemDC, crText);
  301. SetBkColor(hMemDC, crBack);
  302. SelectObject(hMemDC, hBrT);
  303. DeleteObject(hBr);
  304. } // if (hBr)
  305. DeleteObject(hBmpT);
  306. } // if (hBmpT)
  307. DeleteObject(hBmpMono);
  308. } // if (hBmpMono)
  309. DeleteDC(hMemDC);
  310. } // if (hMemDC)
  311. DeleteDC(hDCMid);
  312. } // if (hDCMid)
  313. DeleteDC(hDCSrc);
  314. } // if (hDCSrc)
  315. } // if (hBmp)
  316. }