Source file: /~heha/ewa/Reluktanzmotor/cdesk-201007.zip/gdix.h

// Objektorientierte GDI-Kapselung
#pragma once

#include <windows.h>
#include <windowsx.h>
#include <limits>
#include <commctrl.h>		// GetEffectiveClientRect

#ifndef Float
#  define Float float		// Wertekoordinaten: hier 4-Byte-Gleitkomma
#endif
typedef LONG Int;		// Anzeigekoordinaten, muss zum Elementtyp von Rect (= RECT) passen

#if _MSC_VER >= 1400
#  define FINF (std::numeric_limits<Float>::infinity())
#else
const unsigned FNAN=0xFFFFFFFF;	// Bei double anpassen!	unsigned __int64 0xFFFFFFFFFFFFFFFF
const unsigned FINF=0x7F800000;	//			unsigned __int64 0x7FF0000000000000
#define FNAN (*(Float*)&FNAN)	// #defines rekursieren nicht
#define FINF (*(Float*)&FINF)
#endif

const Int INAN=Int(0x80000000);
const Int IINF= 0x7FFFFFFF;
/* Fast schon langweilige Objektifizierungen = Kapselklassen von GDI-Krimskrams
   Kann so leichter auf GDIplus umgestellt werden
 */

struct Rect:public RECT{	// Bei GdiPlus: RectF? Nee! RectF definiert sich gegenüber RECT durch Breite und Höhe!
  operator SIZE() const {SIZE sz={width(),height()}; return sz;}
  Int width() const {return right-left;}
  Int height() const {return bottom-top;}
  Int center() const {return (left+right)>>1;}
  Int middle() const {return (top+bottom)>>1;}
  Int byIndex(int i) const {
    if ((unsigned)i<4) return (&left)[i];
    switch (i) {
      case 4: return width();
      case 5: return height();
      case 6: return -width();
      case 7: return -height();
      case 8: return center();
      case 9: return middle();
      default: return INAN;
    }
  }
  Int operator[](int i) const {return byIndex(i);}
  Int&at(int i) {
    if ((unsigned)i<4) return (&left)[i];
    return *(Int*)0;
  }
  Int addTo(size_t i,Int v) {
    if (i>=4) return 0;
    return (&left)[i]+=v;
  }
  bool intersect(const Rect*r2) const{
    if (!r2) return true;
    Rect rd;
    return !!IntersectRect(&rd,this,r2);
  }
  void inflate(Int dx,Int dy) {InflateRect(this,dx,dy);}	// aufblasen
  void deflate(Int dx,Int dy) {inflate(-dx,-dy);}	// verkleinern
  void offset(Int dx,Int dy) {OffsetRect(this,dx,dy);}	// versetzen
  Rect() {}
  Rect(HWND w) {GetWindowRect(w,this);}
  Rect(HWND w, bool x) {GetClientRect(w,this);}
  Rect(HWND w, const int*info) {GetEffectiveClientRect(w,this,const_cast<int*>(info));}
  bool inside(const POINT&pt) const {return !!PtInRect(this,pt);}
};

struct Margin:public RECT{
  Margin() {init();}
  Margin(Int l,Int t,Int r,Int b) {init(l,t,r,b);}
  void init() {init(0,0,0,0);}
  void init(const Margin&m) {init(m.left,m.top,m.right,m.bottom);}
  void init(Int l,Int t,Int r,Int b) {left=l;top=t;right=r;bottom=b;}
  void expand(const Margin&m) {expand(m.left,m.top,m.right,m.bottom);}
  void expand(Int l,Int t,Int r,Int b) {
	if (left<l) left=l;
	if (top<t) top=t;
	if (right<r) right=r;
	if (bottom<b) bottom=b;}
  Int getW() const {return left+right;}	// Gesamtrand horizontal
  Int getH() const {return top+bottom;}	// Gesamtrand vertikal
  Int operator[](size_t i) const {switch (i) {
	case 0:case 1:case 2:case 3:return (&left)[i];
	case 4: return getW();
	case 5: return getH();
	default: return INAN;}}
  Int addTo(size_t i,Int v) {
    if (i>=4) return 0;
    return (&left)[i]+=v;
  }
};

