本文由BlueCoder編寫 轉載請說明出處:
http://blog.csdn.net/crocodile__/article/details/9902475
我的郵箱:[email protected] 歡迎大家和我交流編程心得
我的微博:BlueCoder_黎小華 歡迎光臨^_^
在windows程序中,子窗口的應用很常見,基本上大部分窗口都有其指定的子窗口,這些子窗口統統受其父窗口的管理,各自實現相應的功能
老規矩,先簡述今天的實例程序所實現的功能:
在父窗口中先繪製一張位圖,然後在其之上創建36個子窗口,點擊子窗口隱藏,點擊改子窗口占據父窗口的區域就重新顯示該子窗口。
比較好玩兒,可以拼出很多好看的圖形,來看看效果吧:
OK,賞析完了,就來具體研究一下它的實現細節……
在看代碼細節之前,先來學習一個函數:
BOOL MoveWindow( HWND hWnd, // handle to window int X, // horizontal position int Y, // vertical position int nWidth, // width int nHeight, // height BOOL bRepaint // repaint option );
這個函數可用於移動一個窗口,同時改變窗口的size(大小),在創建子窗口中能用到
閱讀代碼細節:
(1)父窗口和子窗口類的註冊
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;
}
wndclass.lpfnWndProc = ChildWndProc;
wndclass.hIcon = NULL;
wndclass.lpszClassName = szChildName;
//註冊子窗口類
RegisterClass(&wndclass);
(2)由於這裏的子窗口都是做同樣一件事——響應鼠標左鍵消息,隱藏自己,因此我們只需要一個回調函數
你可能會有一個疑慮:
程序怎麼知道我們點擊的是哪一個子窗口呢?
問得好。不過你可能忘記了一點,windows是如何管理、定位在它上面運行的所有程序(窗口)呢?
這裏子窗口的定位和其它窗口(包括父窗口)都是由windows來統一確定,無需我們的父窗口來操心
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //父窗口回調函數
LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM); //子窗口回調函數
(3)在父窗口的WM_CREATE消息中獲取位圖信息和創建子窗口
a)在WM_PAINT消息中貼位圖,這個我就不再贅述了,不熟悉的朋友可以查看我之前寫的關於Bitmap位圖應用的博文
b)創建子窗口
用一個for循環
/* 創建子窗口 */ for(i=0; i<DIVISIONS; i++) for(j=0; j<DIVISIONS; j++) hwndChild[i][j] = CreateWindow(szChildName, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
因爲在CREATE消息中我們還不能確定父窗口客戶區大小,所以還需要在WM_SIZE消息中移動一下創建的子窗口
case WM_SIZE: //確定父窗口客戶區大小 cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); //確定子窗口大小 cxChild = cxClient / DIVISIONS; cyChild = cyClient / DIVISIONS; /* 移動子窗口 */ for(i=0; i<DIVISIONS; i++) for(j=0; j<DIVISIONS; j++) MoveWindow(hwndChild[i][j], i * (cxChild + 1), j * (cyChild + 1),//加1是爲了讓子窗口之間有一個明顯的間隙 cxChild, cyChild, TRUE); return 0;
(4)在父窗口的左鍵按下消息中顯示子窗口
/*
因爲在子窗口中通過鼠標消息隱藏,這時父窗口的該區域就可見,
因此我們可以讓父窗口通過鼠標消息顯示子窗口
*/
case WM_LBUTTONDOWN:
{
int xMouse, yMouse;
xMouse = LOWORD(lParam);
yMouse = HIWORD(lParam);
for(i=0; i<DIVISIONS; i++)
for(j=0; j<DIVISIONS; j++)
//如果鼠標點擊位置在子窗口上,就顯示
if((xMouse >= i * cxChild && xMouse < (i+1) * cxChild)
&& (yMouse >= j * cyChild && yMouse < (j+1) * cyChild))
{
ShowWindow(hwndChild[i][j], SW_SHOW);
return 0;
}
}
return 0;
(5)子窗口的回調函數
//子窗口回調函數
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
//點擊子窗口時隱藏
case WM_LBUTTONDOWN:
ShowWindow(hwnd, SW_HIDE);
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
以上就是今天的內容,歡迎各位的品讀^_^……
點擊下載源代碼以及相關資源