您的位置:首页 > 其它

如何修改系统对话框默认的文本

2016-03-28 23:05 477 查看
最近有个项目界面需要国际化,所有的字符串看起来都翻译得差不多了,提交测试之后才发现,项目中大量使用了AfxMessageBox来进行提示。那么问题来了,这个系统对话框的按钮文本竟然是跟随系统自动设置的,看起来好奇葩。如:



网上找资料找了挺久的,最后也终于找到了解决方法,主要是使用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即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: