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

如何在WC_EDIT控件尺寸调整时更新其内容边距?

问题分析与修复方案

我一眼就看出你遇到的问题了——你的编辑控件边距设置被控件自身的WM_SIZE处理给覆盖了!下面给你详细拆解原因和修复方法:

问题根源

你当前的EditWindowProc里,是先调用EM_SETRECT设置边距,再调用原窗口过程origEditProc处理WM_SIZE消息。但编辑控件的原生窗口过程在处理WM_SIZE时(尤其是当你开启了ES_AUTOVSCROLL样式时),会自动把格式化矩形重置为控件的整个客户区大小,这就直接把你刚设置的50像素边距给冲掉了,自然看不到效果。

另外,你在编辑控件的窗口过程里用了全局变量editHwnd,其实完全可以用参数里的hwnd(这个就是当前编辑控件的句柄),这样代码更健壮,也避免了全局变量的潜在问题。

修复方案

调整消息处理的顺序:先让原生窗口过程处理WM_SIZE,再设置自定义的格式化矩形。这样你的边距设置就会覆盖控件的默认值,而不是反过来。

同时替换掉全局变量的使用,优化代码结构。

修改后的完整代码

#include <windows.h>
#include <commctrl.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK EditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

HWND hwnd;
HWND editHwnd;
WNDPROC origEditProc;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow) {
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "Window Class";
    RegisterClass(&wc);

    hwnd = CreateWindow(
        wc.lpszClassName,
        "",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL
    );

    editHwnd = CreateWindow(
        WC_EDIT,
        "Lorem ipsum",
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
        0, 0, 100, 100,
        hwnd, NULL, hInstance, NULL
    );

    origEditProc = (WNDPROC) GetWindowLongPtr(editHwnd, GWLP_WNDPROC);
    SetWindowLongPtr(editHwnd, GWLP_WNDPROC, (LONG_PTR)EditWindowProc);

    ShowWindow(hwnd, nCmdShow);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        case WM_SIZE:
            RECT clientRect;
            GetClientRect(hwnd, &clientRect);
            SetWindowPos(editHwnd, NULL, 0, 0, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK EditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    // 先让原生窗口过程处理消息
    LRESULT result = CallWindowProc(origEditProc, hwnd, uMsg, wParam, lParam);

    switch (uMsg) {
        case WM_SIZE:
            RECT rect;
            // 用当前控件的hwnd,而不是全局变量
            GetClientRect(hwnd, &rect);
            rect.left += 50;
            rect.top += 50;
            rect.right -= 50;
            rect.bottom -= 50;
            // 确保矩形有效(避免边距过大导致left>right的情况)
            if (rect.left < rect.right && rect.top < rect.bottom) {
                SendMessage(hwnd, EM_SETRECT, NULL, (LPARAM)&rect);
            }
            break;
    }

    return result;
}

关键修改点

  • 把CallWindowProc移到了消息处理的最前面,先让控件完成原生的WM_SIZE处理
  • 把全局变量editHwnd替换为窗口过程参数hwnd
  • 添加了矩形有效性检查,避免出现无效矩形导致EM_SETRECT失效

这样修改后,当主窗口调整大小、编辑控件同步缩放时,你的50像素边距就会正常生效了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:02:20