目錄
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 鏈接):

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);
運行結果:
程序源碼

#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繪圖函數中
獲得設備資源描述表實現步驟