QBufferDC.cpp
上传用户:xp9161
上传日期:2009-12-21
资源大小:70k
文件大小:6k
源码类别:

Windows编程

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "QBufferDC.h"
  3. #ifdef _DEBUG
  4. // #define DEBUG_QBUFFERDC // Uncomment this if you want to see debugging info.
  5. #endif
  6. QBufferDC::QBufferDC(CDC * pDC, DWORD dwRopCode /* = SRCCOPY */)
  7. : m_pDC(pDC)
  8. , m_pOldBitmap(NULL)
  9. , m_RopCode(dwRopCode)
  10. {
  11. if (! pDC) return;
  12. ASSERT_VALID(pDC);
  13. if (pDC->IsPrinting())
  14. {
  15. // Do not use a bitmap when printing. There is nothing to gain.
  16. if (pDC->m_hDC != pDC->m_hAttribDC) // Print Preview
  17. {
  18. // This is a hack. In debug mode, Print Preview yields an assert,
  19. // stating: "Cannot Release Output hDC on Attached CDC."
  20. // Although I have not found any nasty consequences, up till now,
  21. // simply setting the handles in stead of attaching seems to work.
  22. m_hDC = pDC->m_hDC;
  23. m_hAttribDC = pDC->m_hAttribDC;
  24. }
  25. else VERIFY(Attach(pDC->Detach()));  // Attach this to the mother DC's handle,
  26. // so this in effect becomes a 'normal' DC.
  27. return;
  28. }
  29. // Get the clipping boundary of the mother DC, in logical coordinates
  30. CRect rcClip;
  31. VERIFY(pDC->GetClipBox(rcClip) != ERROR);
  32. // Transform to device coordinates (pixels), and normalize
  33. pDC->LPtoDP(rcClip);
  34. rcClip.NormalizeRect();
  35. if (m_BufferBitmap.ReserveBitmap(pDC, rcClip.Size()))
  36. {
  37. // Create a compatible DC
  38. VERIFY(CreateCompatibleDC(pDC));
  39. // Select the bitmap in it
  40. ASSERT(m_pOldBitmap == 0);
  41. m_pOldBitmap = (CBitmap *) SelectObject(& m_BufferBitmap.m_Bitmap);
  42. // Copy the mapping settings
  43. int mapmode = pDC->GetMapMode();
  44. SetMapMode(mapmode);
  45. SetWindowOrg(pDC->GetWindowOrg());
  46. SetViewportOrg(pDC->GetViewportOrg());
  47. if (mapmode > MM_MAX_FIXEDSCALE)
  48. {
  49. // These are only relevant to MM_ISOTROPIC and MM_ANISOTROPIC
  50. SetWindowExt(pDC->GetWindowExt());
  51. SetViewportExt(pDC->GetViewportExt());
  52. }
  53. // Fill the clipping boundary with pDC's background color
  54. COLORREF col = pDC->GetBkColor();
  55. #ifdef QBUFFER_DEMO
  56. // In demo mode, change the color slightly so we can see which parts are updated
  57. if (m_bDemoMode) col ^= RGB(rand() % 32, rand() % 32, rand() % 32);
  58. #endif
  59. // Get the mother DC's clipping boundary in logical coordinates
  60. // and fill it.
  61. VERIFY(pDC->GetClipBox(rcClip) != ERROR);
  62. rcClip.NormalizeRect();
  63. if (mapmode != MM_TEXT)
  64. {
  65. // Other mapping modes may lead to roundof errors, causing artefacts
  66. // on the screen. To compensate, we inflate the bounding rectangle
  67. // with two pixels.
  68. CSize szPixels(2, 2);
  69. DPtoLP(& szPixels);
  70. rcClip.InflateRect(szPixels.cx, szPixels.cy);
  71. }
  72. FillSolidRect(rcClip, col);
  73. // Initialize accumulation of boundary information
  74. SetBoundsRect(NULL, DCB_ENABLE | DCB_ACCUMULATE | DCB_RESET);
  75. }
  76. else // We don't have a bitmap
  77. {
  78. #ifdef DEBUG_QBUFFERDC
  79. afxDump << _T("We can't make a bitmapn");
  80. #endif
  81. // Attach this to the mother DC's handle, so this in effect becomes a 'normal' DC.
  82. VERIFY(Attach(pDC->Detach()));
  83. }
  84. }
  85. QBufferDC::~QBufferDC(void)
  86. {
  87. if (!m_pDC) return;
  88. if (m_pDC->IsPrinting() && m_pDC->m_hDC != m_pDC->m_hAttribDC) return;
  89. // Nothing to do if Print Previewing. See remarks in constructor code.
  90. if (m_BufferBitmap.IsValid() && !m_pDC->IsPrinting())
  91. // We have a bitmap, and we are not printing.
  92. {
  93. // We only have to bitblt what is inside the accumulated bounding rectangle.
  94. CRect rcBounds;
  95. GetBoundsRect(rcBounds, DCB_RESET);
  96. rcBounds.NormalizeRect();
  97. #ifdef DEBUG_QBUFFERDC
  98. afxDump << _T("Bounding rectangle: ") << rcBounds << _T("n");
  99. #endif
  100. // No point in bitblt'ing anything outside the clipping box
  101. CRect rcClip;
  102. m_pDC->GetClipBox(rcClip);
  103. rcClip.NormalizeRect();
  104. // So intersect it with the bounding rectangle.
  105. rcBounds &= rcClip;
  106. #ifdef DEBUG_QBUFFERDC
  107. afxDump << _T("  after clipping: ") << rcBounds
  108. << _T("n  clipping rectangle: ") << rcClip << _T("n");
  109. #endif
  110. if (! rcBounds.IsRectEmpty())
  111. {
  112. if (GetMapMode() != MM_TEXT)
  113. {
  114. // Other mapping modes may lead to roundof errors, causing artefacts
  115. // on the screen. To compensate, we inflate the bounding rectangle
  116. // with two pixels.
  117. CSize szPixels(2, 2);
  118. DPtoLP(& szPixels);
  119. rcBounds.InflateRect(szPixels.cx, szPixels.cy);
  120. }
  121. // BitBlt the important part of the bitmap to the screen
  122. VERIFY(m_pDC->BitBlt(
  123. rcBounds.left, rcBounds.top,
  124. rcBounds.Width(), rcBounds.Height(),
  125. this,
  126. rcBounds.left, rcBounds.top,
  127. m_RopCode));
  128. }
  129. // Clean up, deselect the bitmap.
  130. if (m_pOldBitmap) SelectObject(m_pOldBitmap);
  131. }
  132. else // We don't have a bitmap, or we are printing.
  133. {
  134. // Detach from the mother's DC handle, and reattach to the mother
  135. VERIFY(m_pDC->Attach(Detach()));
  136. }
  137. }
  138. BOOL QBufferDC::BufferBitmap::ReserveBitmap(CDC * pDC, CSize sz)
  139. {
  140. if (IsValid()) // We have a bitmap
  141. {
  142. BITMAP bm;
  143. m_Bitmap.GetBitmap(& bm);
  144. #ifdef DEBUG_QBUFFERDC
  145. afxDump << _T("We already have a bitmap, size: ") << CSize(bm.bmWidth, bm.bmHeight) << _T("n");
  146. #endif
  147. // Compare the bitmap size (in pixels) with the requested size (also in pixels)
  148. if (sz.cx > bm.bmWidth || sz.cy > bm.bmHeight)
  149. {
  150. // If the bitmap is too small, delete it; handle will be set to zero
  151. m_Bitmap.DeleteObject();
  152. #ifdef DEBUG_QBUFFERDC
  153. afxDump << _T("Too small, deletedn");
  154. #endif
  155. }
  156. else return TRUE; // Bitmap is big enough
  157. }
  158. // Try to create a bitmap of sufficient size
  159. BOOL r = m_Bitmap.CreateCompatibleBitmap(pDC, sz.cx, sz.cy);
  160. #ifdef DEBUG_QBUFFERDC
  161. afxDump << _T("Tried to create a bitmap, size: ") << sz
  162. << (r ? _T(" - succeededn") : _T(" - failedn"));
  163. #endif
  164. return r;
  165. }
  166. QBufferDC::BufferBitmap QBufferDC::m_BufferBitmap;
  167. #ifdef QBUFFER_DEMO
  168. BOOL QBufferDC::m_bDemoMode = TRUE;
  169. #endif