本文由BlueCoder编写 转载请说明出处:
http://blog.csdn.net/crocodile__/article/details/9902475
我的邮箱:bluecoder@yeah.net 欢迎大家和我交流编程心得
我的微博: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); }
以上就是今天的内容,欢迎各位的品读^_^……
点击下载源代码以及相关资源