1 #include <windows.h> 2 #define DIVISIONS 5 3 4 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 5 LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM); 6 TCHAR szChildClass[] = TEXT("Checker3_Child"); 7 int idFocus = 0;//窗口ID 8 9 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPervInstance, PSTR szCmdLine, int iCmdShow) 10 { 11 WNDCLASS wndclass; 12 MSG msg; 13 HWND hWnd; 14 TCHAR Name_1[] = TEXT("MyClass"), Name_2[] = TEXT("MyWindows"); 15 16 wndclass.cbClsExtra = 0; 17 wndclass.cbWndExtra = 0; 18 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 19 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 20 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 21 wndclass.hInstance = hInstance; 22 wndclass.lpfnWndProc = WndProc; 23 wndclass.lpszClassName = Name_1; 24 wndclass.lpszMenuName = NULL; 25 wndclass.style = CS_HREDRAW | CS_VREDRAW; 26 27 RegisterClass(&wndclass); 28 29 wndclass.lpfnWndProc = ChildWndProc;//同一个类派生的窗口过程 30 wndclass.cbWndExtra = sizeof(long);//分配额外的 窗口过程空间 31 wndclass.hIcon = NULL;//图标设置空 32 wndclass.lpszClassName = szChildClass;//类名设置 33 34 RegisterClass(&wndclass); 35 36 hWnd = CreateWindow(Name_1, Name_2, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 37 NULL, NULL, hInstance, NULL); 38 ShowWindow(hWnd, iCmdShow); 39 UpdateWindow(hWnd); 40 41 while (GetMessage(&msg, NULL, NULL, NULL)) 42 { 43 TranslateMessage(&msg); 44 DispatchMessage(&msg); 45 } 46 return msg.wParam; 47 } 48 49 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)//主窗口 50 { 51 static HWND hwndChild[DIVISIONS][DIVISIONS], z = 0;//数组 [5][5]=25 52 int cxBlock, cyBlock, x, y; 53 54 switch (msg) 55 { 56 case WM_CREATE://窗口生成 57 for (x = 0; x < DIVISIONS; x++) 58 { 59 for (y = 0; y < DIVISIONS; y++) 60 { 61 //数组窗口句柄保存 62 hwndChild[x][y] = CreateWindow(szChildClass, NULL, WS_CHILDWINDOW | WS_VISIBLE, 63 0, 0, 0, 0, hWnd, (HMENU)(y<<8|x), (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); 64 //窗口风格为 子窗口 并且可视 初始大小位置 全部0 父窗口是主窗口 ,后面的参数为子窗口特有的标记 随意 不同即可 后面的是获取窗口实力句柄 65 } 66 } 67 return 0; 68 case WM_SIZE: 69 cxBlock = LOWORD(lParam) / DIVISIONS; 70 cyBlock = HIWORD(lParam) / DIVISIONS; 71 72 for (x = 0; x < DIVISIONS; x++) 73 { 74 for (y = 0; y < DIVISIONS; y++) 75 { 76 MoveWindow(hwndChild[x][y], x*cxBlock, y*cyBlock, cxBlock, cyBlock, TRUE); 77 //设置窗口位置以及大小。 78 } 79 } 80 return 0; 81 case WM_LBUTTONDOWN: 82 MessageBeep(0); 83 return 0; 84 case WM_SETFOCUS://主窗口获得焦点的时候 85 SetFocus(GetDlgItem(hWnd, idFocus));//设置 子窗口 idFocus ID的窗口 为焦点窗口 默认为0; 步骤:1 86 return 0; 87 case WM_KEYDOWN: 88 x = idFocus & 0xFF;// 按位或 取出x的值 89 y = idFocus >> 8;//右移 8位 取出y的值 90 switch (wParam) 91 { 92 case VK_UP: y--; break; 93 case VK_DOWN:y++; break; 94 case VK_LEFT:x--; break; 95 case VK_RIGHT:x++; break; 96 case VK_HOME:x = y = 0; break; 97 case VK_END:x = y = DIVISIONS - 1; break; 98 default:return 0; 99 } 100 101 x = (x + DIVISIONS) % DIVISIONS;//防止出屏幕 102 y = (y + DIVISIONS) % DIVISIONS;//防止出屏幕 103 104 idFocus = y << 8 | x;//还原数据 105 SetFocus(GetDlgItem(hWnd, idFocus));//设置 子窗口ID 为焦点 106 //当主窗口接受到键盘消息 就 移动 x和y的值 最后设置 子窗口ID 为焦点 跳转 子窗口获取焦点 107 return 0; 108 case WM_DESTROY: 109 PostQuitMessage(0); 110 return 0; 111 } 112 return DefWindowProc(hWnd, msg, wParam, lParam); 113 } 114 115 LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)//子窗口过程 25个全部调用这个 116 { 117 HDC hdc; 118 PAINTSTRUCT ps; 119 RECT rect; 120 121 switch (msg) 122 { 123 case WM_CREATE: 124 SetWindowLong(hWnd, 0, 0);//设置额外 内存为 0 125 return 0; 126 case WM_KEYDOWN://因为当前焦点在子窗口 如果接收不为 空格或回车 就返回主窗口 127 if (wParam != VK_RETURN && wParam != VK_SPACE) 128 { 129 SendMessage(GetParent(hWnd), msg, wParam, lParam);//发送消息 画XX 130 return 0; 131 132 } 133 134 case WM_LBUTTONDOWN: 135 SetWindowLong(hWnd, 0, 1 ^ GetWindowLong(hWnd, 0));//设置额外 内存 为 0或1 136 SetFocus(hWnd); 137 InvalidateRect(hWnd, NULL, FALSE);//立即重绘 138 return 0; 139 case WM_SETFOCUS://子窗口获得焦点 步骤:2 140 idFocus = GetWindowLong(hWnd, GWL_ID);//获得子窗口 ID号 给全局变量 141 case WM_KILLFOCUS://失去焦点 142 InvalidateRect(hWnd, NULL, TRUE);//重绘窗口 步骤:3 143 return 0; 144 case WM_PAINT://重绘窗口 步骤:4 下面代码不执行 跳到 步骤:5执行 145 hdc = BeginPaint(hWnd, &ps); 146 147 GetClientRect(hWnd, &rect);//获取窗口矩形大小 148 Rectangle(hdc, 0, 0, rect.right, rect.bottom);//重新绘制矩形 149 if (GetWindowLong(hWnd, 0))//如果标记了 就画XX 150 { 151 MoveToEx(hdc, 0, 0, NULL); 152 LineTo(hdc, rect.right, rect.bottom); 153 MoveToEx(hdc, 0, rect.bottom, NULL); 154 LineTo(hdc, rect.right, 0); 155 } 156 157 if (hWnd == GetFocus())// 这里是 步骤:5 画出 虚线矩形 158 { 159 rect.left += rect.right / 10;// 矩形的左边 = 矩形的左边 + 矩形的右边 / 10 160 rect.right -= rect.left;//矩形的右边 = 矩形的右边 - 矩形的左边 161 rect.top += rect.bottom / 10;//矩形的顶边 = 矩形的顶边 + 矩形的底边 / 10 162 rect.bottom -= rect.top;//矩形的底边 = 矩形的底边 - 矩形的顶边 163 164 //假设 矩形 宽 20 高 20 165 //那么 左边 = 0, 右边 = 20, 顶边 = 0, 底边 = 20 166 // 左边=10 右边=10 顶边=10 底边=10 167 168 SelectObject(hdc, GetStockObject(NULL_BRUSH));//设置为空画刷 169 SelectObject(hdc, CreatePen(PS_DASH, 0, 0));//设置画笔 为 虚线画笔 170 Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);//画出矩形 171 DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN)));//删除 选择的画笔 172 173 } 174 175 EndPaint(hWnd, &ps); 176 return 0; 177 } 178 return DefWindowProc(hWnd, msg, wParam, lParam); 179 }
时间: 2024-10-12 20:26:44