18. BeginPaint

本文深入讲解了Windows API中的BeginPaint函数,它用于为指定窗口的重新绘制做准备,自动设置剪切区域并填充PAINTSTRUCT结构。文章详细解析了函数的参数、返回值及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BeginPaint

函数功能:

BeginPaint 函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。

API 函数原型:

HDC BeginPaint(
  _In_   HWND hwnd,
  _Out_  LPPAINTSTRUCT lpPaint
);

参数解析:

参数含义
hwnd需要重新绘制的窗口句柄
IpPaint指向PAINTSTRUCT结构的指针,用于存放绘画相关的信息

返回值:

  1. 如果函数成功,返回值是指定窗口的“显示设备描述表”句柄;

  2. 如果函数失败,返回值是 NULL,表明没有得到显示设备的内容。

备注:

  1. BeginPaint 函数自动设置显示设备内容的剪切区域,而排除任何更新区域外的区域。该更新区域可以通过 InvalidateRect 或 InvalidateRgn 函数设置,也可以是系统在改变大小、移动、创建、滚动后设置的,或者其他的影响客户区的操作来设置的。

  2. 如果更新区域被标记为可擦除的,BeginPaint 发送一个 WM_ERASEBKGND 消息给窗口。

  3. 一个应用程序除了响应 WM_PAINT 消息外,不应该调用 BeginPaint。

  4. 每次调用 BeginPaint 都应该有相应的 EndPaint 函数。

  5. 如果被绘画的客户区中有一个 caret(caret:插入符。是窗口客户区中的一个闪烁的线,块,或位图。插入符通常表示文本或图形将被插入的地方。即一闪一闪的光标),BeginPaint 自动隐藏该符号,而保证它不被擦除。

  6. 如果窗口类有一个背景刷,BeginPaint 使用这个刷子来擦除更新区域的背景。

