问题描述
- WM_PAINT难以被触发,怎样才能够让它重绘窗口
-
小弟刚学VC,这是我在写一个很小的五子棋项目。现在出现了一个问题就是点击鼠标以后窗口不刷新。
网上也去查了一些原因,大致确定是说WMPAINT消息优先级低,一直被忽略。。(当然我现在还不是很确定是不是这个原因)
嗯,我写的代码看起来比较复杂,大家将就一下:这个是含WinMain的源文件:
#include <tchar.h> #include "gobang.h" #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define BOARD_GAP 20 #define CHESS_RADIUS 9 #define WINDOW_TITLE L"五子棋" HDC g_hdc = NULL; HDC g_mdc = NULL; HBITMAP g_hBg = NULL; HPEN g_hDrawer = NULL; HBRUSH g_hBlkPainter = NULL; HBRUSH g_hWhtPainter = NULL; Processor *proc = NULL; int g_iX = 0; int g_iY = 0; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL Init(HWND hwnd); BOOL Paint(HWND hwnd); BOOL StepPaint(HWND hwnd, Point pt, BoardPointType bpt); BOOL CleanUp(HWND hwnd); INT GetCenterX(Point pt); INT GetCenterY(Point pt); Point MouseClassify(); BOOL CheckDistance(int x, int y); VOID CheckMate(HWND hwnd, Point bp); VOID Win(HWND hwnd, Player player); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { WNDCLASSEX wndClass = { 0 }; wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = (HICON) ::LoadImage(NULL, L"src\icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = L"Gobang"; if (!RegisterClassEx(&wndClass)) return -1; HWND hwnd = CreateWindow(L"Gobang", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); if (!Init(hwnd)) { MessageBox(hwnd, L"资源初始化失败:计算机运行内存不足!", L"错误", 0); return FALSE; } if (wndClass.hIcon == NULL || g_hBg == NULL) { MessageBox(hwnd, L"资源初始化失败:素材缺失,请重新安装", L"错误", 0); return FALSE; } MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true); ShowWindow(hwnd, nShowCmd); UpdateWindow(hwnd); MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } UnregisterClass(L"Gobang", wndClass.hInstance); return 0; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT paintStruct; switch (message) { /*case WM_TIMER: Paint(hwnd); break;*/ case WM_PAINT: g_hdc = BeginPaint(hwnd, &paintStruct); Paint(hwnd); EndPaint(hwnd, &paintStruct); ValidateRect(hwnd, NULL); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) DestroyWindow(hwnd); break; case WM_LBUTTONDOWN: { /*wchar_t temp[50]; swprintf_s(temp, L"Mouse is at (%d, %d)", g_iX, g_iY); MessageBox(hwnd, temp, L"提示", 0);*/ Point clickPoint = MouseClassify(); if (clickPoint.x != 0) { //MessageBox(hwnd, L"Mouse Point caught", L"Debug", 0); if (proc->getPlayer() == PLAYER_BLACK) { if (proc->Dip(clickPoint, PLAYER_BLACK)) { StepPaint(hwnd, clickPoint, BLACK_CHESS); //CheckMate(hwnd, Point{ clickPoint.x, clickPoint.y }, BLACK_CHESS); } } else if (proc->getPlayer() == PLAYER_WHITE) { if (proc->Dip(clickPoint, PLAYER_WHITE)) { StepPaint(hwnd, clickPoint, WHITE_CHESS ); //CheckMate(hwnd, clickPoint, WHITE_CHESS ); } } } break; } case WM_MOUSEMOVE: g_iX = LOWORD(lParam); if (g_iX > WINDOW_WIDTH) g_iX = WINDOW_WIDTH; else if (g_iX < 0) g_iX = 0; g_iY = HIWORD(lParam); if (g_iY > WINDOW_HEIGHT) g_iY = WINDOW_HEIGHT; else if (g_iY < 0) g_iY = 0; break; case WM_DESTROY: CleanUp(hwnd); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); break; } return 0; } BOOL Init(HWND hwnd) { g_hdc = GetDC(hwnd); g_mdc = CreateCompatibleDC(g_hdc); g_hBg = (HBITMAP)LoadImage(NULL, L"src\bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE | LR_DEFAULTSIZE); g_hDrawer = CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); // black pen g_hBlkPainter = CreateSolidBrush(RGB(0, 0, 0)); // black brush g_hWhtPainter = CreateSolidBrush(RGB(255, 255, 255)); proc = new Processor(9, 9); if (g_hdc == NULL || g_mdc == NULL || g_hBlkPainter == NULL || g_hWhtPainter == NULL || proc == NULL) { return FALSE; } //SetTimer(hwnd, 1, 100, NULL); //Game_Paint(hwnd); return TRUE; } BOOL Paint(HWND hwnd) { SelectObject(g_mdc, g_hBg); BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY); SelectObject(g_hdc, g_hDrawer); for (int i = 1; i < proc->getBoardWidth() + 1; i++) { MoveToEx(g_hdc, GetCenterX(Point{1, i}), GetCenterY(Point{1, i}), NULL); LineTo(g_hdc, GetCenterX(Point{ proc->getBoardHeight(), i}), GetCenterY(Point{ proc->getBoardHeight(), i })); } for (int i = 1; i < proc->getBoardWidth() + 1; i++) { MoveToEx(g_hdc, GetCenterX(Point{ i, 1}), GetCenterY(Point{ i, 1}), NULL); LineTo(g_hdc, GetCenterX(Point{i, proc->getBoardWidth() }), GetCenterY(Point{i, proc->getBoardHeight() })); } for (int i = 0; i < proc->getBoardWidth(); i++) { for (int j = 0; j < proc->getBoardHeight(); j++) { StepPaint(hwnd, Point{ i+1, j+1 }, proc->getBoardPointType(Point{i+1, j+1})); } } return TRUE; } BOOL StepPaint(HWND hwnd, Point pt, BoardPointType bpt) { if (bpt== NO_CHESS) { return FALSE; } if (bpt == WHITE_CHESS) { SelectObject(g_hdc, g_hDrawer); SelectObject(g_hdc, g_hWhtPainter); Ellipse(g_hdc, GetCenterX(pt) - CHESS_RADIUS, GetCenterY(pt) - CHESS_RADIUS, GetCenterX(pt) + CHESS_RADIUS, GetCenterY(pt) + CHESS_RADIUS); } else { SelectObject(g_hdc, g_hDrawer); SelectObject(g_hdc, g_hBlkPainter); Ellipse(g_hdc, GetCenterX(pt) - CHESS_RADIUS, GetCenterY(pt) - CHESS_RADIUS, GetCenterX(pt) + CHESS_RADIUS, GetCenterY(pt) + CHESS_RADIUS); } return TRUE; } BOOL CleanUp(HWND hwnd) { //KillTimer(hwnd, 1); DeleteDC(g_mdc); ReleaseDC(hwnd, g_hdc); return TRUE; } INT GetCenterX(Point pt) { int scrctrx = WINDOW_WIDTH / 2; int midx = proc->getBoardWidth() / 2; return scrctrx - (midx - pt.x) * BOARD_GAP; } INT GetCenterY(Point pt) { int scrctry = WINDOW_HEIGHT / 2; int midy = proc->getBoardHeight() / 2; return scrctry - (midy - pt.y) * BOARD_GAP; } Point MouseClassify() { for (int i = 1; i < proc->getBoardWidth() + 1; i++) { for (int j = 1; j < proc->getBoardHeight() + 1; j++) { if (CheckDistance(GetCenterX(Point{ i, j}), GetCenterY(Point{i, j}))) { return Point{i, j}; } } } return Point{0, 0}; } BOOL CheckDistance(int x, int y) { int dx = g_iX - x; int dy = g_iY - y; return dx * dx + dy * dy < CHESS_RADIUS * CHESS_RADIUS; } VOID CheckMate(HWND hwnd, Point bp) { /*if (Board_Check(g_board,bp)) { Win(hwnd, currentPlayer); }*/ MessageBox(hwnd, L"CheckMate not completed", L"Warning", 0); } VOID Win(HWND hwnd, Player player) { //wchar_t msg[20] = (player == PLAYER_BLACK) ? L"Black Win!" : L"White Win!"; if (player == PLAYER_BLACK) { MessageBox(hwnd, L"Black Win!", L"结束", 0); } else { MessageBox(hwnd, L"White Win!", L"结束", 0); } exit(0); }
这个是引用的自己写的一个文件gobang.h:
#ifndef _GOBANG_H_ #define _GOBANG_H_ #include <windows.h> #define DEFAULT_BOARD_WIDTH 19 #define DEFAULT_BOARD_HEIGHT 19 enum BoardPointType { NO_CHESS, BLACK_CHESS, WHITE_CHESS }; enum Player { PLAYER_BLACK, PLAYER_WHITE }; typedef struct S_Point { int x; int y; } Point; class Board { private: int w; int h; BoardPointType **bp; public: Board(); Board(int w, int h); int getW(); int getH(); BoardPointType getBoardPointType(Point pt); }; class Processor { private: Board *board = NULL; bool vsCom; Player currentPlayer; public: Processor(); Processor(int bw, int bh); Processor(bool vsCom); Processor(int bw, int bh, bool vsCom); int getBoardWidth(); int getBoardHeight(); Player getPlayer(); BoardPointType getBoardPointType(Point pt); BOOL Dip(Point pt, Player pl); }; #endif // gobang.h
为什么运行之后不能够正常点一个点在上面。特别是调用了Ellipse(...)函数前后我看了,各项参数都是很正常的。。
每个参数是什么意思应该很好理解吧,我就不多解释了。proc是我定义的一个全局变量,用于对每个步骤进行响应。g_iX, g_iY是用来记录鼠标的位置。编程环境:VS 2013
解决方案
下棋是鼠标点击事件不是窗体重绘事件
解决方案二:
谢谢一楼的回答,虽然不是这个问题。我已经搞定了,只需要把WinMain里的Move, Show, Update函数放在Init函数之前就可以了。这一点我也没有想到为什么,不过还是谢谢了
解决方案三:
单击鼠标并没有使窗口DC失效啊,所以当然不会触发了,你可以用鼠标左键按下的消息啊
时间: 2024-09-21 12:36:44