GDI(Graphics Device Interface)是圖形設(shè)備接口的英文縮寫,主要任務(wù)是負(fù)責(zé)系統(tǒng)與繪圖程序之間的信息交換,處理所有Windows程序的圖形和圖像輸出。GDI的出現(xiàn)使程序員無(wú)需要關(guān)心硬件設(shè)備及設(shè)備正常驅(qū)動(dòng),就可以將應(yīng)用程序的輸出轉(zhuǎn)化為硬件設(shè)備上的輸出和構(gòu)成,實(shí)現(xiàn)了程序開發(fā)者與硬件設(shè)備的隔離,大大方便了開發(fā)工作。
- 消息反射
windows的消息反射機(jī)制,通過(guò)控件之間的消息反射,用來(lái)實(shí)現(xiàn)較為復(fù)雜的多控件之間的交互問(wèn)題.
在vs2019中,我們可以通過(guò)類向?qū)?來(lái)為控件指定對(duì)應(yīng)的消息反射,在類向?qū)е?反射型的消息和單獨(dú)的消息已經(jīng)區(qū)分開了,反射性質(zhì)的叫做命令,普通的消息叫為消息:

當(dāng)然,具體的消息類別,我們可以在逐漸的熟悉使用的過(guò)程中,來(lái)慢慢了解和學(xué)習(xí).
- 成員變量

在類向?qū)е型瑯涌梢栽O(shè)置虛函數(shù),成員變量等其他功能,虛函數(shù)還不甚了解,這里簡(jiǎn)單記錄下使用到的成員變量,通過(guò)類向?qū)?lái)為各個(gè)控件設(shè)置成員變量主要是快速便捷.
不過(guò)比較特殊的是,MFC中有重新封裝控件類型,和值類型.當(dāng)然,在大多時(shí)候,MFC封裝的類型是更加好用的.但是有時(shí)候還是不太適應(yīng).

- 三大坐標(biāo)系
基于MFC的窗口應(yīng)用程序有三大基本坐標(biāo)系:基于客戶區(qū),非客戶區(qū),屏幕.都是以左上角為坐標(biāo)原點(diǎn):

- 通過(guò)空項(xiàng)目來(lái)構(gòu)建從頭構(gòu)建窗口項(xiàng)目
GDI(Graphics Device Interface)是圖形設(shè)備接口的英文縮寫,主要任務(wù)是負(fù)責(zé)系統(tǒng)與繪圖程序之間的信息交換,處理所有Windows程序的圖形和圖像輸出。GDI的出現(xiàn)使程序員無(wú)需要關(guān)心硬件設(shè)備及設(shè)備正常驅(qū)動(dòng),就可以將應(yīng)用程序的輸出轉(zhuǎn)化為硬件設(shè)備上的輸出和構(gòu)成,實(shí)現(xiàn)了程序開發(fā)者與硬件設(shè)備的隔離,大大方便了開發(fā)工作。
在vs2019中創(chuàng)建一個(gè)空項(xiàng)目

創(chuàng)建一個(gè)test_gdi.cpp文件,再添加一個(gè)dialog資源:



進(jìn)入資源屬性界面,更改一下dialog的id: IDD_MAIN_DLG,設(shè)定為主窗口,在之后更改caption 改一下窗口的標(biāo)題為test_GDI,設(shè)定后記得保存一下,查看頭文件resource.h中有沒(méi)有id的聲明:


注意這里一定要有控件id的聲明,否則cpp文件中是無(wú)法識(shí)別的.
再進(jìn)入cpp文件中定義WinMain主函數(shù)(WinMain函數(shù)是windows窗口程序的入口函數(shù),main函數(shù)在windows應(yīng)用程序中是無(wú)法使用的),引入windows.h頭文件和我們的resource,h資源頭文件,記住四個(gè)主要的參數(shù):
#include<Windows.h>
#include"resource.h"
INT_PTR CALLBACK theProc(
HWND hwnDlg,
UINT Msg,
WPARAM wPream,
LPARAM ipream) {
return 0;
}
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPTSTR sCmdLine,int nCmd) {
DialogBox(hInst, (LPCSTR)IDD_MAIN_DLG, NULL, theProc);
return 0;
}
調(diào)試運(yùn)行,在vs2019中,創(chuàng)建的空項(xiàng)目是不能直接運(yùn)行窗口程序的,會(huì)報(bào)錯(cuò):

這主要是因?yàn)関s2019中空項(xiàng)目默認(rèn)的編譯是控制臺(tái)程序,我們將項(xiàng)目屬性中鏈接器->系統(tǒng)->子系統(tǒng)中的subsystem: console修改為windows.

再次編譯運(yùn)行,輸出窗口:

