dcmeta.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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_PRINT_SEG
  12. #pragma code_seg(AFX_PRINT_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CMetaFileDC
  21. CMetaFileDC::CMetaFileDC()
  22. {
  23. }
  24. void CMetaFileDC::SetOutputDC(HDC)
  25. {
  26. TRACE0("Must use Create() or Get() to set Metafile Output DC.\n");
  27. ASSERT(FALSE);
  28. }
  29. void CMetaFileDC::ReleaseOutputDC()
  30. {
  31. TRACE0("Must use Close() to release output Metafile DC.\n");
  32. ASSERT(FALSE);
  33. }
  34. void CMetaFileDC::SetAttribDC(HDC hDC) // Set the Attribute DC
  35. {
  36. if (hDC != m_hDC)
  37. CDC::SetAttribDC(hDC);
  38. if (m_hDC == m_hAttribDC) // if we somehow got to this, correct it
  39. ReleaseAttribDC();
  40. }
  41. CMetaFileDC::~CMetaFileDC()
  42. {
  43. if (m_hDC != NULL) // Must be not wanting to keep the metafile
  44. {
  45. TRACE0("Warning! Destroying CMetaFileDC without closing.\n");
  46. HMETAFILE hmfTemp = Close();
  47. ::DeleteMetaFile(hmfTemp);
  48. }
  49. }
  50. /////////////////////////////////////////////////////////////////////////////
  51. // Device-Context Functions
  52. // Clipping Functions
  53. // Normally both Set and Get clipping functions go directly to the output DC
  54. // With metafiles, we must mirror to both DCs and ask the Attribute DC for
  55. // the Get.
  56. int CMetaFileDC::GetClipBox(LPRECT lpRect) const
  57. {
  58. ASSERT(m_hAttribDC != NULL);
  59. ASSERT(lpRect != NULL);
  60. ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
  61. return ::GetClipBox(m_hAttribDC, lpRect);
  62. }
  63. BOOL CMetaFileDC::PtVisible(int x, int y) const
  64. {
  65. ASSERT(m_hAttribDC != NULL);
  66. return ::PtVisible(m_hAttribDC, x, y);
  67. }
  68. BOOL CMetaFileDC::RectVisible(LPCRECT) const
  69. {
  70. ASSERT(m_hAttribDC != NULL);
  71. return TRUE; // rect is always visible for metafiles
  72. }
  73. // Text Functions
  74. BOOL CMetaFileDC::TextOut(int x, int y, LPCTSTR lpszString, int nCount)
  75. {
  76. ASSERT(m_hDC != NULL);
  77. ASSERT(m_hDC != m_hAttribDC);
  78. ASSERT(lpszString != NULL);
  79. ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
  80. BOOL bSuccess = ::TextOut(m_hDC, x, y, lpszString, nCount);
  81. if (bSuccess && m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
  82. {
  83. CSize size = GetTextExtent(lpszString, nCount);
  84. TEXTMETRIC tm;
  85. GetTextMetrics(&tm);
  86. AdjustCP(size.cx - tm.tmOverhang);
  87. }
  88. return bSuccess;
  89. }
  90. BOOL CMetaFileDC::ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect,
  91. LPCTSTR lpszString, UINT nCount, LPINT lpDxWidths)
  92. {
  93. ASSERT(m_hDC != NULL);
  94. ASSERT(m_hDC != m_hAttribDC);
  95. ASSERT(lpszString != NULL);
  96. ASSERT(lpDxWidths == NULL ||
  97. AfxIsValidAddress(lpDxWidths, sizeof(int) * nCount, FALSE));
  98. ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
  99. BOOL bSuccess = ::ExtTextOut(m_hDC, x, y, nOptions, lpRect,
  100. lpszString, nCount, lpDxWidths);
  101. if (bSuccess && m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
  102. {
  103. int nWidth = 0;
  104. for (UINT i = 0; i < nCount; i++)
  105. nWidth += *lpDxWidths++;
  106. AdjustCP(nWidth);
  107. }
  108. return bSuccess;
  109. }
  110. CSize CMetaFileDC::TabbedTextOut(int x, int y, LPCTSTR lpszString,
  111. int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin)
  112. {
  113. ASSERT(m_hDC != NULL);
  114. ASSERT(m_hAttribDC != NULL);
  115. ASSERT(m_hDC != m_hAttribDC);
  116. ASSERT(lpszString != NULL);
  117. ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
  118. int xStart = x;
  119. CSize size;
  120. int cxTabStop = 0;
  121. int cxDefaultTab = (int)LOWORD(
  122. ::GetTabbedTextExtentA(m_hAttribDC, "\t", 1, 0, NULL));
  123. if (!lpnTabStopPositions)
  124. {
  125. // no tab stops given, use default tab stop
  126. cxTabStop = cxDefaultTab;
  127. }
  128. else if (nTabPositions == 1)
  129. {
  130. // one tab stop given, use it instead of default tab stop
  131. cxTabStop = lpnTabStopPositions[0];
  132. if (cxTabStop == 0)
  133. cxTabStop = 1;
  134. }
  135. // write the string out in tab delimited runs
  136. while (nCount != 0)
  137. {
  138. // find next tab character
  139. LPCTSTR lpszTab = lpszString;
  140. while (nCount != 0 && *lpszTab != '\t')
  141. {
  142. if (_istlead(*lpszTab))
  143. ++lpszTab, --nCount;
  144. ++lpszTab;
  145. --nCount;
  146. }
  147. // write the string
  148. int nChars = lpszTab - lpszString;
  149. ::TextOut(m_hDC, x, y, lpszString, nChars);
  150. // advance by its extent
  151. CSize size;
  152. ::GetTextExtentPoint32(m_hAttribDC, lpszString, nChars, &size);
  153. x += size.cx;
  154. // advance current x co-ordinate based on tab stops
  155. if (nCount != 0)
  156. {
  157. ASSERT(*lpszTab == '\t');
  158. lpszString = lpszTab + 1; // skip over the tab
  159. --nCount;
  160. // calculate next x position based on tab stops
  161. if (cxTabStop == 0)
  162. {
  163. for (int i = 0; i < nTabPositions; i++)
  164. {
  165. if (x < lpnTabStopPositions[i]+nTabOrigin)
  166. {
  167. x = lpnTabStopPositions[i]+nTabOrigin;
  168. break;
  169. }
  170. }
  171. if (i == nTabPositions)
  172. {
  173. // when all out of tab stops, go back to default tab stops
  174. cxTabStop = cxDefaultTab;
  175. }
  176. }
  177. if (cxTabStop != 0)
  178. {
  179. // advance based on single tab stop
  180. x = ((x - nTabOrigin) / cxTabStop) * cxTabStop +
  181. cxTabStop + nTabOrigin;
  182. }
  183. }
  184. }
  185. // adjust the current position
  186. if (m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
  187. {
  188. TEXTMETRIC tm;
  189. GetTextMetrics(&tm);
  190. AdjustCP(x - xStart - tm.tmOverhang);
  191. }
  192. // return the extent
  193. size.cx = x - xStart;
  194. return size;
  195. }
  196. void CMetaFileDC::AdjustCP(int cx)
  197. {
  198. if (m_hAttribDC == NULL)
  199. return; // do nothing
  200. UINT nAlign = GetTextAlign() & (TA_LEFT|TA_CENTER|TA_RIGHT);
  201. if (nAlign == TA_CENTER)
  202. return; // Center Alignment does not affect CP
  203. if (nAlign == TA_RIGHT)
  204. cx = -cx;
  205. CPoint point = GetCurrentPosition();
  206. point.x += cx;
  207. ::MoveToEx(m_hAttribDC, point.x, point.y, NULL);
  208. }
  209. int CMetaFileDC::DrawText(LPCTSTR lpszString, int nCount, LPRECT lpRect,
  210. UINT nFormat)
  211. {
  212. ASSERT(m_hDC != NULL);
  213. ASSERT(m_hDC != m_hAttribDC);
  214. ASSERT(lpszString != NULL);
  215. ASSERT(lpRect != NULL);
  216. ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
  217. ASSERT(nCount == -1 || AfxIsValidAddress(lpszString, nCount, FALSE));
  218. int nHeight = ::DrawText(m_hDC, lpszString, nCount, lpRect, nFormat);
  219. // If adjusting CP:
  220. if (m_hAttribDC != NULL &&
  221. (GetTextAlign() & TA_UPDATECP) && ((nFormat & DT_CALCRECT) == 0))
  222. {
  223. CRect rect(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
  224. nHeight = ::DrawText(m_hAttribDC, lpszString, nCount, &rect,
  225. nFormat | DT_CALCRECT | DT_SINGLELINE);
  226. AdjustCP(rect.Width());
  227. }
  228. return nHeight;
  229. }
  230. // Printer Escape Functions
  231. int CMetaFileDC::Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData)
  232. {
  233. ASSERT(m_hDC != NULL);
  234. ASSERT(m_hDC != m_hAttribDC);
  235. int nRet = ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData);
  236. if (m_hAttribDC == NULL)
  237. return nRet;
  238. // The tact here is to NOT allow any of the document control escapes
  239. // to be passed through. Elimination of StartDoc and EndDoc should
  240. // eliminate anything actually going to the printer. Also anything
  241. // that actually draws something will be filtered.
  242. //
  243. switch (nEscape)
  244. {
  245. case NEXTBAND:
  246. case SETCOLORTABLE:
  247. case GETCOLORTABLE:
  248. case FLUSHOUTPUT:
  249. case DRAFTMODE:
  250. case QUERYESCSUPPORT:
  251. case GETPHYSPAGESIZE:
  252. case GETPRINTINGOFFSET:
  253. case GETSCALINGFACTOR:
  254. case GETPENWIDTH:
  255. case SETCOPYCOUNT:
  256. case SELECTPAPERSOURCE:
  257. case GETTECHNOLOGY:
  258. case SETLINECAP:
  259. case SETLINEJOIN:
  260. case SETMITERLIMIT:
  261. case BANDINFO:
  262. case GETVECTORPENSIZE:
  263. case GETVECTORBRUSHSIZE:
  264. case ENABLEDUPLEX:
  265. case GETSETPAPERBINS:
  266. case GETSETPRINTORIENT:
  267. case ENUMPAPERBINS:
  268. case SETDIBSCALING:
  269. case ENUMPAPERMETRICS:
  270. case GETSETPAPERMETRICS:
  271. case GETEXTENDEDTEXTMETRICS:
  272. case GETEXTENTTABLE:
  273. case GETPAIRKERNTABLE:
  274. case GETTRACKKERNTABLE:
  275. case ENABLERELATIVEWIDTHS:
  276. case ENABLEPAIRKERNING:
  277. case SETKERNTRACK:
  278. case SETALLJUSTVALUES:
  279. case SETCHARSET:
  280. case SET_BACKGROUND_COLOR:
  281. case SET_SCREEN_ANGLE:
  282. case SET_SPREAD:
  283. return ::Escape(m_hAttribDC, nEscape, nCount, lpszInData, lpOutData);
  284. default:
  285. break; // return output DC return value
  286. }
  287. return nRet;
  288. }
  289. // Viewport origin and Viewport extent overrides
  290. // (usually, don't modify viewport orgin and extent on the output dc)
  291. CPoint CMetaFileDC::SetViewportOrg(int x, int y)
  292. {
  293. ASSERT(m_hDC != NULL);
  294. CPoint point;
  295. if (m_hAttribDC == NULL)
  296. ::SetViewportOrgEx(m_hDC, x, y, &point);
  297. else
  298. ::SetViewportOrgEx(m_hAttribDC, x, y, &point);
  299. return point;
  300. }
  301. CPoint CMetaFileDC::OffsetViewportOrg(int nWidth, int nHeight)
  302. {
  303. ASSERT(m_hDC != NULL);
  304. CPoint point;
  305. if (m_hAttribDC == NULL)
  306. ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, &point);
  307. else
  308. ::OffsetViewportOrgEx(m_hAttribDC, nWidth, nHeight, &point);
  309. return point;
  310. }
  311. CSize CMetaFileDC::SetViewportExt(int x, int y)
  312. {
  313. ASSERT(m_hDC != NULL);
  314. CSize size;
  315. if (m_hAttribDC == NULL)
  316. ::SetViewportExtEx(m_hDC, x, y, &size);
  317. else
  318. ::SetViewportExtEx(m_hAttribDC, x, y, &size);
  319. return size;
  320. }
  321. CSize CMetaFileDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom)
  322. {
  323. ASSERT(m_hDC != NULL);
  324. CSize size;
  325. if (m_hAttribDC == NULL)
  326. ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size);
  327. else
  328. ::ScaleViewportExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size);
  329. return size;
  330. }
  331. #ifdef AFX_INIT_SEG
  332. #pragma code_seg(AFX_INIT_SEG)
  333. #endif
  334. IMPLEMENT_DYNAMIC(CMetaFileDC, CDC)
  335. /////////////////////////////////////////////////////////////////////////////