home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
wingdi.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
34KB
|
1,379 lines
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 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_CORE2_SEG
#pragma code_seg(AFX_CORE2_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Diagnostic Output
#ifdef _DEBUG
CDumpContext& AFXAPI operator<<(CDumpContext& dc, SIZE size)
{
return dc << "(" << size.cx << " x " << size.cy << ")";
}
CDumpContext& AFXAPI operator<<(CDumpContext& dc, POINT point)
{
return dc << "(" << point.x << ", " << point.y << ")";
}
CDumpContext& AFXAPI operator<<(CDumpContext& dc, const RECT& rect)
{
return dc << "(L " << rect.left << ", T " << rect.top << ", R " <<
rect.right << ", B " << rect.bottom << ")";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDC
CDC::CDC()
{
m_hDC = NULL;
m_hAttribDC = NULL;
m_bPrinting = FALSE;
}
#ifdef _DEBUG
void CDC::AssertValid() const
{
CObject::AssertValid();
}
void CDC::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_hDC = " << (UINT)m_hDC;
dc << "\nm_hAttribDC = " << (UINT)m_hAttribDC;
dc << "\nm_bPrinting = " << m_bPrinting;
dc << "\n";
}
#endif //_DEBUG
#include "fixalloc.h"
class CTempDC : public CDC
{
DECLARE_DYNCREATE(CTempDC)
DECLARE_FIXED_ALLOC(CTempDC);
};
CHandleMap* PASCAL afxMapHDC(BOOL bCreate)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
if (pState->m_pmapHDC == NULL && bCreate)
{
BOOL bEnable = AfxEnableMemoryTracking(FALSE);
#ifndef _AFX_PORTABLE
_PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
#endif
pState->m_pmapHDC = new CHandleMap(RUNTIME_CLASS(CTempDC),
offsetof(CDC, m_hDC), 2);
#ifndef _AFX_PORTABLE
AfxSetNewHandler(pnhOldHandler);
#endif
AfxEnableMemoryTracking(bEnable);
}
return pState->m_pmapHDC;
}
CDC* PASCAL CDC::FromHandle(HDC hDC)
{
CHandleMap* pMap = afxMapHDC(TRUE); //create map if not exist
ASSERT(pMap != NULL);
CDC* pDC = (CDC*)pMap->FromHandle(hDC);
ASSERT(pDC == NULL || pDC->m_hDC == hDC);
return pDC;
}
BOOL CDC::Attach(HDC hDC)
{
ASSERT(m_hDC == NULL); // only attach once, detach on destroy
ASSERT(m_hAttribDC == NULL); // only attach to an empty DC
if (hDC == NULL)
return FALSE;
CHandleMap* pMap = afxMapHDC(TRUE); // create map if not exist
ASSERT(pMap != NULL);
pMap->SetPermanent(m_hDC = hDC, this);
SetAttribDC(m_hDC); // Default to same as output
return TRUE;
}
HDC CDC::Detach()
{
HDC hDC = m_hDC;
if (hDC != NULL)
{
CHandleMap* pMap = afxMapHDC(); // don't create if not exist
if (pMap != NULL)
pMap->RemoveHandle(m_hDC);
}
ReleaseAttribDC();
m_hDC = NULL;
return hDC;
}
BOOL CDC::DeleteDC()
{
if (m_hDC == NULL)
return FALSE;
return ::DeleteDC(Detach());
}
CDC::~CDC()
{
if (m_hDC != NULL)
::DeleteDC(Detach());
}
void CDC::SetAttribDC(HDC hDC) // Set the Attribute DC
{
m_hAttribDC = hDC;
}
void CDC::SetOutputDC(HDC hDC) // Set the Output DC
{
#ifdef _DEBUG
CHandleMap* pMap = afxMapHDC();
if (pMap != NULL && pMap->LookupPermanent(m_hDC) == this)
{
TRACE0("Cannot Set Output hDC on Attached CDC.\n");
ASSERT(FALSE);
}
#endif
m_hDC = hDC;
}
void CDC::ReleaseAttribDC() // Release the Attribute DC
{
m_hAttribDC = NULL;
}
void CDC::ReleaseOutputDC() // Release the Output DC
{
#ifdef _DEBUG
CHandleMap* pMap = afxMapHDC();
if (pMap != NULL && pMap->LookupPermanent(m_hDC) == this)
{
TRACE0("Cannot Release Output hDC on Attached CDC.\n");
ASSERT(FALSE);
}
#endif
m_hDC = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// Out-of-line routines
int CDC::StartDoc(LPCTSTR lpszDocName)
{
DOCINFO di;
memset(&di, 0, sizeof(DOCINFO));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = lpszDocName;
return StartDoc(&di);
}
int CDC::SaveDC()
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hAttribDC != NULL)
nRetVal = ::SaveDC(m_hAttribDC);
if (m_hDC != m_hAttribDC && ::SaveDC(m_hDC) != 0)
nRetVal = -1; // -1 is the only valid restore value for complex DCs
return nRetVal;
}
BOOL CDC::RestoreDC(int nSavedDC)
{
// if two distinct DCs, nSavedDC can only be -1
ASSERT(m_hDC != NULL);
ASSERT(m_hDC == m_hAttribDC || nSavedDC == -1);
BOOL bRetVal = TRUE;
if (m_hDC != m_hAttribDC)
bRetVal = ::RestoreDC(m_hDC, nSavedDC);
if (m_hAttribDC != NULL)
bRetVal = (bRetVal && ::RestoreDC(m_hAttribDC, nSavedDC));
return bRetVal;
}
CGdiObject* PASCAL CDC::SelectGdiObject(HDC hDC, HGDIOBJ h)
{
return CGdiObject::FromHandle(::SelectObject(hDC, h));
}
CGdiObject* CDC::SelectStockObject(int nIndex)
{
ASSERT(m_hDC != NULL);
HGDIOBJ hObject = ::GetStockObject(nIndex);
HGDIOBJ hOldObj = NULL;
ASSERT(hObject != NULL);
if (m_hDC != m_hAttribDC)
hOldObj = ::SelectObject(m_hDC, hObject);
if (m_hAttribDC != NULL)
hOldObj = ::SelectObject(m_hAttribDC, hObject);
return CGdiObject::FromHandle(hOldObj);
}
CPen* CDC::SelectObject(CPen* pPen)
{
ASSERT(m_hDC != NULL);
HGDIOBJ hOldObj = NULL;
if (m_hDC != m_hAttribDC)
hOldObj = ::SelectObject(m_hDC, pPen->GetSafeHandle());
if (m_hAttribDC != NULL)
hOldObj = ::SelectObject(m_hAttribDC, pPen->GetSafeHandle());
return (CPen*)CGdiObject::FromHandle(hOldObj);
}
CBrush* CDC::SelectObject(CBrush* pBrush)
{
ASSERT(m_hDC != NULL);
HGDIOBJ hOldObj = NULL;
if (m_hDC != m_hAttribDC)
hOldObj = ::SelectObject(m_hDC, pBrush->GetSafeHandle());
if (m_hAttribDC != NULL)
hOldObj = ::SelectObject(m_hAttribDC, pBrush->GetSafeHandle());
return (CBrush*)CGdiObject::FromHandle(hOldObj);
}
CFont* CDC::SelectObject(CFont* pFont)
{
ASSERT(m_hDC != NULL);
HGDIOBJ hOldObj = NULL;
if (m_hDC != m_hAttribDC)
hOldObj = ::SelectObject(m_hDC, pFont->GetSafeHandle());
if (m_hAttribDC != NULL)
hOldObj = ::SelectObject(m_hAttribDC, pFont->GetSafeHandle());
return (CFont*)CGdiObject::FromHandle(hOldObj);
}
int CDC::SelectObject(CRgn* pRgn)
{
ASSERT(m_hDC != NULL);
int nRetVal = GDI_ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = (int)::SelectObject(m_hDC, pRgn->GetSafeHandle());
if (m_hAttribDC != NULL)
nRetVal = (int)::SelectObject(m_hAttribDC, pRgn->GetSafeHandle());
return nRetVal;
}
CPalette* CDC::SelectPalette(CPalette* pPalette, BOOL bForceBackground)
{
ASSERT(m_hDC != NULL);
return (CPalette*) CGdiObject::FromHandle(::SelectPalette(m_hDC,
(HPALETTE)pPalette->GetSafeHandle(), bForceBackground));
}
COLORREF CDC::SetBkColor(COLORREF crColor)
{
ASSERT(m_hDC != NULL);
COLORREF crRetVal = CLR_INVALID;
if (m_hDC != m_hAttribDC)
crRetVal = ::SetBkColor(m_hDC, crColor);
if (m_hAttribDC != NULL)
crRetVal = ::SetBkColor(m_hAttribDC, crColor);
return crRetVal;
}
int CDC::SetBkMode(int nBkMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetBkMode(m_hDC, nBkMode);
if (m_hAttribDC != NULL)
nRetVal = ::SetBkMode(m_hAttribDC, nBkMode);
return nRetVal;
}
int CDC::SetPolyFillMode(int nPolyFillMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetPolyFillMode(m_hDC, nPolyFillMode);
if (m_hAttribDC != NULL)
nRetVal = ::SetPolyFillMode(m_hAttribDC, nPolyFillMode);
return nRetVal;
}
int CDC::SetROP2(int nDrawMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetROP2(m_hDC, nDrawMode);
if (m_hAttribDC != NULL)
nRetVal = ::SetROP2(m_hAttribDC, nDrawMode);
return nRetVal;
}
int CDC::SetStretchBltMode(int nStretchMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetStretchBltMode(m_hDC, nStretchMode);
if (m_hAttribDC != NULL)
nRetVal = ::SetStretchBltMode(m_hAttribDC, nStretchMode);
return nRetVal;
}
COLORREF CDC::SetTextColor(COLORREF crColor)
{
ASSERT(m_hDC != NULL);
COLORREF crRetVal = CLR_INVALID;
if (m_hDC != m_hAttribDC)
crRetVal = ::SetTextColor(m_hDC, crColor);
if (m_hAttribDC != NULL)
crRetVal = ::SetTextColor(m_hAttribDC, crColor);
return crRetVal;
}
int CDC::SetMapMode(int nMapMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetMapMode(m_hDC, nMapMode);
if (m_hAttribDC != NULL)
nRetVal = ::SetMapMode(m_hAttribDC, nMapMode);
return nRetVal;
}
CPoint CDC::SetViewportOrg(int x, int y)
{
ASSERT(m_hDC != NULL);
CPoint point;
if (m_hDC != m_hAttribDC)
VERIFY(::SetViewportOrgEx(m_hDC, x, y, &point));
if (m_hAttribDC != NULL)
VERIFY(::SetViewportOrgEx(m_hAttribDC, x, y, &point));
return point;
}
CPoint CDC::OffsetViewportOrg(int nWidth, int nHeight)
{
ASSERT(m_hDC != NULL);
CPoint point;
if (m_hDC != m_hAttribDC)
VERIFY(::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, &point));
if (m_hAttribDC != NULL)
VERIFY(::OffsetViewportOrgEx(m_hAttribDC, nWidth, nHeight, &point));
return point;
}
CSize CDC::SetViewportExt(int x, int y)
{
ASSERT(m_hDC != NULL);
CSize size;
if (m_hDC != m_hAttribDC)
VERIFY(::SetViewportExtEx(m_hDC, x, y, &size));
if (m_hAttribDC != NULL)
VERIFY(::SetViewportExtEx(m_hAttribDC, x, y, &size));
return size;
}
CSize CDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom)
{
ASSERT(m_hDC != NULL);
CSize size;
if (m_hDC != m_hAttribDC)
VERIFY(::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size));
if (m_hAttribDC != NULL)
VERIFY(::ScaleViewportExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size));
return size;
}
CPoint CDC::SetWindowOrg(int x, int y)
{
ASSERT(m_hDC != NULL);
CPoint point;
if (m_hDC != m_hAttribDC)
VERIFY(::SetWindowOrgEx(m_hDC, x, y, &point));
if (m_hAttribDC != NULL)
VERIFY(::SetWindowOrgEx(m_hAttribDC, x, y, &point));
return point;
}
CPoint CDC::OffsetWindowOrg(int nWidth, int nHeight)
{
ASSERT(m_hDC != NULL);
CPoint point;
if (m_hDC != m_hAttribDC)
VERIFY(::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, &point));
if (m_hAttribDC != NULL)
VERIFY(::OffsetWindowOrgEx(m_hAttribDC, nWidth, nHeight, &point));
return point;
}
CSize CDC::SetWindowExt(int x, int y)
{
ASSERT(m_hDC != NULL);
CSize size;
if (m_hDC != m_hAttribDC)
VERIFY(::SetWindowExtEx(m_hDC, x, y, &size));
if (m_hAttribDC != NULL)
VERIFY(::SetWindowExtEx(m_hAttribDC, x, y, &size));
return size;
}
CSize CDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom)
{
ASSERT(m_hDC != NULL);
CSize size;
if (m_hDC != m_hAttribDC)
VERIFY(::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size));
if (m_hAttribDC != NULL)
VERIFY(::ScaleWindowExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size));
return size;
}
int CDC::GetClipBox(LPRECT lpRect) const
{
ASSERT(m_hDC != NULL);
return ::GetClipBox(m_hDC, lpRect);
}
int CDC::SelectClipRgn(CRgn* pRgn)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::SelectClipRgn(m_hDC, (HRGN)pRgn->GetSafeHandle());
if (m_hAttribDC != NULL)
nRetVal = ::SelectClipRgn(m_hAttribDC, (HRGN)pRgn->GetSafeHandle());
return nRetVal;
}
int CDC::ExcludeClipRect(int x1, int y1, int x2, int y2)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::ExcludeClipRect(m_hDC, x1, y1, x2, y2);
if (m_hAttribDC != NULL)
nRetVal = ::ExcludeClipRect(m_hAttribDC, x1, y1, x2, y2);
return nRetVal;
}
int CDC::ExcludeClipRect(LPCRECT lpRect)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top,
lpRect->right, lpRect->bottom);
if (m_hAttribDC != NULL)
nRetVal = ::ExcludeClipRect(m_hAttribDC, lpRect->left, lpRect->top,
lpRect->right, lpRect->bottom);
return nRetVal;
}
int CDC::IntersectClipRect(int x1, int y1, int x2, int y2)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::IntersectClipRect(m_hDC, x1, y1, x2, y2);
if (m_hAttribDC != NULL)
nRetVal = ::IntersectClipRect(m_hAttribDC, x1, y1, x2, y2);
return nRetVal;
}
int CDC::IntersectClipRect(LPCRECT lpRect)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top,
lpRect->right, lpRect->bottom);
if (m_hAttribDC != NULL)
nRetVal = ::IntersectClipRect(m_hAttribDC, lpRect->left, lpRect->top,
lpRect->right, lpRect->bottom);
return nRetVal;
}
int CDC::OffsetClipRgn(int x, int y)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::OffsetClipRgn(m_hDC, x, y);
if (m_hAttribDC != NULL)
nRetVal = ::OffsetClipRgn(m_hAttribDC, x, y);
return nRetVal;
}
int CDC::OffsetClipRgn(SIZE size)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::OffsetClipRgn(m_hDC, size.cx, size.cy);
if (m_hAttribDC != NULL)
nRetVal = ::OffsetClipRgn(m_hAttribDC, size.cx, size.cy);
return nRetVal;
}
CPoint CDC::MoveTo(int x, int y)
{
ASSERT(m_hDC != NULL);
CPoint point;
if (m_hDC != m_hAttribDC)
VERIFY(::MoveToEx(m_hDC, x, y, &point));
if (m_hAttribDC != NULL)
VERIFY(::MoveToEx(m_hAttribDC, x, y, &point));
return point;
}
BOOL CDC::LineTo(int x, int y)
{
ASSERT(m_hDC != NULL);
if (m_hAttribDC != NULL && m_hDC != m_hAttribDC)
::MoveToEx(m_hAttribDC, x, y, NULL);
return ::LineTo(m_hDC, x, y);
}
UINT CDC::SetTextAlign(UINT nFlags)
{
ASSERT(m_hDC != NULL);
UINT nRetVal = GDI_ERROR;
if (m_hDC != m_hAttribDC)
::SetTextAlign(m_hDC, nFlags);
if (m_hAttribDC != NULL)
nRetVal = ::SetTextAlign(m_hAttribDC, nFlags);
return nRetVal;
}
int CDC::SetTextJustification(int nBreakExtra, int nBreakCount)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
if (m_hAttribDC != NULL)
nRetVal = ::SetTextJustification(m_hAttribDC, nBreakExtra, nBreakCount);
return nRetVal;
}
int CDC::SetTextCharacterExtra(int nCharExtra)
{
ASSERT(m_hDC != NULL);
int nRetVal = 0x8000000;
if (m_hDC != m_hAttribDC)
nRetVal = ::SetTextCharacterExtra(m_hDC, nCharExtra);
if (m_hAttribDC != NULL)
nRetVal = ::SetTextCharacterExtra(m_hAttribDC, nCharExtra);
return nRetVal;
}
DWORD CDC::SetMapperFlags(DWORD dwFlag)
{
ASSERT(m_hDC != NULL);
DWORD dwRetVal = GDI_ERROR;
if (m_hDC != m_hAttribDC)
dwRetVal = ::SetMapperFlags(m_hDC, dwFlag);
if (m_hAttribDC != NULL)
dwRetVal = ::SetMapperFlags(m_hAttribDC, dwFlag);
return dwRetVal;
}
typedef DWORD (CALLBACK* AFX_GDIGETLAYOUTPROC)(HDC);
typedef DWORD (CALLBACK* AFX_GDISETLAYOUTPROC)(HDC, DWORD);
DWORD CDC::GetLayout() const
{
ASSERT(m_hDC != NULL);
HINSTANCE hInst = ::GetModuleHandleA("GDI32.DLL");
ASSERT(hInst != NULL);
DWORD dwGetLayout = LAYOUT_LTR;
AFX_GDIGETLAYOUTPROC pfn;
pfn = (AFX_GDIGETLAYOUTPROC) GetProcAddress(hInst, "GetLayout");
// if they API is available, just call it. If it is not
// available, indicate an error.
if (pfn != NULL)
dwGetLayout = (*pfn)(m_hDC);
else
{
dwGetLayout = GDI_ERROR;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
}
return dwGetLayout;
}
DWORD CDC::SetLayout(DWORD dwSetLayout)
{
ASSERT(m_hDC != NULL);
HINSTANCE hInst = ::GetModuleHandleA("GDI32.DLL");
ASSERT(hInst != NULL);
DWORD dwGetLayout = LAYOUT_LTR;
AFX_GDISETLAYOUTPROC pfn;
pfn = (AFX_GDISETLAYOUTPROC) GetProcAddress(hInst, "SetLayout");
// If the API is availalbe, just call it. If it's not available,
// setting anything other than LAYOUT_LTR is an error.
if (pfn != NULL)
dwGetLayout = (*pfn)(m_hDC, dwSetLayout);
else if (dwSetLayout != LAYOUT_LTR)
{
dwGetLayout = GDI_ERROR;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
}
return dwGetLayout;
}
void CWnd::ScreenToClient(LPRECT lpRect) const
{
ASSERT(::IsWindow(m_hWnd));
::ScreenToClient(m_hWnd, (LPPOINT)lpRect);
::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1);
if (GetExStyle() & WS_EX_LAYOUTRTL)
CRect::SwapLeftRight(lpRect);
}
void CWnd::ClientToScreen(LPRECT lpRect) const
{
ASSERT(::IsWindow(m_hWnd));
::ClientToScreen(m_hWnd, (LPPOINT)lpRect);
::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1);
if (GetExStyle() & WS_EX_LAYOUTRTL)
CRect::SwapLeftRight(lpRect);
}
/////////////////////////////////////////////////////////////////////////////
// Advanced Win32 GDI functions
BOOL CDC::ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
{
ASSERT(m_hDC != NULL);
BOOL bResult = ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
if (m_hDC != m_hAttribDC)
{
CPoint pt;
VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
}
return bResult;
}
int CDC::SetArcDirection(int nArcDirection)
{
ASSERT(m_hDC != NULL);
int nResult = 0;
if (m_hDC != m_hAttribDC)
nResult = ::SetArcDirection(m_hDC, nArcDirection);
if (m_hAttribDC != NULL)
nResult = ::SetArcDirection(m_hAttribDC, nArcDirection);
return nResult;
}
BOOL CDC::PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount)
{
ASSERT(m_hDC != NULL);
BOOL bResult = ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount);
if (m_hDC != m_hAttribDC)
{
CPoint pt;
VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
}
return bResult;
}
BOOL CDC::PolylineTo(const POINT* lpPoints, int nCount)
{
ASSERT(m_hDC != NULL);
BOOL bResult = ::PolylineTo(m_hDC, lpPoints, nCount);
if (m_hDC != m_hAttribDC)
{
CPoint pt;
VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
}
return bResult;
}
BOOL CDC::SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
{
ASSERT(m_hDC != NULL);
BOOL bResult = FALSE;
if (m_hDC != m_hAttribDC)
bResult = ::SetColorAdjustment(m_hDC, lpColorAdjust);
if (m_hAttribDC != NULL)
bResult = ::SetColorAdjustment(m_hAttribDC, lpColorAdjust);
return bResult;
}
BOOL CDC::PolyBezierTo(const POINT* lpPoints, int nCount)
{
ASSERT(m_hDC != NULL);
BOOL bResult = ::PolyBezierTo(m_hDC, lpPoints, nCount);
if (m_hDC != m_hAttribDC)
{
CPoint pt;
VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
}
return bResult;
}
BOOL CDC::SelectClipPath(int nMode)
{
ASSERT(m_hDC != NULL);
// output DC always holds the current path
if (!::SelectClipPath(m_hDC, nMode))
return FALSE;
// transfer clipping region into the attribute DC
BOOL bResult = TRUE;
if (m_hDC != m_hAttribDC)
{
HRGN hRgn = ::CreateRectRgn(0, 0, 0, 0);
if (::GetClipRgn(m_hDC, hRgn) < 0 || !::SelectClipRgn(m_hAttribDC, hRgn))
{
TRACE0("Error: unable to transfer clip region in CDC::SelectClipPath!\n");
bResult = FALSE;
}
DeleteObject(hRgn);
}
return bResult;
}
int CDC::SelectClipRgn(CRgn* pRgn, int nMode)
{
ASSERT(m_hDC != NULL);
int nRetVal = ERROR;
if (m_hDC != m_hAttribDC)
nRetVal = ::ExtSelectClipRgn(m_hDC, (HRGN)pRgn->GetSafeHandle(), nMode);
if (m_hAttribDC != NULL)
nRetVal = ::ExtSelectClipRgn(m_hAttribDC, (HRGN)pRgn->GetSafeHandle(), nMode);
return nRetVal;
}
/////////////////////////////////////////////////////////////////////////////
// Special handling for metafile playback
int CALLBACK AfxEnumMetaFileProc(HDC hDC,
HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam)
{
CDC* pDC = (CDC*)lParam;
ASSERT_VALID(pDC);
switch (pMetaRec->rdFunction)
{
// these records have effects different for each CDC derived class
case META_SETMAPMODE:
pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]);
break;
case META_SETWINDOWEXT:
pDC->SetWindowExt(
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SETWINDOWORG:
pDC->SetWindowOrg(
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SETVIEWPORTEXT:
pDC->SetViewportExt(
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SETVIEWPORTORG:
pDC->SetViewportOrg(
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SCALEWINDOWEXT:
pDC->ScaleWindowExt(
(int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SCALEVIEWPORTEXT:
pDC->ScaleViewportExt(
(int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_OFFSETVIEWPORTORG:
pDC->OffsetViewportOrg(
(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
break;
case META_SAVEDC:
pDC->SaveDC();
break;
case META_RESTOREDC:
pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]);
break;
case META_SETBKCOLOR:
pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
break;
case META_SETTEXTCOLOR:
pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
break;
// need to watch out for SelectObject(HFONT), for custom font mapping
case META_SELECTOBJECT:
{
HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]];
UINT nObjType = GetObjectType(hObject);
if (nObjType == 0)
{
// object type is unknown, determine if it is a font
HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT);
HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont);
HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject);
if (hObjOld == hStockFont)
{
// got the stock object back, so must be selecting a font
pDC->SelectObject(CFont::FromHandle((HFONT)hObject));
break; // don't play the default record
}
else
{
// didn't get the stock object back, so restore everything
::SelectObject(pDC->m_hDC, hFontOld);
::SelectObject(pDC->m_hDC, hObjOld);
}
// and fall through to PlayMetaFileRecord...
}
else if (nObjType == OBJ_FONT)
{
// play back as CDC::SelectObject(CFont*)
pDC->SelectObject(CFont::FromHandle((HFONT)hObject));
break; // don't play the default record
}
}
// fall through...
default:
::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles);
break;
}
return 1;
}
BOOL CDC::PlayMetaFile(HMETAFILE hMF)
{
if (::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE)
{
// playing metafile in metafile, just use core windows API
return ::PlayMetaFile(m_hDC, hMF);
}
// for special playback, lParam == pDC
return ::EnumMetaFile(m_hDC, hMF, AfxEnumMetaFileProc, (LPARAM)this);
}
/////////////////////////////////////////////////////////////////////////////
// Coordinate transforms
void CDC::LPtoDP(LPSIZE lpSize) const
{
ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
CSize sizeWinExt = GetWindowExt();
CSize sizeVpExt = GetViewportExt();
lpSize->cx = MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
lpSize->cy = MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
}
void CDC::DPtoLP(LPSIZE lpSize) const
{
ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
CSize sizeWinExt = GetWindowExt();
CSize sizeVpExt = GetViewportExt();
lpSize->cx = MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx));
lpSize->cy = MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy));
}
/////////////////////////////////////////////////////////////////////////////
// Helper DCs
#ifdef _DEBUG
void CClientDC::AssertValid() const
{
CDC::AssertValid();
ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
}
void CClientDC::Dump(CDumpContext& dc) const
{
CDC::Dump(dc);
dc << "m_hWnd = " << (UINT)m_hWnd;
dc << "\n";
}
#endif
CClientDC::CClientDC(CWnd* pWnd)
{
ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))
AfxThrowResourceException();
}
CClientDC::~CClientDC()
{
ASSERT(m_hDC != NULL);
::ReleaseDC(m_hWnd, Detach());
}
#ifdef _DEBUG
void CWindowDC::AssertValid() const
{
CDC::AssertValid();
ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
}
void CWindowDC::Dump(CDumpContext& dc) const
{
CDC::Dump(dc);
dc << "m_hWnd = " << (UINT)m_hWnd;
dc << "\n";
}
#endif
CWindowDC::CWindowDC(CWnd* pWnd)
{
ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
if (!Attach(::GetWindowDC(m_hWnd = pWnd->GetSafeHwnd())))
AfxThrowResourceException();
}
CWindowDC::~CWindowDC()
{
ASSERT(m_hDC != NULL);
::ReleaseDC(m_hWnd, Detach());
}
#ifdef _DEBUG
void CPaintDC::AssertValid() const
{
CDC::AssertValid();
ASSERT(::IsWindow(m_hWnd));
}
void CPaintDC::Dump(CDumpContext& dc) const
{
CDC::Dump(dc);
dc << "m_hWnd = " << (UINT)m_hWnd;
dc << "\nm_ps.hdc = " << (UINT)m_ps.hdc;
dc << "\nm_ps.fErase = " << m_ps.fErase;
dc << "\nm_ps.rcPaint = " << (CRect)m_ps.rcPaint;
dc << "\n";
}
#endif
CPaintDC::CPaintDC(CWnd* pWnd)
{
ASSERT_VALID(pWnd);
ASSERT(::IsWindow(pWnd->m_hWnd));
if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
AfxThrowResourceException();
}
CPaintDC::~CPaintDC()
{
ASSERT(m_hDC != NULL);
ASSERT(::IsWindow(m_hWnd));
::EndPaint(m_hWnd, &m_ps);
Detach();
}
/////////////////////////////////////////////////////////////////////////////
// CGdiObject
#ifdef _DEBUG
void CGdiObject::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_hObject = " << (UINT)m_hObject;
dc << "\n";
}
void CGdiObject::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_hObject == NULL ||
(afxData.bWin95 || ::GetObjectType(m_hObject) != 0));
}
#endif
#include "fixalloc.h"
class CTempGdiObject : public CGdiObject
{
DECLARE_DYNCREATE(CTempGdiObject)
DECLARE_FIXED_ALLOC(CTempGdiObject);
};
CHandleMap* PASCAL afxMapHGDIOBJ(BOOL bCreate)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
if (pState->m_pmapHGDIOBJ == NULL && bCreate)
{
BOOL bEnable = AfxEnableMemoryTracking(FALSE);
#ifndef _AFX_PORTABLE
_PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
#endif
pState->m_pmapHGDIOBJ = new CHandleMap(RUNTIME_CLASS(CTempGdiObject),
offsetof(CGdiObject, m_hObject));
#ifndef _AFX_PORTABLE
AfxSetNewHandler(pnhOldHandler);
#endif
AfxEnableMemoryTracking(bEnable);
}
return pState->m_pmapHGDIOBJ;
}
CGdiObject* PASCAL CGdiObject::FromHandle(HGDIOBJ h)
{
CHandleMap* pMap = afxMapHGDIOBJ(TRUE); //create map if not exist
ASSERT(pMap != NULL);
CGdiObject* pObject = (CGdiObject*)pMap->FromHandle(h);
ASSERT(pObject == NULL || pObject->m_hObject == h);
return pObject;
}
BOOL CGdiObject::Attach(HGDIOBJ hObject)
{
ASSERT(m_hObject == NULL); // only attach once, detach on destroy
if (hObject == NULL)
return FALSE;
CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
ASSERT(pMap != NULL);
pMap->SetPermanent(m_hObject = hObject, this);
return TRUE;
}
HGDIOBJ CGdiObject::Detach()
{
HGDIOBJ hObject = m_hObject;
if (hObject != NULL)
{
CHandleMap* pMap = afxMapHGDIOBJ(); // don't create if not exist
if (pMap != NULL)
pMap->RemoveHandle(m_hObject);
}
m_hObject = NULL;
return hObject;
}
BOOL CGdiObject::DeleteObject()
{
if (m_hObject == NULL)
return FALSE;
return ::DeleteObject(Detach());
}
/////////////////////////////////////////////////////////////////////////////
// Standard GDI objects
/////////////////////////////////////////////////////////////////////////////
// CPen
CPen::CPen(int nPenStyle, int nWidth, COLORREF crColor)
{
if (!Attach(::CreatePen(nPenStyle, nWidth, crColor)))
AfxThrowResourceException();
}
CPen::CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush,
int nStyleCount, const DWORD* lpStyle)
{
if (!Attach(::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount,
lpStyle)))
AfxThrowResourceException();
}
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
void CPen::Dump(CDumpContext& dc) const
{
CGdiObject::Dump(dc);
if (m_hObject == NULL)
return;
if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_PEN)
{
// not a valid object
dc << "has ILLEGAL HPEN!";
return;
}
LOGPEN lp;
VERIFY(GetObject(sizeof(lp), &lp));
dc << "lgpn.lopnStyle = " << lp.lopnStyle;
dc << "\nlgpn.lopnWidth.x (width) = " << lp.lopnWidth.x;
dc << "\nlgpn.lopnColor = " << (void*)lp.lopnColor;
dc << "\n";
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CBrush
CBrush::CBrush(COLORREF crColor)
{
if (!Attach(::CreateSolidBrush(crColor)))
AfxThrowResourceException();
}
CBrush::CBrush(int nIndex, COLORREF crColor)
{
if (!Attach(::CreateHatchBrush(nIndex, crColor)))
AfxThrowResourceException();
}
CBrush::CBrush(CBitmap* pBitmap)
{
ASSERT_VALID(pBitmap);
if (!Attach(::CreatePatternBrush((HBITMAP)pBitmap->m_hObject)))
AfxThrowResourceException();
}
BOOL CBrush::CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage)
{
ASSERT(hPackedDIB != NULL);
const void* lpPackedDIB = ::GlobalLock(hPackedDIB);
ASSERT(lpPackedDIB != NULL);
BOOL bResult = Attach(::CreateDIBPatternBrushPt(lpPackedDIB, nUsage));
::GlobalUnlock(hPackedDIB);
return bResult;
}
#ifdef _DEBUG
void CBrush::Dump(CDumpContext& dc) const
{
CGdiObject::Dump(dc);
if (m_hObject == NULL)
return;
if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_BRUSH)
{
// not a valid window
dc << "has ILLEGAL HBRUSH!";
return;
}
LOGBRUSH lb;
VERIFY(GetObject(sizeof(lb), &lb));
dc << "lb.lbStyle = " << lb.lbStyle;
dc << "\nlb.lbHatch = " << lb.lbHatch;
dc << "\nlb.lbColor = " << (void*)lb.lbColor;
dc << "\n";
}
#endif
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
void CFont::Dump(CDumpContext& dc) const
{
CGdiObject::Dump(dc);
if (m_hObject == NULL)
return;
if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_FONT)
{
// not a valid GDI object
dc << "has ILLEGAL HFONT!";
return;
}
LOGFONT lf;
VERIFY(GetObject(sizeof(lf), &lf));
dc << "lf.lfHeight = " << lf.lfHeight;
dc << "\nlf.lfWidth = " << lf.lfWidth;
dc << "\nlf.lfEscapement = " << lf.lfEscapement;
dc << "\nlf.lfOrientation = " << lf.lfOrientation;
dc << "\nlf.lfWeight = " << lf.lfWeight;
dc << "\nlf.lfItalic = " << (int)lf.lfItalic;
dc << "\nlf.lfUnderline = " << (int)lf.lfUnderline;
dc << "\nlf.lfStrikeOut = " << (int)lf.lfStrikeOut;
dc << "\nlf.lfCharSet = " << (int)lf.lfCharSet;
dc << "\nlf.lfOutPrecision = " << (int)lf.lfOutPrecision;
dc << "\nlf.lfClipPrecision = " << (int)lf.lfClipPrecision;
dc << "\nlf.lfQuality = " << (int)lf.lfQuality;
dc << "\nlf.lfPitchAndFamily = " << (int)lf.lfPitchAndFamily;
dc << "\nlf.lfFaceName = " << (LPCTSTR)lf.lfFaceName;
dc << "\n";
}
#endif
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
void CBitmap::Dump(CDumpContext& dc) const
{
CGdiObject::Dump(dc);
if (m_hObject == NULL)
return;
if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_BITMAP)
{
// not a valid object
dc << "has ILLEGAL HBITMAP!";
return;
}
BITMAP bm;
VERIFY(GetObject(sizeof(bm), &bm));
dc << "bm.bmType = " << bm.bmType;
dc << "\nbm.bmHeight = " << bm.bmHeight;
dc << "\nbm.bmWidth = " << bm.bmWidth;
dc << "\nbm.bmWidthBytes = " << bm.bmWidthBytes;
dc << "\nbm.bmPlanes = " << bm.bmPlanes;
dc << "\nbm.bmBitsPixel = " << bm.bmBitsPixel;
dc << "\n";
}
#endif
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNAMIC(CResourceException, CException)
CResourceException _simpleResourceException(FALSE, AFX_IDS_RESOURCE_EXCEPTION);
IMPLEMENT_DYNAMIC(CUserException, CException)
CUserException _simpleUserException(FALSE, AFX_IDS_USER_EXCEPTION);
IMPLEMENT_DYNCREATE(CDC, CObject)
IMPLEMENT_DYNAMIC(CClientDC, CDC)
IMPLEMENT_DYNAMIC(CWindowDC, CDC)
IMPLEMENT_DYNAMIC(CPaintDC, CDC)
IMPLEMENT_DYNCREATE(CGdiObject, CObject)
IMPLEMENT_DYNAMIC(CPen, CGdiObject)
IMPLEMENT_DYNAMIC(CBrush, CGdiObject)
IMPLEMENT_DYNAMIC(CFont, CGdiObject)
IMPLEMENT_DYNAMIC(CBitmap, CGdiObject)
IMPLEMENT_DYNAMIC(CPalette, CGdiObject)
IMPLEMENT_DYNAMIC(CRgn, CGdiObject)
IMPLEMENT_DYNCREATE(CTempDC, CDC);
IMPLEMENT_DYNCREATE(CTempGdiObject, CGdiObject);
/////////////////////////////////////////////////////////////////////////////
// Standard exception processing
#ifdef AFX_CORE2_SEG
#pragma code_seg(AFX_CORE2_SEG)
#endif
// resource failure
void AFXAPI AfxThrowResourceException()
{
THROW((CResourceException*)&_simpleResourceException);
}
// user alert
void AFXAPI AfxThrowUserException()
{
THROW((CUserException*)&_simpleUserException);
}
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
#pragma warning(disable: 4074)
#pragma init_seg(compiler)
IMPLEMENT_FIXED_ALLOC(CTempDC, 64);
IMPLEMENT_FIXED_ALLOC(CTempGdiObject, 64);
/////////////////////////////////////////////////////////////////////////////