C++ Win32开发:如何增大GetWindowText的缓冲区容量?
Win32编辑框文本超长传输异常的解决方法
问题场景
我正在学习用C++编写基础Win32应用,需求是点击按钮后将可编辑文本框中的内容传递到新窗口。在Visual Studio 2019(64位Windows 10系统)中发现,文本传输的默认缓冲区仅能容纳20字符,超过该长度就会抛出异常。我需要增大缓冲区容量,以便后续传递文件路径并打开对应文件。尝试修改GetWindowTextA的第三个参数至4000,但问题未解决。
问题根源
代码核心错误在于错误使用std::string缓冲区:
- 初始化空
std::string input;时,内部缓冲区长度极小(甚至为空),input.c_str()返回的是只读指针且空间不足 GetWindowTextA需要可写且足够大的缓冲区,直接传入空string的c_str()会导致内存越界,和第三个参数设置无关
解决步骤
- 先获取文本长度,分配足够缓冲区
调用GetWindowTextLengthA获取编辑框内文本的实际长度,初始化std::string到该长度+1(预留字符串结束符\0的位置) - 使用可写的字符串缓冲区
不能用c_str()(只读),改用&input[0]或input.data()(C++17及以后支持)传递可写指针给GetWindowTextA - 修复窗口位置偏移问题
原代码中offset是局部变量,每次点击会重置为0导致新窗口重复覆盖,需改为静态变量
修正后的完整代码
#include <windows.h> #include <string> #include <iostream> //lresult callback prototype LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); //window handles HWND hMainWindow; HINSTANCE hMainInstance; HWND hLblOutput; HWND hTxtInput; HWND hButton; #define IDC_TEXTBOX 1000 #define IDC_BUTTON 1001 //call to winmain - equivalent of main for win32 environments int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg = { 0 }; WNDCLASS wc = { 0 }; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); wc.lpszClassName = TEXT("NiceWindowsApp"); if (!RegisterClass(&wc)) return 1; hMainWindow = CreateWindow(wc.lpszClassName, TEXT("My Windows Application"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, NULL); hMainInstance = wc.hInstance; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } //callback definition LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static int offset = 0; // 改为静态变量,保留每次点击后的偏移值 switch (message) { case WM_CREATE: hMainWindow = hWnd; hTxtInput = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("Type something here"), WS_VISIBLE | WS_CHILD | ES_LEFT, 50, 50, 400, 25, hWnd, (HMENU)IDC_TEXTBOX, hMainInstance, NULL); hButton = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("BUTTON"), TEXT("Press Me!"), WS_VISIBLE | WS_CHILD, 500, 30, 100, 60, hWnd, (HMENU)IDC_BUTTON, hMainInstance, NULL); break; case WM_COMMAND: if (LOWORD(wParam) == IDC_BUTTON) { // 获取文本长度,加1预留结束符位置 int textLen = GetWindowTextLengthA(hTxtInput); std::string input(textLen + 1, '\0'); // 使用可写的缓冲区指针 GetWindowTextA(hTxtInput, &input[0], input.size()); ++offset; hLblOutput = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), input.c_str(), WS_VISIBLE | WS_CHILD | ES_READONLY | ES_LEFT, 50, 200 + offset * 26, 800, 25, hWnd, (HMENU)(IDC_TEXTBOX + offset), // 每个新窗口用唯一ID,避免冲突 hMainInstance, NULL); } break; // 避免执行default分支的默认窗口处理 default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
额外说明
- 给
WM_COMMAND分支添加break,避免触发不必要的默认窗口行为 - 为每个新编辑框分配唯一菜单ID,防止控件ID冲突
- 移除按钮创建时无效的
WM_COPY | ES_LEFT样式(按钮控件无需编辑框样式)
内容的提问来源于stack exchange,提问作者AlexM
相关产品推荐
相关产品推荐

