You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

510 lines
13 KiB
C++

2 years ago
// 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 <math.h>
#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