mirror of https://github.com/lianthony/NT4.0
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.
387 lines
9.3 KiB
387 lines
9.3 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFX_PRINT_SEG
|
|
#pragma code_seg(AFX_PRINT_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMetaFileDC
|
|
|
|
CMetaFileDC::CMetaFileDC()
|
|
{
|
|
}
|
|
|
|
void CMetaFileDC::SetOutputDC(HDC)
|
|
{
|
|
TRACE0("Must use Create() or Get() to set Metafile Output DC.\n");
|
|
ASSERT(FALSE);
|
|
}
|
|
void CMetaFileDC::ReleaseOutputDC()
|
|
{
|
|
TRACE0("Must use Close() to release output Metafile DC.\n");
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
void CMetaFileDC::SetAttribDC(HDC hDC) // Set the Attribute DC
|
|
{
|
|
if (hDC != m_hDC)
|
|
CDC::SetAttribDC(hDC);
|
|
if (m_hDC == m_hAttribDC) // if we somehow got to this, correct it
|
|
ReleaseAttribDC();
|
|
}
|
|
|
|
CMetaFileDC::~CMetaFileDC()
|
|
{
|
|
if (m_hDC != NULL) // Must be not wanting to keep the metafile
|
|
{
|
|
TRACE0("Warning! Destroying CMetaFileDC without closing.\n");
|
|
HMETAFILE hmfTemp = Close();
|
|
::DeleteMetaFile(hmfTemp);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Device-Context Functions
|
|
|
|
// Clipping Functions
|
|
// Normally both Set and Get clipping functions go directly to the output DC
|
|
// With metafiles, we must mirror to both DCs and ask the Attribute DC for
|
|
// the Get.
|
|
|
|
int CMetaFileDC::GetClipBox(LPRECT lpRect) const
|
|
{
|
|
ASSERT(m_hAttribDC != NULL);
|
|
ASSERT(lpRect != NULL);
|
|
ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
|
|
|
|
return ::GetClipBox(m_hAttribDC, lpRect);
|
|
}
|
|
|
|
BOOL CMetaFileDC::PtVisible(int x, int y) const
|
|
{
|
|
ASSERT(m_hAttribDC != NULL);
|
|
return ::PtVisible(m_hAttribDC, x, y);
|
|
}
|
|
|
|
BOOL CMetaFileDC::RectVisible(LPCRECT) const
|
|
{
|
|
ASSERT(m_hAttribDC != NULL);
|
|
|
|
return TRUE; // rect is always visible for metafiles
|
|
}
|
|
|
|
// Text Functions
|
|
BOOL CMetaFileDC::TextOut(int x, int y, LPCTSTR lpszString, int nCount)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
ASSERT(m_hDC != m_hAttribDC);
|
|
ASSERT(lpszString != NULL);
|
|
ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
|
|
|
|
BOOL bSuccess = ::TextOut(m_hDC, x, y, lpszString, nCount);
|
|
if (bSuccess && m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
|
|
{
|
|
CSize size = GetTextExtent(lpszString, nCount);
|
|
TEXTMETRIC tm;
|
|
GetTextMetrics(&tm);
|
|
AdjustCP(size.cx - tm.tmOverhang);
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL CMetaFileDC::ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect,
|
|
LPCTSTR lpszString, UINT nCount, LPINT lpDxWidths)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
ASSERT(m_hDC != m_hAttribDC);
|
|
ASSERT(lpszString != NULL);
|
|
ASSERT(lpDxWidths == NULL ||
|
|
AfxIsValidAddress(lpDxWidths, sizeof(int) * nCount, FALSE));
|
|
ASSERT(AfxIsValidAddress(lpszString, nCount));
|
|
|
|
BOOL bSuccess = ::ExtTextOut(m_hDC, x, y, nOptions, lpRect,
|
|
lpszString, nCount, lpDxWidths);
|
|
|
|
if (bSuccess && m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
|
|
{
|
|
int nWidth = 0;
|
|
for (UINT i = 0; i < nCount; i++)
|
|
nWidth += *lpDxWidths++;
|
|
AdjustCP(nWidth);
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
CSize CMetaFileDC::TabbedTextOut(int x, int y, LPCTSTR lpszString,
|
|
int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
ASSERT(m_hAttribDC != NULL);
|
|
ASSERT(m_hDC != m_hAttribDC);
|
|
ASSERT(lpszString != NULL);
|
|
ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
|
|
|
|
int xStart = x;
|
|
CSize size;
|
|
int cxTabStop = 0;
|
|
int cxDefaultTab = (int)LOWORD(
|
|
::GetTabbedTextExtentA(m_hAttribDC, "\t", 1, 0, NULL));
|
|
|
|
if (!lpnTabStopPositions)
|
|
{
|
|
// no tab stops given, use default tab stop
|
|
cxTabStop = cxDefaultTab;
|
|
}
|
|
else if (nTabPositions == 1)
|
|
{
|
|
// one tab stop given, use it instead of default tab stop
|
|
cxTabStop = lpnTabStopPositions[0];
|
|
if (cxTabStop == 0)
|
|
cxTabStop = 1;
|
|
}
|
|
|
|
// write the string out in tab delimited runs
|
|
while (nCount != 0)
|
|
{
|
|
// find next tab character
|
|
LPCTSTR lpszTab = lpszString;
|
|
while (nCount != 0 && *lpszTab != '\t')
|
|
{
|
|
if (_istlead(*lpszTab))
|
|
++lpszTab, --nCount;
|
|
++lpszTab;
|
|
--nCount;
|
|
}
|
|
|
|
// write the string
|
|
int nChars = lpszTab - lpszString;
|
|
::TextOut(m_hDC, x, y, lpszString, nChars);
|
|
|
|
// advance by its extent
|
|
CSize size;
|
|
::GetTextExtentPoint(m_hAttribDC, lpszString, nChars, &size);
|
|
x += size.cx;
|
|
|
|
// advance current x co-ordinate based on tab stops
|
|
if (nCount != 0)
|
|
{
|
|
ASSERT(*lpszTab == '\t');
|
|
lpszString = lpszTab + 1; // skip over the tab
|
|
--nCount;
|
|
|
|
// calculate next x position based on tab stops
|
|
if (cxTabStop == 0)
|
|
{
|
|
for (int i = 0; i < nTabPositions; i++)
|
|
{
|
|
if (x < lpnTabStopPositions[i]+nTabOrigin)
|
|
{
|
|
x = lpnTabStopPositions[i]+nTabOrigin;
|
|
break;
|
|
}
|
|
}
|
|
if (i == nTabPositions)
|
|
{
|
|
// when all out of tab stops, go back to default tab stops
|
|
cxTabStop = cxDefaultTab;
|
|
}
|
|
}
|
|
if (cxTabStop != 0)
|
|
{
|
|
// advance based on single tab stop
|
|
x = ((x - nTabOrigin) / cxTabStop) * cxTabStop +
|
|
cxTabStop + nTabOrigin;
|
|
}
|
|
}
|
|
}
|
|
|
|
// adjust the current position
|
|
if (m_hAttribDC != NULL && (GetTextAlign() & TA_UPDATECP))
|
|
{
|
|
TEXTMETRIC tm;
|
|
GetTextMetrics(&tm);
|
|
AdjustCP(x - xStart - tm.tmOverhang);
|
|
}
|
|
|
|
// return the extent
|
|
size.cx = x - xStart;
|
|
return size;
|
|
}
|
|
|
|
void CMetaFileDC::AdjustCP(int cx)
|
|
{
|
|
if (m_hAttribDC == NULL)
|
|
return; // do nothing
|
|
UINT nAlign = GetTextAlign() & (TA_LEFT|TA_CENTER|TA_RIGHT);
|
|
if (nAlign == TA_CENTER)
|
|
return; // Center Alignment does not affect CP
|
|
if (nAlign == TA_RIGHT)
|
|
cx = -cx;
|
|
|
|
CPoint point = GetCurrentPosition();
|
|
point.x += cx;
|
|
::MoveToEx(m_hAttribDC, point.x, point.y, NULL);
|
|
}
|
|
|
|
int CMetaFileDC::DrawText(LPCTSTR lpszString, int nCount, LPRECT lpRect,
|
|
UINT nFormat)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
ASSERT(m_hDC != m_hAttribDC);
|
|
ASSERT(lpszString != NULL);
|
|
ASSERT(lpRect != NULL);
|
|
ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
|
|
ASSERT(nCount == -1 || AfxIsValidAddress(lpszString, nCount, FALSE));
|
|
|
|
int nHeight = ::DrawText(m_hDC, lpszString, nCount, lpRect, nFormat);
|
|
|
|
// If adjusting CP:
|
|
if (m_hAttribDC != NULL &&
|
|
(GetTextAlign() & TA_UPDATECP) && ((nFormat & DT_CALCRECT) == 0))
|
|
{
|
|
CRect rect(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
|
|
nHeight = ::DrawText(m_hAttribDC, lpszString, nCount, &rect,
|
|
nFormat | DT_CALCRECT | DT_SINGLELINE);
|
|
AdjustCP(rect.Width());
|
|
}
|
|
|
|
return nHeight;
|
|
}
|
|
|
|
|
|
// Printer Escape Functions
|
|
int CMetaFileDC::Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
ASSERT(m_hDC != m_hAttribDC);
|
|
int nRet = ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData);
|
|
|
|
if (m_hAttribDC == NULL)
|
|
return nRet;
|
|
|
|
// The tact here is to NOT allow any of the document control escapes
|
|
// to be passed through. Elimination of StartDoc and EndDoc should
|
|
// eliminate anything actually going to the printer. Also anything
|
|
// that actually draws something will be filtered.
|
|
//
|
|
|
|
switch (nEscape)
|
|
{
|
|
case NEXTBAND:
|
|
case SETCOLORTABLE:
|
|
case GETCOLORTABLE:
|
|
case FLUSHOUTPUT:
|
|
case DRAFTMODE:
|
|
case QUERYESCSUPPORT:
|
|
case GETPHYSPAGESIZE:
|
|
case GETPRINTINGOFFSET:
|
|
case GETSCALINGFACTOR:
|
|
case GETPENWIDTH:
|
|
case SETCOPYCOUNT:
|
|
case SELECTPAPERSOURCE:
|
|
case GETTECHNOLOGY:
|
|
case SETLINECAP:
|
|
case SETLINEJOIN:
|
|
case SETMITERLIMIT:
|
|
case BANDINFO:
|
|
case GETVECTORPENSIZE:
|
|
case GETVECTORBRUSHSIZE:
|
|
case ENABLEDUPLEX:
|
|
case GETSETPAPERBINS:
|
|
case GETSETPRINTORIENT:
|
|
case ENUMPAPERBINS:
|
|
case SETDIBSCALING:
|
|
case ENUMPAPERMETRICS:
|
|
case GETSETPAPERMETRICS:
|
|
case GETEXTENDEDTEXTMETRICS:
|
|
case GETEXTENTTABLE:
|
|
case GETPAIRKERNTABLE:
|
|
case GETTRACKKERNTABLE:
|
|
case ENABLERELATIVEWIDTHS:
|
|
case ENABLEPAIRKERNING:
|
|
case SETKERNTRACK:
|
|
case SETALLJUSTVALUES:
|
|
case SETCHARSET:
|
|
case SET_BACKGROUND_COLOR:
|
|
case SET_SCREEN_ANGLE:
|
|
case SET_SPREAD:
|
|
return ::Escape(m_hAttribDC, nEscape, nCount, lpszInData, lpOutData);
|
|
|
|
default:
|
|
break; // return output DC return value
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
// Viewport origin and Viewport extent overrides
|
|
// (usually, don't modify viewport orgin and extent on the output dc)
|
|
|
|
CPoint CMetaFileDC::SetViewportOrg(int x, int y)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
CPoint point;
|
|
if (m_hAttribDC == NULL)
|
|
::SetViewportOrgEx(m_hDC, x, y, &point);
|
|
else
|
|
::SetViewportOrgEx(m_hAttribDC, x, y, &point);
|
|
return point;
|
|
}
|
|
|
|
CPoint CMetaFileDC::OffsetViewportOrg(int nWidth, int nHeight)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
CPoint point;
|
|
if (m_hAttribDC == NULL)
|
|
::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, &point);
|
|
else
|
|
::OffsetViewportOrgEx(m_hAttribDC, nWidth, nHeight, &point);
|
|
return point;
|
|
}
|
|
|
|
CSize CMetaFileDC::SetViewportExt(int x, int y)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
CSize size;
|
|
if (m_hAttribDC == NULL)
|
|
::SetViewportExtEx(m_hDC, x, y, &size);
|
|
else
|
|
::SetViewportExtEx(m_hAttribDC, x, y, &size);
|
|
return size;
|
|
}
|
|
|
|
CSize CMetaFileDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom)
|
|
{
|
|
ASSERT(m_hDC != NULL);
|
|
CSize size;
|
|
if (m_hAttribDC == NULL)
|
|
::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size);
|
|
else
|
|
::ScaleViewportExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size);
|
|
return size;
|
|
}
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(CMetaFileDC, CDC)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|