Windows编程课程|有关GDI绘图|位图|双缓冲|救救孩子😭到底是为什么?!

#include <windows.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <time.h>
#pragma comment(lib,"msimg32.lib")
#include<strsafe.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
const TCHAR lpszTitle[] = TEXT("简易版推箱子"); //窗口标题
wndclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); //NULL
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = TEXT("MyClass");

if (!RegisterClass(&wndclass))
{
    MessageBox(NULL, TEXT("RegisterClass fail!"), TEXT("error"), MB_ICONERROR);
    return 0;
}

hwnd = CreateWindow(
    TEXT("MyClass"),        // window class name
    lpszTitle,        // window caption
    WS_OVERLAPPEDWINDOW,    // window style
    CW_USEDEFAULT,            // initial x position
    CW_USEDEFAULT,            // initial y position
    840,            // initial x size
    600,            // initial y size
    NULL,                // parent window handle
    NULL,                // window menu handle
    hInstance,        // program instance handle
    NULL);            // creation parameters


if (!hwnd)
{
    MessageBox(NULL, TEXT("CreateWindow fail!!"), TEXT("error"), MB_ICONERROR);
    return 0;
}

ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);

PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
while (msg.message != WM_QUIT) //确保可以进入消息循环,且只有在获取到WM_QUIT消息时才退出循环
{
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HPEN hPen, hOldPen; //画笔
HBRUSH hbr;

static HDC hdcBox,hdcMem; //位图缓冲
static HBITMAP hbmBox,hbm;
static BITMAP bmBox,bm;
static RECT rt;
static int x = 50;
static int y = 50;
#define STEP 50
switch (message)
{
case WM_CREATE:
GetClientRect(hwnd, &rt);
hdc = GetDC(hwnd);

    hdcMem = CreateCompatibleDC(hdc); //位图缓冲
    //给hdcMem内存设备环境设置白色画刷
    hbr = (HBRUSH)GetStockObject(WHITE_BRUSH);
    SelectObject(hdcMem, hbr);
    //给hdcMem设置显示平面
    hbm = CreateCompatibleBitmap(hdc, rt.right - rt.left, rt.bottom - rt.top);
    SelectObject(hdcMem, hbm);
    
    hdcBox = CreateCompatibleDC(hdc); //位图缓冲
    hbmBox = (HBITMAP)LoadImage(NULL, TEXT("box1.bmp"), IMAGE_BITMAP
        , 0, 0, LR_LOADFROMFILE);
    SelectObject(hdcBox, hbmBox);
    GetObject(hbmBox, sizeof(BITMAP), &bmBox); //位图尺寸
    ReleaseDC(hwnd, hdc);

case WM_PAINT://Windows在窗口中出现无效区域时,给应用程序发送WM_PAINT消息
    hdc = BeginPaint(hwnd, &ps);

    FillRect(hdcMem, &rt, (HBRUSH)GetStockObject(WHITE_BRUSH));//每次刷新用白色画刷填充窗口大小区域
    hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
    hOldPen = (HPEN)SelectObject(hdcMem, hPen);
    //绘制格子(绘制在后备缓冲hdcMem中)
    SelectObject(hdcMem, hPen);
    for (x = 50; x <= 750; x+=50)//竖线
    {
        MoveToEx(hdcMem, x, 50, NULL);
        LineTo(hdcMem, x, 500);
    }
    for (y = 50; y <= 500; y += 50)
    {
        MoveToEx(hdcMem, 50, y, NULL); //横线
        LineTo(hdcMem, 750, y);
    }
    SelectObject(hdc, hOldPen);
    DeleteObject(hPen);

    TransparentBlt(hdc, x, y, bmBox.bmWidth, bmBox.bmHeight, hdcBox,
        0, 0, bmBox.bmWidth, bmBox.bmHeight, GetPixel(hdcBox, 0, 0));
    BitBlt(hdc, rt.left, rt.top, rt.right, rt.bottom, hdcMem, 0, 0, SRCCOPY);

    EndPaint(hwnd, &ps);
    return 0;
case WM_KEYDOWN:
    switch (wParam)
    {
    case VK_UP:
        y = y - STEP;
        if (y <= 0)
            y = 0;
        break;
    case VK_DOWN:
        y = y + STEP;
        if (y > rt.bottom - bmBox.bmHeight)
            y = rt.bottom - bmBox.bmHeight;
        break;

case VK_LEFT:
x = x - STEP;
if (x <= 0)
x = 0;
break;
case VK_RIGHT:
x = x + STEP;
if (x > rt.right - bmBox.bmWidth);
x = rt.right - bmBox.bmWidth;
break;
case VK_END:
x = rt.right - bmBox.bmWidth;
y = rt.bottom - bmBox.bmHeight;
break;
case VK_ESCAPE: //按下esc键退出
SendMessage(hwnd, WM_CLOSE, 0, 0);
return 0;
}
InvalidateRect(hwnd, NULL, true); //刷新窗口,擦除旧的内容
return 0;
case WM_DESTROY:
DeleteObject(hbmBox);
DeleteObject(hbm);
DeleteDC(hdcMem);
DeleteDC(hdcBox);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

不知道为什么总是不对,箱子跑到底下,如果把网格删掉又正常移动,,求大神赐教!!😭😭已经看了好几个小时了,也改了很多,就是不正常😭😭😭😭(这还之前简单的弄出来,后面还有随机那些,大神会不会弄😭)

你贴源代码还能看看,这么贴图没法整。只看到case VK_END缺少break;