#if _MSC_VER >= 1400
#  define NODEFAULT =delete	// bei neuerem C++
#else
#  define NODEFAULT
#endif

struct Color{
 COLORREF c;
 Color(COLORREF cr=0):c(cr) {}		// TODO: Transparent initialisieren!! Hier: Schwarz
 Color(BYTE r, BYTE g, BYTE b, BYTE t=0):c(RGB(r,g,b)) {}
 Color operator=(COLORREF cr) {return c=cr;}
 operator COLORREF() const {return c;}
};

struct GdiObj{
 HGDIOBJ h;
 GdiObj(HGDIOBJ obj=0):h(obj) {}
 GdiObj(GdiObj&obj):h(obj) {obj.h=0;}
 GdiObj operator=(GdiObj&obj) {if (h) DeleteObject(h); h=obj; obj.h=0; return*this;}
 GdiObj operator=(HGDIOBJ obj) {if (h) DeleteObject(h); return h=obj;}
 ~GdiObj() {if (h) DeleteObject(h);}
 operator HGDIOBJ() const {return h;}	// wenn HGDIOBJ gefragt wird
 operator bool() const {return !!h;}
 bool operator!() const {return !h;}
};

struct Pen:public GdiObj{
 Pen(HPEN pen=0):GdiObj(pen) {}	// Achtung! Destruktor zerstört den Stift!
 Pen(Pen&pen):GdiObj(pen) {pen.h=0;}
// Pen(const Pen&)NODEFAULT;	// Dreierregel: Kopieren und Zuweisen verboten
// Pen&operator=(const Pen&)NODEFAULT;
 static HPEN create(int width, Color color) {return CreatePen(PS_SOLID,width,color);}
 static HPEN create(int style,int width,Color color) {return CreatePen(style,width,color);}
 Pen(int width,Color color):GdiObj(create(width,color)) {}
 Pen(int style,int width,Color color):GdiObj(create(style,width,color)) {}
 void operator=(HPEN p) {if (h) DeletePen(h); h=p;}
 operator HPEN() const {return (HPEN)h;}	// wenn HPEN gefragt wird
};

struct Brush:public GdiObj{
 Brush(HBRUSH br=0):GdiObj(br) {}	// Achtung! Destruktor zerstört den Pinsel!
 static HBRUSH create(Color color) {return CreateSolidBrush(color);}
 static HBRUSH create(int hatch, Color color) {CreateHatchBrush(hatch,color);}
 Brush(Color color):GdiObj(create(color)) {}
 Brush(int hatch, Color color):GdiObj(create(hatch,color)) {}
 void operator=(HBRUSH br) {if (h) DeleteBrush(h); h=br;}
 operator HBRUSH() const {return (HBRUSH)h;}	// wenn HBRUSH gefragt wird
};

