如何修改已绘制的TextOut?方向键无法移动文本问题排查
问题:方向键无法移动Windows窗口中的文本
我尝试通过方向键移动静态变量static TCHAR greeting[] = _T("123");显示的文本,但文本完全无法移动。已用MessageBox确认能获取键盘输入,相关代码如下:
void move(HWND hWnd, WPARAM wParam, LPARAM lParam, unsigned int *x, unsigned int * y) { RECT rt; if (wParam == VK_LEFT) { GetClientRect(hWnd, &rt); x = x - 5; InvalidateRect(hWnd, &rt, FALSE); MessageBox(hWnd, LPCSTR("123"), LPCSTR("123"), MB_OK); } if (wParam == VK_DOWN) { GetClientRect(hWnd, &rt); y = y - 5; InvalidateRect(hWnd, &rt, FALSE); } if (wParam == VK_UP) { GetClientRect(hWnd, &rt); y = y + 5; InvalidateRect(hWnd, &rt, FALSE); } if (wParam == VK_RIGHT) { GetClientRect(hWnd, &rt); x = x + 5; InvalidateRect(hWnd, &rt, FALSE); } } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static TCHAR greeting[] = _T("123"); unsigned int x = 50; unsigned int y = 50; switch (message) { case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); TextOut(hdc, x, y, greeting, 3); EndPaint(hWnd, &ps); break; } case WM_KEYDOWN: move(hWnd, wParam, lParam, &x, &y); break; case WM_DESTROY: { PostQuitMessage(0); break; } default: { return DefWindowProc(hWnd, message, wParam, lParam); break; } } return 0; }
我正在学习<Windows.h>,希望有人解释问题所在,且不要把代码改得过于复杂。
问题分析与修正
你的代码有两个核心问题导致文本无法移动:
1. x、y是局部变量,每次消息处理都会重置初始值
WndProc是窗口的消息处理函数,每次收到Windows消息时都会重新执行。你在WndProc里定义的unsigned int x = 50; y = 50;是局部变量,每次执行WndProc都会把x、y重新初始化为50——也就是说,你修改的x/y值在下次消息触发时会被覆盖,文本永远画在初始位置。
修正:把x、y改成static变量,让它们的值在WndProc多次调用间保持:
static unsigned int x = 50; static unsigned int y = 50;
2. move函数错误操作指针本身,而非指向的变量
move函数的参数是unsigned int *x(指针),你当前写的x = x - 5;是在修改指针的内存地址,而不是指针指向的x变量的值。这相当于完全没修改到WndProc里的x、y变量。
修正:通过*x、*y访问指针指向的变量,修改它们的值:
void move(HWND hWnd, WPARAM wParam, LPARAM lParam, unsigned int *x, unsigned int * y) { RECT rt; GetClientRect(hWnd, &rt); // 可以把这行提到外面,不用每个if都重复调用 if (wParam == VK_LEFT) { *x = *x - 5; InvalidateRect(hWnd, &rt, FALSE); MessageBox(hWnd, LPCSTR("123"), LPCSTR("123"), MB_OK); } if (wParam == VK_DOWN) { *y = *y + 5; // 窗口y轴向下增长,DOWN应该对应y增加,原代码逻辑反了 InvalidateRect(hWnd, &rt, FALSE); } if (wParam == VK_UP) { *y = *y - 5; // UP对应y减少,修正原逻辑 InvalidateRect(hWnd, &rt, FALSE); } if (wParam == VK_RIGHT) { *x = *x + 5; InvalidateRect(hWnd, &rt, FALSE); } }
另外补充:Windows窗口的y轴坐标是向下增长的,你原代码里DOWN对应y-5、UP对应y+5会导致方向逻辑反转,上面的修正已经调整过来了。
内容的提问来源于stack exchange,提问作者Arkham Knight
相关产品推荐
相关产品推荐

