步驟:1、新建窗口類,在窗口類中指名對應的自定義的窗口過程。窗口類類名要唯一,它
是各窗口類相互區別的標識。注意,類名或爲靜態變量,或爲全局變量,因爲程
序隨時都用他們。
2、創建窗體時,指定其風格之一爲WS_CHILD, 指定其父窗口句柄,得到父窗體實
例句柄,並賦給子窗體。
3、在主窗體的create消息中,創建0尺寸的子窗體,主窗體的size消息中,利用
movewindow函數,重設窗體大小,重置窗體位置。
實例爲CTRL002,CTRL003
實例CTRL001單擊按鈕顯示對應文字
子窗口向父窗口發送消息
CreateWindow呼叫使用下面這些參數:
Class name(類別名稱) Window text(窗口文字) Window style(窗口樣式) x position(x位置) y position(y位置) Width(寬度) Height(高度) Parent window(父窗口) Child window ID(子窗口ID) Instance handle(執行實體句柄 )Extra parameters(附加參數) |
TEXT ("button") button[i].szText WS_CHILD|WS_VISIBLE|button[i].iStyle cxChar cyChar * (1 + 2 * i) 20 * xChar 7 * cyChar / 4 hwnd (HMENU)i ((LPCREATESTRUCT) lParam) -> hInstance NULL |
說明:從WM_COMMAND區別出單擊了哪個按鈕。通過子窗口的ID號來區分。每個子窗口在創建時,就已經分配了一個唯一的ID號。ID號包含在WM_COMMAND消息中wParam的低字節位。用LOWORD()宏來獲取ID。
“用鼠標單擊按鈕時,子窗口控制就向其父窗口發送一個WM_COMMAND消息。...捕獲WM_COMMAND消息....”
“LOWORD(wParam) 子窗口ID
HIWORD(wParam) 通知碼
lParam 子窗口句柄”
- #include <windows.h>
- int iFlag=1;//記錄被單擊按鈕的ID
- //定義一個按鈕類型結構體,方便創建按鈕,提高代碼複用率
- struct
- {
- int iStyle ;
- TCHAR * szText ;
- }
- button[] =
- {
- BS_PUSHBUTTON, TEXT ("PUSHBUTTON"),
- BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"),
- BS_CHECKBOX, TEXT ("CHECKBOX"),
- BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"),
- BS_RADIOBUTTON, TEXT ("RADIOBUTTON"),
- BS_3STATE, TEXT ("3STATE"),
- BS_AUTO3STATE, TEXT ("AUTO3STATE"),
- BS_GROUPBOX, TEXT ("GROUPBOX"),
- BS_AUTORADIOBUTTON, TEXT ("AUTORADIO"),
- BS_OWNERDRAW, TEXT ("OWNERDRAW")
- } ;
- #define NUM (sizeof button / sizeof button[0])
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("BtnLook") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ;
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- if (!RegisterClass (&wndclass))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow (szAppName, TEXT ("Button Look"),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, hInstance, NULL) ;
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static HWND hwndButton[NUM] ;//句柄是一個數值,所以可以定義成數組形式
- static int cxChar, cyChar ;
- int iLength=0;
- int i ;
- HDC hdc ;
- PAINTSTRUCT ps ;
- switch (message)
- {
- case WM_CREATE :
- cxChar = LOWORD (GetDialogBaseUnits ()) ;
- cyChar = HIWORD (GetDialogBaseUnits ()) ;
- //得用 button[] ,簡化創建一系列按鈕過程,這就是編輯的藝術
- for (i = 0 ; i < NUM-1 ; i++)
- hwndButton[i] = CreateWindow ( TEXT("button"),
- button[i].szText,
- WS_CHILD | WS_VISIBLE | button[i].iStyle,
- cxChar, cyChar * (1 + 2 * i),
- 20 * cxChar, 7 * cyChar / 4,
- hwnd, (HMENU) i,
- ((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
- //((HMENU) i),爲子窗口指定唯一的ID號。按鈕是子窗口的一種。該參數通常用於指定程序的菜單,因此子窗口ID必須被強制轉換爲HMENU
- /* hwndButton[9] = CreateWindow ( TEXT("button"),
- button[9].szText,
- WS_CHILD | WS_VISIBLE | button[9].iStyle,
- cxChar, cyChar * (1 + 2 * 9),
- 20 * cxChar, 7 * cyChar / 4,
- hwnd, (HMENU) 9,
- ((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
- *這種按鈕,會不斷地觸發WM_COMMAND消息,不斷地調用WM_COMMAND中的InvalidateRect,
- 使客戶區不斷更新,出現閃爍現象。
- */
- return 0 ;
- case WM_PAINT :
- //InvalidateRect (hwnd, &rect, TRUE) ;
- hdc = BeginPaint (hwnd, &ps) ;
- //爲舉例方便起見,將窗口ID號數值大小順序設定成自定義按鈕結構體的順序
- TextOut(hdc,300,200,button[iFlag].szText,lstrlen(button[iFlag].szText));
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_DRAWITEM :
- case WM_COMMAND :
- hdc = GetDC (hwnd) ;
- //得到子窗口的ID號
- iFlag=LOWORD(wParam);//LOWORD=LOW WORD,HIWORD=HIGH WORD
- ReleaseDC (hwnd, hdc) ;
- InvalidateRect (hwnd, NULL, TRUE) ;//使客戶區失效,發出WM_PAINT消息,導致重繪發生
- return 0;
- case WM_DESTROY :
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
實例CTRL002 利用多個靜態窗體繪製棋盤
說明:1、窗體類別必需是static類,否則程序不能生成靜態窗體
2、利用GetWindowLong得到窗體實例句柄
3、HWND是數值類型,可以定義成數組
4、創建子窗體時,將大小設爲0,以便重置
4、利用movewidow(...)函數重置靜態子窗體位置
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("HelloWin") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ;
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = CreateSolidBrush (0) ;//將背景色設成黑色
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- if (!RegisterClass (&wndclass))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow (szAppName, // window class name
- TEXT ("Chess"), // window caption
- WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX
- & ~WS_THICKFRAME & ~ WS_MINIMIZEBOX //去除max、minbox,禁止改變窗體大小
- , // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- ////////////////////
- static HWND hwndRect[32];
- HINSTANCE hinstance;
- int iw,ik,im,cxClient, cyClient ;//不能將它們定義在switch中
- switch (message)
- {
- case WM_CREATE:
- hinstance=(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
- //得到程序的實例
- //窗體類別必需是static類,否則程序不能生成靜態窗體。
- for(iw=0;iw<32;iw++)
- {
- hwndRect[iw]=CreateWindow(TEXT("STATIC"),NULL,
- WS_CHILD|WS_VISIBLE|SS_WHITERECT, //將static 窗體背景色設成白色,好像只能設成黑/白彩色
- 0,0,0,0,
- hwnd,(HMENU)iw,
- hinstance,
- NULL
- );
- }
- MoveWindow(hwnd,0,0,300,300,TRUE);
- return 0 ;
- case WM_SIZE:
- //MoveWindow(hwnd,0,0,400,400,TRUE);
- cxClient = LOWORD (lParam) ;//得到客戶區寬度
- cyClient = HIWORD (lParam) ;//得到客戶區高度
- //SetRect(&rcColor,icxClient/2,0,icxClient,icyClient);
- /*
- //歸納法
- for(ik=0;ik<4;ik++)
- //for(im=0;im<4;im++)
- MoveWindow (hwndRect[ik], (0%2+ik)*cxClient/4, 0, cxClient/8, cyClient/8, TRUE) ;
- for(ik=0;ik<4;ik++)
- MoveWindow (hwndRect[ik+4], (1%2)*cxClient/8+ik*cxClient/4, cyClient/8, cxClient/8, cyClient/8, TRUE) ;
- */
- MoveWindow(hwnd,200,100,300,300,TRUE);
- for(ik=0;ik<4;ik++)
- for(im=0;im<8;im++)
- MoveWindow (hwndRect[ik+4*im], (im%2)*cxClient/8+ik*cxClient/4, im*cyClient/8, cxClient/8, cyClient/8, TRUE) ;
- return 0;
- case WM_DESTROY:
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
運行結果如下圖
- 實例CTRL003利用多個子窗口製做簡易五子棋
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//主窗口過程
- LRESULT CALLBACK ChessWndProc (HWND, UINT, WPARAM, LPARAM) ;//棋盤cell窗口過程
- TCHAR szChdChess[]=TEXT("ChessPlane");
- #define iRow 15
- #define iColumn 15
- int iFlag=0;
- int iYN[iRow][iColumn];
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("MyCHess") ;//需用類名,故聲明爲靜態,也可聲明爲全局變量
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ; //主窗口類
- WNDCLASS chd_chessclass;//棋盤子窗口類
- WNDCLASS chd_stateclass;//狀態子窗口類,可以用wndclass類爲模板,但這樣寫是爲了明確過程,便於理解
- //主窗口類
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- //棋盤子窗口類
- chd_chessclass.style = CS_HREDRAW | CS_VREDRAW ; //創建窗體是加子(WS_CHILDWINDOW)窗體風格
- chd_chessclass.lpfnWndProc = ChessWndProc ; //修改項:換成指定的窗口過程
- chd_chessclass.cbClsExtra = 0 ;
- chd_chessclass.cbWndExtra = sizeof(long) ;
- chd_chessclass.hInstance = hInstance ;
- chd_chessclass.hIcon = NULL;//修改項:不需要圖標,設爲NULL
- chd_chessclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- chd_chessclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;//修改項:改爲黑色
- chd_chessclass.lpszMenuName = NULL ;
- chd_chessclass.lpszClassName = szChdChess ;//修改項:修改類名,窗口類之間相互區分的標識
- if (!RegisterClass (&wndclass))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- RegisterClass(&chd_chessclass);//註冊自定義的窗口類
- hwnd = CreateWindow (szAppName, // window class name
- TEXT ("SimpleChess"), // window caption
- WS_OVERLAPPEDWINDOW& ~WS_MAXIMIZEBOX
- & ~WS_THICKFRAME & ~ WS_MINIMIZEBOX, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- //需將子窗口句柄聲明爲static或聲明爲全局變量,否則新建的窗口,在下次窗口過程調用中會丟失。
- static HWND hwndChess[iRow][iColumn];
- HDC hdc ;
- PAINTSTRUCT ps ;
- RECT rect ;
- int ixclient,iyclient,ik,iw,ixtemp,iytemp;
- switch (message)
- {
- case WM_CREATE:
- //創建chesscell窗體,加上子窗體風格,成爲子窗體
- for(ik=0;ik<iRow;ik++)
- for(iw=0;iw<iColumn;iw++)
- {
- hwndChess[ik][iw]=CreateWindow (szChdChess, NULL,
- WS_CHILDWINDOW | WS_VISIBLE,
- 0, 0, 0, 0,
- hwnd, (HMENU)(iw+ik*iColumn),
- (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
- NULL) ;
- }
- MoveWindow(hwnd,0,0,600,600,TRUE);
- return 0 ;
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_SIZE:
- ixclient=LOWORD(lParam);
- iyclient=HIWORD(lParam);
- ixtemp=ixclient/iRow;
- iytemp=iyclient/iColumn;
- //重設窗體大小,重置窗體位置
- for(ik=0;ik<iRow;ik++)
- for(iw=0;iw<iColumn;iw++)
- {
- MoveWindow(hwndChess[ik][iw],ixtemp*ik,iytemp*iw,ixtemp,iytemp,TRUE);//?????????
- }
- return 0;
- case WM_DESTROY:
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
- LRESULT CALLBACK ChessWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc ;
- PAINTSTRUCT ps ;
- RECT rect ;
- HBRUSH hChdBrush,holdBrush;
- HBRUSH WorBBrush[2];
- int in=0;
- switch (message)
- {
- case WM_CREATE:
- SetWindowLong(hwnd,0,0);//很有用的函數,可以傳遞一些信息
- return 0 ;
- case WM_LBUTTONDOWN :
- iFlag=1^iFlag;//1是黑,0是白
- //iYN[ik][iw]
- SetWindowLong(hwnd,0,1);
- InvalidateRect(hwnd,NULL,TRUE);//響應單擊
- return 0;
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- hChdBrush=CreateSolidBrush(RGB(110,110,110));
- holdBrush=SelectObject(hdc,hChdBrush);
- GetClientRect (hwnd, &rect) ;
- //填充背景色
- FillRect(hdc,&rect,hChdBrush);
- //畫網格
- MoveToEx(hdc,0,(rect.bottom-rect.top)/2,NULL);
- LineTo(hdc,rect.right,(rect.bottom-rect.top)/2);
- MoveToEx(hdc,(rect.right-rect.left)/2,0,NULL);
- LineTo(hdc,(rect.right-rect.left)/2,rect.bottom);
- //畫棋子
- //創建黑、白兩個畫刷
- if(GetWindowLong(hwnd,0))
- {
- WorBBrush[0]=CreateSolidBrush(RGB(0,0,0));
- WorBBrush[1]=CreateSolidBrush(RGB(255,255,255));
- //畫黑或白棋子
- SelectObject(hdc,WorBBrush[iFlag]);
- Ellipse(hdc,0,0,rect.bottom,rect.right);
- DeleteObject(WorBBrush[0]);
- DeleteObject(WorBBrush[1]);
- }
- SelectObject(hdc,holdBrush);
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_DESTROY:
- DeleteObject(hChdBrush);
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
- 轉自(http://blog.csdn.net/dreamcs/article/details/3888323)