如何修改系统对话框默认的文本
2016-03-28 23:05
477 查看
最近有个项目界面需要国际化,所有的字符串看起来都翻译得差不多了,提交测试之后才发现,项目中大量使用了AfxMessageBox来进行提示。那么问题来了,这个系统对话框的按钮文本竟然是跟随系统自动设置的,看起来好奇葩。如:
![](https://img-blog.csdn.net/20160328230512472?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
网上找资料找了挺久的,最后也终于找到了解决方法,主要是使用Hook(在对话框显示之前进行Hook,显示之后解除)。下面是笔记:
1. 在CXXXApp里面增加函数CBTMessageBox,在调用MessageBox之前对 WH_CBT进行Hook
HHOOK hhk;
INT CBTMessageBox(HWND hwnd, LPSTR lpText, LPSTR lpCaption,UINT uType)
{
hhk = SetWindowsHookEx(WH_CBT, &CBTProc, 0,
GetCurrentThreadId());
return MessageBox(hwnd, lpText, lpCaption, uType);
}
2. 实现CBTProc,动态设置按钮文本
LRESULT CALLBACK CBTProc(INT nCode, WPARAM wParam, LPARAM lParam)
{
HWND hChildWnd;
CString str;
if (nCode == HCBT_ACTIVATE)
{
// 获取对话框句柄
hChildWnd = (HWND)wParam;
UINT result;
if(GetDlgItem(hChildWnd,IDYES)!=NULL)
{
str.LoadString(IDS_YES); //动态加载字符串
result= SetDlgItemText(hChildWnd,IDYES,str);
}
if(GetDlgItem(hChildWnd,IDOK)!=NULL)
{
str.LoadString(IDS_OK); //<span style="font-family: Arial, Helvetica, sans-serif;">动态加载字符串</span>
result= SetDlgItemText(hChildWnd,IDOK,str);
}
// 解除Hook
UnhookWindowsHookEx(hhk);
}
else CallNextHookEx(hhk, nCode, wParam, lParam);
return 0;
}
3. 重写DoMessageBox接口
4. 在应用程序继续调用AfxMessageBox,查看结果(这里只修改了一个按钮):
![](https://img-blog.csdn.net/20160328230344691?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这里使用的是多字节字符集,UNICODE的话把LPSTR改成LPCWSTR即可。
网上找资料找了挺久的,最后也终于找到了解决方法,主要是使用Hook(在对话框显示之前进行Hook,显示之后解除)。下面是笔记:
1. 在CXXXApp里面增加函数CBTMessageBox,在调用MessageBox之前对 WH_CBT进行Hook
HHOOK hhk;
INT CBTMessageBox(HWND hwnd, LPSTR lpText, LPSTR lpCaption,UINT uType)
{
hhk = SetWindowsHookEx(WH_CBT, &CBTProc, 0,
GetCurrentThreadId());
return MessageBox(hwnd, lpText, lpCaption, uType);
}
2. 实现CBTProc,动态设置按钮文本
LRESULT CALLBACK CBTProc(INT nCode, WPARAM wParam, LPARAM lParam)
{
HWND hChildWnd;
CString str;
if (nCode == HCBT_ACTIVATE)
{
// 获取对话框句柄
hChildWnd = (HWND)wParam;
UINT result;
if(GetDlgItem(hChildWnd,IDYES)!=NULL)
{
str.LoadString(IDS_YES); //动态加载字符串
result= SetDlgItemText(hChildWnd,IDYES,str);
}
if(GetDlgItem(hChildWnd,IDOK)!=NULL)
{
str.LoadString(IDS_OK); //<span style="font-family: Arial, Helvetica, sans-serif;">动态加载字符串</span>
result= SetDlgItemText(hChildWnd,IDOK,str);
}
// 解除Hook
UnhookWindowsHookEx(hhk);
}
else CallNextHookEx(hhk, nCode, wParam, lParam);
return 0;
}
3. 重写DoMessageBox接口
int CXXXApp::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt) { EnableModeless(FALSE); HWND hWndTop; HWND hWnd = CWnd::GetSafeOwner_(NULL, &hWndTop); // WINBUG: re-enable the parent window, so that focus is restored // correctly when the dialog is dismissed. if (hWnd != hWndTop) EnableWindow(hWnd, TRUE); // set help context if possible DWORD* pdwContext = NULL; if (hWnd != NULL) { // use app-level context or frame level context LRESULT lResult = ::SendMessage(hWnd, WM_HELPPROMPTADDR, 0, 0); if (lResult != 0) pdwContext = (DWORD*)lResult; } // for backward compatibility use app context if possible if (pdwContext == NULL && this != NULL) pdwContext = &m_dwPromptContext; DWORD dwOldPromptContext = 0; if (pdwContext != NULL) { // save old prompt context for restoration later dwOldPromptContext = *pdwContext; if (nIDPrompt != 0) *pdwContext = HID_BASE_PROMPT+nIDPrompt; } // 设置ICON if ((nType & MB_ICONMASK) == 0) { switch (nType & MB_TYPEMASK) { case MB_OK: case MB_OKCANCEL: nType |= MB_ICONEXCLAMATION; break; case MB_YESNO: case MB_YESNOCANCEL: nType |= MB_ICONEXCLAMATION; break; case MB_ABORTRETRYIGNORE: case MB_RETRYCANCEL: // No default icon for these types, since they are rarely used. // The caller should specify the icon. break; } } TCHAR szAppName[_MAX_PATH]; szAppName[0] = '\0'; LPCTSTR pszAppName; if (this != NULL) pszAppName = m_pszAppName; else { pszAppName = szAppName; DWORD dwLen = GetModuleFileName(NULL, szAppName, _MAX_PATH); if (dwLen == _MAX_PATH) szAppName[_MAX_PATH - 1] = '\0'; }
// 调用自己的函数,显示对话框 int nResult=CBTMessageBox(hWnd,LPSTR(lpszPrompt),LPSTR(pszAppName),nType); // restore prompt context if possible if (pdwContext != NULL) *pdwContext = dwOldPromptContext; // re-enable windows if (hWndTop != NULL) ::EnableWindow(hWndTop, TRUE); EnableModeless(TRUE); return nResult; }
4. 在应用程序继续调用AfxMessageBox,查看结果(这里只修改了一个按钮):
这里使用的是多字节字符集,UNICODE的话把LPSTR改成LPCWSTR即可。
相关文章推荐
- 1.Two Sum
- qt 中 c 编译选项/链接库如何链接
- 《AndroidStudio实用指南》反馈问题和建议
- BZOJ3931 [CQOI2015]网络吞吐量(最大流)
- 由数字、26个英文字母、下划线或汉字的正则表达式
- MFC中透明位图原理
- Android Studio插件推荐(PreIOC,GsonFormat)
- 素数筛选法
- 深入PHP中的引用
- VIM环境的Markdown配置
- UDP 和 TCP 对比讲解
- Spring3自定义环境配置 <beans profile="">
- 南阳理工学院软件月赛
- HTTP深入浅出
- 如何利用gulp构建前端自动化
- 第三百六十天 how can I 坚持
- 单链表各种操作,VS2013+番茄插件写着真爽
- MyBatis关于识别器和缓存的简单理解
- 面试准备
- hdu-5637 Transform(位运算+bfs)