使用視窗程式
本節說明如何執行與視窗程式相關聯的下列工作。
設計視窗程式
下列範例顯示一般視窗程式的結構。 視窗程式會使用 switch 語句中的 message 引數,以及個別 案例 語句所處理的個別訊息。 請注意,每個案例都會傳回每個訊息的特定值。 對於未處理的訊息,視窗過程會呼叫 DefWindowProc 函式。
LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
switch (uMsg)
{
case WM_CREATE:
// Initialize the window.
return 0;
case WM_PAINT:
// Paint the window's client area.
return 0;
case WM_SIZE:
// Set the size and position of the window.
return 0;
case WM_DESTROY:
// Clean up window-specific data objects.
return 0;
//
// Process other messages.
//
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
WM_NCCREATE訊息會在建立視窗之後傳送,但如果應用程式傳回FALSE來回應此訊息,CreateWindowEx函式就會失敗。 建立視窗之後,就會傳送 WM_CREATE 訊息。
當視窗即將終結時,就會傳送 WM_DESTROY 訊息。 DestroyWindow函式會負責終結視窗的任何子視窗。 WM_NCDESTROY訊息會在視窗終結之前傳送。
至少,視窗程式應該處理 WM_PAINT 訊息以繪製本身。 一般而言,它也應該處理滑鼠和鍵盤訊息。 請參閱個別訊息的描述,以判斷您的視窗程式是否應該處理這些訊息。
您的應用程式可以在處理訊息時呼叫 DefWindowProc 函式。 在這種情況下,應用程式可以在將訊息傳遞至 DefWindowProc之前修改訊息參數,也可以在執行自己的作業之後繼續進行預設處理。
對話方塊程式會接收 WM_INITDIALOG 訊息,而不是 WM_CREATE 訊息,而且不會將未處理的訊息傳遞至 DefDlgProc 函式。 否則,對話方塊程式與視窗程式完全相同。
將視窗程式與視窗類別產生關聯
註冊類別時,您會將視窗程式與視窗類別產生關聯。 您必須使用 類別的相關資訊填入 WNDCLASS 結構, 而 lpfnWndProc 成員必須指定視窗程式的位址。 若要註冊 類別,請將 WNDCLASS 結構的位址傳遞至 RegisterClass 函式。 註冊視窗類別之後,視窗程式會自動與使用該類別建立的每個新視窗相關聯。
下列範例示範如何將上一個範例中的視窗程式與視窗類別產生關聯。
int APIENTRY WinMain(
HINSTANCE hinstance, // handle to current instance
HINSTANCE hinstPrev, // handle to previous instance
LPSTR lpCmdLine, // address of command-line string
int nCmdShow) // show-window type
{
WNDCLASS wc;
// Register the main window class.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MainWindowClass";
if (!RegisterClass(&wc))
return FALSE;
//
// Process other messages.
//
}
子類別化視窗
若要子類別視窗的實例,請呼叫 SetWindowLong 函式,並指定視窗的控制碼,以子類別化GWL_WNDPROC旗標和子類別程式的指標。 SetWindowLong 會傳回原始視窗程式的指標;使用此指標將訊息傳遞至原始程式。 子類別視窗程式必須使用 CallWindowProc 函式來呼叫原始視窗程式。
注意
若要撰寫與 32 位和 64 位版本的 Windows 相容的程式碼,請使用 SetWindowLongPtr 函式。
下列範例示範如何在對話方塊中將編輯控制項的實例子類別化。 每當控制項具有輸入焦點時,子類別視窗程式可讓編輯控制項接收所有鍵盤輸入,包括 ENTER 鍵和 TAB 鍵。
WNDPROC wpOrigEditProc;
LRESULT APIENTRY EditBoxProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
HWND hwndEdit;
switch(uMsg)
{
case WM_INITDIALOG:
// Retrieve the handle to the edit control.
hwndEdit = GetDlgItem(hwndDlg, ID_EDIT);
// Subclass the edit control.
wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit,
GWL_WNDPROC, (LONG) EditSubclassProc);
//
// Continue the initialization procedure.
//
return TRUE;
case WM_DESTROY:
// Remove the subclass from the edit control.
SetWindowLong(hwndEdit, GWL_WNDPROC,
(LONG) wpOrigEditProc);
//
// Continue the cleanup procedure.
//
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
}
// Subclass procedure
LRESULT APIENTRY EditSubclassProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg == WM_GETDLGCODE)
return DLGC_WANTALLKEYS;
return CallWindowProc(wpOrigEditProc, hwnd, uMsg,
wParam, lParam);
}