如何翻译第三方.NET应用资源?按钮文本修改后界面不更新
.NET WinForms按钮SetWindowText后界面不更新的解决办法
问题现象
通过MFC调用CreateProcess启动一个仅含标签和意大利语按钮的.NET WinForms应用,用FindWindowEx定位控件后:
- 标签用
SetWindowText修改文本后,界面显示正常更新 - 按钮调用
SetWindowText后,GetWindowTextW和Spy++均能读取到新文本,但界面始终显示旧内容 - 无该.NET应用源码,自制测试程序可复现此问题
根因分析
.NET WinForms的Button控件会维护自身的Text属性,而非完全依赖原生Windows窗口的文本存储。通过WinAPI直接修改原生窗口文本后,WinForms控件不会自动同步更新内部的Text属性,后续重绘时仍会使用旧的属性值。而Label控件的实现逻辑不同,原生窗口文本变更会同步到控件内部属性,因此显示正常。
解决步骤
- 直接通过
SendMessage发送WM_SETTEXT消息修改按钮文本,确保触发WinForms控件的内部属性同步 - 发送消息后强制控件重绘,确保界面刷新
修改后的代码示例
// 启动.NET应用部分代码保留,替换按钮文本修改逻辑 Sleep(500); // 建议替换为WaitForInputIdle(pi.hProcess, INFINITE),更可靠 // 找到.NET主窗口 HWND ingran_main_hwnd = FindTopWindow(pi.dwProcessId); CWnd* ingran_main_pWnd = CWnd::FromHandle(ingran_main_hwnd); // 标签修改逻辑保留 CWnd* label_pWnd = FindWindowEx(ingran_main_hwnd, NULL, NULL, _T("OriginalTextLabel")); CString reset_btn; label_pWnd->GetWindowTextW(reset_btn); label_pWnd->SetWindowText(_T("TranslatedTextLabel")); label_pWnd->GetWindowTextW(reset_btn); // 修改按钮文本的逻辑替换为以下代码 CWnd* button_pWnd = FindWindowEx(ingran_main_hwnd, NULL, NULL, _T("OriginalTextButton")); button_pWnd->GetWindowTextW(reset_btn); // 直接发送WM_SETTEXT消息 ::SendMessage(button_pWnd->m_hWnd, WM_SETTEXT, 0, (LPARAM)_T("TranslatedTextButton")); // 强制控件重绘 ::InvalidateRect(button_pWnd->m_hWnd, NULL, TRUE); ::SendMessage(button_pWnd->m_hWnd, WM_PAINT, 0, 0); button_pWnd->GetWindowTextW(reset_btn); // 显示主窗口 ingran_main_pWnd->ShowWindow(SW_SHOW);
额外优化建议
- 替换
Sleep(500)为WaitForInputIdle(pi.hProcess, INFINITE),等待.NET应用完成初始化,避免因窗口未创建完全导致的定位失败 - 确保
FindTopWindow能准确匹配目标进程的主窗口,可通过窗口类名进一步筛选(.NET WinForms主窗口类名通常为WindowsForms10.Window.8.app.0.141b42a_r11_ad1这类格式,可通过Spy++获取)
内容的提问来源于stack exchange,提问作者Andrey Angerchik
相关产品推荐
相关产品推荐

