Windows
图形设备接口(
Graphics Device Interface, GDI
)是为与设备无关的图形设计的,由操作系统屏蔽了硬件设备的差异,简化了程序员的程序编写工作。
设备上下文(
Device Context, DC
)
定义了一系列图形对象及其属性的结构,包括图形模式及输出。
PS
:
DC
一词的翻译上有些疑惑,不明白为什么这么叫。
context:
背景,环境,上下文
目前设备上下文有四种类型:显示,打印,存储和消息类型。
图形对象及其属性:
位图,画刷,调色板,字体,画笔,区域
应用程序每一次图形操作均参照设备
上下文
中的属性执行,
DC
可以看作是图形的“输出模板”。
图形刷新
Windows
应用程序在使用过程中,窗口大小的调整,窗口移动或者被其它窗口覆盖后,都必须要刷新原窗口内用户区显示的内容。但是
windows
系统只能在有限的几种情况下自动刷新。因此应用程序必须具有及时处理刷新请求和刷新响应的功能。
Windows
系统通常通过发送
WM_PAINT
消息将刷新请求传递给应用程序。一般情况下,刷新有三种可能:
(1)
窗口移动后的刷新
用户区移动,窗口大小改变,滚动条的使用等
(2)
被覆盖区域的刷新
下拉式菜单关闭后需恢复被覆盖部分,清除消息框后进行的恢复等
(3)
对象穿越后的刷新
光标穿过用户区,图标拖过用户区等
Windows
系统为每个窗口建立了一个
PAINTSTRUCT
结构,该结构中包含了指明一个窗口被另一个窗口覆盖的“无效区域”的最小矩形结构
RECT
,程序可根据这个矩形进行刷新。
常用刷新方法包括:
(1)
保持一个显示输出副本,需要时重绘窗口
(2)
记录发生的事件,需要时重新调用该事件
(3)
重新绘图,简单图形常用的方法
获取设备
上下文
获取设备
上下文
是应用程序输出图形的先决条件,常用函数有:
BeginPaint
响应
WM_PAINT
消息进行图形刷新
GetDC
非
WM_PAINT
消息驱动时用于获取设备
上下文
GetDCEx
返回指向特定窗口客户区的整个窗口句柄,是
GetDC
的扩展
绘图工具与颜色
1.
画笔
&
画刷
画笔的功能是用来画直线和曲线,画刷用于指定区域的填充
可以使用
CreatePen
和
CreateBrush
创建自定义画笔画刷,也或以使用
GetStockObject
函数获取系统默认的样式。
HPEN hPen = CreatePen
(
int nPenStyle,
int nWidth,
COLORREF rgbColor
);
HBRUSH hBrush = CreateBrush
(
int nHatchStyle,
COLORREF rgbColor
)
画笔画刷不再使用时应使用
DeleteObject
函数删除并释放资源
2.
颜色
winodws
使用宏
RGB
定义绘图颜色
RGB(nRed, nGreen, nBlue)
其中
nRed, nGreen, nBlue
分别表示红,绿,蓝的数值。
3.
常用绘图函数
(1)
BOOL MoveToEx {
HDC hdc,
int x, int y,
LPPOINT lpPoint //
存放原画笔位置的
POINT
结构
}
(2)
BOOL LineTo {
HDC hdc,
int x, int y
}
(3)
BOOL Rectangle {
HDC hdc,
int x1, int y1, //
矩形左上角逻辑坐标
int x2, int y2 //
矩形右下角逻辑坐标
}
(4)
BOOL Polygon {
HDC hdc,
LPPOINT lpPoints, //
包含各顶点坐标的
POINT
数组
int nCount //
多边形顶点个数
}
应用实例
–
简单的图形绘制
#include
windows.h
>
#include
math.h
>
const
double
pi
=
3.1415926
;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, UINT wParam, LONG lParam)
{
HDC hDC;
HBRUSH hBrh;
HPEN hPen;
POINT oldPt;
PAINTSTRUCT ptStr;
//
定义绘图信息结构体
switch
(iMsg)
{
case
WM_PAINT:
//
处理绘图信息
hDC
=
BeginPaint(hWnd,
&
ptStr);
//
获取设备上下文
SetMapMode(hDC, MM_TEXT);
//
设置映射模式
hPen
=
(HPEN)GetStockObject(BLACK_PEN);
//
获取默认黑色画笔
SelectObject(hDC, hPen);
//
将画笔选入
设备上下文
hBrh
=
(HBRUSH)(GetStockObject(DKGRAY_BRUSH));
//
深灰色画刷
SelectObject(hDC, hBrh);
RoundRect(hDC,
50
,
50
,
200
,
350
,
25
,
25
);
//
圆角矩形
hBrh
=
(HBRUSH)(GetStockObject(HOLLOW_BRUSH));
//
虚画刷,填充无效果
SelectObject(hDC, hBrh);
Pie(hDC,
300
,
50
,
400
,
300
,
300
,
50
,
400
,
50
);
//
饼图
//
一个五角星
MoveToEx(hDC,
500
,
150
,
&
oldPt);
LineTo(hDC,
650
,
150
);
LineTo(hDC,
525
,
250
);
LineTo(hDC,
575
,
100
);
LineTo(hDC,
625
,
250
);
LineTo(hDC,
500
,
150
);
//
坐标系
MoveToEx(hDC,
700
,
150
,
&
oldPt);
LineTo(hDC,
700
,
300
);
LineTo(hDC,
1500
,
300
);
MoveToEx(hDC,
700
,
300
,
&
oldPt);
//
近似的正弦曲线
for
(
int
i
=
0
; i
3000
;
++
i)
{
LineTo(hDC,
700
+
i
*
20
,
300
-
sin(i)
*
20
);
}
EndPaint(hWnd,
&
ptStr);
//
结束绘图
return
0
;
case
WM_DESTROY:
PostQuitMessage(
0
);
return
0
;
default
:
//
其它消息的默认处理函数
return
(DefWindowProc(hWnd, iMsg, wParam, lParam));
}
}
//
对窗口进行初始化
BOOL InitWindow(HINSTANCE hInst,
int
nCmdShow)
{
HWND hWnd;
hWnd
=
CreateWindow(
"
WinFill
"
,
//
类名
"
填充示例
"
,
//
标题
WS_SYSMENU,
//
窗口风格
0
,
0
,
//
窗口左上角坐标
CW_USEDEFAULT, CW_USEDEFAULT,
//
窗口宽高
NULL, NULL,
hInst,
NULL);
if
(
!
hWnd)
{
return
FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return
TRUE;
}
BOOL InitWindowClass(HINSTANCE hInst)
{
WNDCLASS wndClass;
wndClass.cbClsExtra
=
0
;
wndClass.cbWndExtra
=
0
;
wndClass.hbrBackground
=
(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor
=
LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon
=
LoadIcon(NULL,
"
END
"
);
wndClass.hInstance
=
hInst;
wndClass.lpfnWndProc
=
WndProc;
wndClass.lpszClassName
=
"
WinFill
"
;
wndClass.lpszMenuName
=
"
NULL
"
;
wndClass.style
=
CS_HREDRAW
|
CS_VREDRAW;
return
RegisterClass(
&
wndClass);
}
int
APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int
nCmdShow)
{
MSG msg;
if
(
!
InitWindowClass(hInstance))
{
return
FALSE;
}
if
(
!
InitWindow(hInstance, nCmdShow))
{
return
FALSE;
}
while
(GetMessage(
&
msg,
0
,
0
,
0
))
{
TranslateMessage(
&
msg);
DispatchMessage(
&
msg);
}
return
msg.wParam;
}
|