1 //这个类用于定义用于绘图的函数 2 #pragma once 3 4 enum class Alignment //对齐方式 5 { 6 LEFT, 7 RIGHT, 8 AUTO, // 用于歌词对齐选项,原来的居中,支持卡拉OK显示 9 CENTER 10 }; 11 12 enum ImageType 13 { 14 IT_JPG, 15 IT_PNG, 16 IT_GIF, 17 IT_BMP 18 }; 19 20 class DrawAreaGuard; 21 22 class CDrawCommon 23 { 24 public: 25 26 //拉伸模式 27 enum class StretchMode 28 { 29 STRETCH, //拉伸,会改变比例 30 FILL, //填充,不改变比例,会裁剪长边 31 FIT //适应,不会改变比例,不裁剪 32 }; 33 34 //用于在DrawScrollText函数调用时使用的一些需要在函数调用完毕后继续存在的变量 35 struct ScrollInfo 36 { 37 int shift_cnt{}; //移动的次数 38 bool shift_dir{}; //移动的方向,右移为false,左移为true 39 int freez{}; //当该变量大于0时,文本不滚动,直到小于等于0为止 40 bool dir_changed{ false }; //如果方向发生了变化,则为true 41 CString last_string; //上一次绘制的文本 42 43 void Reset(); 44 }; 45 46 friend class DrawAreaGuard; 47 48 CDrawCommon(); 49 virtual ~CDrawCommon(); // 基类析构方法需要是虚方法 50 51 virtual void Create(CDC* pDC, CFont* pFont = nullptr); 52 void Create(CDC* pDC, Gdiplus::Graphics* pGraphics, CFont* pFont = nullptr); 53 CFont* SetFont(CFont* pFont); // 设置绘制文本的字体(返回原来的字体) GetFont()54 CFont* GetFont() { return m_pfont; } 55 void SetDC(CDC* pDC); //设置绘图的DC GetDC()56 CDC* GetDC() 57 { 58 return m_pDC; 59 } 60 GetGraphics()61 Gdiplus::Graphics* GetGraphics() 62 { 63 return m_pGraphics; 64 } 65 66 //在指定的矩形区域内绘制有颜色的文本 67 //rect: 文本的矩形区域 68 //lpszString: 要绘制的文本 69 //color: 文本的颜色 70 //align: 文本的对齐方式(默认值:左对齐) 71 //no_clip_area: 如果为true,则不在输出文字时限制绘图区域 72 //multi_line: 是否多行显示 73 //default_right_align: 如果文本的宽度大于矩形区域,是否右对齐 74 void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align = Alignment::LEFT, bool no_clip_area = false, bool multi_line = false, bool default_right_align = false); 75 76 //在指定的矩形区域内绘制分割颜色的文本 77 //rect: 文本的矩形区域 78 //lpszString: 要绘制的文本 79 //color1: 分割位置左边的文本颜色 80 //color2: 分割位置右边的文本颜色 81 //split: 颜色分割位置,取值为0~1000(用于歌词动态显示) 82 //align: 文本对齐方式 83 //no_clip_area: 如果为true,则不在输出文字时限制绘图区域 84 void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color1, COLORREF color2, int split, Alignment align = Alignment::LEFT, bool no_clip_area = false); 85 86 //在控件上绘制滚动的文本(当长度不够时),pixel指定此函数调用一次移动的像素值,如果reset为true,则滚动到初始位置 87 //rect: 文本的矩形区域 88 //lpszString: 要绘制的文本 89 //color: 文本的颜色 90 //pixel: 此函数调用一次滚动的像素值,值越小滚动越慢 91 //center: true时文本居中,false时左对齐 92 //scroll_info: 用来保存一些当前文本滚动的状态信息 93 //reset: 如果reset为true,则重置scroll_info,并滚动到初始位置 94 void DrawScrollText(CRect rect, LPCTSTR lpszString, COLORREF color, double pixel, bool center, ScrollInfo& scroll_info, bool reset = false, bool no_clip_area = false); 95 96 //函数功能和DrawScrollText一样,只是这个函数只会从左到右滚动,不会更换方向 97 void DrawScrollText2(CRect rect, LPCTSTR lpszString, COLORREF color, double pixel, bool center, ScrollInfo& scroll_info, bool reset = false); 98 99 public: 100 //绘制一个位图(使用GDI) 101 void DrawBitmap(CBitmap& bitmap, CPoint start_point, CSize size, StretchMode stretch_mode, bool no_clip_area = false); 102 void DrawBitmap(UINT bitmap_id, CPoint start_point, CSize size, StretchMode stretch_mode, bool no_clip_area = false); 103 void DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode, bool no_clip_area = false); 104 105 //绘制一个图像(使用GDI+) 106 void DrawImage(const CImage& image, CPoint start_point, CSize size, StretchMode stretch_mode, bool no_clip_area = false); 107 void DrawImage(Gdiplus::Image* pImage, CPoint start_point, CSize size, StretchMode stretch_mode, bool no_clip_area = false); 108 109 void DrawIcon(HICON hIcon, CPoint start_point, CSize size); 110 void DrawIcon(HICON hIcon, CRect rect); 111 void DrawIcon(HICON hIcon, CRect rect, int icon_size); 112 113 void FillRect(CRect rect, COLORREF color, bool no_clip_area = false); 114 void FillAlphaRect(CRect rect, COLORREF color, BYTE alpha, bool no_clip_area = false); //填充一个半透明的矩形(参照http://blog.csdn.net/lee353086/article/details/38311421) 115 116 void DrawRectTopFrame(CRect rect, COLORREF color, int pilex = 1); 117 void DrawRectOutLine(CRect rect, COLORREF color, int width, bool dot_line); 118 void DrawRectFrame(CRect rect, COLORREF color, int width, BYTE alpha = 255); //绘制一个矩形边框 119 void DrawLine(CPoint point1, CPoint point2, COLORREF color, int width, bool dot_line); 120 121 void DrawRoundRect(CRect rect, COLORREF color, int radius, BYTE alpha = 255); //绘制圆角矩形(使用GDI+) 122 void DrawRoundRect(Gdiplus::Rect rect, Gdiplus::Color color, int radius); //绘制圆角矩形(使用GDI+) 123 124 void DrawEllipse(CRect rect, COLORREF color, BYTE alpha = 255); //绘制椭圆(使用GDI+) 125 void DrawEllipse(Gdiplus::Rect rect, Gdiplus::Color color); //绘制椭圆(使用GDI+) 126 127 CSize GetTextExtent(LPCTSTR str); 128 129 ////将图片拉伸到指定尺寸(https://blog.csdn.net/sichuanpb/article/details/22986877) 130 //static bool BitmapStretch(CImage *pImage, CImage *ResultImage, CSize size); 131 132 //将图片拉伸到指定尺寸 133 static void ImageResize(const CImage& img_src, CImage& img_dest, CSize size); 134 135 //重设图片的大小,不改变图片比例,size为更改后图片长边的大小,单位为像素。type指定输出的文件格式 136 static void ImageResize(const CImage& img_src, const wstring& path_dest, int size, ImageType type); 137 static void ImageResize(const wstring& path_src, const wstring& path_dest, int size, ImageType type); 138 139 //复制一个bitmap (http://wupei.j2megame.org/archives/86) 140 //(这两个函数未测试成功,复制的图片为全黑色,原因暂时未知,后面再调查) 141 static HBITMAP CopyBitmap(HBITMAP hSourceHbitmap); 142 static void CopyBitmap(CBitmap& dest, CBitmap& src); 143 144 //将一个Bitmap保存到文件 145 static void SaveBitmap(HBITMAP bitmap, LPCTSTR path); 146 147 void ImageDrawAreaConvert(CSize image_size, CPoint& start_point, CSize& size, StretchMode stretch_mode); 148 149 //计算一个矩形中正方形图标的矩形区域 150 static CRect CalculateCenterIconRect(CRect rect, int icon_size); 151 152 protected: 153 CDC* m_pDC{}; //用于绘图的CDC类的指针 154 CFont* m_pfont{}; 155 Gdiplus::Graphics* m_pGraphics{}; 156 bool m_auto_destory_graphics{}; //是否自动析构Graphics对象,如果Graphics对象是内部创建的,则为true,如果是从外面传过来的,则为false 157 }; 158 159 160 //用于双缓冲绘图的类 161 class CDrawDoubleBuffer 162 { 163 public: CDrawDoubleBuffer(CDC * pDC,CRect rect)164 CDrawDoubleBuffer(CDC* pDC, CRect rect) 165 : m_pDC(pDC), m_rect(rect) 166 { 167 m_memDC.CreateCompatibleDC(NULL); 168 m_memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); 169 m_pOldBit = m_memDC.SelectObject(&m_memBitmap); 170 } 171 ~CDrawDoubleBuffer()172 ~CDrawDoubleBuffer() 173 { 174 m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), &m_memDC, 0, 0, SRCCOPY); 175 m_memDC.SelectObject(m_pOldBit); 176 m_memBitmap.DeleteObject(); 177 m_memDC.DeleteDC(); 178 } 179 GetMemDC()180 CDC* GetMemDC() 181 { 182 return &m_memDC; 183 } 184 185 private: 186 CDC* m_pDC; 187 CDC m_memDC; 188 CBitmap m_memBitmap; 189 CBitmap* m_pOldBit; 190 CRect m_rect; 191 }; 192 193 194 //用于在UI中设置绘图区域。 195 //在需要设置绘图区域时,创建此类的一个局部对象,它会在构造时设置绘图区域,并在析构时恢复上次绘图区域 196 class DrawAreaGuard 197 { 198 public: 199 DrawAreaGuard(const DrawAreaGuard&) = delete; 200 DrawAreaGuard(CDrawCommon* drawer, CRect rect, bool gdi_only = false, bool enable = true) m_drawer(drawer)201 : m_drawer(drawer), m_gdi_only(gdi_only), m_enable(enable) 202 { 203 if (m_drawer != nullptr && m_enable) 204 old_rect = SetDrawArea(rect, gdi_only); 205 } 206 ~DrawAreaGuard()207 ~DrawAreaGuard() 208 { 209 if (m_drawer != nullptr && m_enable) 210 SetDrawArea(old_rect, m_gdi_only); 211 } 212 213 private: 214 //设置绘图区域,并返回上次的绘图区域 215 CRect SetDrawArea(CRect rect, bool gdi_only); 216 217 //恢复绘图区域 218 void ResetDrawArea(bool gdi_only); 219 220 private: 221 CDrawCommon* m_drawer{}; 222 bool m_enable{ true }; 223 bool m_gdi_only{}; 224 CRect old_rect; 225 }; 226 227