Daniel_suzhou 2015-11-25 07:33 采纳率: 0%
浏览 2981

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

  • 写回答

3条回答 默认 最新

  • CDSN_SB_SYY 2015-11-25 08:03
    关注

    下棋是鼠标点击事件不是窗体重绘事件

    评论

报告相同问题?

悬赏问题

  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用