struct Font:public GdiObj{
  enum{	// Font-Flags
    bold=4,
    italic=8,
    underline=16,
    strikeout=32,
    symbol=64,
  };
  struct Data{
    TCHAR*name;
    int size;
    int flags;
    int rotation;
    HFONT operator()() const {
      return CreateFont(size,0,rotation,rotation,
       flags&bold?FW_BOLD:FW_NORMAL,
       flags&italic?TRUE:FALSE,
       flags&underline?TRUE:FALSE,
       flags&strikeout?TRUE:FALSE,
       flags&symbol?SYMBOL_CHARSET:ANSI_CHARSET,
       OUT_TT_PRECIS,
       CLIP_DEFAULT_PRECIS,
       PROOF_QUALITY,//  lf.lfQuality=CLEARTYPE_QUALITY;
       DEFAULT_PITCH|FF_DONTCARE,
       name);
    }
    Data&operator()(HFONT f) {
      LOGFONT lf;
      GetObject(f,sizeof lf,&lf);
      rotation=lf.lfOrientation;
      flags=0;
      if (lf.lfWeight>FW_NORMAL) flags|=bold;
      if (lf.lfItalic) flags|=italic;
      if (lf.lfUnderline) flags|=underline;
      if (lf.lfStrikeOut) flags|=strikeout;
      if (lf.lfCharSet==SYMBOL_CHARSET) flags|=symbol;
      size=lf.lfHeight;
      lstrcpyn(name,lf.lfFaceName,LF_FACESIZE);
    }
  };
  struct Data1:public Data{
    TCHAR buf[LF_FACESIZE];
    Data1&operator=(const Data&d)	{memcpy(this,&d,sizeof d); lstrcpyn(buf,name,LF_FACESIZE);}
    Data1&operator=(const Data1&d)	{memcpy(this,&d,sizeof*this);}
    HFONT operator()()			{name=buf; return Data::operator()();}
    Data1&operator()(HFONT f)		{name=buf; return (Data1&)Data::operator()(f);}
  };
  Font(HFONT f=0):GdiObj(f) {}	// Achtung! Destruktor zerstört die Schrift!
// Font(Font&f):h(f.h) {f.h=0;}		// Raubkopie, geht das?
// Font(const Font&)NODEFAULT;
// Font&operator=(const Font&)NODEFAULT;
  Font(HWND w):GdiObj(GetWindowFont(w)) {}	// avoid destruction by setting Font::h=0 before scope leaving!
  Font(HDC dc):GdiObj(GetCurrentObject(dc,OBJ_FONT)) {}
#ifdef _M_IX86
  static HFONT _stdcall create(LPCTSTR name,int size,BYTE flags=0,int rotation=0) {
    Data&d=*(Data*)&name;		// Parameter direkt vom Stack nehmen
    return d();
  }
#else
  static HFONT create(LPCTSTR name,int size,BYTE flags=0,int rotation=0) {
    Data d={const_cast<TCHAR*>(name),size,flags,rotation};	// Parameter umstapeln
    return d();
  }
#endif
  static HFONT create(const Data&d) {return d();}
  Font(LPCTSTR name,int size,BYTE flags=0,int rotation=0):GdiObj(create(name,size,flags,rotation)) {}
  Font(const Data&d):GdiObj(d()) {}
  Font(Data1&d):GdiObj(d()) {}
  Font(const LOGFONT&lf):GdiObj(CreateFontIndirect(&lf)) {}
  void query(LOGFONT&lf) {GetObject(h,sizeof lf,&lf);}
  void query(Data&d) {d(HFONT(h));}
  void query(Data1&d) {d(HFONT(h));}
  void operator=(HFONT f) {if (h) DeleteFont(h); h=(HGDIOBJ)f;}
  operator HFONT() const {return (HFONT)h;}	// wenn HFONT gefragt wird
};

// A small metric structure suitable for function return: 32 bits
// All four needed Y values for font processing; extlead only for multi-line text
struct Metric{
  BYTE height,ascent,intlead,extlead;
  Metric(const TEXTMETRIC&tm):
   height(BYTE(tm.tmHeight)),	// Height of "Äq"
   ascent(BYTE(tm.tmAscent)),	// Height of "Ä"
   intlead(BYTE(tm.tmInternalLeading)),	// Height of "Ä" - "A"
   extlead(BYTE(tm.tmExternalLeading)) {}	// multi-line gap (Durchschuss)
  Metric(HDC dc) {
    TEXTMETRIC tm;
    GetTextMetrics(dc,&tm);
    height=BYTE(tm.tmHeight);
    ascent=BYTE(tm.tmAscent);
    intlead=BYTE(tm.tmInternalLeading);
    extlead=BYTE(tm.tmExternalLeading);
  }
  BYTE descent() const {return height-ascent;}	// Unterlänge
};
Detected encoding: UTF-80