#define UNICODE #define _UNICODE #include <windows.h> #include <math.h> #include <wchar.h> // 宽字符支持 // 窗口及常量定义 #define WIN_WIDTH 600 #define WIN_HEIGHT 500 #define BALL_RADIUS 10 #define GRAVITY 0.0008 #define REBOUND_FACTOR 0.5 #define GROUND_Y (WIN_HEIGHT - 150) // 地面高度 // 控件 ID #define IDC_HEIGHT_INPUT 201 // 高度输入框 #define IDC_LANDINGS_INPUT 202 // 落地次数输入框 #define IDC_SUBMIT_BUTTON 203 // 提交按钮 #define TIMER_ID 101 // 定时器 ID // 小球结构体定义 typedef struct { double x, y; // 小球位置 (像素) double vy; // 垂直速度 double currentHeight; // 当前高度 (像素) int landings; // 当前落地次数 int maxLandings; // 最大落地次数 BOOL isActive; // 是否处于运动状态 BOOL isFalling; // 是否处于下落状态 double holdTime; // 停留时间(毫秒) } Ball; // 全局变量定义 Ball ball = {0}; // 小球数据 double totalDistance = 0.0; // 小球累计运动的总距离 double landingHeights[100] = {0}; // 每次落地高度记录 HWND heightInput, landingsInput, submitButton; // 窗口控件句柄 HWND mainHwnd, outputHwnd = NULL; // 主窗口和结果窗口句柄 int scrollOffset = 0; // 滚动条偏移量 int lineHeight = 20; // 每行内容高度 SCROLLINFO scrollInfo; // 滚动条状态信息 // 函数声明 LRESULT CALLBACK OutputWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void InitializeBall(double initialHeightMeters, int maxLandings); void UpdateBall(DWORD deltaTime); void RenderScene(HDC hdc); void ShowResultWindow(HINSTANCE hInstance); // 初始化小球 void InitializeBall(double initialHeightMeters, int maxLandings) { if (initialHeightMeters <= 0 || maxLandings <= 0) return; double initialHeightPixels = initialHeightMeters * 2.0; // 假设 1米 = 2像素 ball.x = WIN_WIDTH / 2.0; // 水平居中 ball.y = GROUND_Y - initialHeightPixels; // 初始高度 ball.vy = 0; // 初始速度为 0 ball.currentHeight = initialHeightPixels; // 初始高度 ball.landings = 0; // 当前落地次数 ball.maxLandings = maxLandings; // 最大落地次数 ball.isActive = TRUE; // 小球处于运动状态 ball.isFalling = TRUE; // 初始状态为下落 ball.holdTime = 2000.0; // 停留时间2秒 totalDistance = 0.0; // 重置总运动距离 memset(landingHeights, 0, sizeof(landingHeights)); // 清空落地高度记录 } // 更新小球物理状态 void UpdateBall(DWORD deltaTime) { if (!ball.isActive) return; // 检查是否在停留时间内 if (ball.holdTime > 0) { ball.holdTime -= deltaTime; if (ball.holdTime <= 0) ball.holdTime = 0; return; } // 小球运动 if (ball.isFalling) { ball.vy += GRAVITY * deltaTime; // 更新速度 ball.y += ball.vy * deltaTime; // 更新位置 if (ball.y >= GROUND_Y - BALL_RADIUS) { // 到达地面 ball.y = GROUND_Y - BALL_RADIUS; // 保持在地面 ball.isFalling = FALSE; // 切换为上升状态 landingHeights[ball.landings++] = ball.currentHeight / 2.0; // 保存落地高度 totalDistance += ball.currentHeight; // 累加总路程 if (ball.landings < ball.maxLandings) { ball.currentHeight *= REBOUND_FACTOR; // 下次反弹高度 ball.vy = -sqrt(2 * GRAVITY * ball.currentHeight); // 反弹初速度 } else { ball.isActive = FALSE; // 达到最大次数停止运动 } } } else { ball.y += ball.vy * deltaTime; // 更新上升位置 ball.vy += GRAVITY * deltaTime; // 重力作用减速 if (ball.vy >= 0) ball.isFalling = TRUE; // 到达最高点切换为下落 } } void RenderScene(HDC hdc) { // 调用用于绘制地面 RenderGround(hdc); // 调用用于绘制小球 RenderBall(hdc); } // 绘制结果窗口内容 LRESULT CALLBACK OutputWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); wchar_t buffer[256]; int offset = 10; // 起始绘制偏移 HFONT hFont = CreateFontW( 18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"SimSun"); // 宋体字体 HFONT oldFont = SelectObject(hdc, hFont); // 显示总路程 swprintf(buffer, 256, L"小球总运动路程:%.2f 米", totalDistance / 2.0); TextOutW(hdc, 10, offset, buffer, wcslen(buffer)); offset += lineHeight; // 显示每次落地高度 for (int i = 0; i < ball.landings; i++) { swprintf(buffer, 256, L"第 %d 次落地高度:%.2f 米", i + 1, landingHeights[i]); TextOutW(hdc, 10, offset, buffer, wcslen(buffer)); offset += lineHeight; } SelectObject(hdc, oldFont); DeleteObject(hFont); EndPaint(hwnd, &ps); break; } case WM_DESTROY: outputHwnd = NULL; return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } // 显示结果窗口 void ShowResultWindow(HINSTANCE hInstance) { if (outputHwnd != NULL) { // 如果结果窗口已打开,刷新其内容 InvalidateRect(outputHwnd, NULL, TRUE); return; } const wchar_t OUTPUT_CLASS_NAME[] = L"ResultWindow"; WNDCLASS wc = {0}; wc.lpfnWndProc = OutputWindowProc; wc.hInstance = hInstance; wc.lpszClassName = OUTPUT_CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); RegisterClass(&wc); outputHwnd = CreateWindow( OUTPUT_CLASS_NAME, L"运动结果", WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL); ShowWindow(outputHwnd, SW_SHOW); } // 主窗口过程 LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static DWORD lastTime = 0; switch (uMsg) { case WM_CREATE: CreateWindow(L"STATIC", L"初始高度 (米):", WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 140, 110, 30, hwnd, NULL, NULL, NULL); heightInput = CreateWindow(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 140, 100, 30, hwnd, (HMENU)IDC_HEIGHT_INPUT, NULL, NULL); CreateWindow(L"STATIC", L"最大落地次数:", WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 100, 110, 30, hwnd, NULL, NULL, NULL); landingsInput = CreateWindow(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 100, 100, 30, hwnd, (HMENU)IDC_LANDINGS_INPUT, NULL, NULL); submitButton = CreateWindow(L"BUTTON", L"提交", WS_VISIBLE | WS_CHILD, 250, WIN_HEIGHT - 120, 100, 40, hwnd, (HMENU)IDC_SUBMIT_BUTTON, NULL, NULL); SetTimer(hwnd, TIMER_ID, 10, NULL); // 定时器,10ms刷新 return 0; case WM_COMMAND: if (LOWORD(wParam) == IDC_SUBMIT_BUTTON) { wchar_t heightBuffer[256], landingsBuffer[256]; GetWindowText(heightInput, heightBuffer, 256); GetWindowText(landingsInput, landingsBuffer, 256); double height = _wtof(heightBuffer); int landings = _wtoi(landingsBuffer); // 检查输入合法性 if (height <= 0 || height > 150) { MessageBox(hwnd, L"高度超出范围!请输入 0 到 150 之间的数值。", L"输入无效", MB_ICONERROR); return 0; } if (landings < 1) { MessageBox(hwnd, L"落地次数无效!请输入大于或等于1的整数。", L"输入无效", MB_ICONERROR); return 0; } if (ball.isActive) KillTimer(hwnd, TIMER_ID); InitializeBall(height, landings); SetTimer(hwnd, TIMER_ID, 10, NULL); InvalidateRect(hwnd, NULL, TRUE); } break; case WM_TIMER: if (wParam == TIMER_ID) { DWORD currentTime = GetTickCount(); DWORD deltaTime = currentTime - lastTime; lastTime = currentTime; if (ball.isActive) { UpdateBall(deltaTime); RECT updateRect = {0, 0, WIN_WIDTH, GROUND_Y}; InvalidateRect(hwnd, &updateRect, TRUE); } else { KillTimer(hwnd, TIMER_ID); // 停止定时器 ShowResultWindow((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE)); // 显示结果窗口 } } break; case WM_PAINT: PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RenderScene(hdc); // 渲染场景 EndPaint(hwnd, &ps); break; case WM_DESTROY: KillTimer(hwnd, TIMER_ID); PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } // WinMain 程序入口 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const wchar_t CLASS_NAME[] = L"BouncingBallWindow"; WNDCLASS wc = {0}; wc.lpfnWndProc = MainWindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); if (!RegisterClass(&wc)) return 0; mainHwnd = CreateWindow( CLASS_NAME, L"小球反弹模拟", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, WIN_WIDTH, WIN_HEIGHT, NULL, NULL, hInstance, NULL); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
08-08
#define UNICODE #define _UNICODE #include <windows.h> #include <math.h> #include <wchar.h> // 宽字符支持 // 窗口及常量定义 #define WIN_WIDTH 600 #define WIN_HEIGHT 500 #define BALL_RADIUS 10 #define GRAVITY 0.0008 #define REBOUND_FACTOR 0.5 #define GROUND_Y (WIN_HEIGHT - 150) // 地面高度 // 控件 ID #define IDC_HEIGHT_INPUT 201 // 高度输入框 #define IDC_REBOUNDS_INPUT 202 // 最大反弹次数输入框 #define IDC_SUBMIT_BUTTON 203 // 提交按钮 #define TIMER_ID 101 // 定时器 ID // 小球结构体定义 typedef struct { double x, y; // 小球位置 (像素) double vy; // 垂直速度 double currentHeight; // 当前高度 (像素) int rebounds; // 当前反弹次数 int maxRebounds; // 最大反弹次数 BOOL isActive; // 是否处于运动状态 BOOL isFalling; // 是否处于下落状态 double holdTime; // 静止时间(毫秒) double cumulativeDistance; // 累计运动总距离 } Ball; // 全局变量定义 Ball ball = {0}; // 小球数据 double reboundHeights[100] = {0}; // 每次反弹高度记录 double cumulativeDistances[100] = {0}; // 每次落地累计总路程 HWND heightInput, reboundsInput, submitButton; // 窗口句柄 HWND mainHwnd, outputHwnd = NULL; // 主窗口和结果窗口句柄 DWORD lastTime = 0; // 上次定时器触发的时间戳 SCROLLINFO scrollInfo; // 滚动条信息 // 函数声明 void RenderGround(HDC hdc); // 绘制地面 void RenderBall(HDC hdc); // 绘制小球 void RenderScene(HDC hdc); // 渲染整个场景 void InitializeBall(double initialHeightMeters, int maxRebounds); void UpdateBall(DWORD deltaTime); void ShowResultWindow(HINSTANCE hInstance); LRESULT CALLBACK OutputWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // 初始化小球 void InitializeBall(double initialHeightMeters, int maxRebounds) { if (initialHeightMeters <= 0 || maxRebounds <= 0) return; double initialHeightPixels = initialHeightMeters * 2.0; // 假设 1米 = 2像素 ball.x = WIN_WIDTH / 2.0; // 水平居中 ball.y = GROUND_Y - initialHeightPixels; // 初始高度 ball.vy = 0; // 初始速度为0 ball.currentHeight = initialHeightPixels; // 初始高度 ball.rebounds = 0; // 初始反弹次数 ball.maxRebounds = maxRebounds; // 最大反弹次数 ball.isActive = TRUE; // 小球处于运动状态 ball.isFalling = FALSE; // 初始状态为静止 ball.holdTime = 2000.0; // 设置静止时间为2秒 ball.cumulativeDistance = 0.0; // 初始化总路程 memset(reboundHeights, 0, sizeof(reboundHeights)); // 清空反弹高度记录 memset(cumulativeDistances, 0, sizeof(cumulativeDistances)); // 清空累计路径记录 } // 更新小球物理状态 void UpdateBall(DWORD deltaTime) { if (!ball.isActive) return; // 检查是否在静止时间内 if (ball.holdTime > 0) { ball.holdTime -= deltaTime; // 静止倒计时 if (ball.holdTime <= 0) { // 倒计时结束 ball.holdTime = 0; ball.isFalling = TRUE; // 开始进入下落状态 } return; // 在静止时间内不进行运动 } // 小球运动逻辑 if (ball.isFalling) { ball.vy += GRAVITY * deltaTime; // 更新速度 ball.y += ball.vy * deltaTime; // 更新位置 if (ball.y >= GROUND_Y - BALL_RADIUS) { // 到达地面 ball.y = GROUND_Y - BALL_RADIUS; // 保持在地面 ball.isFalling = FALSE; // 切换为上升状态 // 每次落地时记录路径和反弹高度 cumulativeDistances[ball.rebounds] = ball.cumulativeDistance + ball.currentHeight; // 路径记录 reboundHeights[ball.rebounds] = ball.currentHeight * REBOUND_FACTOR; // 记录反弹高度 ball.cumulativeDistance += ball.currentHeight; // 累加经过的距离 ball.rebounds++; // 增加反弹次数 // 检查反弹次数是否超过限制 if (ball.rebounds < ball.maxRebounds) { ball.currentHeight *= REBOUND_FACTOR; // 更新下次反弹高度 ball.vy = -sqrt(2 * GRAVITY * ball.currentHeight); // 更新初始向上速度 } else { ball.isActive = FALSE; // 达到最大反弹次数停止运动 } } } else { ball.y += ball.vy * deltaTime; // 更新上升位置 ball.vy += GRAVITY * deltaTime; // 重力作用减速 if (ball.vy >= 0) ball.isFalling = TRUE; // 达到最高点后切换为下落 } } // 绘制地面 void RenderGround(HDC hdc) { HPEN groundPen = CreatePen(PS_SOLID, 2, RGB(0, 128, 0)); // 绿色地面 HPEN oldPen = SelectObject(hdc, groundPen); MoveToEx(hdc, 0, GROUND_Y, NULL); LineTo(hdc, WIN_WIDTH, GROUND_Y); // 绘制地面线条 SelectObject(hdc, oldPen); DeleteObject(groundPen); } // 绘制小球 void RenderBall(HDC hdc) { HBRUSH ballBrush = CreateSolidBrush(RGB(139, 69, 19)); // 棕色小球 HBRUSH oldBrush = SelectObject(hdc, ballBrush); Ellipse(hdc, (int)(ball.x - BALL_RADIUS), (int)(ball.y - BALL_RADIUS), (int)(ball.x + BALL_RADIUS), (int)(ball.y + BALL_RADIUS)); // 绘制圆形 SelectObject(hdc, oldBrush); DeleteObject(ballBrush); } // 渲染场景 void RenderScene(HDC hdc) { RenderGround(hdc); // 绘制地面 RenderBall(hdc); // 绘制小球 } // 显示结果窗口 void ShowResultWindow(HINSTANCE hInstance) { if (outputHwnd != NULL) { InvalidateRect(outputHwnd, NULL, TRUE); // 刷新已有窗口 return; } const wchar_t OUTPUT_CLASS_NAME[] = L"ResultWindow"; WNDCLASS wc = {0}; wc.lpfnWndProc = OutputWindowProc; wc.hInstance = hInstance; wc.lpszClassName = OUTPUT_CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); RegisterClass(&wc); outputHwnd = CreateWindow( OUTPUT_CLASS_NAME, L"运动结果", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, // 增加结果窗口大小 NULL, NULL, hInstance, NULL); ShowWindow(outputHwnd, SW_SHOW); } // 结果窗口处理函数 LRESULT CALLBACK OutputWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); wchar_t buffer[256]; int offset = 10; // 起始绘制偏移 HFONT hFont = CreateFontW( 18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"SimSun"); // 宋体字体 HFONT oldFont = SelectObject(hdc, hFont); // 显示总路程 swprintf(buffer, 256, L"小球总运动路程:%.2f 米", ball.cumulativeDistance / 2.0); TextOutW(hdc, 10, offset, buffer, wcslen(buffer)); offset += 20; // 显示每次反弹高度和累计总路程 for (int i = 1; i <= ball.rebounds; i++) { swprintf(buffer, 256, L"第 %d 次反弹高度:%.2f 米", i, reboundHeights[i - 1] / 2.0); TextOutW(hdc, 10, offset, buffer, wcslen(buffer)); offset += 20; swprintf(buffer, 256, L"第 %d 次落地时累计总路程:%.2f 米", i, cumulativeDistances[i - 1] / 2.0); TextOutW(hdc, 10, offset, buffer, wcslen(buffer)); offset += 20; } SelectObject(hdc, oldFont); DeleteObject(hFont); EndPaint(hwnd, &ps); break; } case WM_DESTROY: outputHwnd = NULL; return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } // 主窗口逻辑 LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: CreateWindow(L"STATIC", L"初始高度 (米):“, WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 140, 110, 30, hwnd, NULL, NULL, NULL); heightInput = CreateWindow(L"EDIT”, L"“, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 140, 100, 30, hwnd, (HMENU)IDC_HEIGHT_INPUT, NULL, NULL); CreateWindow(L"STATIC”, L"最大反弹次数:“, WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 100, 110, 30, hwnd, NULL, NULL, NULL); reboundsInput = CreateWindow(L"EDIT”, L"“, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 100, 100, 30, hwnd, (HMENU)IDC_REBOUNDS_INPUT, NULL, NULL); submitButton = CreateWindow(L"BUTTON”, L"提交", WS_VISIBLE | WS_CHILD, 250, WIN_HEIGHT - 120, 100, 40, hwnd, (HMENU)IDC_SUBMIT_BUTTON, NULL, NULL); SetTimer(hwnd, TIMER_ID, 10, NULL); // 定时器,10ms刷新 return 0; case WM_COMMAND: if (LOWORD(wParam) == IDC_SUBMIT_BUTTON) { wchar_t heightBuffer[256], reboundsBuffer[256]; GetWindowText(heightInput, heightBuffer, 256); GetWindowText(reboundsInput, reboundsBuffer, 256); double height = _wtof(heightBuffer); int maxRebounds = _wtoi(reboundsBuffer); // 检查输入是否合法 if (height <= 0 || height > 150) { MessageBox(hwnd, L"高度超出范围!请输入 0 到 150 之间的数值。“, L"输入无效”, MB_ICONERROR); return 0; } if (maxRebounds <= 0) { MessageBox(hwnd, L"反弹次数无效!请输入大于0的整数。“, L"输入无效”, MB_ICONERROR); return 0; } KillTimer(hwnd, TIMER_ID); // 停止旧定时器 InitializeBall(height, maxRebounds); // 初始化小球状态 SetTimer(hwnd, TIMER_ID, 10, NULL); // 设置新的定时器 InvalidateRect(hwnd, NULL, TRUE); // 刷新窗口 } break; case WM_TIMER: if (wParam == TIMER_ID) { DWORD currentTime = GetTickCount(); DWORD deltaTime = currentTime - lastTime; lastTime = currentTime; if (ball.isActive) { UpdateBall(deltaTime); RECT updateRect = {0, 0, WIN_WIDTH, GROUND_Y}; InvalidateRect(hwnd, &updateRect, TRUE); } else { KillTimer(hwnd, TIMER_ID); // 停止定时器 ShowResultWindow((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE)); // 显示结果窗口 } } break; case WM_PAINT: PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RenderScene(hdc); // 渲染场景 EndPaint(hwnd, &ps); break; case WM_DESTROY: KillTimer(hwnd, TIMER_ID); PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } // WinMain 程序入口 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const wchar_t CLASS_NAME[] = L"BouncingBallWindow"; WNDCLASS wc = {0}; wc.lpfnWndProc = MainWindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); if (!RegisterClass(&wc)) return 0; mainHwnd = CreateWindow( CLASS_NAME, L"小球反弹模拟", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, WIN_WIDTH, WIN_HEIGHT, NULL, NULL, hInstance, NULL); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } 分析一下为什么用户点击一次提交时小球不会停留,但点击两次会停留2s 我用的C语言,给出完整的修改后的C语言代码
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值