计算机-WM_PAINT难以被触发,怎样才能够让它重绘窗口

问题描述

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

计算机-WM_PAINT难以被触发,怎样才能够让它重绘窗口的相关文章

Windows窗口消息实例详解_C 语言

本文实例总结了Windows窗口消息.分享给大家供大家参考.具体如下: 复制代码 代码如下: //////////////////////////////////////////////////////////////////////////    #include "AFXPRIV.H"//消息值的定义来源    #include "Dde.h"//DDE消息值的定义来源    #include "CPL.H"//控制面板消息值的定义来源   

mfc-请教一个MFC设置文本颜色的问题

问题描述 请教一个MFC设置文本颜色的问题 CWnd* wnd = FindWindow(NULL, L"无标题 - 记事本"); wnd->GetDC()->SetTextColor(RGB(255, 0, 0));//文本颜色设置为红色 while (1) { wnd->GetDC()->TextOutW(0, 0, L"123456", 6); Sleep(200); } SetTextColor根本不起作用呀,请问是为什么呀?用API

MFC常见问题解惑

MFC类的分类 1 Root: CObject : CObject2 Application Architecture Classes: CWinApp/CFrameWnd/... 3 Window, Dialog, and Control Classes:CWnd/CDialog/...4 Drawing and Printing Classes : CGdiObject/CPrintInfo/...5 Simple Data Type Classes :CString/CRect/...6 

c++中 invalidate用法

  void Invalidate( BOOL bErase = TRUE );该函数的作用是使整个窗口客户区无效.窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘.这时Windows会在应用程序的消息队列中放置WM_PAINT消息.MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口.视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDra

TextOut看不到输出字符显示

问题描述 我现在使用TextOut进行字符输出,发现看不到输出字符显示,找不到原因,下面是我的部分代码:voidCcalendar::feastdate(CPaintDC&dc){#defineDISP_X15#defineDISP_Y210CFontfont;LOGFONTlf;memset(&lf,0,sizeof(LOGFONT));lf.lfHeight=20;//字体的高font.CreateFontIndirect(&lf);dc.SelectObject(&f

自绘控件的子类化方法

  1.       新建一个基于对话框的MFC程序. 2.       在工程中添加一个新类CMyButton,基类选择CButton. 3.       然后转至新生成的MyButton.h头文件中,将鼠标放在类名CMyButton上点击一下,打开"属性"窗口,在"消息"按钮下为此类添加 WM_LBUTTONDOWN,WM_LBUTTONUP消息,并重写DrawItem虚函数(这个函数是重绘按钮时要调用的,在这里面可以自定义一些绘制按钮的操作,必须设置控件属性为

刷新--MFC界面刷新函数比较

一:什么时候才会发生重绘窗口的消息?       当需要更新或重新绘制窗口的外观时,应用程序就会发送WM_PAINT消息.对窗口进行重新绘制. 二:Invalidate() -- RedrawWindow() -- UpdateWindow()三个函数有什么异同?       Invalidate()是强制系统进行重画,但是不一定就马上进行重画.因为Invalidate()只是通知系统,此 时的窗口已经变为无效.强制系统调用WM_PAINT,而这个消息只是Post就是将该消息放入消息队列.当执行

Win32开发入门(3) 窗口的重绘

我们今天来吹一下关于窗口重绘的事情,在开始吹牛之前,我们先用上一篇博文中说到的方法写一 个简单的Win32应用程序.代码如下: #include <Windows.h> //先声明一下消息处理函数 LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // 入口点 int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrvInst

汇编教程之绘制文本

本课中,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: Windows 中的文本是一个GUI(图形用户界面)对象.每一个字符实际上是由许多的像素点组成,这些点在有笔画的地方显示出来,这样就会出现字符.这也是为什么我说"绘制"字符,而不是写字符.通常您都是在您应用程序的客户区"绘制"字符串(尽管您也可以在客户区外"绘制").Windows 下的"绘制&quo