ScrollWindowEx()滚动窗口内容异常,求代码问题排查与修复方法
问题分析与修复方案
核心问题原因
ScrollWindowEx参数理解错误
ScrollWindowEx的dy参数定义为:正数表示内容向上滚动,负数表示内容向下滚动。你传入dy=13实际是让内容向上滚13像素,而非预期的向下滚动,这直接导致更新区域计算错误。未维护滚动偏移,绘制逻辑未适配滚动状态
你的WM_PAINT始终从客户区y=0位置开始绘制文本,完全没有考虑窗口滚动后的偏移量。滚动后系统需要重绘暴露的新区域,但固定的绘制位置会导致内容错位,同时也干扰了ScrollWindowEx对更新区域的判断。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
相关产品推荐
相关产品推荐

