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

ScrollWindowEx()滚动窗口内容异常,求代码问题排查与修复方法

问题分析与修复方案

核心问题原因

  1. ScrollWindowEx参数理解错误
    ScrollWindowEx的dy参数定义为:正数表示内容向上滚动,负数表示内容向下滚动。你传入dy=13实际是让内容向上滚13像素,而非预期的向下滚动,这直接导致更新区域计算错误。

  2. 未维护滚动偏移,绘制逻辑未适配滚动状态
    你的WM_PAINT始终从客户区y=0位置开始绘制文本,完全没有考虑窗口滚动后的偏移量。滚动后系统需要重绘暴露的新区域,但固定的绘制位置会导致内容错位,同时也干扰了ScrollWindowEx对更新区域的判断。

  3. SW_SMOOTHSCROLL的干扰
    使用平滑滚动标志时,系统会分帧逐步完成滚动,此时返回的updateRect是单帧的小更新区域(比如1像素高),而非最终完整的暴露区域。如果不需要平滑效果,建议先移除该标志简化调试。


修复代码

1. 添加滚动偏移变量

在窗口过程的作用域内添加静态变量维护滚动位置(或使用窗口额外存储,避免全局变量):

LRESULT CALLBACK TestWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static int g_nScrollY = 0; // 垂直滚动偏移量,初始为0
    // ... 其他代码
}

2. 修正ScrollWindowEx调用

将dy改为负数,更新滚动偏移,并移除不必要的平滑滚动标志:

RECT updateRect;
int nScrollStep = 13;
g_nScrollY += nScrollStep; // 更新滚动偏移

// 向下滚动13像素,dy传-nScrollStep
ScrollWindowEx(hTestWindowWnd, 0, -nScrollStep, NULL, NULL, NULL, &updateRect, SW_SCROLLCHILDREN);

InvalidateRect(hTestWindowWnd, &updateRect, TRUE);
UpdateWindow(hTestWindowWnd);

3. 适配滚动偏移的WM_PAINT逻辑

修改绘制起始位置,基于滚动偏移计算文本的绘制坐标:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hDC = BeginPaint(hwnd, &ps);
    HFONT oldFont = (HFONT)SelectObject(hDC, hEditFont);

    int textPosY = -g_nScrollY; // 从滚动偏移的对应位置开始绘制
    int lineNum = 0;

    //fill the window with text
    for(int i = 0; i < 7; i++)
    {
        strcpy(textData, "String___#");
        itoa(lineNum, buf, 10);
        strcat(textData, buf);

        TextOutA(hDC, 10, textPosY, textData, strlen(textData));
        lineNum++;
        textPosY += 13;
    }

    SelectObject(hDC, oldFont);
    EndPaint(hwnd, &ps);
    return 0;
}

额外说明

  • 如果需要保留平滑滚动(SW_SMOOTHSCROLL),则不能依赖单次ScrollWindowEx返回的updateRect,而是需要在滚动完成后(通过WM_SCROLL或定时器)统一重绘暴露区域。
  • 窗口类的CS_PARENTDC标志可以保留,但建议使用自己维护的滚动偏移来控制绘制,避免依赖DC的自动偏移导致的不可预期问题。

内容的提问来源于stack exchange,提问作者Ig_M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:38:09