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.

755 lines
19 KiB

  1. /*****************************************************************************************************************
  2. FILENAME: Graphix.cpp
  3. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  4. */
  5. #include "stdafx.h"
  6. #ifndef SNAPIN
  7. #include <windows.h>
  8. #endif
  9. #include "ErrMacro.h"
  10. #include "Graphix.h"
  11. /*****************************************************************************************************************
  12. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  13. ROUTINE DESCRIPTION:
  14. This routine draws a one line border with given dimensions in the given HDC.
  15. INPUT:
  16. OutputDC - The HDC to draw into.
  17. pRect - The rect for the border -- it'll be drawn just on the inside edge.
  18. BorderType - 1 means indented border, 2 means raised border.
  19. RETURN:
  20. TRUE - Success.
  21. FALSE - Failure.
  22. */
  23. BOOL DrawBorder(
  24. HDC OutputDC,
  25. RECT * pRect,
  26. int BorderType)
  27. {
  28. HPEN hPen1, hPen2;
  29. HGDIOBJ hOld;
  30. //Depending whether it is a raised or sunken border, just swap
  31. //white and black pens.
  32. switch(BorderType){
  33. case 1:
  34. hPen1 = (HPEN)GetStockObject(BLACK_PEN);
  35. EF_ASSERT(hPen1);
  36. hPen2 = (HPEN)GetStockObject(WHITE_PEN);
  37. EF_ASSERT(hPen2);
  38. break;
  39. case 2:
  40. hPen1 = (HPEN)GetStockObject(WHITE_PEN);
  41. EF_ASSERT(hPen1);
  42. hPen2 = (HPEN)GetStockObject(BLACK_PEN);
  43. EF_ASSERT(hPen2);
  44. break;
  45. default:
  46. return FALSE;
  47. }
  48. //Draw the left and upper edges.
  49. if (hPen1)
  50. hOld = SelectObject(OutputDC, hPen1);
  51. MoveToEx(OutputDC, pRect->right, pRect->top, NULL);
  52. LineTo(OutputDC, pRect->left, pRect->top);
  53. LineTo(OutputDC, pRect->left, pRect->bottom);
  54. //Draw the lower and right edges.
  55. if (hPen2)
  56. SelectObject(OutputDC, hPen2);
  57. LineTo(OutputDC, pRect->right, pRect->bottom);
  58. LineTo(OutputDC, pRect->right, pRect->top);
  59. SelectObject(OutputDC, hOld);
  60. return TRUE;
  61. }
  62. /*****************************************************************************************************************
  63. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  64. ROUTINE DESCRIPTION:
  65. This routine draws a one line box with given dimensions in the given HDC.
  66. INPUT:
  67. OutputDC - The HDC to draw into.
  68. pRect - The rect for the border -- it'll be drawn just on the inside edge.
  69. crColor - The color of the box.
  70. RETURN:
  71. TRUE - Success.
  72. FALSE - Failure.
  73. */
  74. BOOL ESIDrawEdge(
  75. HDC OutputDC,
  76. int startX,
  77. int startY,
  78. int endX,
  79. int endY)
  80. {
  81. // Highlight color for three-dimensional display elements (white)
  82. // (for edges facing the light source.)
  83. HPEN pen3DHilight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
  84. EF_ASSERT(pen3DHilight);
  85. // Light color for three-dimensional display elements
  86. // (for edges facing the light source.) (grey)
  87. HPEN pen3DLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
  88. EF_ASSERT(pen3DLight);
  89. // Face color for three-dimensional display elements (grey)
  90. HPEN pen3DFace = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DFACE));
  91. EF_ASSERT(pen3DFace);
  92. // Shadow color for three-dimensional display elements
  93. // (for edges facing away from the light source). (dark grey)
  94. HPEN pen3DShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
  95. EF_ASSERT(pen3DShadow);
  96. // Dark shadow for three-dimensional display elements (black)
  97. HPEN pen3DDKShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
  98. EF_ASSERT(pen3DDKShadow);
  99. HGDIOBJ hOld = SelectObject(OutputDC, pen3DLight);
  100. MoveToEx(OutputDC, startX, startY++, NULL);
  101. LineTo(OutputDC, endX, endY++);
  102. SelectObject(OutputDC, pen3DHilight);
  103. MoveToEx(OutputDC, startX, startY++, NULL);
  104. LineTo(OutputDC, endX, endY++);
  105. for (int i=0; i<3; i++){
  106. hOld = SelectObject(OutputDC, pen3DLight);
  107. MoveToEx(OutputDC, startX, startY++, NULL);
  108. LineTo(OutputDC, endX, endY++);
  109. }
  110. SelectObject(OutputDC, pen3DShadow);
  111. MoveToEx(OutputDC, startX, startY++, NULL);
  112. LineTo(OutputDC, endX, endY++);
  113. SelectObject(OutputDC, pen3DDKShadow);
  114. MoveToEx(OutputDC, startX, startY++, NULL);
  115. LineTo(OutputDC, endX, endY++);
  116. SelectObject(OutputDC, hOld);
  117. DeleteObject(pen3DHilight);
  118. DeleteObject(pen3DLight);
  119. DeleteObject(pen3DFace);
  120. DeleteObject(pen3DShadow);
  121. DeleteObject(pen3DDKShadow);
  122. return TRUE;
  123. }
  124. /*****************************************************************************************************************
  125. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  126. ROUTINE DESCRIPTION:
  127. This routine draws a one line border of given types with given dimensions
  128. and given colors in the given HDC. The colors are light and dark for 3D
  129. effect except for the PLAIN_BORDER which uses the crLight color.
  130. NOTE: There is NO error checking on the MoveToEx() and LineTo() routines.
  131. This is to maximize performance.
  132. INPUT:
  133. hdcOutput - HDC to draw into.
  134. prect - rect for the border - it'll be drawn just on the inside edge.
  135. iBorderType - PLAIN_BORDER - 2D
  136. SUNKEN_BORDER - 3D
  137. RAISED_BORDER - 3D
  138. SUNKEN_BOX - 3D
  139. RAISED_BOX - 3D
  140. HRESULT:
  141. S_OK
  142. ERROR_INVALID_PARAMETER
  143. */
  144. HRESULT
  145. DrawBorderEx(
  146. IN HDC hdcOutput,
  147. IN RECT rect,
  148. IN int iBorderType
  149. )
  150. {
  151. // Validate input.
  152. if(hdcOutput == NULL) {
  153. return ERROR_INVALID_PARAMETER;
  154. }
  155. // Highlight color for three-dimensional display elements (white)
  156. // (for edges facing the light source.)
  157. HPEN pen3DHilight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
  158. EE_ASSERT(pen3DHilight);
  159. // Light color for three-dimensional display elements
  160. // (for edges facing the light source.) (grey)
  161. HPEN pen3DLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
  162. EE_ASSERT(pen3DLight);
  163. // Face color for three-dimensional display elements (grey)
  164. HPEN pen3DFace = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DFACE));
  165. EE_ASSERT(pen3DFace);
  166. // Shadow color for three-dimensional display elements
  167. // (for edges facing away from the light source). (dark grey)
  168. HPEN pen3DShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
  169. EE_ASSERT(pen3DShadow);
  170. // Dark shadow for three-dimensional display elements (black)
  171. HPEN pen3DDKShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
  172. EE_ASSERT(pen3DDKShadow);
  173. HGDIOBJ hOld = SelectObject(hdcOutput, pen3DLight);
  174. // Move to the top-right corner to start.
  175. MoveToEx(hdcOutput, rect.right, rect.top, NULL);
  176. // Depending whether it is a raised or sunken, swap the Dark and Light colors.
  177. switch(iBorderType) {
  178. case SUNKEN_BOX:
  179. //Draw the top and left sides with black
  180. SelectObject(hdcOutput, pen3DDKShadow);
  181. LineTo(hdcOutput, rect.left, rect.top);
  182. LineTo(hdcOutput, rect.left, rect.bottom);
  183. //Draw the right and bottom sides with white
  184. SelectObject(hdcOutput, pen3DHilight);
  185. LineTo(hdcOutput, rect.right, rect.bottom);
  186. LineTo(hdcOutput, rect.right, rect.top);
  187. break;
  188. case SUNKEN_BORDER:
  189. //Draw the top, left, right and bottom sides with dark grey
  190. SelectObject(hdcOutput, pen3DShadow);
  191. LineTo(hdcOutput, rect.left, rect.top);
  192. LineTo(hdcOutput, rect.left, rect.bottom);
  193. LineTo(hdcOutput, rect.right, rect.bottom);
  194. LineTo(hdcOutput, rect.right, rect.top);
  195. //Draw the top and left sides with white
  196. SelectObject(hdcOutput, pen3DHilight);
  197. MoveToEx(hdcOutput, rect.right-1, rect.top+1, NULL);
  198. LineTo(hdcOutput, rect.left+1, rect.top+1);
  199. LineTo(hdcOutput, rect.left+1, rect.bottom);
  200. //Draw the bottom and right sides with white
  201. MoveToEx(hdcOutput, rect.left, rect.bottom+1, NULL);
  202. LineTo(hdcOutput, rect.right+1, rect.bottom+1);
  203. LineTo(hdcOutput, rect.right+1, rect.top-1);
  204. break;
  205. case PLAIN_BORDER:
  206. //Draw the top, left, right and bottom sides black
  207. SelectObject(hdcOutput, pen3DDKShadow);
  208. LineTo(hdcOutput, rect.left, rect.top);
  209. LineTo(hdcOutput, rect.left, rect.bottom);
  210. LineTo(hdcOutput, rect.right, rect.bottom);
  211. LineTo(hdcOutput, rect.right, rect.top);
  212. break;
  213. case RAISED_BORDER:
  214. //Draw the top, left, right and bottom sides
  215. SelectObject(hdcOutput, pen3DHilight);
  216. LineTo(hdcOutput, rect.left, rect.top);
  217. LineTo(hdcOutput, rect.left, rect.bottom);
  218. LineTo(hdcOutput, rect.right, rect.bottom);
  219. LineTo(hdcOutput, rect.right, rect.top);
  220. //Draw the top and left sides
  221. SelectObject(hdcOutput, pen3DShadow);
  222. MoveToEx(hdcOutput, rect.right-1, rect.top+1, NULL);
  223. LineTo(hdcOutput, rect.left+1, rect.top+1);
  224. LineTo(hdcOutput, rect.left+1, rect.bottom);
  225. //Draw the bottom and right sides
  226. MoveToEx(hdcOutput, rect.left, rect.bottom+1, NULL);
  227. LineTo(hdcOutput, rect.right+1, rect.bottom+1);
  228. LineTo(hdcOutput, rect.right+1, rect.top-1);
  229. break;
  230. case RAISED_BOX:
  231. //Draw the top and left sides with black
  232. SelectObject(hdcOutput, pen3DDKShadow);
  233. LineTo(hdcOutput, rect.left, rect.top);
  234. LineTo(hdcOutput, rect.left, rect.bottom);
  235. //Draw the right and bottom sides
  236. SelectObject(hdcOutput, pen3DShadow);
  237. LineTo(hdcOutput, rect.right, rect.bottom);
  238. LineTo(hdcOutput, rect.right, rect.top);
  239. break;
  240. default:
  241. return ERROR_INVALID_PARAMETER;
  242. }
  243. // Replace the saved object.
  244. SelectObject(hdcOutput, hOld);
  245. DeleteObject(pen3DHilight);
  246. DeleteObject(pen3DLight);
  247. DeleteObject(pen3DFace);
  248. DeleteObject(pen3DShadow);
  249. DeleteObject(pen3DDKShadow);
  250. return S_OK;
  251. }
  252. /*****************************************************************************************************************
  253. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  254. ROUTINE DESCRIPTION:
  255. This routine draws a progress display of the specified size, color and percent done value.
  256. NOTE: There is NO error checking on the MoveToEx() and LineTo() routines.
  257. This is to maximize perfromance.
  258. GLOBAL DATA:
  259. INPUT:
  260. hdcOutput - HDC to draw into.
  261. prect - rect for the border - it'll be drawn just on the inside edge.
  262. hFont - The font to write text in.
  263. iWidth - width of the bars in pixels
  264. iSpace - the space between the bars in pixels - can be zero for a solid progress dsiplay
  265. iPercent - the percent done between 0 - 100.
  266. RETURN:
  267. HRESULT - S_OK
  268. HRESULT - ERROR_INVALID_PARAMETER
  269. */
  270. HRESULT
  271. ProgressBar(
  272. IN HDC hdcOutput,
  273. IN RECT* prect,
  274. IN HFONT hFont,
  275. IN int iWidth,
  276. IN int iSpace,
  277. IN int iPercent
  278. )
  279. {
  280. // Validate input - note if iPercent is the same as previously do nothing.
  281. if(iPercent > 100 || iWidth < 1 || hdcOutput == NULL || prect == NULL) {
  282. return ERROR_INVALID_PARAMETER;
  283. }
  284. int i, iStart, iEnd;
  285. ////////////////////////////////////
  286. // Set the progress bar back to zero
  287. ////////////////////////////////////
  288. // the null bar color
  289. HPEN hBlankBar = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_INACTIVECAPTION));
  290. // if can't do it, use a stock object (this can't fail)
  291. if (hBlankBar == NULL)
  292. {
  293. hBlankBar = (HPEN)GetStockObject(WHITE_PEN);
  294. }
  295. // Select the new pen and save the current pen
  296. HGDIOBJ hOld;
  297. if (hBlankBar)
  298. hOld = SelectObject(hdcOutput, hBlankBar);
  299. // Get the start and end
  300. iStart = prect->left;
  301. iEnd = prect->right;
  302. while(iStart < iEnd) {
  303. // Draw a bar
  304. for(i=0; i<iWidth && iStart < iEnd; i++, iStart++) {
  305. // Move to the top-left corner to start.
  306. MoveToEx(hdcOutput, iStart, prect->top, NULL);
  307. // Draw the one vertical line.
  308. LineTo(hdcOutput, iStart, prect->bottom);
  309. }
  310. // Make the space between the bars
  311. iStart += iSpace;
  312. }
  313. // Replace the previous pen
  314. SelectObject(hdcOutput, hOld);
  315. // delete the new pen
  316. DeleteObject(hBlankBar);
  317. if (iPercent < 0)
  318. iPercent = 0;
  319. // We are done if iPercent is zero.
  320. if (iPercent == 0)
  321. return S_OK;
  322. ////////////////////////////////////
  323. // Now draw the progress
  324. ////////////////////////////////////
  325. // Adjust iPercent for decimal point
  326. //iPercent = 1000 / iPercent;
  327. // Calculate the end based on iPercent
  328. //iEnd = (10 * (prect->right - prect->left - 30)) / iPercent) + prect->left + 30;
  329. iEnd = prect->left + 30 + (prect->right - prect->left - 30) * iPercent / 100;
  330. // Get the start.
  331. iStart = prect->left;
  332. // Save the old pen and set the new one
  333. // the colored bar color
  334. HPEN hColorBar = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_ACTIVECAPTION));
  335. // if can't do it, use a stock object (this can't fail) bug 455614
  336. if (hColorBar == NULL)
  337. {
  338. hColorBar = (HPEN)GetStockObject(BLACK_PEN);
  339. }
  340. if (hColorBar)
  341. hOld = SelectObject(hdcOutput, hColorBar);
  342. while(iStart < iEnd) {
  343. // Draw a solid bar of iWidth pixels in size
  344. for(i=0; i<iWidth && iStart < iEnd; i++, iStart++) {
  345. // Move to the top-left corner to start.
  346. MoveToEx(hdcOutput, iStart, prect->top, NULL);
  347. // Draw the one vertical line.
  348. LineTo(hdcOutput, iStart, prect->bottom);
  349. }
  350. // Make the space
  351. iStart += iSpace;
  352. }
  353. // Go back to the old pen
  354. SelectObject(hdcOutput, hOld);
  355. // delete the progress bar pen
  356. DeleteObject(hColorBar);
  357. return S_OK;
  358. }
  359. /*****************************************************************************************************************
  360. CLASS: CBMP
  361. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  362. CLASS DESCRIPTION:
  363. CBmp is a bitmap class. It will draw the bitmap and do various actions
  364. on the bitmap automatically.
  365. */
  366. // This is the constructor for a single bitmap.
  367. CBmp::CBmp(HINSTANCE hInstance, LPTSTR BitmapResource)
  368. {
  369. hInst = hInstance;
  370. // So as not to confuse the rest of the class that is built for multiple bitmaps,
  371. // set this bitmap into a single bitmap array.
  372. BitmapArray = new HBITMAP [1];
  373. // load it
  374. if (BitmapArray != NULL) {
  375. iNumBitmaps = 1;
  376. if ((BitmapArray[0] = LoadBitmap((HINSTANCE) hInst, BitmapResource)) == NULL) {
  377. DeleteBitmaps();
  378. EH(BitmapArray);
  379. }
  380. }
  381. // unless memory allocation failed
  382. else {
  383. iNumBitmaps = 0;
  384. }
  385. }
  386. // Constructor for loading multiple bitmaps.
  387. CBmp::CBmp(HINSTANCE hInstance, INT_PTR * piBitmapsToLoadArray, int iNumBitmapsToLoad)
  388. {
  389. hInst = hInstance;
  390. iNumBitmaps = 0;
  391. BitmapArray = NULL;
  392. // The person may not know what bitmaps to load yet -- if not he'll have to call
  393. // CBmp::LoadBitmaps() below and pass in 0 for iNumBitmapsToLoad.
  394. if (iNumBitmapsToLoad > 0) {
  395. LoadBitmaps(piBitmapsToLoadArray, iNumBitmapsToLoad);
  396. }
  397. }
  398. void CBmp::DeleteBitmaps()
  399. {
  400. if (BitmapArray != NULL) {
  401. for (int ii = 0; ii < iNumBitmaps; ii++) {
  402. DeleteObject(BitmapArray[ii]);
  403. }
  404. delete [] BitmapArray;
  405. BitmapArray = NULL;
  406. }
  407. iNumBitmaps = 0;
  408. }
  409. CBmp::~CBmp()
  410. {
  411. DeleteBitmaps();
  412. }
  413. // If the user did't know what bitmaps he wanted when calling the class
  414. // he can call the multiple bitmap constructor and feed it a value of 0 bitmaps to load.
  415. // Then he must call this function before continuing.
  416. void CBmp::LoadBitmaps(INT_PTR * piBitmapsToLoadArray, int iNumBitmapsToLoad)
  417. {
  418. // If bitmaps are already loaded, then deallocate them and load again.
  419. DeleteBitmaps();
  420. // load new stuff
  421. if (iNumBitmapsToLoad > 0) {
  422. BitmapArray = new HBITMAP [iNumBitmapsToLoad];
  423. // load 'em
  424. if (BitmapArray != NULL) {
  425. iNumBitmaps = iNumBitmapsToLoad;
  426. // Load each bitmap the user requested in his array: piBitmapsToLoadArray.
  427. for (int ii = 0; ii < iNumBitmapsToLoad; ii++) {
  428. BitmapArray[ii] = LoadBitmap((HINSTANCE) hInst,
  429. (LPCTSTR) piBitmapsToLoadArray[ii]);
  430. // abort on failure
  431. if (BitmapArray[ii] == NULL) {
  432. DeleteBitmaps();
  433. EH(BitmapArray);
  434. break;
  435. }
  436. }
  437. }
  438. // unless memory allocation failed
  439. else {
  440. iNumBitmaps = 0;
  441. }
  442. }
  443. }
  444. // Shell for the multiple version of ChangeColor -- allows user to use this class
  445. // for single bitmaps without the complexity of dealing with the bitmap number.
  446. BOOL CBmp::ChangeColor(int iOldColor, int iNewColor)
  447. {
  448. return ChangeColor(0, iOldColor, iNewColor);
  449. }
  450. // Changes the a color in the bitmap.
  451. // All iOldColor colored pixels are replaced with iNewColor.
  452. BOOL CBmp::ChangeColor(int iBitmap, int iOldColor, int iNewColor)
  453. {
  454. if (BitmapArray != NULL) {
  455. require(iBitmap < iNumBitmaps);
  456. BITMAP bmData;
  457. HBITMAP hBitmap = BitmapArray[iBitmap];
  458. GetObject(hBitmap, sizeof(BITMAP), &bmData);
  459. // Must be one byte per pixel.
  460. // This function is only implemented for 256 color bitmaps.
  461. if ((bmData.bmPlanes != 1) && (bmData.bmBitsPixel != 8)) {
  462. return FALSE;
  463. }
  464. // Get the bitmap data.
  465. int iNumBitmapBytes = bmData.bmWidth * bmData.bmHeight;
  466. char * cBitData = new char [iNumBitmapBytes];
  467. EF_ASSERT(cBitData);
  468. if (!GetBitmapBits(hBitmap, iNumBitmapBytes, cBitData)) {
  469. if (cBitData != NULL) {
  470. delete [] cBitData;
  471. }
  472. return FALSE;
  473. }
  474. // Swap colors.
  475. for (int ii = 0; ii < iNumBitmapBytes; ii++) {
  476. if (cBitData[ii] == (char) iOldColor) {
  477. cBitData[ii] = (char) iNewColor;
  478. }
  479. }
  480. // Replace the old bitmap with the one we just created.
  481. HBITMAP hNewBitmap = CreateBitmap(bmData.bmWidth, bmData.bmHeight, 1, 8, cBitData);
  482. if (hNewBitmap != NULL) {
  483. DeleteObject(BitmapArray[iBitmap]);
  484. BitmapArray[iBitmap] = hNewBitmap;
  485. }
  486. if (cBitData != NULL) {
  487. delete [] cBitData;
  488. }
  489. if (hNewBitmap != NULL) {
  490. return TRUE;
  491. }
  492. }
  493. return FALSE;
  494. }
  495. // Shell for multiple version of GetBmpSize.
  496. BOOL CBmp::GetBmpSize(int * piX, int * piY)
  497. {
  498. return GetBmpSize(0, piX, piY);
  499. }
  500. // Returns the size of the bitmap.
  501. BOOL CBmp::GetBmpSize(int iBitmap, int * piX, int * piY)
  502. {
  503. if (BitmapArray != NULL) {
  504. require(iBitmap < iNumBitmaps);
  505. BITMAP bmData;
  506. if (!GetObject(BitmapArray[iBitmap], sizeof(BITMAP), &bmData)) {
  507. return FALSE;
  508. }
  509. *piX = bmData.bmWidth;
  510. *piY = bmData.bmHeight;
  511. return TRUE;
  512. }
  513. return FALSE;
  514. }
  515. // Shell for multiple version of DrawBmpInHDC.
  516. BOOL CBmp::DrawBmpInHDC(HDC OutputDC, int iX, int iY)
  517. {
  518. return DrawBmpInHDC(OutputDC, 0, iX, iY);
  519. }
  520. // Draws the bitmap at location (iX, iY) in OutputDC.
  521. BOOL CBmp::DrawBmpInHDC(HDC OutputDC, int iBitmap, int iX, int iY)
  522. {
  523. if (BitmapArray != NULL) {
  524. require(iBitmap < iNumBitmaps);
  525. HBITMAP hBitmap = BitmapArray[iBitmap];
  526. // BitBlt the bitmap into the OutputDC
  527. BITMAP bmData;
  528. if (!GetObject(hBitmap, sizeof(BITMAP), &bmData)) {
  529. return FALSE;
  530. }
  531. HDC CommonDC = CreateCompatibleDC(OutputDC);
  532. EF_ASSERT(CommonDC);
  533. HGDIOBJ hOld = SelectObject(CommonDC, hBitmap);
  534. BOOL ok = BitBlt(OutputDC, iX, iY, bmData.bmWidth, bmData.bmHeight,
  535. CommonDC, 0, 0, SRCCOPY);
  536. SelectObject(CommonDC, hOld);
  537. DeleteDC(CommonDC);
  538. if (ok) {
  539. return TRUE;
  540. }
  541. }
  542. return FALSE;
  543. }
  544. // Shell for multiple version of DrawBmpInHDCTruncate.
  545. BOOL CBmp::DrawBmpInHDCTruncate(HDC OutputDC, RECT * Rect)
  546. {
  547. return DrawBmpInHDCTruncate(OutputDC, 0, Rect);
  548. }
  549. // Draws the bitmap within RECT in OutputDC.
  550. BOOL CBmp::DrawBmpInHDCTruncate(HDC OutputDC, int iBitmap, RECT * Rect)
  551. {
  552. if (BitmapArray != NULL) {
  553. require(iBitmap < iNumBitmaps);
  554. HBITMAP hBitmap = BitmapArray[iBitmap];
  555. // BitBlt the bitmap into the OutputDC
  556. BITMAP bmData;
  557. if (!GetObject(hBitmap, sizeof(BITMAP), &bmData)) {
  558. return FALSE;
  559. }
  560. int nWidth = (bmData.bmWidth > (Rect->right - Rect->left)) ?
  561. (Rect->right - Rect->left) : bmData.bmWidth;
  562. int nHeight = (bmData.bmHeight > (Rect->bottom - Rect->top)) ?
  563. (Rect->bottom - Rect->top) : bmData.bmHeight;
  564. HDC CommonDC = CreateCompatibleDC(OutputDC);
  565. EF_ASSERT(CommonDC);
  566. HGDIOBJ hOld = SelectObject(CommonDC, hBitmap);
  567. EH_ASSERT(hOld);
  568. BOOL ok = BitBlt(OutputDC, Rect->left, Rect->top, nWidth, nHeight, CommonDC,
  569. 0, 0, SRCCOPY);
  570. SelectObject(CommonDC, hOld);
  571. DeleteDC(CommonDC);
  572. if (ok) {
  573. return TRUE;
  574. }
  575. }
  576. return FALSE;
  577. }