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

来源:互联网 发布:linux改为中文 编辑:程序博客网 时间:2024/05/22 15:18

最近有个项目界面需要国际化,所有的字符串看起来都翻译得差不多了,提交测试之后才发现,项目中大量使用了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);}// 解除HookUnhookWindowsHookEx(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 possibleDWORD* pdwContext = NULL;if (hWnd != NULL){// use app-level context or frame level contextLRESULT lResult = ::SendMessage(hWnd, WM_HELPPROMPTADDR, 0, 0);if (lResult != 0)pdwContext = (DWORD*)lResult;}// for backward compatibility use app context if possibleif (pdwContext == NULL && this != NULL)pdwContext = &m_dwPromptContext;DWORD dwOldPromptContext = 0;if (pdwContext != NULL){// save old prompt context for restoration laterdwOldPromptContext = *pdwContext;if (nIDPrompt != 0)*pdwContext = HID_BASE_PROMPT+nIDPrompt;}// 设置ICONif ((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 possibleif (pdwContext != NULL)*pdwContext = dwOldPromptContext;// re-enable windowsif (hWndTop != NULL)::EnableWindow(hWndTop, TRUE);EnableModeless(TRUE);return nResult;}

4. 在应用程序继续调用AfxMessageBox,查看结果(这里只修改了一个按钮):

这里使用的是多字节字符集,UNICODE的话把LPSTR改成LPCWSTR即可。

0 0
原创粉丝点击