home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / dcmeta.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  10KB  |  388 lines

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