You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改已绘制的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 10:45:47