一、坐标系
1.坐标系分类
1)设备坐标系:显示器的设备坐标系,坐标原点位于左上角,X轴向右为正,Y轴向下为正,1个单位就是一个像素。
A.屏幕坐标系,以屏幕的左上角为原点。
B.窗口坐标系,以窗口的左上角为原点。
C.客户坐标系,以客户区的左上角为原点。
像素的大小与成像设备有关。
显示器的寸数就是对角线的长度。
2)逻辑坐标系:坐标单位、坐标原点、坐标轴的方向皆可设置。
在GDI绘图中所使用的坐标系都是逻辑坐标系。
默认情况下,逻辑坐标系与设备坐标系重合。
1逻辑=1设备
显示器:1设备=1像素
打印机:1设备=1/1440英寸(0.018毫米)
2.坐标映射
1)映射模式
A.确定了逻辑坐标系与设备坐标系之间的映射关系。
B.设备坐标系的单位不能通过代码修改,但是逻辑坐标系可以修改。
int SetMapMode (
HDC hdc, // 设备上下文句柄
int fnMapMode // 映射模式
);
成功返回原映射模式,失败返回0。
fnMapMode取值:
MM_TEXT - 正文模式:1逻辑=1像素,原点左上,X向右,Y向下。(缺省模式)
MM_LOENGLISH - 低英制模式:1逻辑=0.01英寸,原点左上,X向右,Y向上。
MM_HIENGLISH - 高英制模式:1逻辑=0.001英寸,原点左上,X向右,Y向上。
MM_LOMETRIC - 低公制模式:1逻辑=0.1毫米,原点左上,X向右,Y向上。
MM_HIMETRIC - 搞公制模式:1逻辑=0.01毫米,原点左上,X向右,Y向上。
MM_TWIPS - 打印机模式:1逻辑=1/1440英寸,原点左上,X向右,Y向上。
MM_ISOTROPIC - 各向同性模式:1逻辑=自定义,原点自定义,轴方向自定义。逻辑单位与设备单位的比例在水平和垂直方向上取一致。
MM_ANISOTROPIC - 各向异性模式:1逻辑=自定义,原点自定义,轴方向自定义。逻辑单位与设备单位的比例在水平和垂直方向上可以不一致。
2)设置逻辑单位与设备单位的比例
BOOL SetViewportExtEx (
HDC hdc, // 设备上下文句柄
int nXExtent, // 设备单位X尺度
int nYExtent, // 设备单位Y尺度
LPSIZE lpSize // 设备单位原尺度,可为NULL
);
成功返回TRUE,失败返回FALSE。
BOOL SetWindowExtEx (
HDC hdc, // 设备上下文句柄
int nXExtent, // 逻辑单位X尺度
int nYExtent, // 逻辑单位Y尺度
LPSIZE lpSize // 逻辑单位原尺度,可为NULL
);
成功返回TRUE,失败返回FALSE。
SetWindowExtEx (hDC, 1, 1, NULL);
SetViewportExtEx (hDC, 2, 3, NULL);
X方向:1逻辑=2设备
Y方向:1逻辑=3设备(对各向同性模式,忽略L/D值小的)
等价于:
SetWindowExtEx (hDC, 1000, 1000, NULL);
SetViewportExtEx (hDC, 2000, 3000, NULL);
改变轴的方向:
SetWindowExtEx (hDC, 1, -1, NULL);
SetViewportExtEx (hDC, 2, 3, NULL);
二、文字
1.绘制单行文字
BOOL TextOut (
HDC hdc, // 设备上下文句柄
int nXStart, // 文本行位置
int nYStart,
LPCTSTR lpString, // 文本字符串
int cbString // 字符串长度
);
成功返回TRUE,失败返回FALSE。
2.在矩形内绘制文字
int DrawText (
HDC hdc, // 设备上下文句柄
LPCTSTR lpString, // 文本字符串
int cbString, // 字符串长度
LPRECT lpRect, // 矩形区域
UINT uFormat // 文本格式
);
成功返回文本高度,失败返回0。
uFormat取值:
DT_LEFT - 靠左
DT_CENTER - 水平居中
DT_RIGHT - 靠右
DT_TOP - 靠上
DT_VCENTER - 垂直居中
DT_BOTTOM - 靠下
DT_SINGLELINE - 单行
DT_WORDBREAK - 按单词这行
DT_WORD_ELLIPSIS - 显示不下的单词以省略号表示
DT_NOCLIP - 超出矩形区域部分不做裁剪
DT_NOPREFIX - 不转义&字符
3.按照指定字间距输出文本
BOOL ExtTextOut (
HDC hdc, // 设备上下文句柄
int X, // 文本行位置
int Y,
UINT fuOptions, // 文本输出选项
CONST RECT* lprc, // 矩形区域
LPCTSTR lpString, // 文本字符串
UINT cbCount, // 字符串长度
CONST INT* lpDx // 字间距表
);
成功返回TRUE,失败返回FALSE。
4.设置文字颜色
COLORREF SetTextColor (
HDC hdc, // 设备上下文句柄
COLORREF crColor // 文字颜色
);
成功返回原文字颜色,失败返回CLR_INVALID。
5.设置文字背景颜色
COLORREF SetBkColor (
HDC hdc, // 设备上下文句柄
COLORREF crColor // 背景颜色
);
成功返回原背景颜色,失败返回CLR_INVALID。
6.设置背景模式
int SetBkMode (
HDC hdc, // 设备上下文句柄
int iBkMode // 背景模式
);
成功返回原背景模式,失败返回0。
iBkMode取值:
TRANSPARENT - 透明模式,不绘制文本背景
OPAQUE - 非透明模式,绘制文本背景,缺省模式
三、字体
1.Windows常用字体格式:TrueType字体
每一种字体都用一个字体文件(c:/windows/fonts/xxx.ttf)保存。
双击字体文件可以看到字体名。
2.创建字体
HFONT CreateFont (
int nHeight, // 字体高度
int nWidth, // 字体宽度
int nEscapement, // 倾斜角度
int nOrientation, // 旋转角度,没用,填0
int fnWeight, // 字体粗细
DWORD fdwItalic, // 斜体
DWORD fdwUnderline, // 下划线
DWORD fdwStrikeOut, // 删除线
DWORD fdwCharSet, // 字符集,GB2312_CHARSET
DWORD fdwOutputPrecision, // 输出精度,置0
DWORD fdwClipPrecision, // 剪切精度,置0
DWORD fdwQuality, // 输出质量,置0
DWORD fdwPitchAndFamily, // 匹配字体
LPCTSTR lpszFace // 字体名
);
成功返回字体句柄,失败返回NULL。
HFONT CreateFontIndirect(
CONST LOGFONT *lplf // 逻辑字体结构
);
3.应用字体
HFONT hfontOld = SelectObject (hDC, hfontNew);
4.绘制文字
TextOut/DrawText/ExtTextOutEx
5.恢复字体
SelectObject (hDC, hfontOld);
6.删除字体
DeleteObject (hfontNew);
练习:在窗口中显示时钟。
文字:FreeType开源的
2D图形:Cario开源的
图像:xImage
3D渲染:Direct3D
#include<math.h>
在窗口处理函数中:
//跟踪窗口大小
static SIZE sizeClient={0};
static tm tmLocal={0};
static HPEN hpenHour=NULL;
static HPEN hpenMin=NULL;
static HPEN hpenSec=NULL;
case WM_SIZE:
sizeClient.cx=LOWORD(lParam);
sizeClient.cy=HIWORD(lParam);
break;
case WM_PAINT{
PAINTSTRUCT ps;
HDC hDC=BeginPaint(hWnd,&ps);
//将圆点中心放在客户区中心
SetViewportOrgEx(hDC,sizeClient.cx/2,sizeClient.cy/2,NULL);
int nRadius=min(sizeClient.cx,sizeClient.cy)/2;
double fAngle;//保存角度
//先把表画出来
for(fAngle=0.0,fAngle<2*3.14159;fAngle+=3.14159/6){
MoveToEx(hDC,(int)(nRadius*cos(fAngle)*4/5+0.5),(int)(nRadius*sin(fAngle)*4/5+0.5),NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)+0.5),(int)(nRadius*sin(fAngle)+0.5);
}
//根据时间值来画针
//时针
HPEN hpenOld=SelectObject(hDC,hpenHour);
fAngle=(tmLocal.tm_hour+tmLocal.tm_min/60.0+tmLocal.tm_sec/3600.0)*3.14159/6-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)*2/3+0.5),(int)(nRadius*sin(fAngle*2/3+0.5));
//分针
SelectObject(hDC,hpenMin);
fAngle=(tmLocal.tm_min+tmLocal.tm_sec/60.0)*3.14159/30-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)*8/9+0.5),(int)(nRadius*sin(fAngle*8/9+0.5));
//秒针
fAngle=(tmLocal.tm_sec)*3.14159/30-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)+0.5),(int)(nRadius*sin(fAngle+0.5));
SelectObject(hDC,hpenOld);
Ellipse(hDC,-nRadius/20,-nRadius/20,nRadius/20,nRadius/20);
EndPaint(hWnd,&ps);
break;
}
case WM_CREATE:{
tim_t t=time(NULL);
tmLocal=*localtime(&t);
SetTimer(hWnd,IDT_TICK,1000,NULL);
hpenHour=CreatePen(PS_SOLID,6,RGB(0,0,255));
hpenMin=CreatePen(PS_SOLID,3,RGB(0,128,0));
hpenSec=CreatePen(PS_SOLID,1,RGB(255,0,0));
return 0;
}
//定时器
case WM_TIMER:
tim_t t=time(NULL);
tmLocal=*local(hWnd,TRUE);
InvalidateRect(hWnd,NULL,TRUE);
case WM_DESTROY:
DeleteObject(hpenHour);
DeleteObject(hpenMin);
DeleteObject(hpenSec);
1.坐标系分类
1)设备坐标系:显示器的设备坐标系,坐标原点位于左上角,X轴向右为正,Y轴向下为正,1个单位就是一个像素。
A.屏幕坐标系,以屏幕的左上角为原点。
B.窗口坐标系,以窗口的左上角为原点。
C.客户坐标系,以客户区的左上角为原点。
像素的大小与成像设备有关。
显示器的寸数就是对角线的长度。
2)逻辑坐标系:坐标单位、坐标原点、坐标轴的方向皆可设置。
在GDI绘图中所使用的坐标系都是逻辑坐标系。
默认情况下,逻辑坐标系与设备坐标系重合。
1逻辑=1设备
显示器:1设备=1像素
打印机:1设备=1/1440英寸(0.018毫米)
2.坐标映射
1)映射模式
A.确定了逻辑坐标系与设备坐标系之间的映射关系。
B.设备坐标系的单位不能通过代码修改,但是逻辑坐标系可以修改。
int SetMapMode (
HDC hdc, // 设备上下文句柄
int fnMapMode // 映射模式
);
成功返回原映射模式,失败返回0。
fnMapMode取值:
MM_TEXT - 正文模式:1逻辑=1像素,原点左上,X向右,Y向下。(缺省模式)
MM_LOENGLISH - 低英制模式:1逻辑=0.01英寸,原点左上,X向右,Y向上。
MM_HIENGLISH - 高英制模式:1逻辑=0.001英寸,原点左上,X向右,Y向上。
MM_LOMETRIC - 低公制模式:1逻辑=0.1毫米,原点左上,X向右,Y向上。
MM_HIMETRIC - 搞公制模式:1逻辑=0.01毫米,原点左上,X向右,Y向上。
MM_TWIPS - 打印机模式:1逻辑=1/1440英寸,原点左上,X向右,Y向上。
MM_ISOTROPIC - 各向同性模式:1逻辑=自定义,原点自定义,轴方向自定义。逻辑单位与设备单位的比例在水平和垂直方向上取一致。
MM_ANISOTROPIC - 各向异性模式:1逻辑=自定义,原点自定义,轴方向自定义。逻辑单位与设备单位的比例在水平和垂直方向上可以不一致。
2)设置逻辑单位与设备单位的比例
BOOL SetViewportExtEx (
HDC hdc, // 设备上下文句柄
int nXExtent, // 设备单位X尺度
int nYExtent, // 设备单位Y尺度
LPSIZE lpSize // 设备单位原尺度,可为NULL
);
成功返回TRUE,失败返回FALSE。
BOOL SetWindowExtEx (
HDC hdc, // 设备上下文句柄
int nXExtent, // 逻辑单位X尺度
int nYExtent, // 逻辑单位Y尺度
LPSIZE lpSize // 逻辑单位原尺度,可为NULL
);
成功返回TRUE,失败返回FALSE。
SetWindowExtEx (hDC, 1, 1, NULL);
SetViewportExtEx (hDC, 2, 3, NULL);
X方向:1逻辑=2设备
Y方向:1逻辑=3设备(对各向同性模式,忽略L/D值小的)
等价于:
SetWindowExtEx (hDC, 1000, 1000, NULL);
SetViewportExtEx (hDC, 2000, 3000, NULL);
改变轴的方向:
SetWindowExtEx (hDC, 1, -1, NULL);
SetViewportExtEx (hDC, 2, 3, NULL);
二、文字
1.绘制单行文字
BOOL TextOut (
HDC hdc, // 设备上下文句柄
int nXStart, // 文本行位置
int nYStart,
LPCTSTR lpString, // 文本字符串
int cbString // 字符串长度
);
成功返回TRUE,失败返回FALSE。
2.在矩形内绘制文字
int DrawText (
HDC hdc, // 设备上下文句柄
LPCTSTR lpString, // 文本字符串
int cbString, // 字符串长度
LPRECT lpRect, // 矩形区域
UINT uFormat // 文本格式
);
成功返回文本高度,失败返回0。
uFormat取值:
DT_LEFT - 靠左
DT_CENTER - 水平居中
DT_RIGHT - 靠右
DT_TOP - 靠上
DT_VCENTER - 垂直居中
DT_BOTTOM - 靠下
DT_SINGLELINE - 单行
DT_WORDBREAK - 按单词这行
DT_WORD_ELLIPSIS - 显示不下的单词以省略号表示
DT_NOCLIP - 超出矩形区域部分不做裁剪
DT_NOPREFIX - 不转义&字符
3.按照指定字间距输出文本
BOOL ExtTextOut (
HDC hdc, // 设备上下文句柄
int X, // 文本行位置
int Y,
UINT fuOptions, // 文本输出选项
CONST RECT* lprc, // 矩形区域
LPCTSTR lpString, // 文本字符串
UINT cbCount, // 字符串长度
CONST INT* lpDx // 字间距表
);
成功返回TRUE,失败返回FALSE。
4.设置文字颜色
COLORREF SetTextColor (
HDC hdc, // 设备上下文句柄
COLORREF crColor // 文字颜色
);
成功返回原文字颜色,失败返回CLR_INVALID。
5.设置文字背景颜色
COLORREF SetBkColor (
HDC hdc, // 设备上下文句柄
COLORREF crColor // 背景颜色
);
成功返回原背景颜色,失败返回CLR_INVALID。
6.设置背景模式
int SetBkMode (
HDC hdc, // 设备上下文句柄
int iBkMode // 背景模式
);
成功返回原背景模式,失败返回0。
iBkMode取值:
TRANSPARENT - 透明模式,不绘制文本背景
OPAQUE - 非透明模式,绘制文本背景,缺省模式
三、字体
1.Windows常用字体格式:TrueType字体
每一种字体都用一个字体文件(c:/windows/fonts/xxx.ttf)保存。
双击字体文件可以看到字体名。
2.创建字体
HFONT CreateFont (
int nHeight, // 字体高度
int nWidth, // 字体宽度
int nEscapement, // 倾斜角度
int nOrientation, // 旋转角度,没用,填0
int fnWeight, // 字体粗细
DWORD fdwItalic, // 斜体
DWORD fdwUnderline, // 下划线
DWORD fdwStrikeOut, // 删除线
DWORD fdwCharSet, // 字符集,GB2312_CHARSET
DWORD fdwOutputPrecision, // 输出精度,置0
DWORD fdwClipPrecision, // 剪切精度,置0
DWORD fdwQuality, // 输出质量,置0
DWORD fdwPitchAndFamily, // 匹配字体
LPCTSTR lpszFace // 字体名
);
成功返回字体句柄,失败返回NULL。
HFONT CreateFontIndirect(
CONST LOGFONT *lplf // 逻辑字体结构
);
3.应用字体
HFONT hfontOld = SelectObject (hDC, hfontNew);
4.绘制文字
TextOut/DrawText/ExtTextOutEx
5.恢复字体
SelectObject (hDC, hfontOld);
6.删除字体
DeleteObject (hfontNew);
练习:在窗口中显示时钟。
文字:FreeType开源的
2D图形:Cario开源的
图像:xImage
3D渲染:Direct3D
#include<math.h>
在窗口处理函数中:
//跟踪窗口大小
static SIZE sizeClient={0};
static tm tmLocal={0};
static HPEN hpenHour=NULL;
static HPEN hpenMin=NULL;
static HPEN hpenSec=NULL;
case WM_SIZE:
sizeClient.cx=LOWORD(lParam);
sizeClient.cy=HIWORD(lParam);
break;
case WM_PAINT{
PAINTSTRUCT ps;
HDC hDC=BeginPaint(hWnd,&ps);
//将圆点中心放在客户区中心
SetViewportOrgEx(hDC,sizeClient.cx/2,sizeClient.cy/2,NULL);
int nRadius=min(sizeClient.cx,sizeClient.cy)/2;
double fAngle;//保存角度
//先把表画出来
for(fAngle=0.0,fAngle<2*3.14159;fAngle+=3.14159/6){
MoveToEx(hDC,(int)(nRadius*cos(fAngle)*4/5+0.5),(int)(nRadius*sin(fAngle)*4/5+0.5),NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)+0.5),(int)(nRadius*sin(fAngle)+0.5);
}
//根据时间值来画针
//时针
HPEN hpenOld=SelectObject(hDC,hpenHour);
fAngle=(tmLocal.tm_hour+tmLocal.tm_min/60.0+tmLocal.tm_sec/3600.0)*3.14159/6-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)*2/3+0.5),(int)(nRadius*sin(fAngle*2/3+0.5));
//分针
SelectObject(hDC,hpenMin);
fAngle=(tmLocal.tm_min+tmLocal.tm_sec/60.0)*3.14159/30-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)*8/9+0.5),(int)(nRadius*sin(fAngle*8/9+0.5));
//秒针
fAngle=(tmLocal.tm_sec)*3.14159/30-3.14159/2;
MoveToEx(hDC,0,0,NULL);
LineTo(hDC,(int)(nRadius*cos(fAngle)+0.5),(int)(nRadius*sin(fAngle+0.5));
SelectObject(hDC,hpenOld);
Ellipse(hDC,-nRadius/20,-nRadius/20,nRadius/20,nRadius/20);
EndPaint(hWnd,&ps);
break;
}
case WM_CREATE:{
tim_t t=time(NULL);
tmLocal=*localtime(&t);
SetTimer(hWnd,IDT_TICK,1000,NULL);
hpenHour=CreatePen(PS_SOLID,6,RGB(0,0,255));
hpenMin=CreatePen(PS_SOLID,3,RGB(0,128,0));
hpenSec=CreatePen(PS_SOLID,1,RGB(255,0,0));
return 0;
}
//定时器
case WM_TIMER:
tim_t t=time(NULL);
tmLocal=*local(hWnd,TRUE);
InvalidateRect(hWnd,NULL,TRUE);
case WM_DESTROY:
DeleteObject(hpenHour);
DeleteObject(hpenMin);
DeleteObject(hpenSec);