wingdix.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_CORE4_SEG
  12. #pragma code_seg(AFX_CORE4_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. AFX_STATIC_DATA HBRUSH _afxHalftoneBrush = 0;
  19. void AFX_CDECL AfxWingdixTerm()
  20. {
  21. AfxDeleteObject((HGDIOBJ*)&_afxHalftoneBrush);
  22. }
  23. char _afxWingdixTerm = (char)atexit(&AfxWingdixTerm);
  24. /////////////////////////////////////////////////////////////////////////////
  25. // More coordinate transforms (in separate file to avoid transitive refs)
  26. #define HIMETRIC_INCH 2540 // HIMETRIC units per inch
  27. void CDC::DPtoHIMETRIC(LPSIZE lpSize) const
  28. {
  29. ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  30. int nMapMode;
  31. if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
  32. nMapMode != MM_TEXT)
  33. {
  34. // when using a constrained map mode, map against physical inch
  35. ((CDC*)this)->SetMapMode(MM_HIMETRIC);
  36. DPtoLP(lpSize);
  37. ((CDC*)this)->SetMapMode(nMapMode);
  38. }
  39. else
  40. {
  41. // map against logical inch for non-constrained mapping modes
  42. int cxPerInch, cyPerInch;
  43. if (this != NULL)
  44. {
  45. ASSERT_VALID(this);
  46. ASSERT(m_hDC != NULL); // no HDC attached or created?
  47. cxPerInch = GetDeviceCaps(LOGPIXELSX);
  48. cyPerInch = GetDeviceCaps(LOGPIXELSY);
  49. }
  50. else
  51. {
  52. cxPerInch = afxData.cxPixelsPerInch;
  53. cyPerInch = afxData.cyPixelsPerInch;
  54. }
  55. ASSERT(cxPerInch != 0 && cyPerInch != 0);
  56. lpSize->cx = MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
  57. lpSize->cy = MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
  58. }
  59. }
  60. void CDC::HIMETRICtoDP(LPSIZE lpSize) const
  61. {
  62. ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  63. int nMapMode;
  64. if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
  65. nMapMode != MM_TEXT)
  66. {
  67. // when using a constrained map mode, map against physical inch
  68. ((CDC*)this)->SetMapMode(MM_HIMETRIC);
  69. LPtoDP(lpSize);
  70. ((CDC*)this)->SetMapMode(nMapMode);
  71. }
  72. else
  73. {
  74. // map against logical inch for non-constrained mapping modes
  75. int cxPerInch, cyPerInch;
  76. if (this != NULL)
  77. {
  78. ASSERT_VALID(this);
  79. ASSERT(m_hDC != NULL); // no HDC attached or created?
  80. cxPerInch = GetDeviceCaps(LOGPIXELSX);
  81. cyPerInch = GetDeviceCaps(LOGPIXELSY);
  82. }
  83. else
  84. {
  85. cxPerInch = afxData.cxPixelsPerInch;
  86. cyPerInch = afxData.cyPixelsPerInch;
  87. }
  88. ASSERT(cxPerInch != 0 && cyPerInch != 0);
  89. lpSize->cx = MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
  90. lpSize->cy = MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
  91. }
  92. }
  93. void CDC::LPtoHIMETRIC(LPSIZE lpSize) const
  94. {
  95. ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  96. LPtoDP(lpSize);
  97. DPtoHIMETRIC(lpSize);
  98. }
  99. void CDC::HIMETRICtoLP(LPSIZE lpSize) const
  100. {
  101. ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  102. HIMETRICtoDP(lpSize);
  103. DPtoLP(lpSize);
  104. }
  105. /////////////////////////////////////////////////////////////////////////////
  106. // special CDC drawing primitives/helpers
  107. CBrush* PASCAL CDC::GetHalftoneBrush()
  108. {
  109. AfxLockGlobals(CRIT_HALFTONEBRUSH);
  110. if (_afxHalftoneBrush == NULL)
  111. {
  112. WORD grayPattern[8];
  113. for (int i = 0; i < 8; i++)
  114. grayPattern[i] = (WORD)(0x5555 << (i & 1));
  115. HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
  116. if (grayBitmap != NULL)
  117. {
  118. _afxHalftoneBrush = ::CreatePatternBrush(grayBitmap);
  119. DeleteObject(grayBitmap);
  120. }
  121. }
  122. AfxUnlockGlobals(CRIT_HALFTONEBRUSH);
  123. return CBrush::FromHandle(_afxHalftoneBrush);
  124. }
  125. void CDC::DrawDragRect(LPCRECT lpRect, SIZE size,
  126. LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush, CBrush* pBrushLast)
  127. {
  128. ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT), FALSE));
  129. ASSERT(lpRectLast == NULL ||
  130. AfxIsValidAddress(lpRectLast, sizeof(RECT), FALSE));
  131. // first, determine the update region and select it
  132. CRgn rgnNew;
  133. CRgn rgnOutside, rgnInside;
  134. rgnOutside.CreateRectRgnIndirect(lpRect);
  135. CRect rect = *lpRect;
  136. rect.InflateRect(-size.cx, -size.cy);
  137. rect.IntersectRect(rect, lpRect);
  138. rgnInside.CreateRectRgnIndirect(rect);
  139. rgnNew.CreateRectRgn(0, 0, 0, 0);
  140. rgnNew.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
  141. CBrush* pBrushOld = NULL;
  142. if (pBrush == NULL)
  143. pBrush = CDC::GetHalftoneBrush();
  144. if (pBrushLast == NULL)
  145. pBrushLast = pBrush;
  146. CRgn rgnLast, rgnUpdate;
  147. if (lpRectLast != NULL)
  148. {
  149. // find difference between new region and old region
  150. rgnLast.CreateRectRgn(0, 0, 0, 0);
  151. rgnOutside.SetRectRgn(lpRectLast);
  152. rect = *lpRectLast;
  153. rect.InflateRect(-sizeLast.cx, -sizeLast.cy);
  154. rect.IntersectRect(rect, lpRectLast);
  155. rgnInside.SetRectRgn(rect);
  156. rgnLast.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
  157. // only diff them if brushes are the same
  158. if (pBrush->m_hObject == pBrushLast->m_hObject)
  159. {
  160. rgnUpdate.CreateRectRgn(0, 0, 0, 0);
  161. rgnUpdate.CombineRgn(&rgnLast, &rgnNew, RGN_XOR);
  162. }
  163. }
  164. if (pBrush->m_hObject != pBrushLast->m_hObject && lpRectLast != NULL)
  165. {
  166. // brushes are different -- erase old region first
  167. SelectClipRgn(&rgnLast);
  168. GetClipBox(&rect);
  169. pBrushOld = SelectObject(pBrushLast);
  170. PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
  171. SelectObject(pBrushOld);
  172. pBrushOld = NULL;
  173. }
  174. // draw into the update/new region
  175. SelectClipRgn(rgnUpdate.m_hObject != NULL ? &rgnUpdate : &rgnNew);
  176. GetClipBox(&rect);
  177. pBrushOld = SelectObject(pBrush);
  178. PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
  179. // cleanup DC
  180. if (pBrushOld != NULL)
  181. SelectObject(pBrushOld);
  182. SelectClipRgn(NULL);
  183. }
  184. void CDC::FillSolidRect(LPCRECT lpRect, COLORREF clr)
  185. {
  186. ASSERT_VALID(this);
  187. ASSERT(m_hDC != NULL);
  188. ::SetBkColor(m_hDC, clr);
  189. ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
  190. }
  191. void CDC::FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
  192. {
  193. ASSERT_VALID(this);
  194. ASSERT(m_hDC != NULL);
  195. ::SetBkColor(m_hDC, clr);
  196. CRect rect(x, y, x + cx, y + cy);
  197. ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
  198. }
  199. void CDC::Draw3dRect(LPCRECT lpRect,
  200. COLORREF clrTopLeft, COLORREF clrBottomRight)
  201. {
  202. Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  203. lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
  204. }
  205. void CDC::Draw3dRect(int x, int y, int cx, int cy,
  206. COLORREF clrTopLeft, COLORREF clrBottomRight)
  207. {
  208. FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
  209. FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
  210. FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
  211. FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
  212. }
  213. /////////////////////////////////////////////////////////////////////////////
  214. // out-of-line CBrush, CFont, etc. helpers
  215. // nPointSize is actually scaled 10x
  216. BOOL CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC)
  217. {
  218. ASSERT(AfxIsValidString(lpszFaceName));
  219. LOGFONT logFont;
  220. memset(&logFont, 0, sizeof(LOGFONT));
  221. logFont.lfCharSet = DEFAULT_CHARSET;
  222. logFont.lfHeight = nPointSize;
  223. lstrcpyn(logFont.lfFaceName, lpszFaceName, _countof(logFont.lfFaceName));
  224. return CreatePointFontIndirect(&logFont, pDC);
  225. }
  226. // pLogFont->nHeight is interpreted as PointSize * 10
  227. BOOL CFont::CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC)
  228. {
  229. ASSERT(AfxIsValidAddress(lpLogFont, sizeof(LOGFONT), FALSE));
  230. HDC hDC;
  231. if (pDC != NULL)
  232. {
  233. ASSERT_VALID(pDC);
  234. ASSERT(pDC->m_hAttribDC != NULL);
  235. hDC = pDC->m_hAttribDC;
  236. }
  237. else
  238. hDC = ::GetDC(NULL);
  239. // convert nPointSize to logical units based on pDC
  240. LOGFONT logFont = *lpLogFont;
  241. POINT pt;
  242. pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * logFont.lfHeight;
  243. pt.y /= 720; // 72 points/inch, 10 decipoints/point
  244. ::DPtoLP(hDC, &pt, 1);
  245. POINT ptOrg = { 0, 0 };
  246. ::DPtoLP(hDC, &ptOrg, 1);
  247. logFont.lfHeight = -abs(pt.y - ptOrg.y);
  248. if (pDC == NULL)
  249. ReleaseDC(NULL, hDC);
  250. return CreateFontIndirect(&logFont);
  251. }
  252. /////////////////////////////////////////////////////////////////////////////
  253. // out-of-line CRect, CSize, etc. helpers
  254. void CRect::NormalizeRect()
  255. {
  256. int nTemp;
  257. if (left > right)
  258. {
  259. nTemp = left;
  260. left = right;
  261. right = nTemp;
  262. }
  263. if (top > bottom)
  264. {
  265. nTemp = top;
  266. top = bottom;
  267. bottom = nTemp;
  268. }
  269. }
  270. void CRect::InflateRect(LPCRECT lpRect)
  271. {
  272. left -= lpRect->left;
  273. top -= lpRect->top;
  274. right += lpRect->right;
  275. bottom += lpRect->bottom;
  276. }
  277. void CRect::InflateRect(int l, int t, int r, int b)
  278. {
  279. left -= l;
  280. top -= t;
  281. right += r;
  282. bottom += b;
  283. }
  284. void CRect::DeflateRect(LPCRECT lpRect)
  285. {
  286. left += lpRect->left;
  287. top += lpRect->top;
  288. right -= lpRect->right;
  289. bottom -= lpRect->bottom;
  290. }
  291. void CRect::DeflateRect(int l, int t, int r, int b)
  292. {
  293. left += l;
  294. top += t;
  295. right -= r;
  296. bottom -= b;
  297. }
  298. CRect CRect::MulDiv(int nMultiplier, int nDivisor) const
  299. {
  300. return CRect(
  301. ::MulDiv(left, nMultiplier, nDivisor),
  302. ::MulDiv(top, nMultiplier, nDivisor),
  303. ::MulDiv(right, nMultiplier, nDivisor),
  304. ::MulDiv(bottom, nMultiplier, nDivisor));
  305. }
  306. /////////////////////////////////////////////////////////////////////////////