WinapiExtension
 All Classes Files Functions Variables Typedefs Pages
gdi.h
1 #ifndef WINAPI_EX_GDI_H
2 #define WINAPI_EX_GDI_H
3 
11 {
12 public:
14  SaveRestoreDC(HDC pDC) { dc = pDC; saved = SaveDC(dc); }
15  ~SaveRestoreDC() { RestoreDC(dc, saved); }
16 private:
17  HDC dc;
18  int saved;
19 };
20 
24 class IDC
25 {
26 public:
27  virtual ~IDC() {}
28 
33  virtual HDC _InternalGetHandle() = 0;
34 
39  HGDIOBJ Select(HGDIOBJ object) { return SelectObject(_InternalGetHandle(), object); }
40 
42  HBRUSH SetBrush(HBRUSH brush) { return (HBRUSH)Select(brush); }
44  HPEN SetPen(HPEN pen) { return (HPEN)Select(pen); }
46  HFONT SetFont(HFONT font) { return (HFONT)Select(font); }
48  HRGN SetRegion(HRGN region) { return (HRGN)Select(region); }
49 
51  BOOL BitBlt(int x, int y, int width, int height, HDC sourceDC, int srcX, int srcY, DWORD rasterOp = SRCCOPY)
52  {
53  return ::BitBlt(_InternalGetHandle(), x, y, width, height,
54  sourceDC, srcX, srcY,
55  rasterOp);
56  }
57 
59  BOOL BitBlt(const RECT& rect, HDC sourceDC, const POINT& sourcePoint, DWORD rasterOp = SRCCOPY)
60  {
61  return ::BitBlt(_InternalGetHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
62  sourceDC, sourcePoint.x, sourcePoint.y,
63  rasterOp);
64  }
65 
69  int SetStretchBltMode(int mode) { return ::SetStretchBltMode(_InternalGetHandle(), mode); }
70 
72  BOOL StretchBlt(int x, int y, int width, int height, HDC sourceDC, int srcX, int srcY, int srcWidth, int srcHeight, DWORD rasterOp = SRCCOPY)
73  {
74  return ::StretchBlt(_InternalGetHandle(), x, y, width, height,
75  sourceDC, srcX, srcY, srcWidth, srcHeight,
76  rasterOp);
77  }
78 
80  BOOL StretchBlt(const RECT& rect, HDC sourceDC, const RECT& sourceRect, DWORD rasterOp = SRCCOPY)
81  {
82  return ::StretchBlt(_InternalGetHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
83  sourceDC, sourceRect.left, sourceRect.top, sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top,
84  rasterOp);
85  }
86 
88  void FillRect(const RECT& r, HBRUSH brush) { ::FillRect(_InternalGetHandle(), &r, brush); }
90  void FillRegion(HRGN region, HBRUSH brush) { ::FillRgn(_InternalGetHandle(), region, brush); }
91 
95  void SetBkModeOpaque() { SetBkMode(_InternalGetHandle(), OPAQUE); }
99  void SetBkModeTransparent() { SetBkMode(_InternalGetHandle(), TRANSPARENT); }
100 
102  void SetTextColor(COLORREF color) { ::SetTextColor(_InternalGetHandle(), color); }
106  void SetBkColor(COLORREF color) { ::SetBkColor(_InternalGetHandle(), color); }
107 
111  void DrawText(const tstring& text, RECT& boundingRect, UINT format = DT_LEFT|DT_TOP)
112  {
113  ::DrawText(_InternalGetHandle(), text.c_str(), -1, &boundingRect, format);
114  }
116  void DrawText(const tstring& text, int x, int y) { DrawText(text, Rect(x, y, LONG_MAX, LONG_MAX)); }
117 
122  Size GetTextSize(const tstring& text, UINT format = DT_LEFT|DT_TOP, LONG maxWidth = LONG_MAX)
123  {
124  // use DrawText to support multiline text
125  Rect r(0, 0, maxWidth, 0);
126  DrawText(text, r, format | DT_CALCRECT);
127  return r.GetSize();
128  }
129 };
130 
134 class BaseDC : public IDC
135 {
136 public:
138  BaseDC(HDC pDC = NULL) : dc(pDC) {}
139 
140  HDC _InternalGetHandle() { return dc; }
141 
143  void operator=(HDC pDC) { dc = pDC; }
145  operator HDC() { return dc; }
146 
147  HDC dc;
148 };
149 
153 class PaintDC : public IDC
154 {
155 public:
157  PaintDC(HWND pHwnd) : hwnd(pHwnd) { dc = BeginPaint(hwnd, &ps); }
158  ~PaintDC() { EndPaint(hwnd, &ps); }
159 
160  HDC _InternalGetHandle() { return dc; }
161 
163  operator HDC() { return dc; }
165  HDC GetHDC() { return dc; }
166 private:
167  HWND hwnd;
168  HDC dc;
169  PAINTSTRUCT ps;
170 };
171 
175 class ClientDC : public IDC
176 {
177 public:
179  ClientDC(HWND win) : window(win) { dc = GetDC(window); }
180  ~ClientDC() { ReleaseDC(window, dc); }
181 
182  HDC _InternalGetHandle() { return dc; }
183 
185  operator HDC() { return dc; }
187  HDC GetHDC() { return dc; }
188 private:
189  HWND window;
190  HDC dc;
191 };
192 
198 class MemoryDC : public IDC
199 {
200 public:
202  MemoryDC(HBITMAP bitmap) { Init(ClientDC(NULL), bitmap); }
204  MemoryDC(HDC other, HBITMAP bitmap) { Init(other, bitmap); }
205  ~MemoryDC() { if(dc) { RestoreDC(dc, -1); DeleteDC(dc); } }
206 
207  HDC _InternalGetHandle() { return dc; }
208 
210  operator HDC() { return dc; }
212  HDC GetHDC() { return dc; }
214  HBITMAP GetBitmap() { return attachedBitmap; }
215 private:
216  void Init(HDC other, HBITMAP bitmap);
217  HDC dc;
218  HBITMAP attachedBitmap;
219 };
220 
224 template<typename HANDLE_T>
226 {
227 public:
228  GdiObject(HANDLE_T pHandle = NULL) : handle(pHandle) {}
229  ~GdiObject() { if(handle) DeleteObject(handle); }
230  void SetHandle(HANDLE_T pHandle) { if(handle) DeleteObject(handle); handle = pHandle; }
231  operator HANDLE_T() { return handle; }
232  HANDLE_T handle;
233 };
234 
238 class SolidBrush : public GdiObject<HBRUSH>
239 {
240 public:
244  SolidBrush(COLORREF color) { Create(color); }
245 
247  void Create(COLORREF color) { SetHandle(CreateSolidBrush(color)); }
248 };
249 
253 class HatchBrush : public GdiObject<HBRUSH>
254 {
255 public:
259  HatchBrush(int hatch, COLORREF color) { Create(hatch, color); }
260 
262  void Create(int hatch, COLORREF color) { SetHandle(CreateHatchBrush(hatch, color)); }
263 };
264 
268 class PatternBrush : public GdiObject<HBRUSH>
269 {
270 public:
274  PatternBrush(HBITMAP bitmap) { Create(bitmap); }
275 
277  void Create(HBITMAP bitmap) { SetHandle(CreatePatternBrush(bitmap)); }
278 };
279 
280 // there are also GetSysColorBrush() and GetStockObject(), but these don't need to be managed
281 
285 class Pen : public GdiObject<HPEN>
286 {
287 public:
289  Pen() {}
291  Pen(COLORREF color, int width = 1, int penStyle = PS_SOLID) { Create(color, width, penStyle); }
292 
294  void Create(COLORREF color, int width = 1, int penStyle = PS_SOLID) { SetHandle(CreatePen(penStyle, width, color)); }
295 };
296 
300 class Bitmap : public GdiObject<HBITMAP>
301 {
302 public:
304  Bitmap() {}
306  Bitmap(int width, int height, UINT planes, UINT bpp, const void* data) { CreateBitmap(width, height, planes, bpp, data); }
308  Bitmap(HDC compatibleDC, int width, int height) { CreateCompatibleBitmap(compatibleDC, width, height); }
310  Bitmap(TCHAR* filename) { LoadBitmap(filename); }
311 
313  void CreateBitmap(int width, int height, UINT planes, UINT bpp, const void* data) { SetHandle(::CreateBitmap(width, height, planes, bpp, data)); }
315  void CreateCompatibleBitmap(HDC compatibleDC, int width, int height) { SetHandle(::CreateCompatibleBitmap(compatibleDC, width, height)); }
317  void LoadBitmap(TCHAR* filename) { DeleteObject(handle); SetHandle((HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)); }
318 };
319 
323 class BitmapData : public BITMAP
324 {
325 public:
326  BitmapData(HBITMAP bitmap) { ZeroMemory(this, sizeof(BitmapData)); GetObject(bitmap, sizeof(BitmapData), this); }
327 };
328 
332 class DibSection : public GdiObject<HBITMAP>
333 {
334 public:
336  DibSection();
338  DibSection(int width, int height, int bpp, bool bottomup = true);
340  DibSection(HBITMAP bitmap, int bpp, bool bottomup);
342  DibSection(HBITMAP bitmap);
344  DibSection& operator= (const DibSection& other);
345 
347  static int BPP(HBITMAP bitmap);
349  static bool IsDibSection(HBITMAP bitmap);
351  static bool IsBottomUp(HBITMAP bitmap);
353  static void FillBitmapInfo(BITMAPINFO& bmi, int w, int h, int bpp, bool bottomup = true);
354 
356  bool Create(int width, int height, int bpp, bool bottomup = true);
358  bool CopyCreate(HBITMAP bitmap, int bpp, bool bottomup);
360  bool CopyCreate(HBITMAP bitmap) { return CopyCreate(bitmap, BPP(bitmap), IsBottomUp(bitmap)); }
361 
363  bool Attach(HBITMAP bitmap);
365  HBITMAP Detach();
367  void Clear();
369  bool CopyFromBitmap(HBITMAP bitmap);
371  bool CopyToBitmap(HBITMAP bitmap);
372 
374  int GetWidth() { return dibData.bmWidth; }
376  int GetHeight() { return dibData.bmHeight; }
378  int GetBPP() { return dibData.bmBitsPixel; }
380  void* GetBits() { return dibData.bmBits; }
382  void* GetPixelAddress(int x, int y) { return (BYTE*)dibData.bmBits + y*dibData.bmWidthBytes + x*dibData.bmBitsPixel/8; }
384  bool IsBottomUp() { return dibInfo.bmiHeader.biHeight > 0; }
386  int FlippedY(int y) { return IsBottomUp() ? dibData.bmHeight - 1 - y : y; }
387 
388  BITMAP dibData;
389  BITMAPINFO dibInfo;
390 private:
391  template<typename T>
392  static bool GetObject(HANDLE handle, T& obj) { return ::GetObject(handle, sizeof(obj), &obj) == sizeof(obj); }
393 };
394 
401 {
402 public:
403  FontParams()
404  : width(0)
405  , escapement(0)
406  , orientation(0)
407  , weight(FW_DONTCARE)
408  , italic(FALSE)
409  , underline(FALSE)
410  , strikeout(FALSE)
411  , charset(ANSI_CHARSET)
412  , outPrecision(OUT_DEFAULT_PRECIS)
413  , clipPrecision(CLIP_DEFAULT_PRECIS)
414  , quality(PROOF_QUALITY)
415  , pitchAndFamily(VARIABLE_PITCH | FF_DONTCARE)
416  {}
417 
419  FontParams& SetWidth(int pWidth) { width = pWidth; return *this; }
421  FontParams& SetEscapment(int pEscapement) { escapement = pEscapement; return *this; }
423  FontParams& SetOrientation(int pOrientation) { orientation = pOrientation; return *this; }
425  FontParams& SetWeight(int pWeight) { weight = pWeight; return *this; }
427  FontParams& SetItalic(BOOL set) { italic = set; return *this; }
429  FontParams& SetUnderline(BOOL set) { underline = set; return *this; }
431  FontParams& SetStrikeout(BOOL set) { strikeout = set; return *this; }
433  FontParams& SetCharSet(BYTE pCharset) { charset = pCharset; return *this; }
435  FontParams& SetOutPrecision(BYTE pOutPrecision) { outPrecision = pOutPrecision; return *this; }
437  FontParams& SetClipPrecision(BYTE pClipPrecision) { clipPrecision = pClipPrecision; return *this; }
439  FontParams& SetQuality(BYTE pQuality) { quality = pQuality; return *this; }
441  FontParams& SetPitchAndFamily(BYTE pPitchAndFamily) { pitchAndFamily = pPitchAndFamily; return *this; }
443  FontParams& SetFaceName(const tstring& pFacename) { facename = pFacename; return *this; }
444 
446  HFONT CreateFont(int height) const
447  {
448  return ::CreateFont(height,
449  width,
450  escapement,
451  orientation,
452  weight,
453  italic,
454  underline,
455  strikeout,
456  charset,
457  outPrecision,
458  clipPrecision,
459  quality,
460  pitchAndFamily,
461  facename.c_str());
462  }
463 
464  int width;
465  int escapement;
466  int orientation;
467  int weight;
468  DWORD italic;
469  DWORD underline;
470  DWORD strikeout;
471  DWORD charset;
472  DWORD outPrecision;
473  DWORD clipPrecision;
474  DWORD quality;
475  DWORD pitchAndFamily;
476  tstring facename;
477 };
478 
482 class Font : public GdiObject<HFONT>
483 {
484 public:
485  Font(HFONT font = NULL) : GdiObject<HFONT>(font) {}
486  Font(int height, const FontParams& params = FontParams()) { Create(height, params); }
487 
488  void Create(int height, const FontParams& params = FontParams()) { SetHandle(params.CreateFont(height)); }
489 
499  {
500  // get message box font
501  NONCLIENTMETRICS ncm;
502  ncm.cbSize = sizeof(ncm);
503 
504  // If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct
505  // will be the wrong size for previous versions, so we need to adjust it.
506 #if(WINVER >= 0x0600)
507  OSVERSIONINFO os;
508  os.dwOSVersionInfoSize = sizeof(os);
509  GetVersionEx(&os);
510 
511  if(os.dwMajorVersion < 6)
512  // In versions of Windows prior to Vista, the iPaddedBorderWidth member
513  // is not present, so we need to subtract its size from cbSize.
514  ncm.cbSize -= sizeof(ncm.iPaddedBorderWidth);
515 #endif
516  SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
517 
518  // create a font that matches the message box font
519  SetHandle(CreateFontIndirect(&ncm.lfMessageFont));
520  }
521 };
522 
523 //-----------------------------------------------------------------------------
524 
525 inline void MemoryDC::Init(HDC other, HBITMAP bitmap)
526 {
527  attachedBitmap = bitmap;
528 
529  dc = CreateCompatibleDC(other);
530  assert(dc != NULL);
531  if(dc)
532  {
533  SaveDC(dc);
534  SelectObject(dc, bitmap);
535  }
536 }
537 
538 //-----------------------------------------------------------------------------
539 
541 {
542  handle = NULL;
543  Clear();
544 }
545 
546 inline DibSection::DibSection(int width, int height, int bpp, bool bottomup)
547 {
548  handle = NULL;
549  Create(width, height, bpp, bottomup);
550 }
551 
552 inline DibSection::DibSection(HBITMAP bitmap, int bpp, bool bottomup)
553 {
554  handle = NULL;
555  CopyCreate(bitmap, bpp, bottomup);
556 }
557 
558 inline DibSection::DibSection(HBITMAP bitmap)
559 {
560  handle = NULL;
561  CopyCreate(bitmap);
562 }
563 
565 {
566  handle = NULL;
567  CopyCreate(other.handle);
568  return *this;
569 }
570 
571 inline int DibSection::BPP(HBITMAP bitmap)
572 {
573  BITMAP bm;
574  if(GetObject(bitmap, bm))
575  return bm.bmBitsPixel;
576  return 0;
577 }
578 
579 inline bool DibSection::IsDibSection(HBITMAP bitmap)
580 {
581  DIBSECTION ds;
582  return GetObject(bitmap, ds);
583 }
584 
585 inline bool DibSection::IsBottomUp(HBITMAP bitmap)
586 {
587  DIBSECTION ds;
588  if(GetObject(bitmap, ds))
589  return ds.dsBmih.biHeight > 0;
590  return true;
591 }
592 
593 inline void DibSection::FillBitmapInfo(BITMAPINFO& bmi, int w, int h, int bpp, bool bottomup)
594 {
595  ZeroMemory(&bmi, sizeof(bmi));
596  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
597  bmi.bmiHeader.biWidth = w;
598  bmi.bmiHeader.biHeight = h;
599  if(!bottomup)
600  bmi.bmiHeader.biHeight = -h;
601  bmi.bmiHeader.biBitCount = bpp;
602  bmi.bmiHeader.biPlanes = 1;
603  bmi.bmiHeader.biCompression = BI_RGB;
604  bmi.bmiHeader.biXPelsPerMeter = 0x0ec4; // this is a standard value
605  bmi.bmiHeader.biYPelsPerMeter = 0x0ec4;
606 }
607 
608 inline bool DibSection::Create(int width, int height, int bpp, bool bottomup)
609 {
610  DeleteObject(handle);
611 
612  FillBitmapInfo(dibInfo, width, height, bpp, bottomup);
613  handle = CreateDIBSection(ClientDC(NULL), &dibInfo, DIB_RGB_COLORS, NULL, NULL, 0);
614  if(handle)
615  if(GetObject(handle, dibData))
616  if(dibData.bmBits)
617  return true;
618 
619  Clear();
620  return false;
621 }
622 
623 inline bool DibSection::CopyCreate(HBITMAP bitmap, int bpp, bool bottomup)
624 {
625  BITMAP bm;
626  if(GetObject(bitmap, bm))
627  if(Create(bm.bmWidth, bm.bmHeight, bpp, bottomup))
628  if(CopyFromBitmap(bitmap))
629  return true;
630 
631  Clear();
632  return false;
633 }
634 
635 inline bool DibSection::Attach(HBITMAP bitmap)
636 {
637  DIBSECTION ds;
638  if(GetObject(bitmap, ds)){
639  DeleteObject(handle);
640  handle = bitmap;
641  dibData = ds.dsBm;
642  dibInfo.bmiHeader = ds.dsBmih;
643  return true;
644  }
645 
646  Clear();
647  return false;
648 }
649 
650 inline HBITMAP DibSection::Detach()
651 {
652  HBITMAP result = handle;
653  handle = NULL;
654  Clear();
655  return result;
656 }
657 
658 inline void DibSection::Clear()
659 {
660  DeleteObject(handle);
661  handle = NULL;
662  ZeroMemory(&dibData, sizeof(dibData));
663  ZeroMemory(&dibInfo, sizeof(dibInfo));
664 }
665 
666 inline bool DibSection::CopyFromBitmap(HBITMAP bitmap)
667 {
668  BITMAP bm;
669  if(GetObject(bitmap, bm))
670  if(bm.bmWidth == GetWidth() && bm.bmHeight == GetHeight())
671  if(GetDIBits(ClientDC(NULL), bitmap, 0, GetHeight(), dibData.bmBits, &dibInfo, DIB_RGB_COLORS) == GetHeight())
672  return true;
673 
674  return false;
675 }
676 
677 inline bool DibSection::CopyToBitmap(HBITMAP bitmap)
678 {
679  BITMAP bm;
680  if(GetObject(bitmap, bm))
681  if(bm.bmWidth == GetWidth() && bm.bmHeight == GetHeight())
682  if(SetDIBits(ClientDC(NULL), bitmap, 0, GetHeight(), dibData.bmBits, &dibInfo, DIB_RGB_COLORS) == GetHeight())
683  return true;
684 
685  return false;
686 }
687 
688 #endif