首頁 >運維 >windows維 >Win32 SDK基礎(五)之關於視窗類別的簡單介紹

Win32 SDK基礎(五)之關於視窗類別的簡單介紹

黄舟
黄舟原創
2017-06-06 09:42:552585瀏覽

一、引言

        在上一文中,我們從零開始建立了一個視窗。其中很重要的一個步驟,就是註冊視窗類,如下面的程式碼:

//注册窗口类
BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
{
    WNDCLASSEX wce = { 0 };
    wce.cbSize = sizeof(wce);
    wce.cbClsExtra = 0;
    wce.cbWndExtra = 0;
    wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wce.hCursor = NULL;
    wce.hIcon = NULL;
    wce.hIconSm = NULL;
    wce.hInstance = g_hInstance;
    wce.lpfnWndProc = wndProc;
    wce.lpszClassName = lpClassName;
    wce.lpszMenuName = NULL;
    wce.style = CS_HREDRAW | CS_VREDRAW;
    ATOM nAtom = RegisterClassEx(&wce);
    if (nAtom == 0)
        return FALSE;
    return true;
}

        Windows下的任何一個視窗,在創建之前都要在系統中已經明確的註冊,我們在使用CreateWindowEx進行視窗的建立時,第二個參數的名稱就是視窗類別名稱,這個名稱在我們程式碼可見的作用域內應該是唯一的。本文主要討論下Windows下,視窗類別的問題。

二、視窗類別分類

        Windows中所有可見的一切元素基本上都屬於一個視窗,不管它的形狀如何,是圓的、方的、甚至是無規則的。所有的這些視窗都屬於某一個視窗類,大體上來說Windows的視窗類共分為三種:
(1)系統視窗類別
(2)全域視窗類別
(3)局部視窗類別
下面,我將分別就Windows中視窗類別的分類進行討論。

2.1 系統視窗類別

        一個按鈕、一個編輯框所有這些我們在windows作業系統中可見的控制項其實都是一個視窗。當我們安裝完作業系統之後,Windows會在作業系統內部註冊大量的系統層級的視窗類,我們在進行開發時,可以直接根據視窗類名稱建立這些視窗。為了解釋這個問題,在上一文的程式碼之上,我們引入下面的程式碼。

HWND CreateMain(LPSTR lpClassName, LPSTR lpWndName)
{
	HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName,
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL);
	return hWnd;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	// TODO: Place code here.

	g_hInstance = hInstance;
	
	HWND hWnd = CreateMain("Button", "window");
	Display(hWnd);
	Message();
	return 0;
}

        CreateMain是我們定義的一個建立視窗的函數。它接收兩個參數,第一個時已經註冊的視窗類別名稱,第二個是視窗的標題。與上一文中的程式碼不同,我們省去了註冊自訂視窗的步驟。而是在WinMain函數中,呼叫CreateMain建立了一個視窗類別名稱為「Button」的視窗。我想你已經知道我們要做什麼了吧?對,就是要產生一個Button按鈕。我們常用的所有控制項都已經被作業系統註冊成了系統視窗類,我們都可以直接使用。請看下面的程式運行結果:



        你也可以嘗試建立諸如編輯框、下拉框等其他系統層級的視窗。

2.2 全域視窗類別

        全域視窗類別指註冊後可在應用程式全域範圍內使用的視窗類別。例如,我們可以在dll中對全域視窗類別進行註冊,那麼引入該dll的所有程式都可以使用該類別。註冊全域使用的視窗類別時,我們只需要在註冊時對wec的結構體的style成員加入CS_GLOBALCLASS屬性,如下:

	wce.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;

        為了驗證這個問題,我們新新增一個dll項目,然後定義一個如下的視窗註冊函數RegisterWindow():

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage返回0
		break;
	default:
		break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

 BOOL RegisterWindow()
{
	WNDCLASSEX wce = { 0 };
	wce.cbSize = sizeof(wce);
	wce.cbClsExtra = 0;
	wce.cbWndExtra = 0;
	wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wce.hCursor = NULL;
	wce.hIcon = NULL;
	wce.hIconSm = NULL;
	wce.hInstance = NULL;
	wce.lpfnWndProc = WndProc;
	wce.lpszClassName = "DllMain";
	wce.lpszMenuName = NULL;
	wce.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
	ATOM nAtom = RegisterClassEx(&wce);
	if (nAtom == 0)
		return FALSE;
	return true;
}

        RegisterWindow()中註冊的視窗類別名稱為"DllMain",我們在dll的主函數中呼叫該註冊函數完成註冊:

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	....
	RegisterWindow();
	return TRUE;
}
}

        在我們的主程式中使用此視窗類別建立視窗:

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	...
	HWND hWnd = CreateMain("DllMain", "我是一个Dll注册的窗口");
	Display(hWnd);
	Message();
	return 0;
}

        執行程式你會發現我們也成功生產了這個視窗:



2.3 局部視窗類別

        局部視窗類別從定義上來說,凡是未在wce的style中加入CS_GLOBALCLASS,而註冊的視窗類別都是局部視窗類。

#
wce.style = CS_HREDRAW | CS_VREDRAW;//未添加CS_GLOBALCLASS

       我们在上一文中注册的窗口就是一个局部的窗口类,它的特点就是只能在注册的作用域内使用,由于它和全局窗口类只在注册的style和作用域上有分别,这里就不再详述,如要了解,请参照上一文。

以上是Win32 SDK基礎(五)之關於視窗類別的簡單介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn