// XTPFlowGraphDrawContextGdiPlus.cpp : implementation of the CXTPFlowGraphDrawContextGdiPlus class. // // This file is a part of the XTREME TOOLKIT PRO MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include "Common/XTPDrawHelpers.h" #include "Common/XTPResourceManager.h" #include "Common/XTPVC80Helpers.h" #include "GraphicLibrary/GdiPlus/GdiPlus.h" #include "Markup/XTPMarkupObject.h" #include "Markup/XTPMarkupInputElement.h" #include "Markup/XTPMarkupUIElement.h" #include "Markup/XTPMarkupContext.h" #include "Markup/XTPMarkupDrawingContext.h" #include "XTPFlowGraphTools.h" #include "XTPFlowGraphDrawContext.h" #include "XTPFlowGraphDrawContextGdiPlus.h" #include "XTPFlowGraphControl.h" #include "XTPFlowGraphImage.h" #pragma comment(lib, "GdiPlus.lib") using namespace Gdiplus; using namespace Gdiplus::DllExports; ////////////////////////////////////////////////////////////////////////// // CXTPFlowGraphDrawContextGdiPlus class CXTPFlowGraphDrawContextGdiPlus::CGdiPlus { public: CGdiPlus() { m_hModule = NULL; m_nGdiplusToken = NULL; m_nCount = 0; } public: void Register(BOOL bInit); public: HMODULE m_hModule; ULONG_PTR m_nGdiplusToken; int m_nCount; }; void CXTPFlowGraphDrawContextGdiPlus::CGdiPlus::Register(BOOL bInit) { if (bInit) { m_nCount++; if (m_nCount > 1) return; ASSERT(m_nGdiplusToken == 0 && m_hModule == 0); m_hModule = LoadLibrary(_T("GdiPlus.dll")); if (m_hModule) { GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&m_nGdiplusToken, &gdiplusStartupInput, NULL); } } else { m_nCount--; if (m_nCount != 0) return; if (m_hModule) { GdiplusShutdown(m_nGdiplusToken); FreeLibrary(m_hModule); } m_hModule = NULL; m_nGdiplusToken = 0; } } void CXTPFlowGraphDrawContextGdiPlus::Register(BOOL bInit) { static CGdiPlus GdiPlus; GdiPlus.Register(bInit); } CXTPFlowGraphDrawContextGdiPlus::CXTPFlowGraphDrawContextGdiPlus(HDC hDC, HDC hAttribDC, BOOL bPrinting) : CXTPFlowGraphDrawContext(hDC, hAttribDC, bPrinting) { m_hDC = hDC; m_bPrinting = FALSE; if (hAttribDC && hAttribDC != hDC) { m_pGraphics = new Graphics(hDC, hAttribDC); } else { m_pGraphics = new Graphics(hDC); } m_bPrinting = bPrinting; m_pGraphics->SetPageUnit(UnitPixel); m_pGraphics->SetSmoothingMode(SmoothingModeHighQuality); m_pGraphics->SetPixelOffsetMode(PixelOffsetModeHalf); #if 0 SetSmoothingMode(0); #endif m_pActiveBrush = NULL; m_pActivePen = NULL; m_pActiveTextBrush = NULL; m_pActiveFont = NULL; Rect rcScreenBounds; m_pGraphics->GetClipBounds(&rcScreenBounds); m_rcClipRect = CRect(rcScreenBounds.GetLeft(), rcScreenBounds.GetTop(), rcScreenBounds.GetRight(), rcScreenBounds.GetBottom()); m_nBrushCount = 0; } void CXTPFlowGraphDrawContextGdiPlus::SetSmoothingMode(int nMode) { if (nMode) { m_pGraphics->SetTextRenderingHint(TextRenderingHintSystemDefault); m_pGraphics->SetSmoothingMode(SmoothingModeHighQuality); m_pGraphics->SetPixelOffsetMode(PixelOffsetModeHalf); } else { m_pGraphics->SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit); m_pGraphics->SetSmoothingMode(SmoothingModeHighSpeed); m_pGraphics->SetPixelOffsetMode(PixelOffsetModeHighSpeed); } } CXTPFlowGraphDrawContextGdiPlus::~CXTPFlowGraphDrawContextGdiPlus() { SAFE_DELETE(m_pActivePen); SAFE_DELETE(m_pActiveFont); for (int i = 0; i < m_nBrushCount; i++) { delete m_arrBrushes[i].pBrush; } } void CXTPFlowGraphDrawContextGdiPlus::SetWorldTransform(CPoint ptOffset, double dZoomLevel) { m_pGraphics->ResetTransform(); m_pGraphics->TranslateTransform((REAL)-ptOffset.x, (REAL)-ptOffset.y, MatrixOrderAppend); m_pGraphics->ScaleTransform((REAL)dZoomLevel, (REAL)dZoomLevel, MatrixOrderAppend); Rect rcScreenBounds; m_pGraphics->GetClipBounds(&rcScreenBounds); m_rcClipRect = CRect(rcScreenBounds.GetLeft(), rcScreenBounds.GetTop(), rcScreenBounds.GetRight(), rcScreenBounds.GetBottom()); } void CXTPFlowGraphDrawContextGdiPlus::SetClipRect(CRect rc) { Rect rcClip(rc.left, rc.top, rc.Width(), rc.Height()); m_pGraphics->SetClip(rcClip); Rect rcScreenBounds; m_pGraphics->GetClipBounds(&rcScreenBounds); m_rcClipRect = CRect(rcScreenBounds.GetLeft(), rcScreenBounds.GetTop(), rcScreenBounds.GetRight(), rcScreenBounds.GetBottom()); } CRect CXTPFlowGraphDrawContextGdiPlus::GetClipRect() const { return m_rcClipRect; } DWORD CXTPFlowGraphDrawContextGdiPlus::ColorRefToARGB(COLORREF clr) { DWORD dwArgb = RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)); if (clr & 0xFF000000) dwArgb |= (clr & 0xFF000000); else dwArgb |= 0xFF000000; return dwArgb; } void CXTPFlowGraphDrawContextGdiPlus::Clear(COLORREF clr) { m_pGraphics->Clear(ColorRefToARGB(clr)); } void CXTPFlowGraphDrawContextGdiPlus::FillSolidRect(LPCRECT lpRect, COLORREF clr) { FillSolidRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, clr); } Gdiplus::Brush* CXTPFlowGraphDrawContextGdiPlus::CreateBrush(COLORREF clr) { int i; for (i = 0; i < m_nBrushCount; i++) { if (m_arrBrushes[i].clr == clr) return m_arrBrushes[i].pBrush; } if (m_nBrushCount == MAX_BRUSH) { delete m_arrBrushes[m_nBrushCount - 1].pBrush; } else if (m_nBrushCount) { m_arrBrushes[m_nBrushCount] = m_arrBrushes[m_nBrushCount - 1]; } for (i = m_nBrushCount - 1; i >= 1; i--) { m_arrBrushes[i] = m_arrBrushes[i - 1]; } if (m_nBrushCount != MAX_BRUSH) m_nBrushCount++; m_arrBrushes[0].pBrush = new SolidBrush(ColorRefToARGB(clr)); m_arrBrushes[0].clr = clr; return m_arrBrushes[0].pBrush; } void CXTPFlowGraphDrawContextGdiPlus::FillSolidRect(int x, int y, int cx, int cy, COLORREF clr) { if (cx < 0) { x += cx; cx = -cx; } if (cy < 0) { y += cy; cy = -cy; } Brush* pBrush = CreateBrush(clr); m_pGraphics->FillRectangle(pBrush, x, y, cx, cy); } void CXTPFlowGraphDrawContextGdiPlus::Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) { Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); } void CXTPFlowGraphDrawContextGdiPlus::Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) { FillSolidRect(x, y, cx - 1, 1, clrTopLeft); FillSolidRect(x, y, 1, cy - 1, clrTopLeft); FillSolidRect(x + cx, y, -1, cy, clrBottomRight); FillSolidRect(x, y + cy, cx, -1, clrBottomRight); } void CXTPFlowGraphDrawContextGdiPlus::DrawFrame(int x, int y, int cx, int cy, int sz, COLORREF clr) { FillSolidRect(x, y, cx - sz, sz, clr); FillSolidRect(x, y, sz, cy - sz, clr); FillSolidRect(x + cx, y, -sz, cy, clr); FillSolidRect(x, y + cy, cx, -sz, clr); } CSize CXTPFlowGraphDrawContextGdiPlus::MeasureMarkupElement(CXTPMarkupUIElement* pMarkupUIElement) { pMarkupUIElement->GetMarkupContext()->SetDefaultFont(&m_lfActiveFont); CXTPMarkupDrawingContext dc(pMarkupUIElement->GetMarkupContext(), m_pGraphics); pMarkupUIElement->Measure(&dc, CSize(INT_MAX, INT_MAX)); CSize sz = pMarkupUIElement->GetDesiredSize(); return sz; } void CXTPFlowGraphDrawContextGdiPlus::DrawMarkupElement(CXTPMarkupUIElement* pMarkupUIElement, LPCRECT lpRect, UINT /*uFormat*/) { pMarkupUIElement->GetMarkupContext()->SetDefaultFont(&m_lfActiveFont); pMarkupUIElement->GetMarkupContext()->SetDefaultTextColor(m_clrTextColor); CXTPMarkupDrawingContext dc(pMarkupUIElement->GetMarkupContext(), m_pGraphics); pMarkupUIElement->Arrange(lpRect); pMarkupUIElement->Render(&dc); } CSize CXTPFlowGraphDrawContextGdiPlus::MeasureString(const CString& str) { if (!m_pActiveFont) return CSize(0, 0); RectF boundingBox; RectF layoutRect(0, 0, 0.0f, 0.0f); if (str.GetLength() != 0) { m_pGraphics->MeasureString(XTP_CT2CW(str), -1, m_pActiveFont, layoutRect, StringFormat::GenericTypographic(), &boundingBox); } else { m_pGraphics->MeasureString(L" ", 1, m_pActiveFont, layoutRect, StringFormat::GenericTypographic(), &boundingBox); } return CSize((int)ceil(boundingBox.Width), (int)(boundingBox.Height)); } void CXTPFlowGraphDrawContextGdiPlus::DrawText(LPCTSTR lpszText, LPCRECT lpRect, UINT uFormat) { if (!m_pActiveFont) return; StringFormat stringFormat(StringFormat::GenericTypographic()); stringFormat.SetLineAlignment(uFormat & DT_VCENTER ? StringAlignmentCenter: StringAlignmentNear); stringFormat.SetAlignment(uFormat & DT_CENTER ? StringAlignmentCenter : uFormat & DT_RIGHT ? StringAlignmentFar : StringAlignmentNear); RectF rect((REAL)lpRect->left, (REAL)lpRect->top, (REAL)lpRect->right - lpRect->left, (REAL)lpRect->bottom - lpRect->top); m_pGraphics->DrawString(XTP_CT2CW(lpszText), -1, m_pActiveFont, rect, &stringFormat, m_pActiveTextBrush); } void CXTPFlowGraphDrawContextGdiPlus::DrawCurve(Gdiplus::GraphicsPath* pPath) { if (m_pActivePen) { m_pGraphics->DrawPath(m_pActivePen, pPath); } } void CXTPFlowGraphDrawContextGdiPlus::Ellipse(LPCRECT lpRect) { if (m_pActiveBrush) { m_pGraphics->FillEllipse(m_pActiveBrush, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top); } if (m_pActivePen) { m_pGraphics->DrawEllipse(m_pActivePen, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top); } } void CXTPFlowGraphDrawContextGdiPlus::Line(float x1, float y1, float x2, float y2) { if (m_pActivePen) { m_pGraphics->DrawLine(m_pActivePen, x1, y1, x2, y2); } } void CXTPFlowGraphDrawContextGdiPlus::SetBrush(COLORREF clr) { m_pActiveBrush = CreateBrush(clr); } void CXTPFlowGraphDrawContextGdiPlus::SetPen(COLORREF clrPen, int nWidth) { SAFE_DELETE(m_pActivePen); if (nWidth) { m_pActivePen = new Pen(ColorRefToARGB(clrPen), (REAL)nWidth); } } void CXTPFlowGraphDrawContextGdiPlus::SetTextColor(COLORREF clr) { m_pActiveTextBrush = CreateBrush(clr); m_clrTextColor = clr; } void CXTPFlowGraphDrawContextGdiPlus::SetFont(LOGFONT* lf) { SAFE_DELETE(m_pActiveFont); if (!lf) return; m_pActiveFont = new Gdiplus::Font(m_hDC, lf); m_lfActiveFont = *lf; } void CXTPFlowGraphDrawContextGdiPlus::DrawGrid(CRect rc, CPoint ptScrollOffset, double dZoomLevel, COLORREF clrGridColor) { double gap = 15.0 * dZoomLevel; double x = -ptScrollOffset.x * dZoomLevel; int cnt = int(x / gap); x -= cnt * gap; while (x < 0) x += gap; while (x > gap) x -= gap; SmoothingMode nSmoothingMode= m_pGraphics->GetSmoothingMode(); m_pGraphics->SetSmoothingMode(SmoothingModeHighSpeed); Brush* pBrush = CreateBrush(clrGridColor); for (x; x < rc.right; x += gap) { m_pGraphics->FillRectangle(pBrush, (int)x, rc.top, 1, rc.Width()); } double y = -ptScrollOffset.y * dZoomLevel; cnt = int(y / gap); y -= cnt * gap; while (y < 0) y += gap; while (y > gap) y -= gap; for (y; y < rc.bottom; y += gap) { m_pGraphics->FillRectangle(pBrush, rc.left, (int)y, rc.Width(), 1); } m_pGraphics->SetSmoothingMode(nSmoothingMode); } void CXTPFlowGraphDrawContextGdiPlus::GradientFill(CRect rc, COLORREF clrFrom, COLORREF clrTo, BOOL bHoriz) { LinearGradientBrush brush(Rect(rc.left, rc.top, rc.Width(), rc.Height()), ColorRefToARGB(clrFrom), ColorRefToARGB(clrTo), bHoriz ? LinearGradientModeHorizontal : LinearGradientModeVertical); m_pGraphics->FillRectangle(&brush, rc.left, rc.top, rc.Width(), rc.Height()); } void CXTPFlowGraphDrawContextGdiPlus::DrawImage(CXTPFlowGraphImage* pImage, CRect rc) { m_pGraphics->DrawImage(pImage->GetImage(), rc.left, rc.top, rc.Width(), rc.Height()); } void CXTPFlowGraphDrawContextGdiPlus::FillPolygon(const POINT* pts, int nCount) { m_pGraphics->FillPolygon(m_pActiveBrush, (Point*)pts, nCount); } #ifdef _XTP_DEMOMODE void CXTPFlowGraphDrawContextGdiPlus::DrawWatermarkBackground(CRect rc) { m_pGraphics->SetTextRenderingHint(TextRenderingHintAntiAlias); SolidBrush brush(Color(100, 102, 102, 102)); LOGFONT lf = {0}; lf.lfHeight = LONG(rc.Width() * 80 / 1000); lf.lfWeight = FW_BOLD; STRCPY_S(lf.lfFaceName, LF_FACESIZE, _T("Myraid Pro")); Font font(m_hDC, &lf); StringFormat stringFormat; stringFormat.SetLineAlignment(StringAlignmentCenter); stringFormat.SetAlignment(StringAlignmentCenter); RectF rcRect((float)rc.left, (float)rc.top, (float)rc.Width(), (float)rc.Height()); m_pGraphics->DrawString(L"Codejock Chart Pro Trial", -1, &font, rcRect, &stringFormat, &brush); } #endif