如何在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
相关产品推荐
相关产品推荐

