《Windows程序设计》之鼠标3

来源:互联网 发布:不属于网络群众路线 编辑:程序博客网 时间:2024/05/01 14:16

感觉这次加的注释比较多,把全部代码拿上来了。

这个实现的效果与第一个比是一样的,但是实现方法不一样。

我认为值得学习的地方:

1、首次实现两个窗口类的注册,并且在子窗口类中加入cbWndExtra来保存子窗口状态。

2、循环创建25个子窗口,句柄保存到数组中。

3、首次一个函数中出现两个回调函数。

#include <windows.h>#define DIVISIONS 5LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);LRESULT CALLBACK ChildWndProc(HWND,UINT,WPARAM,LPARAM);TCHAR szChileClass[]=TEXT("Checker3_Child");int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow ){static TCHAR szAppName[]=TEXT("Checker3");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style=CS_HREDRAW|CS_VREDRAW;wndclass.lpfnWndProc=WndProc;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.hInstance=hInstance;wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);wndclass.lpszClassName=szAppName;wndclass.lpszMenuName=NULL;if(!RegisterClass(&wndclass)){MessageBox(NULL,TEXT("Program requires Windows NT!"),szAppName,MB_ICONERROR);return 0;}//以下是注册子窗口类wndclass.lpfnWndProc=ChildWndProc;//cbWndExtra这个字段被设置成长整形变量的4个字节//这个字段通知Windows在内部结构中给基于这个窗口类的每个窗口预留4个字节的额外空间。//用户利用这些空间为每个窗口保存不同的信息。wndclass.cbWndExtra=sizeof(long);wndclass.hIcon=NULL;wndclass.lpszClassName=szChileClass;//注册子窗口类RegisterClass(&wndclass);hwnd=CreateWindow(szAppName,TEXT("Checker3 Mouse Hit-Test Demo"),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 hwndChild[DIVISIONS][DIVISIONS];int cxBlock,cyBlock,x,y;switch(message){//创建多个子窗口case WM_CREATE:for(x=0;x<DIVISIONS;x++)for(y=0;y<DIVISIONS;y++)//(HMENU)字段为每个子窗口ID,(HINSTANCE)创建子窗口时,必须调用GetWindowLong从Windows给窗口保留的结构中提取hInstnace的值.//hwndChild[x][y]保存窗口句柄hwndChild[x][y]=CreateWindow(szChileClass,NULL,WS_CHILDWINDOW|WS_VISIBLE,//y左移8位后与x进行位或运算 //获取应用实例的句柄0,0,0,0,hwnd,(HMENU)(y<<8|x),(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);return 0;//改变大小后,子窗口也要跟随移动改变case WM_SIZE:cxBlock=LOWORD(lParam)/DIVISIONS;cyBlock=HIWORD(lParam)/DIVISIONS;for(x=0;x<DIVISIONS;x++)for(y=0;y<DIVISIONS;y++)//改变窗口的位置和大小MoveWindow(hwndChild[x][y],x*cxBlock,y*cyBlock,cxBlock,cyBlock,TRUE);return 0;//这个在实际应用中其实不是有很大的影响。//只是在窗口下边与右边没有被子窗口覆盖的部分,会发出声音case WM_LBUTTONDOWN:MessageBeep(0);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd,message,wParam,lParam);}//子窗口的回调函数LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){HDC hdc;PAINTSTRUCT ps;RECT rect;switch(message){case WM_CREATE://设置前面为每个子窗口预留的cbWndExtra为0,为了保存矩形当前状态。SetWindowLong(hwnd,0,0);return 0;case WM_LBUTTONDOWN://点击之后,取出cbWndExtra中的值与1做位异或运算SetWindowLong(hwnd,0,1^GetWindowLong(hwnd,0));//并使子窗口无效,重绘区域InvalidateRect(hwnd,NULL,FALSE);return 0;case WM_PAINT:hdc=BeginPaint(hwnd,&ps);//获取子窗口的区域GetClientRect(hwnd,&rect);//绘制方格Rectangle(hdc,0,0,rect.right,rect.bottom);//下面判断,是否绘制对角线if(GetWindowLong(hwnd,0)){MoveToEx(hdc,0,0,NULL);LineTo(hdc,rect.right,rect.bottom);MoveToEx(hdc,0,rect.bottom,NULL);LineTo(hdc,rect.right,0);}EndPaint(hwnd,&ps);return 0;}return DefWindowProc(hwnd,message,wParam,lParam);}