Windows
圖形設(shè)備接口(
Graphics Device Interface, GDI
)是為與設(shè)備無關(guān)的圖形設(shè)計(jì)的,由操作系統(tǒng)屏蔽了硬件設(shè)備的差異,簡化了程序員的程序編寫工作。
?
???????????
設(shè)備上下文(
Device Context, DC
)
定義了一系列圖形對象及其屬性的結(jié)構(gòu),包括圖形模式及輸出。
PS
:
DC
一詞的翻譯上有些疑惑,不明白為什么這么叫。
context:
背景,環(huán)境,上下文
目前設(shè)備上下文有四種類型:顯示,打印,存儲和消息類型。
圖形對象及其屬性:
位圖,畫刷,調(diào)色板,字體,畫筆,區(qū)域
應(yīng)用程序每一次圖形操作均參照設(shè)備
上下文
中的屬性執(zhí)行,
DC
可以看作是圖形的“輸出模板”。
?
???????????
圖形刷新
Windows
應(yīng)用程序在使用過程中,窗口大小的調(diào)整,窗口移動或者被其它窗口覆蓋后,都必須要刷新原窗口內(nèi)用戶區(qū)顯示的內(nèi)容。但是
windows
系統(tǒng)只能在有限的幾種情況下自動刷新。因此應(yīng)用程序必須具有及時(shí)處理刷新請求和刷新響應(yīng)的功能。
Windows
系統(tǒng)通常通過發(fā)送
WM_PAINT
消息將刷新請求傳遞給應(yīng)用程序。一般情況下,刷新有三種可能:
(1)?????
窗口移動后的刷新
用戶區(qū)移動,窗口大小改變,滾動條的使用等
(2)?????
被覆蓋區(qū)域的刷新
下拉式菜單關(guān)閉后需恢復(fù)被覆蓋部分,清除消息框后進(jìn)行的恢復(fù)等
(3)?????
對象穿越后的刷新
光標(biāo)穿過用戶區(qū),圖標(biāo)拖過用戶區(qū)等
Windows
系統(tǒng)為每個窗口建立了一個
PAINTSTRUCT
結(jié)構(gòu),該結(jié)構(gòu)中包含了指明一個窗口被另一個窗口覆蓋的“無效區(qū)域”的最小矩形結(jié)構(gòu)
RECT
,程序可根據(jù)這個矩形進(jìn)行刷新。
常用刷新方法包括:
(1)?????
保持一個顯示輸出副本,需要時(shí)重繪窗口
(2)?????
記錄發(fā)生的事件,需要時(shí)重新調(diào)用該事件
(3)?????
重新繪圖,簡單圖形常用的方法
?
???????????
獲取設(shè)備
上下文
獲取設(shè)備
上下文
是應(yīng)用程序輸出圖形的先決條件,常用函數(shù)有:
BeginPaint?????
響應(yīng)
WM_PAINT
消息進(jìn)行圖形刷新
GetDC??????????
非
WM_PAINT
消息驅(qū)動時(shí)用于獲取設(shè)備
上下文
GetDCEx???????
返回指向特定窗口客戶區(qū)的整個窗口句柄,是
GetDC
的擴(kuò)展
???????????
繪圖工具與顏色
1.????????
畫筆
&
畫刷
畫筆的功能是用來畫直線和曲線,畫刷用于指定區(qū)域的填充
可以使用
CreatePen
和
CreateBrush
創(chuàng)建自定義畫筆畫刷,也或以使用
GetStockObject
函數(shù)獲取系統(tǒng)默認(rèn)的樣式。
HPEN hPen = CreatePen
(
?????? int nPenStyle,
?????? int nWidth,
?????? COLORREF rgbColor
);
????????????? HBRUSH hBrush = CreateBrush
??????????????????????????? (
?????????????????????????????????? int nHatchStyle,
?????????????????????????????????? COLORREF rgbColor
)
?????????????
畫筆畫刷不再使用時(shí)應(yīng)使用
DeleteObject
函數(shù)刪除并釋放資源
2.????????
顏色
winodws
使用宏
RGB
定義繪圖顏色
????????? RGB(nRed, nGreen, nBlue)
其中
nRed, nGreen, nBlue
分別表示紅,綠,藍(lán)的數(shù)值。
3.????????
常用繪圖函數(shù)
(1)?????
BOOL ??? MoveToEx
{
HDC hdc,
int x, int y,
LPPOINT lpPoint?? //
存放原畫筆位置的
POINT
結(jié)構(gòu)
}
(2)?????
BOOL LineTo
{
HDC hdc,
int x, int y
}
(3)?????
BOOL Rectangle
{
HDC hdc,
int x1, int y1,???????? //
矩形左上角邏輯坐標(biāo)
int x2, int y2????????? //
矩形右下角邏輯坐標(biāo)
}
(4)?????
BOOL Polygon
{
HDC hdc,
LPPOINT lpPoints,????????????? //
包含各頂點(diǎn)坐標(biāo)的
POINT
數(shù)組
int nCount??????????????????? //
多邊形頂點(diǎn)個數(shù)
}
?
?
???????????
應(yīng)用實(shí)例
–
簡單的圖形繪制
#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;
//
定義繪圖信息結(jié)構(gòu)體
???????
switch
(iMsg)


???????
{

???????
case
?WM_PAINT:
//
處理繪圖信息
??????????????hDC?
=
?BeginPaint(hWnd,?
&
ptStr);
//
獲取設(shè)備上下文
??????????????SetMapMode(hDC,?MM_TEXT);
//
設(shè)置映射模式
?

??????????????hPen?
=
?(HPEN)GetStockObject(BLACK_PEN);
//
獲取默認(rèn)黑色畫筆
??????????????SelectObject(hDC,?hPen);
//
將畫筆選入
設(shè)備上下文
??????????????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
);

?

??????????????
//
坐標(biāo)系
??????????????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);
//
結(jié)束繪圖
??????????????
return
?
0
;

???????
case
?WM_DESTROY:

??????????????PostQuitMessage(
0
);

??????????????
return
?
0
;

???????
default
:
//
其它消息的默認(rèn)處理函數(shù)
??????????????
return
?(DefWindowProc(hWnd,?iMsg,?wParam,?lParam));

???????}
}
?

//
對窗口進(jìn)行初始化
BOOL?InitWindow(HINSTANCE?hInst,?
int
?nCmdShow)


{

???????HWND?hWnd;

???????hWnd?
=
?CreateWindow(
"
WinFill
"
,?
//
類名
??????????????????????????????????????????
"
填充示例
"
,????
//
標(biāo)題
??????????????????????????????????????????WS_SYSMENU,????
//
窗口風(fēng)格
??????????????????????????????????????????
0
,?
0
,?
//
窗口左上角坐標(biāo)
??????????????????????????????????????????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;

}