Win32編程:是調用Win32SDK中的API函數進行編程,注冊窗口類,建立窗口,現實窗口,設置消息循環……等等的方式建立Windows程序,以前的Windows程序都這樣開發的,寫程序要寫大量代碼。
MFC庫:後來微軟為了方便編程人員開發,將Win32SDK中的函數進行C/C++封裝,於是就是MFC庫(架構),開發程序比以往的Win32SDK方式更加簡便快捷。
相同:調用的API都是Win32SDK的API
不同:MFC的程序執行起來慢,而且用MFC寫程序不自由
Win32SDK開發速度慢,而且要編寫的代碼多得驚人
一般在Win32下編程,簡單的步驟是:
(1)設計窗口類
(2) 注冊窗口類
(3)Create窗口
(4)顯示窗口
(5)更新窗口
(6)消息循環(關鍵)
我們用Visual Studio創建一個win32項目上會自動生成一個注冊窗口類。如下:
1 ATOM MyRegisterClass(HINSTANCE hInstance) 2 { 3 WNDCLASSEX wcex; 4 5 wcex.cbSize = sizeof(WNDCLASSEX); // UINT cbSize 6 7 wcex.style = CS_HREDRAW | CS_VREDRAW; // UINT style 8 wcex.lpfnWndProc = WndProc; // WNDPROC lpfnWndProc 9 wcex.cbClsExtra = 0; // int cbClsExtra 10 wcex.cbWndExtra = 0; // int cbWndExtra 11 wcex.hInstance = hInstance; // HINSTANCE hInstance 12 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT5)); // HICON hIcon 13 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // HCURSOR hCursor 14 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // HBRUSH hbrBackground 15 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32PROJECT5); // LPCTSTR lpszMenuName 16 wcex.lpszClassName = szWindowClass; // LPCTSTR lpszClassName 17 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); // HICON hIconSm 18 19 return RegisterClassEx(&wcex); 20 }
WNDCLASSEX結構體中:
cbSize:存儲表示該結構大小的字節數,通常以sizeof(WNDCLASSEX)的形式對該域進行設置
style :存儲表示窗口類風格的整數,它決定了該窗口的外觀和內在特征。
lpfnWndProc:指向窗口處理函數(回調函數)。
cbClsExtra :為窗口類的額外信息做記錄,初始化為0。
cbWndExtra :記錄窗口實例的額外信息,系統初始為0
hIcon :存儲該類窗口的圖標的句柄
hCursor:存貯表示窗口類光標的句柄,該域必須是一個光標資源的句柄。
hbrBackground:窗口類的背景刷,為背景刷句柄,也可以為系統顏色值,如果顏色值已給出,則必須轉化為以下的HBRUSH的值
lpszMenuName:存儲以空結尾的指定類菜單資源名的字符串指針,類菜單資源名已經在資源文件中進行了定義。
lpszClassName:存儲以空結尾的字符串的指針,或存儲一個原子元素(ATOM)。
hIConSm:存儲該類窗口小圖標的句柄。
MFC下編程,省去了窗口設計步驟,直接通過GetClassInfo()來獲取標准窗口的信息。
MFC中,#32770 代表標准窗口類。
BOOL CBBBApp::SetRegisterClass() { WNDCLASS wndcls; ZeroMemory(&wndcls, sizeof(WNDCLASS)); // start with NULL HINSTANCE hInst; hInst = AfxGetInstanceHandle(); ASSERT(hInst != 0);
GetClassInfo(hInst, _T("#32770"), &wndcls); wndcls.lpszClassName = _T("YourClassName"); if (FALSE == AfxRegisterClass(&wndcls)) { AfxThrowResourceException(); return FALSE; } return TRUE; }
1)AfxGetInstanceHandle
作用:獲取當前實例句柄
原型:HINSTANCE AFXAPI AfxGetInstanceHandle( );
返回值:返回應用程序當前實例的句柄。如果是從與MFC的USRDLL版本連接的DLL內調用的,則返回代表DLL的HINSTANCE值
2)GetClassInfo
作用:獲得窗體類信息
原型:
BOOL GetClassInfo(
HINSTANCE hInstance,
LPCTSTR lpClassName,
LPWNDCLASS lpWndClass
);
參數:hInstance,創建類的應用程序實例
lpClassName,類名
lpWndClass,指向WNDCLASS結構體的指針
返回值:返回非零成功,返回零不成功
3)AfxRegisterClass
作用:注冊類
原型:BOOL AFXAPI AfxRegisterClass( WNDCLASS* lpWndClass );
參數:指向WNDCLASS結構體的指針
返回值:若類成功注冊則返回零,否則非零。
4)AfxThrowResourceException
這個函數拋出一個資源異常。通常在不能載入Windows資源的時候調用這個函數。
1)注冊窗口類以後同一類窗口都用一套WindowProc。有統一的行為
在我們構造一個窗口類結構後,我們需要將這個類結構指針加入到system atom table 即SAT中,這樣系統就可以通過查找這張表來找到用戶自定義的窗口類
2)注冊好窗口類之後就可以用FindWindow函數來找到這個窗口類並獲得其句柄,然後即可以向該窗口發送消息。
HWND hComm = ::FindWindow(_T("YourClassName"), NULL); if (NULL == hComm) return FALSE;
if (hComm && ::IsWindow(hComm)) { DWORD dwResult = 0; LRESULT lResult = ::SendMessageTimeout(hComm, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 500, &dwResult); }
1)FindWindow
作用:該函數獲得一個頂層窗口的句柄,該窗口的類名和窗口名與給定的字符串相匹配。
原型:
HWND FindWindow( LPCSTR lpClassName, // {即窗口的類名} LPCSTR lpWindowName // {即窗口的標題} 如果此參數為NULL,則匹配所有窗口名。 ); 返回值: 如果函數執行成功,則返回值是擁有指定窗口類名或窗口名的窗口的句柄。 如果函數執行失敗,則返回值為 NULL 2)FindWindowEX //FindWindowEx 比 FindWindow 多出兩個句柄參數:2)SendMessageTimeout
作用:該函數將指定的消息發送到一個或多個窗口。
原型:
LRESULT SendMessageTimeout( HWND hwnd, // 其窗口程序將接收消息的窗口的句柄。 // 如果此參數為HWND_BROADCAST,則消息將被發送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口。 UINT Msg, // 指定被發送的消息 WPARAM wParam,// 指定附加的消息指定信息。 LPARAM IParam, // 指定附加的消息指定信息。 UINT fuFlags, // 指定如何發送消息。 // SMTO_ABORTIFHUNG:如果接收進程處於“hung”狀態,不等待超時周期結束就返回。 // SMTO_BLOCK:阻止調用線程處理其他任何請求,直到函數返回。 // SMTO_NORMAL:調用線程等待函數返回時,不被阻止處理其他請求。 // SMTO_NOTIMEOUTIFNOTHUNG:Windows 95及更高版本:如果接收線程沒被掛起,當超時周期結束時不返回。 UIUT uTimeout, // 為超時周期指定以毫秒為單位的持續時間。如果GetLastError返回零,表明函數超時 LPDWORD lpdwResultult // 指定消息處理的結果,依賴於所發送的消息 );返回值:若函數調用成功則返回非零值,若失敗或超時返回零。