GDI+ 笔记
1.GDI+模板
#include<windows.h> #include<GdiPlus.h> #include <time.h> #include <math.h> #pragma comment(lib,"gdiplus.lib") //链接GDI+库 #define WINDOW_CLASS L"GdiWindows" #define WINDOW_NAME L"GdiTemplate" #define NULL 0 using namespace Gdiplus; LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); ATOM RegClass(HINSTANCE ); BOOL CreateWnd(HINSTANCE ); void view(HDC hdc); void view1(); HWND hwnd; ULONG_PTR gdiplusToken; WORD windosWidth=640,windowsHeighi=480; Bitmap* CacheImage; Graphics* CacheGraphics; int WINAPI wWinMain(HINSTANCE hinst,HINSTANCE ph,PWSTR cmd, int s) { if (RegClass(hinst) == 0) return -1; if (CreateWnd(hinst) == FALSE) return -1; GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL); CacheImage = new Bitmap(windosWidth,windowsHeighi); CacheGraphics = new Graphics(CacheImage); MSG msg; ZeroMemory(&msg, sizeof(msg)); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //RenderScene(); } } return msg.wParam; } LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { static HDC hdc; static PAINTSTRUCT ps; switch(msg) { case WM_DESTROY: delete CacheImage; delete CacheGraphics; GdiplusShutdown(gdiplusToken); PostQuitMessage(0); return 0; case WM_CREATE: //Sleep(1500); //SetLayeredWindowAttributes(hwnd,NULL,100,LWA_ALPHA); return 0; case WM_KEYUP: if(wp == VK_ESCAPE) //PostQuitMessage(0); view1(); return 0; /* case WM_ERASEBKGND: //CacheGraphics->Clear(Color::White); InvalidateRect(hWnd,0,1); return true; */ case WM_SIZE: windosWidth = LOWORD(lp); windowsHeighi = HIWORD(lp); //InvalidateRect(hWnd,0,0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); view(hdc); EndPaint(hwnd, &ps); return 0; } return DefWindowProc(hWnd, msg, wp, lp); } void view(HDC hdc) { // InvalidateRect(hwnd,0,1); /* Pen pen(Color::Red,1); SolidBrush brush(Color::Green); CacheGraphics->DrawLine(&pen,Point(100,100),Point(200,100)); FontFamily fon(L"宋体"); Font font(&fon,13,FontStyleRegular,UnitPixel); CacheGraphics->DrawString(L"你好啊",-1,&font,PointF(0,0),&brush); Graphics graphics(hdc); graphics.DrawImage(CacheImage,0,0,CacheImage->GetWidth(),CacheImage->GetHeight()); */ Graphics graphics(hdc); wchar_t hehe[255]; Pen pen( Color(9,101,188) ,4.0f); FontFamily fontFamily(L"宋体"); Font font(&fontFamily,24,FontStyleRegular,UnitPixel); SolidBrush brush(Color(255,255,0)); SolidBrush brush1(Color(255,0,255)); Point a1(10,10),a2(windosWidth-10,10),a3(10,windowsHeighi-10),a4(windosWidth-10,windowsHeighi-10); Point pos[]={a1,a2,a3,a4}; PointF pointf(100,100); graphics.FillRectangle(&brush1,0,0,windosWidth,windowsHeighi); // graphics.DrawLines(&pen,pos,4); // graphics.DrawClosedCurve(&pen,pos,4,REAL(0.7f)); graphics.DrawString(L"GDI+程序",-1,&font,pointf,&brush); Rect rect(0,0,100,100); graphics.DrawArc(&pen,rect,REAL(180.0f),REAL(-90.0f)); graphics.DrawImage(CacheImage,0,0,CacheImage->GetWidth(),CacheImage->GetHeight()); } void view1() { Pen pen(Color::Green,1); CacheGraphics->DrawLine(&pen,Point(100,10),Point(200,10)); Graphics graphics(hwnd,true); graphics.DrawImage(CacheImage,0,0,CacheImage->GetWidth(),CacheImage->GetHeight()); } ATOM RegClass(HINSTANCE hInstance) { WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0, 0, GetModuleHandle(NULL), NULL, NULL, (HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WINDOW_CLASS, NULL}; return RegisterClassEx(&wc); } BOOL CreateWnd(HINSTANCE hInstance) { hwnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZEBOX|WS_MINIMIZEBOX |WS_SYSMENU|WS_THICKFRAME|WS_EX_LAYERED, 100, 100, windosWidth,windowsHeighi, NULL, NULL, hInstance, NULL); if (hwnd == 0) { return false; } else { ShowWindow(hwnd,SW_SHOWDEFAULT); UpdateWindow(hwnd); SetWindowLong(hwnd,GWL_EXSTYLE,WS_EX_LAYERED); return true; } }
2.GDI+笔记
1.环境配置
在开始调用GDI+各种函数前,需要使用 GdiplusStattup 函数进行初始化
在结束GDI+调用进行销毁之前,应该使用 GdiplusShutdowbn 函数销毁操作
在项目中需要加入 GDIplus.Lib 的库文件,与头文件. 如下:
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
GDI+使用 Gdiplus的命名空间,要将该名字空间添加到程序中,修改 stdafx,h,
在该头文件结尾处加入下列代码:
#include<gdiplus.h>
using namespace Gdiplus;
注释:stdafx的英文全称为:Standard Application Framework Extensions
(标准应用程序框架的扩展)
所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
2.初始化与销毁
ps:
初始化: ULONG_PTR gdiplusToken; //为全局变量
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
销毁:
GdiplusShutdown(gdiplusToken);
3.Graphics成员
GDI+中主要操作对象 Graphics,他的构造函数有4种,构造函数决定了在何处作为背景绘图
绘制操作:
1.graphics.DrawLine();绘制直线
2.graphics.Rectangle();绘制矩形
3.graphics.Rectangles();绘制多个矩形,实例如下
RectF r1(10,10,100,50),r2(10,10,20,30);
RectF res[] = {r1,r2};
4.graphics.DrawCurve(); 绘制开放曲线
5.graphics.DrawClosedCurve(); 绘制封闭曲线
6.graphics.DrawBezier(); 绘制贝塞尔曲线
7.graphics.DrawPolygon();绘制多边形
8.graphics.DrawArc(); 绘制圆弧
9.graphics.DrawImage();绘制图片
10.graphics.DrawString();绘制文本
填充操作:
FillClosedCurve() 填充封闭曲线
FillEllipse() 填充椭圆
FillPath() 填充路径
FillPie() 填充扇形
Fillpolygon() 填充多边形
FillRectangle() 填充矩形
FillRectangles() 填充矩形集合
FillRegion() 填充区域
色彩:
GDI+中,色彩通过 Color 类来描述
参数从前往后依次是 a,r,g,b , 分别代表透明度和3种色彩值
透明度计算公式: 输出色彩=前景色 X Alpha/255 + 背景色 X (255-Alpha)/255
图像指定色透明:对其每一像素比较值和设置值. GDI+中对像素访问通过 Bitmap对象的函数
GetPixel()获得像素,SetPixel()设置像素.用图片的宽度与高度嵌套2个循环.
透明实例:
for(int i=0;i<图片高度;i++)
{
for(int j=0;j<图片宽度;j++)
{
photo.GetPixel(j,i.&color);
if( color.GetRed()==255 && color.GetGreen()==255 && color.GetBlue()==255 )
//对比三原色,这里都是255,代表白色,
alpha=0;
else
alpha=255;
colorTemp.SetValue( color.MakeARGB(alpha,color.GetRed(),color.GetGreen
(),color.GetBlue()) ) ; //重新定义像素色彩
photo.SetPixel(k,i,colorTemp);
}
}
这种办法相当繁琐效率也不高,GDI+提供了同意的修改图片透明度方法,就是 色彩阵列
(ColorMatrix)
ImageAttrbutesimageAtt; //ImageAttributes对象包含有关如何操作位图和图元文件颜色在渲
染过程中的信息。 ImageAttributes对象维护多个颜色调整设置,包括颜色调整矩阵,灰度调整矩阵,
伽玛修正值,颜色映射表和颜色阈值。
ColorMatrix colorMatrix = {1.0f,0.0f,0.0f.0.0f.0.0f,省略} //色彩阵列类型
画刷:
SolidBrush blackBrush(Color::Black);纯色画刷
TextureBrush tBrush(&image);纹理画刷
HatchBrush()影线画刷,用线形图案填充
LinearGraientBrush() 线性渐变画刷
PathGradientBrush()路径渐变画刷
enum WrapMode{ //纹理画刷排列方式
WrapModeTile,//平铺
WrapModeTileFlipX,//水平方向每隔一个图像翻转
WrapModeTileFlipY,//Y轴翻转
WrapModeTileFilpXY, //
WrapModeClamp //不平铺
};
TextureBrush.RotateTransform(30) //将画刷旋转30度,(旋转变换)
TextureBrush.ResetTransorm() //将画刷恢复初始状态
TextureBrush.ScaleTransform(3,1) //将画刷向上扩大三倍(缩放变换)
TextureBrush.TranslateTransform(30,0,MatrxOrderAppend); //将画刷在水平方向上平移30个像素(平移变换)
enum LinearGradientMode{ //线性渐变模式
LinearGradientModeHorizontal =0, //水平渐变,起点左边
LinearGradientModeVertical =1, //垂直渐变,起点上边
LinearGradientModeForwardDiagonal =2, //左上角到右下角
LinearGradientModeBackWardDiagonal =3 //右上角到左下角
};
渐变线代表色彩渐变方向,在构造函数的参数中设置
多色渐变是指画刷的起点,终点2色的渐变过程中加入其他过渡色,又称为 插值色(Interpolation Color)
LinearGraientBrush.SetInterpolationColor(Color* pres, REAL* blend,int count)// 设置插值色
参数pres包含多种预定色的数组,参数blend包含色彩合成位置,用百分比表示0%-100%,参数count色彩总数
路径渐变画刷是指画刷的色彩变化在指定的路径内完成,从路径中心逐渐过渡到边框
画笔
Pen pen(); 画笔有宽度而画刷没有宽度
成员如下:
pen.SetDashStyle()设置画笔线形,提供的枚举如下
--------------------------------------------------------------------------
enum DashStyle{ //线形
DashStySolid = 0, // 实线
DashStyleDash =1, //虚线
DashStyleDot = 2, //点线
DashStyleDashDot = 3, //点划线
DashStyleDashDotDot = 4,//双点划线
DashStyleCustom = 5 // 自定义线形
};
--------------------------------------------------------------------------
pen.SetDashPattern() 设置线形风格,格式为 划线部分长度,间隔长度,依次.
自定义线形实例:
REAL dashVats[4] = {5,2,15,4} ; // 线长5间断2,线长15间断4
pen.SetDashPattern(dashVals,4);
-------------------------------------------
pen.GetDashPattern() 获取线形风格
pen.GetDashPatternCount()获取线形定义总点数
画笔的对齐方式由 PenAlignment枚举来描述的
pen.SetAligonment() 函数来设置对齐方式
--------------------------------------------------------------------------
enum PenAlignment{ //对齐方式
PenAlignmentCenter =0, //居中
PenAlignmentInset =1 //嵌入
};
--------------------------------------------------------------------------
pen.ScaleTransform()//缩放变换
在画笔的某个方向,放大或者缩小画笔宽度
pen.RptateTransform()//旋转画笔, 输入角度和模式
线帽(LineCap) 是线条首尾的外观,枚举如下
pen.SetStarCap()设置起点线帽
pen.Endap()设置终点线帽
--------------------------------------------------------------------------
enum LineCap{ //线帽
LineCapFlat = 0, //平面,直线的起始点始于平面右侧
LineCapSquare =1, //矩形,高度等于直线宽度,直线端点起于矩形中心点
LineCapRound =2, //圆形,直径等于直线宽度,圆形终点即直线端点
LineCapTriange =3,//二角型,高度等于直线宽度,直线端点起于二角型边线
LineCapNoAnchor =0x10,
LineCapSquareAnchor =0x11, //矩形,高度大于直线宽度,直线端点起于角型边线
LineCapRoundAnchor = 0x12,//圆形,直径大于直线宽度,圆形终点即直线端点
LineCapDiamondAnchor = 0x13,//菱形(矩形翻转75度),高度大于直线宽度,中心点即直线端点
LineCapArrowAnchor = 0x14, //箭头,高度大于直线宽度,直线端点即箭头终点
LineCapCusrotn = 0xff //自定义形状,使用 CustomLineCap自定义线帽
};
--------------------------------------------------------------------------
pen.SetCustomStartCap() 设置自定义起点线帽
pen.SetCustomEndCap() 设置自定义终点线帽
CustomLineCap 创建的自定义线帽,这是一个类型不是函数
此外,GDI+还提供了连接点属性,所谓连接点就是2条直线端点重合区域,有4种连接方式
斜接(LineJoinMiter) ,斜切(LineJoinBevel),圆形(LineJoinRound),剪裁斜接(LineJoinMiterClipped)
这些都在 LineJoin的枚举里,
pen.SetLineJoin() 设置连接方式
--------------------------------------------------------------------------
enmu LineJoin{ //LineJoin连接点方式
LineJoinMiter=0, //斜接
LineJoinBevel=1, //斜切
LineJoinRound=2, //圆形
LineJoinMiterClipped=3 //剪裁斜接
};
--------------------------------------------------------------------------
其他技巧:
Graphics.SetRenderingOrigin(x,y) // 设置绘图原点
文本和字体:
GDI+ 提供了几个用于绘制文本的类:
FontFamily (字体系列) , Font , StringFormat(字符串格式) , InstalleFontCollection(已安装字体信息),
PrivateFontCollection(私有字体信息)
FontFamily (字体系列)
相同字样,包括不同风格的字体称为字体系列. 字体从系列中获得名称,重量(如粗体,规则,加亮)以及风格
FontFamily(L"宋体") //构造函数给出字体系列名和字体集的对象指针FontCollection,默认为NULL
FontFamily 往往与 Font 配套使用, 下面演示,使用 Arial 字体系列定义一个 规则字体对象font
FontFamily fontmi(L"Arial") // 创建字体系列 Arial
Font fo(&fontmi, 16,FontStyleReguular,UnitPixel); // 用Arial字体系列创建大小为16,规则,单位为像素的字体对象
接下来认识一些数据类型
字体信息指针
typedef struct {
LONG ifHeight; //字高
LONG ifWith; //字宽
LONGifEscapement; //字体旋转角度
LONG ifOrientation; //字体方向
LONG ifWeight; //字体轻重
BYTE ifItalic; //是否倾斜
BYTE ifUnderline; //是否下划线
BYTE ifStrukeOut; //是否强调线
BYTE ifCharSet;//字符集
BYTE ifOutPrecision;//输出精度
BYTE ifClipPrecision;裁剪精度
Byte ifQuality; //输出质量
Byte ifPitchAndFamily; //间距和字体系列
WCHAR ifFaceName[LF_FACESIZE]; //字体名
}LOGFONTW;
字体单位大小
enum Unit{
UnitWorld, //世界坐标,非物理上的单位
UnitDisplay, //使用和输出设备相同的单位,如显示器的单位为像素
UnitPixel, //像素
UnitPoint, //点(磅),1点等于1/72英寸
UnitInch, //英寸
UnitDocument, //1/300英寸
UnitMillimeter //毫米
};
字体风格FontStyle
enum FontStyle{
FontStyleRegular =0, //常规
FontStyleBold =1, //加粗
FontStyleItalic =2, //倾斜
FontStyleBoldItalic =3, //粗斜
FontStyleUnderline =4, //下划线
FontStyleStrikeout =5 //强调线
};
Font类定义字体对象
Font(hdc); Font(HDC,LOGFONTW*);
Font(const FontFamily* , REAL , INT ,Unit) //FontFaily对象,字体高度和风和单位
Font(cconst WCHAR*, REAL.INT);
InstalleFontCollection(已安装字体信息)
InstalleFontCollection.GetFamilyCount() 获取字体总数
InstalleFontCollection.GetFamilies(INT numSought, FontFamily* gpfamilies, INT* numFound) 获取字体信息
给出字体系列总数,gpfamilies是一个FontFamily类型的数组,数组要大于字体总数,numFound是一个int指针,返回大小
字体平滑处理
TextRenderingHint Graphics.GetTextRenderingHint() 获取字体边缘处理方式
Graphics.SetTextRenderingHint(TextRenderingHint newMode); 设置字体边缘处理方式
enum TextRenderingHint {
TextRenderingHintSystemDefault =0, //与系统处理方式相同
TextRenderingHintSingleBitPerPixelGridfit,//不消除锯齿,使用网格匹配
TextRenderingHintSingleBitPerPixel,//不消除锯齿,不使用网格匹配
TextRenderingHintAntiAliasGridFit,//消除锯齿,使用网格匹配
TextRenderingHintAntiAlias, //消除锯齿,不使用网格匹配
TextRenderingHintClearTypeGridFit //在液晶显示器上使用 ClearType技术增强字体清晰度
};
StringFormat(字符串格式)
StringFormat format;
format.SetFormatFlags(StringFormatFlagsNoClip); //禁用自动剪裁
Format.SetTrimming(StringTrimmingWord); //输出文本以单词结束
文本的剪裁是文本在矩形中容不下了,就可以出现字体的一半被显示,想要完全显示,可以设置矩形高度为字体高度的整数倍
或者禁用剪裁
注意设置去尾方式,想生效,需要在输出文本时候指定矩形而不是指定点
enum StringTrimming{ //去尾方式
StringTrimmingNone=0, //不去尾
StringTrimmingCharacter=1, //已字符为单位去尾
StringTrimmingWprd=2,//以单词为单位去尾
StringTrimmingEllipsisCharacter =3, //以字符为单位去尾,略去部分使用省略号
StringTrimmingEllipsosWord=4, //以单词为单位去尾,略去部分使用省略号
StringTrimmingEllipsisPath=5//略去字符串中间部分,保证字符首尾都能显示
};
format.SetFormatFlags(flag) // 设置文本输出方向
StringFormatFlagsDirectionRightToLeft //从右往左
StringFormatFlagsDirectionVertial //垂直方向输出文本
等等都在 StringFormatFlags 枚举中
format.SetAlignment(StringAlignment align); //设置水平对齐方式
format.SetLineAlignment(StringAlignment align);//设置垂直对齐方式
获取字体尺寸
FontFamily.GetEmHeight(FontStyle) //获取字体全身长
FontFamily.GetCellAscent(FontStyle)//获取字体上部间距
FontFamily.GetCellDescent(FontStyle)//获取字体下部家具
FontFamily.GetLineSpacing(FontStyle)//获取字体行距
测量字符串
graphics.MeasureString(string1,strlen,&font,layoutRect,NULL,&boumdRect,&codepointsFitted,&linesFilled);
string1待测量的字符串,strlen字符串长度,字符串字体,layoutRect字符串输出矩形.boumdRect计算后的文本输出矩形
codepointsFitted在字符串输出矩形能够显示多少字,linesFilled在字符串输出矩形能够显示多少行
//RectF 类型boumdRect,layoutRect;其他int类型
5.路径与区域
GDI+中定义路径通过 GraphicsPath类来表示
GraphicsPath(fillMode); fillMode填充模式, FillModeAlternate 或 FillModeWinding之一
GraphicsPath(Point* points, BYTE* types, INT count, FillMode fillMode);
points子路径的点,types为子路径的描述类型, 在PathPointType枚举内
enum PathPointType{
PathPointTypeStart =0, //子路径起点
PathPointTypepeLine=1,//直线的起点或终点
PathPointTypeBeier=3, //贝塞尔曲线的端点或控制点
PathPointTypePathTypeMake= 0x07,//路径点类型掩码
PathPointTypeDashMode=0x10,//
PathPointTypePathMarker = 0x20,//标记点
PathPointTypeCloseSubpath = 0x80,//封闭子路径的最后一点
PathPointTypeBezier3 =3
};
3.UNICODE相关
1.Windows 定义的Unicode数据类型:
WCHAR Unicode字符
PWSTR 指向Unicode字符串的指针
PCWSTR 指向一个恒定的Unicode字符串指针
2.标准ANSI C字符串函数和等价的 Unicode函数
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'
char* strcat(char* dest ,const char* src);
wchar_t* wcscat(wchar_t* dest , const wchar_t* src);
功能:比较字符串s1和s2, s1<s2 返回-1 , s1>s2返回1,等于返回0
ps:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止
int strcmp(const char* s1, const char* s2);
int wcscmp(const wchar_t* s1,const wchar_t* s2);
功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
char* strcpy(char* dest,const char* src);
wchar_t wcscpy(wchar_t* dest, const wchar_t* src);
size_t strlen(const char*);
size_t wcslen(const wchar_t*);
总结: Unicode函数均以 wcs开头,wcs是宽字符串的英文缩写
wchar_t *sError = L"Error";
字符串(literal string)前面的大写字母L,用于告诉编译器该字符串应该作为unicode字符
3.Wi n d o w s中的U n i c o d e函数和A N S I函数
windows的API函数中, 结尾为大些A的是 ANSI ,结尾是大些W的,是unicode
比如,CreateWindowExA,CreateWindowExW
4.应用程序进入点:
程序类型 进入点 嵌入可执行文件的启动函数
需要ANSI字符和字符串的GUI程序 WinMain WinMainCRTStartup
需要Unicode字符和字符串的GUI程序 wWinMain wWinMainCRTStartup
需要ANSI字符和字符串的CUI程序 main mainCRTSTARTUP
需要Unicode字符和字符串的CUI程序 wmain wmainCRTSTARTUP
5.程序能够使用的C / C + +运行期全局变量
变量名 _pgmptr 类型 char* 指向正在运行程序的全路径
变量名 _wpgmptr 类型 wchar_t* 指向正在运行程序的全路径
变量名 __argc 类型 unsigned int 命令行参数个数
变量名 __argv 类型 char** 指向 __argc大小数组,每个数组均指向一个命令行参数
变量名 __wargv 类型 wchar_t** 指向 __argc大小数组,每个数组均指向一个命令行参数
6.other
extern用于表示变量或者函数的定义在别的文件中,例:extern char *a;
LOWORD() HIWORD() 取低位高位
#pragma comment(lib,"DllDemo.lib") 载入链接库