WM_PAINT消息 :功能和發(fā)生時(shí)間,
beginPaint與EndPaint必須成對(duì)使用.
BeginPaint返回的DC句柄,是基于其所關(guān)聯(lián)的窗口的客戶區(qū)坐標(biāo)系繪制圖形的.
在MFC中是把這兩個(gè)函數(shù)封裝為一個(gè)類:CPaintDC類的.
MFC第二大類 CDC繪圖類.
CDC類的核心句柄就是m_hdDC.它的繪圖功能基本都是來(lái)自m_hDC句柄原有的功能.封裝而成.
派生類有:
CPaint類,客戶區(qū)標(biāo)準(zhǔn)繪圖類,專門提供給WM_PAINT消息提供的.
CClientDC類,客戶區(qū)臨時(shí)繪圖類.在任何其他消息中都可以使用的.
CWindowDC類: 非客戶區(qū)標(biāo)準(zhǔn)繪圖類,專門在WM_NC_PAINT消息下使用(不常使用,基本不會(huì)有使用到在非客戶區(qū)進(jìn)行繪制圖像的使用場(chǎng)景).
要想在客戶區(qū)進(jìn)行標(biāo)準(zhǔn)繪圖,首先要在回調(diào)函數(shù) theProc中聲明一個(gè)switch結(jié)構(gòu),來(lái)對(duì)各種不同類消息進(jìn)行不同的處理:
// 窗口句柄參數(shù):HWND hwnDlg, UINT 消息類型參數(shù).
INT_PTR CALLBACK theProc(HWND hwnDlg,UINT uMsg,WPARAM wPream,LPARAM ipream) {
switch (uMsg)
{
// WM_NCPAINT消息是一個(gè)非客戶區(qū)的一個(gè)繪制消息.
case WM_NCPAINT:
OnNCPaint(hwnDlg);
return TRUE;
// 繪圖非常重要的一個(gè)消息,WM_PAINT消息,在客戶區(qū)內(nèi)繪制:
case WM_PAINT:
// 調(diào)用函數(shù)
OnPaint(hwnDlg);
return TRUE;
case WM_COMMAND:
if (wPream == IDCANCEL) {
EndDialog(hwnDlg, IDCANCEL);
return TRUE;
}
return FALSE;
default:
break;
}
return 0;
}
在switch結(jié)構(gòu)中對(duì)應(yīng)的消息支路上,調(diào)用對(duì)應(yīng)的繪制函數(shù),即可完成簡(jiǎn)單的繪制工作任務(wù):
//定義一個(gè)OnPint函數(shù),傳入一個(gè)句柄參數(shù),在MFC中將窗口句柄都封裝到類中了:
void OnPaint(HWND hwndDlg) {
// 相當(dāng)于beginpaint
PAINTSTRUCT ps;
// HDC是一個(gè)繪圖句柄,相當(dāng)于指定繪制圖形的窗口的作用.
HDC hdc = BeginPaint(hwndDlg, &ps);
// 在beginpaint與endpaint之間就可以進(jìn)行繪圖操作了,可以調(diào)用各種封裝好的繪制函數(shù)來(lái)實(shí)現(xiàn)繪制各種東西的.
/*
橢圓繪制函數(shù),五個(gè)參數(shù),第一個(gè)是繪圖句柄hdc類型的參數(shù),指定繪制的窗口,
其余四個(gè)int變量指定位置和橢圓的高度和寬度,也可以用來(lái)繪制圓形.
WM_PAINT消息繪制是基于客戶區(qū)繪制的.
*/
// textout方法,繪制文本
LPCSTR str = _T("text 測(cè)試消息");
TextOut(hdc,100,100,str,strlen(str));
Ellipse(hdc, 0, 0,100,100);
// 結(jié)束的位置 endpaint 與beginpaint必須得成對(duì)使用才行
EndPaint(hwndDlg,&ps);
// 提供的一個(gè)控制臺(tái)輸出函數(shù),相當(dāng)于printf
OutputDebugString(_T("WM_PAINT_onpaint \n"));
}

WM_NCPAINT 消息是非客戶區(qū)的標(biāo)準(zhǔn)繪圖消息.可以通過(guò)該消息來(lái)實(shí)現(xiàn)在非窗口區(qū)的繪制(但是該方法一般不常使用).
void OnNCPaint(HWND hwndDlg) {
// 獲取坐標(biāo)系,相當(dāng)于屏幕.
RECT rect;
GetWindowRect(hwndDlg,&rect);
// 獲取一個(gè)窗口的HDC句柄對(duì)象.
HDC hdc = GetWindowDC(hwndDlg); // CWindwDC在MFC中封裝了getWindDC函數(shù)
// 繪制矩形
Rectangle(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
// 在兩個(gè)函數(shù)之間就可以執(zhí)行一些繪圖,或者文字輸出的功能了
LPCTSTR str =_T("testNCPaint消息");
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc, 2, 2,str,strlen(str));
ReleaseDC(hwndDlg,hdc); //反函數(shù)是releaseDC,將hdc與窗口連接
}

2019.12.20
8.42