目录
GUI作图概述
描绘图形
位图
文本输出
设置画刷/画笔/字体
MFC 资源句柄的获得与释放
(本章节中例子都是用 VS2005 编译调试的)
GUI作图概述
作图步骤
- 获得设备描述表资源句柄
- 绘图操作
- 释放设备描述表资源句柄
流程图如下:

获取/释放设备资源描述表
- 获取设备资源描述表: BeginPaint / GetDC
- 释放设备资源描述表: EndPaint / ReleaseDC
BeginPaint / GetDC 两种方式的区别:
BeginPaint GetDC
使用环境 只用于图形刷新时获取设备环境 使用较为广泛
操作区域 无效区 特定窗口的客户区或者整个窗口
释放设备环境所用函数 EndPaint () ReleaseDC ()
代码示例:
在 WM_PAINT 添加 BeginPaint 事件,在 WM_LBUTTONDOWN 添加 GetDC 事件.
BeginPaint 使用:
//获得资源DC
hdc=BeginPaint(hwnd,&ps);
//获得窗口大小
GetClientRect(hwnd,&rect);
//绘制文本
DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
//释放资源DC
EndPaint(hwnd,&ps);
GetDC 使用:
//获得设备资源描述表 hdc = GetDC(hwnd); //绘制带圆角矩形 RoundRect(hdc,10,10,110,60,10,10); //释放设备资源描述表 ReleaseDC(hwnd,hdc);
运行结果:
单击鼠标右键和重绘窗口时

在单击鼠标右键后

绘图操作分类
- 描绘图形
- 位图
- 文本输出
与设备描述表相关函数
- 背景色: GetBkColor / SetBkColor
- 背景模式: GetBkMode / SetBkMode
- 位图: CreateBitMap / CreateBitMapIndirect / CreateCompatibleBitmap / SelectObject
- 画刷: CreateBrushIndirect / CreateDIBPatternBrush CreateHatchBrush / CreatePatternBrush / CreateSolidBrush / SelectObject
- 画刷起始位置: GetBrushOrg / SetBrushOrg / UnrealizeObject
- 剪裁域: ExcludeClipRect / IntersectClipRect / OffsetClipRgn / SelectClipPath / SelectObject / SelectClipRgn
- 颜色调色板: CreatePalette / RealizePalette / SelectPalette
- 绘图方式: GetROP2 / SetROP2
- 字体: CreateFont / CreateFontIndirect / SelectObject
- 字符间距: GetTextCharacterExtra / SetTextCharacterExtra
- 映射方式: GetMapMode / SetMapMode
- 画笔: CreatePen / CreatePenIndirect / SelectObject
- 多边形填充方式: GetPolyFillMode / SetPolyFillMode
- 缩放模式: SetStretchBltMode / GetStretchBltMode
- 文本颜色: GetTextColor / SetTextColor
- 视图范围: GetViewportExtEx / SetViewportExtEx / ScaleViewportExtEx
- 视图原点: GetViewportOrgEx / SetViewportOrgEx
- 窗口范围: GetWindowExtEx / SetWindowExtEx / ScaleWindowExtEx
- 窗口原点: GetWindowOrgEx / SetWindowOrgEx
描绘图形
常用绘图函数:
- 画贝塞尔曲线:
- 画点: SetPixel
- 画矩形: Rectangle
- 画带圆角的矩形: RoundRect
函数原型: BOOL RoundRect( HDC hdc, int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nWidth,int nHeight);
参数说明:

- 画椭圆: Ellipse
- 画椭圆的一部分(即画一个弦): Chord
- 画一个扇形区并用当前画刷填充: Pie
- 画椭圆弧线: Arc
函数原型: BOOL Arc(HDC hdc,int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc);
参数说明:

- 画椭圆弧线: ArcTo
- 画正圆弧线: AngleArc
函数原型: BOOL AngleArc(HDC hdc,int X,int Y,DWORD dwRadius,FLOAT eStartAngle,FLOAT eSweepAngle);
参数说明:

