小弟刚学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