Win32知識之窗口本質
一丶摘要
在學習Win32的時候. 很多操作都是窗口進行操作的.那么今天就說一下窗口的本質是什么.
窗口的本質是不斷繪制.是windows通過消息機制進行繪制的.
我們知道.內存分為高低2G 低2G是給應用程序使用的. 高2G是給操作系統使用的.而我們畫圖形的操作都是操作系統通過底層的 win32k.sys這個驅動來提供的.
進程跟線程管理是通過notokerner.exe這個程序來管理的.但是三環不能使用.所以提供接口給三環. 分別是kerner32.dll 跟user32.dll gdi.dll
那么他們之間的區別是什么.
1.kerner32.dll 管理進程線程跟內存的一個dll
2.user32.dll 窗口管理.圖形界面管理.
3.gdi.dll 自己繪制的的管理.
而我們要認識一下窗口的創建.那么需要了解幾個基礎的只是.
1.設備對象.
2.DC設備上下文.
3.圖形對象.
1.設備對象是什么.
簡而言之設備對象的意思就是你要畫圖形要往哪里畫. 每一個窗口都有一個窗口句柄.而且是存放在全局窗口句柄表中的. 我們可以獲取一下.使用Spy++獲取.
2.DC設備上下文.
DC設備上下文其實就是這個窗口有一塊內存是繪制用的. 我們想要往這個窗口繪制.需要先繪制到這個內存中才可以.這塊內存就稱為DC上下文.
3.圖形對象.
圖形對象就是指畫筆 畫刷 位圖. 等等這些對象.因為我們要往內存中畫的時候.可以畫默認的.但是一般我們想改變一下形式.所以創建圖形對象跟DC相關聯.那么我們繪制就可以使用圖形對象了.
二丶繪制窗口步驟
繪制窗口免不了使用API.但是使用之前.需要知道我們要操作的步驟.
1.獲取窗口句柄.也就是設備對象.
2.獲取窗口中的DC上下文.可以理解為獲取指定窗口的繪圖的那塊內存.
3.創建圖形對象. 要想繪制.那么首先就需要你自定義的一個繪制的東西才可以.
4.關聯圖形對象跟DC. 只要關聯了.那么繪制的時候自動就使用你的圖形對象了.
5.進行你的繪圖操作. 這里就是你寫的繪圖代碼了.
6.釋放資源. 不管是窗口句柄也好. DC也好.圖形對象也好.都是內核對象.所以我們需要進行釋放.
具體API:
1.獲取指定窗口句柄. FindWindowA/FindWindowW
HWND FindWindowA( LPCSTR lpClassName, 窗口類名.字符串. 可以用Spy++獲取 LPCSTR lpWindowName 窗口名稱 ); 返回窗口句柄.
2.獲取DC設備上下文. GetDc()
HDC GetDC(
HWND hWnd 傳入設備對象.也就是窗口句柄
);
3.創建圖形對象.
PS: 創建圖形對象.圖形對象有很多. 有畫筆. 畫刷. 等等.
HPEN CreatePen( int iStyle, 創建筆的風格, 意思就是你的畫筆是實心的 還是虛線 還是其他. int cWidth, 筆的寬度.如果實心的.筆的寬度則自定義設置.如果其他.不能超過1 COLORREF color RGB的顏色. 你的畫筆是什么顏色的.是一串16進制可以在線取色 ); 返回圖形對象
還有常用的.創建矩形區域.
HRGN CreateRectRgn( int x1, int y1, 坐標 int x2, int y2 );
具體使用可以查詢MSDN: https://docs.microsoft.com/zh-cn/windows/desktop/gdi/windows-gdi 代碼使用例子
如果你安裝了MSDN 2001版本.搜索SelectObject可以看到. 圖形對象有很多.並且告訴你相應的API
Bitmap 位圖. 后面是操作的API
Brush 畫刷
字體
筆
矩形
4.關聯DC跟圖形對象.
HGDIOBJ SelectObject( HDC hdc, // handle to DC HGDIOBJ hgdiobj // handle to object);
5.寫你想要繪制的代碼.
這里如果是畫線. 則用 LineTo(Hdc,x,y) 這個API 給定一個DC.給個x y坐標.則可以繪制.
當然如果指定在哪里開始繪制則用MoveToEx指定起始位置.
BOOL MoveToEx( HDC hdc, int x, int y, LPPOINT lppt );
6.釋放資源.
釋放資源很簡單了. 如果是圖形對象.同一使用DeleteObject(對象) 進行刪除.
如果是DC. 如果是創建的Dc.則用DeleteDc(DC對象)來進行刪除.
如果是獲取的DC.則用ReleaseDc(Dc對象) 來進行刪除.
題外話. windows程序中還有一個API.可以獲取DC中默認的圖形對象.
HGDIOBJ GetStockObject( int i 對象的類型.你想從DC中獲取什么對象類型. );
圖像類型如果是 DC_BRUSH 則是獲取純色刷.就不用自己創建色刷了.可以通過操作色刷的API進行操作.
COLORREF SetDCBrushColor(
HDC hdc,
COLORREF color RGB顏色
);
三丶繪制圖形.
1.繪制直線的代碼例子.
#include "stdafx.h" #include <Windows.h> int main(int argc, char *argv[]) { //1.獲取窗口句柄 HWND hwnd = ::FindWindow(NULL, TEXT("計算器")); //2.獲取DC. HDC hdc = ::GetDC(hwnd); //3.創建圖形對象. HPEN hPen = CreatePen(PS_SOLID, 10, RGB(0xFF, 0, 0)); //設置為紅色畫筆 //4.關聯圖形對象跟DC HPEN oldPen = (HPEN)::SelectObject(hdc, hPen); //返回舊的畫筆 //5.繪制直線. MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, 600, 100); //6.釋放資源. ::SelectObject(hdc, oldPen); //首先還原舊畫筆 DeleteObject(hPen); //刪除圖形對象. ReleaseDC(hwnd,hdc); //釋放Dc system("pause"); return 0; }
運行之后圖片.注意不要遮擋計算器.
2.繪制矩形.獲取默認畫刷.設置畫刷區域顏色.
繪制代碼
#include "stdafx.h" #include <Windows.h> int main(int argc, char *argv[]) { //1.獲取窗口句柄 HWND hwnd = ::FindWindow(NULL, TEXT("計算器")); //2.獲取DC. HDC hdc = ::GetDC(hwnd); //3.創建圖形對象. HPEN hPen = CreatePen(PS_SOLID, 10, RGB(0xFF, 0, 0)); //設置為紅色畫筆 HBRUSH hBru = (HBRUSH)::GetStockObject(DC_BRUSH); //4.關聯圖形對象跟DC HPEN oldPen = (HPEN)::SelectObject(hdc, hPen); //返回舊的畫筆 SetDCBrushColor(hdc, RGB(0, 0xFF, 0)); //設置畫刷顏色 HBRUSH oldBrush = (HBRUSH)::SelectObject(hdc, hBru); //5.繪制句柄 Rectangle(hdc, 0, 0, 100, 100); //6.釋放資源. ::SelectObject(hdc, oldPen); //首先還原舊畫筆 DeleteObject(hPen); //刪除圖形對象. ReleaseDC(hwnd,hdc); //釋放Dc system("pause"); return 0; }
其中新用到的API就是繪制矩形的API.
繪制完畢結果