- 画一系列相连的直线:
- 画线条:
位图
步骤:
- 建立位图资源
- 载入/创建位图资源
- 获取设备内存
- 选入内存设备
- 贴图
流程图如下所示:

代码示例:
.rc 内容(位图资源):
IDB_BITMAP1 BITMAP "8c8a09f1gw1ds3qh4vtcyj.bmp"
位图(8c8a09f1gw1ds3qh4vtcyj.bmp 尺寸信息:440*622):

在鼠标左键单击事件中添加贴图操作:
加载位图:
hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));
创建兼容 DC 并将位图选入兼容 DC 中:
hcmdc = CreateCompatibleDC(hdc); SelectObject(hcmdc,hBmp);
获得窗口大小(被显示的区域),获得位图信息(要显示的区域)
//获取窗口大小 GetClientRect(hwnd,&rect); //获取位图信息(在 StretchBlt 时候有用到,而 BitBlt 没有) GetObject(hBmp, sizeof(BITMAP), &bmp);
显示位图:
//显示方式一, 按原图比例显示 BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY); //显示方式二, 拉伸式显示 StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
运行结果:
- 在未点击鼠标右键时候:

- 点击鼠标左键(用 BitBlt 方法):

- 点击鼠标左键(用 StretchBlt 方法):

文本输出
文本输出操作
- 文字输出: TextOut
- 显示字符串: DrawText
有关文本操作:
- 获取文字信息: GetTextMetrics
- 格式化文字: GetTextExtentPoint32
- 设置字体颜色和背景颜色:
- 字体: SetTextColor
- 背景: SetBkColor
设置画刷/画笔/字体
相关结构体:
字体结构体
TEXTMETRIC
作用: 记录基本的字体信息
结构体定义(MSDN 链接):
View Code
typedef struct tagTEXTMETRIC {
LONG tmHeight; // Specifies the height (ascent descent) of characters.
LONG tmAscent; // Specifies the ascent (units above the base line) of characters.
LONG tmDescent; // Specifies the descent (units below the base line) of characters.
LONG tmInternalLeading; // Specifies the amount of leading (space) inside the bounds set by the tmHeight member.
LONG tmExternalLeading; // Specifies the amount of extra leading (space) that the application adds between rows.
LONG tmAveCharWidth; // Specifies the average width of characters in the font.
LONG tmMaxCharWidth; // Specifies the width of the widest character in the font.
LONG tmWeight; // Specifies the weight of the font.
LONG tmOverhang; // Specifies the extra width per string that may be added to some synthesized fonts
LONG tmDigitizedAspectX; // Specifies the horizontal aspect of the device for which the font was designed.
LONG tmDigitizedAspectY; // Specifies the vertical aspect of the device for which the font was designed.
TCHAR tmFirstChar; // Specifies the value of the first character defined in the font.
TCHAR tmLastChar; // Specifies the value of the last character defined in the font.
TCHAR tmDefaultChar; // Specifies the value of the character to be substituted for characters not in the font.
TCHAR tmBreakChar; // Specifies the value of the character that will be used to define word breaks for text justification.
BYTE tmItalic; // Specifies an italic font if it is nonzero.
BYTE tmUnderlined; // Specifies an underlined font if it is nonzero.
BYTE tmStruckOut; // Specifies a strikeout font if it is nonzero.
BYTE tmPitchAndFamily; // Specifies information about the pitch, the technology, and the family of a physical font.
BYTE tmCharSet; // Specifies the character set of the font.
} TEXTMETRIC, *PTEXTMETRIC;
图示:

步骤:
- 创建资源句柄
- 创建自定义资源/调用系统资源
- 将资源选入系统
如下图所示:

代码示例:
在窗口重画的时候添加创建新画笔操作:
创建新画笔,并将画笔选入设备描述表中
pen = CreatePen(PS_DOT,3,RGB(255,100,100)); SelectObject(hdc,pen);
为了区别创建画笔前和创建画笔后的作图的区别
在创建画笔前绘制一条直线:
//rect 为记录窗口大小的 RECT 结构体 MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL); LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);
在创建画笔后绘制一条直线:
MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL); LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);
运行结果:

