2 * @file ccrystalrenderergdi.cpp
4 * @brief Implementation of the CCrystalRendererGDI class
8 #include "ccrystalrenderergdi.h"
11 CImageList* CCrystalRendererGDI::s_pIcons = nullptr;
13 /////////////////////////////////////////////////////////////////////////////
14 // CCrystalRendererGDI construction/destruction
16 CCrystalRendererGDI::CCrystalRendererGDI() :
19 , m_gridPen(PS_SOLID, 0, RGB(0xC0, 0xC0, 0xC0))
23 CCrystalRendererGDI::~CCrystalRendererGDI ()
27 void CCrystalRendererGDI::BindDC(const CDC& dc, const CRect& rc)
29 m_pDC = const_cast<CDC *>(&dc);
32 void CCrystalRendererGDI::BeginDraw()
37 bool CCrystalRendererGDI::EndDraw()
43 void CCrystalRendererGDI::SetFont(const LOGFONT &lf)
46 for (int nIndex = 0; nIndex < 4; ++nIndex)
48 bool bold = (nIndex & 1) != 0;
49 bool italic = (nIndex & 2) != 0;
50 m_apFonts[nIndex].reset(new CFont());
51 if (!m_lfBaseFont.lfHeight)
53 CClientDC dc (CWnd::GetDesktopWindow());
54 m_lfBaseFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
56 m_lfBaseFont.lfWeight = bold ? FW_BOLD : FW_NORMAL;
57 m_lfBaseFont.lfItalic = (BYTE) italic;
58 if (!m_apFonts[nIndex]->CreateFontIndirect(&m_lfBaseFont))
59 m_apFonts[nIndex].reset(nullptr);
63 void CCrystalRendererGDI::SwitchFont(bool italic, bool bold)
70 m_pDC->SelectObject(m_apFonts[nIndex].get());
73 CSize CCrystalRendererGDI::GetCharWidthHeight()
76 SetFont(m_lfBaseFont);
77 CClientDC dc (CWnd::GetDesktopWindow());
78 CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
79 CSize sizeItalicBold = dc.GetTextExtent(_T("X"));
80 dc.SelectObject(m_apFonts[0].get());
81 CSize sizeNormal = dc.GetTextExtent(_T("X"));
82 dc.SelectObject(pOldFont);
83 return CSize{ sizeNormal.cx, (std::max)(sizeNormal.cy, sizeItalicBold.cy) };
86 bool CCrystalRendererGDI::GetCharWidth(unsigned start, unsigned end, int * nWidthArray)
89 SetFont(m_lfBaseFont);
90 CClientDC dc (CWnd::GetDesktopWindow());
91 CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
92 bool succeeded = !!GetCharWidth32(dc.m_hDC, start, end, nWidthArray);
93 dc.SelectObject(pOldFont);
97 void CCrystalRendererGDI::SetTextColor(COLORREF clr)
99 m_pDC->SetTextColor(clr);
102 void CCrystalRendererGDI::SetBkColor(COLORREF clr)
104 m_pDC->SetBkColor(clr);
107 void CCrystalRendererGDI::FillRectangle(const CRect &rc)
109 m_pDC->FillSolidRect(&rc, m_pDC->GetBkColor());
112 void CCrystalRendererGDI::FillSolidRectangle(const CRect &rc, COLORREF color)
114 m_pDC->FillSolidRect(&rc, color);
117 void CCrystalRendererGDI::DrawRoundRectangle(int left, int top, int right, int bottom, int width, int height)
120 brush.CreateStockObject(NULL_BRUSH);
121 CBrush* pOldBrush = m_pDC->SelectObject(&brush);
122 CPen pen(PS_SOLID, 1, m_pDC->GetTextColor());
123 CPen *pOldPen = m_pDC->SelectObject(&pen);
125 m_pDC->RoundRect(left, top, right, bottom, width, height);
127 m_pDC->SelectObject(pOldPen);
128 m_pDC->SelectObject(pOldBrush);
131 void CCrystalRendererGDI::PushAxisAlignedClip(const CRect & rc)
134 m_pDC->IntersectClipRect(&rc);
137 void CCrystalRendererGDI::PopAxisAlignedClip()
139 m_pDC->RestoreDC(-1);
142 void CCrystalRendererGDI::DrawMarginIcon(int x, int y, int iconIndex)
144 if (s_pIcons == nullptr)
146 s_pIcons = new CImageList;
147 VERIFY(s_pIcons->Create(MARGIN_ICON_WIDTH, MARGIN_ICON_HEIGHT,
148 ILC_COLOR32 | ILC_MASK, 0, 1));
150 bmp.LoadBitmap(IDR_MARGIN_ICONS);
151 s_pIcons->Add(&bmp, RGB(255, 255, 255));
156 VERIFY(s_pIcons->Draw(m_pDC, iconIndex, pt, ILD_TRANSPARENT));
160 void CCrystalRendererGDI::DrawMarginLineNumber(int x, int y, int number)
162 CFont *pOldFont = m_pDC->SelectObject(m_apFonts[0].get());
164 int len = wsprintf(szNumbers, _T("%d"), number);
165 UINT uiOldAlign = m_pDC->SetTextAlign(TA_RIGHT);
166 m_pDC->TextOut(x - (m_pDC->IsPrinting() ? 0 : 4), y, szNumbers, len);
167 m_pDC->SetTextAlign(uiOldAlign);
168 m_pDC->SelectObject(pOldFont);
171 void CCrystalRendererGDI::DrawBoundaryLine(int left, int right, int y)
173 CPen *pOldPen = (CPen *)m_pDC->SelectStockObject(BLACK_PEN);
174 m_pDC->MoveTo(left, y);
175 m_pDC->LineTo(right, y);
176 m_pDC->SelectObject(pOldPen);
179 void CCrystalRendererGDI::DrawGridLine(int x1, int y1, int x2, int y2)
181 if (x1 == x2 || y1 == y2)
184 dcMem.CreateCompatibleDC(m_pDC);
187 bitmap.CreateCompatibleBitmap(m_pDC, 1, y2 - y1);
189 bitmap.CreateCompatibleBitmap(m_pDC, x2 - x1, 1);
190 CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
191 dcMem.SetBkColor(RGB(0, 255, 0));
192 BLENDFUNCTION blend = { 0 };
193 blend.BlendOp = AC_SRC_OVER;
194 blend.SourceConstantAlpha = 24;
196 m_pDC->AlphaBlend(x1, y1, 1, y2 - y1, &dcMem, 0, 0, 1, y2 - y1, blend);
198 m_pDC->AlphaBlend(x1, y1, x2 - x1, 1, &dcMem, 0, 0, x2 - x1, 1, blend);
199 dcMem.SelectObject(pOldBitmap);
203 CPen* pOldPen = (CPen*)m_pDC->SelectObject(&m_gridPen);
204 m_pDC->MoveTo(x1, y1);
205 m_pDC->LineTo(x2, y2);
206 m_pDC->SelectObject(pOldPen);
210 void CCrystalRendererGDI::DrawLineCursor(int left, int right, int y, int height)
213 dcMem.CreateCompatibleDC(m_pDC);
215 bitmap.CreateCompatibleBitmap(m_pDC, right - left, height);
216 CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
217 dcMem.SetBkColor(RGB(0, 255, 0));
218 BLENDFUNCTION blend = { 0 };
219 blend.BlendOp = AC_SRC_OVER;
220 blend.SourceConstantAlpha = 24;
221 m_pDC->AlphaBlend(left, y, right - left, height, &dcMem, 0, 0, right - left, height, blend);
222 dcMem.SelectObject(pOldBitmap);
225 void CCrystalRendererGDI::DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[])
227 m_pDC->ExtTextOut(x, y, ETO_CLIPPED | ETO_OPAQUE, &rc, text, static_cast<UINT>(len), const_cast<int *>(nWidths));
230 void CCrystalRendererGDI::DrawRuler(int left, int top, int width, int height, int charwidth, int offset)
232 CFont *pOldFont = m_pDC->SelectObject(m_apFonts[0].get());
233 UINT uiOldAlign = m_pDC->SetTextAlign(TA_LEFT);
234 CPen *pOldPen = (CPen *)m_pDC->SelectStockObject(BLACK_PEN);
235 int bottom = top + height - 1;
236 int prev10 = (offset / 10) * 10;
238 int len = wsprintf(szNumbers, _T("%d"), prev10);
239 if ((offset % 10) != 0 && offset - prev10 < len)
240 m_pDC->TextOut(left, bottom - height, szNumbers + (offset - prev10), len - (offset - prev10));
241 for (int i = 0; i < width / charwidth; ++i)
243 int x = left + i * charwidth;
244 if (((i + offset) % 10) == 0)
246 len = wsprintf(szNumbers, _T("%d"), offset + i);
247 m_pDC->TextOut(x, bottom - height + 1, szNumbers, len);
249 float tickscale = [](int i, int offset) {
250 if (((i + offset) % 10) == 0)
252 else if (((i + offset) % 5) == 0)
257 m_pDC->MoveTo(x, bottom - static_cast<int>(height * tickscale));
258 m_pDC->LineTo(x, bottom);
260 m_pDC->MoveTo(left, bottom);
261 m_pDC->LineTo(left + width, bottom);
262 m_pDC->SelectObject(pOldPen);
263 m_pDC->SetTextAlign(uiOldAlign);
264 m_pDC->SelectObject(pOldFont);