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;

}