程序源码
View Code
#include<windows.h>
#include"resource.h"
HINSTANCE hinstance;
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
WNDCLASS wndclass;
HWND hwnd;
MSG msg;
//设计窗口类
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=textprom;
wndclass.lpszClassName="text";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
//注册窗口类
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,"create windows error!","error",MB_OK | MB_ICONSTOP);
}
//创建无菜单资源的窗口窗口
hwnd=CreateWindow("text","hellow world",WS_DLGFRAME | WS_MINIMIZEBOX | WS_SYSMENU,0,0,500,300,NULL,NULL,hInstance,NULL);
//显示更新窗口
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
hinstance = hInstance;
//消息循环
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
HDC hdc,hcmdc;
PAINTSTRUCT ps;
RECT rect;
HBITMAP hBmp;
SIZE size;
BITMAP bmp;
HPEN pen;
switch(uMsg)
{
//重绘事件
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
//显示文本
GetClientRect(hwnd,&rect);
DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
//画笔
MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);
pen = CreatePen(PS_DOT,3,RGB(255,100,100));
SelectObject(hdc,pen);
MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);
EndPaint(hwnd,&ps);
break;
//绘制圆角矩形
case WM_LBUTTONDOWN:
hdc = GetDC(hwnd);
RoundRect(hdc,10,10,110,60,10,10);
ReleaseDC(hwnd,hdc);
break;
//贴图
case WM_RBUTTONDOWN:
hdc = GetDC(hwnd);
hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));
hcmdc = CreateCompatibleDC(hdc);
SelectObject(hcmdc,hBmp);
GetClientRect(hwnd,&rect);
GetObject(hBmp, sizeof(BITMAP), &bmp);
StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
//BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY);
ReleaseDC(hwnd,hdc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
MFC 资源句柄的获得与释放
绘图是选用GDI资源的说明
在程序中,当构造函数构造一个GDI对象后,该对象并不会立刻生效,必须选入设备描述表,它才会在以后的操作中生效,利用SelectObject函数可以实现把GDI对象选入设备描述表中,并且返回指向先前GDI设备对象的指针,一般情况下,在完成绘图操作后,都要利用SelectObject函数吧先前的GDI对象选入设备表,以便使恢复到先前状态
GDI绘图对象(CPen,CFont.CBitmap,CBrush)都派生于CGdiObject类对象,都有一个m_hObject记录与对应资源联系的关系,当其对象与对应的资源调用CreateXXXX建立联系后若想把对象关联上新的资源时候,必须先对旧的资源释放才能和新的资源建立上联系,可以用CGdiObject对象的DeleteObject函数去切断与旧资源的联系,并释放旧的资源
相关函数
获得资源设备表
函数原型
CDC* GetDC();
返回值: 如果调用成功,则返回CWnd客户区的设备环境;否则,返回NULL。这个指针可能是临时的,不能被保存以供将来使用
说明: 这个函数获得一个指针,指向一个客户区的公用的、属于类的或者私有的设备环境,依赖于为CWnd指定的类风格。对于公用的设备环境,GetDC每次获得设备环境时都给它赋予缺省值。对于属于类的或者私有的设备环境,GetDC保持原来的属性不变。在随后的图形设备接口(GDI)函数中可以使用设备环境以在客户区中绘图
释放资源设备表
函数原型
int ReleaseDC( CDC* pDC );
参数说明: pDC 标识了要释放的设备环境
返回值: 如果成功,则返回非零值;否则返回0
说明: 释放设备环境,以供其它应用程序使用。ReleaseDC成员函数的效果依赖于设备环境的
CPainDC与CCleintDC的区别
- CPaintDC
- CPaintDC继承于CDC
- 在构造函数中调用BeginPaint
- 在析构函数调用EndPaint函数
- 用于相应WM_PAINT消息的函数中
- CClientDC
- CClientDC继承于CDC
- 在析构函数中调用GetDC
- 在析构函数中调用ReleaseDC
- 用于非WM_PAINT消息的GDI绘图函数中
获得设备资源描述表实现步骤

来源:https://www.cnblogs.com/kzang/archive/2012/11/01/2747565.html






