Respect UI language flow direction in message boxes

- Add a function to check flow direction of currently selected
UI language
- Add MB_RIGHT|MB_RTLREADING to message boxes when language is RTL

Note: though we use MessageBoxEx() for popups, and pass langId to it,
buttons like OK/Cancel are not automatically localized. It seems these
get localized based on the current locale, not the langID passed in.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/556/head
Selva Nair 2022-11-28 18:34:35 -05:00
parent 27e73d0636
commit 4d99c9b9f9
5 changed files with 34 additions and 12 deletions

View File

@ -69,6 +69,22 @@ FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
return FindResource(o.hInstance, resId, resType); return FindResource(o.hInstance, resId, resType);
} }
/*
* Return value: 0 for LTR, 1 for RTL, 2 or 3 for vertical
*/
int
LangFlowDirection(void)
{
int res = 0; /* LTR by default */
wchar_t lcname[LOCALE_NAME_MAX_LENGTH];
wchar_t data[2];
if (LCIDToLocaleName(MAKELCID(GetGUILanguage(), SORT_DEFAULT), lcname, _countof(lcname), 0) != 0
&& GetLocaleInfoEx(lcname, LOCALE_IREADINGLAYOUT, data, 2) != 0)
{
res = _wtoi(data);
}
return res;
}
LANGID LANGID
GetGUILanguage(void) GetGUILanguage(void)
@ -257,10 +273,9 @@ static int
__ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, va_list args) __ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, va_list args)
{ {
return MessageBoxEx(parent, __LoadLocalizedString(stringId, args), caption, return MessageBoxEx(parent, __LoadLocalizedString(stringId, args), caption,
type | MB_SETFOREGROUND, GetGUILanguage()); type | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage());
} }
int int
ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, ...) ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, ...)
{ {

View File

@ -37,5 +37,11 @@ HWND CreateLocalizedDialogParam(const UINT, DLGPROC, const LPARAM);
HWND CreateLocalizedDialog(const UINT, DLGPROC); HWND CreateLocalizedDialog(const UINT, DLGPROC);
INT_PTR CALLBACK GeneralSettingsDlgProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK GeneralSettingsDlgProc(HWND, UINT, WPARAM, LPARAM);
LANGID GetGUILanguage(void); LANGID GetGUILanguage(void);
/*
* Detect whether the selected UI language is LTR or RTL.
* Returns 0 for LTR, 1 for RTL, 2 or 3 for vertical
*/
int LangFlowDirection(void);
#define MBOX_RTL_FLAGS ((LangFlowDirection() == 1) ? MB_RIGHT|MB_RTLREADING : 0)
#endif #endif

2
main.c
View File

@ -938,7 +938,7 @@ ErrorExit(int exit_code, const wchar_t *msg)
{ {
if (msg) if (msg)
MessageBoxExW(NULL, msg, TEXT(PACKAGE_NAME), MessageBoxExW(NULL, msg, TEXT(PACKAGE_NAME),
MB_OK | MB_SETFOREGROUND|MB_ICONERROR, GetGUILanguage()); MB_OK | MB_SETFOREGROUND | MB_ICONERROR | MBOX_RTL_FLAGS, GetGUILanguage());
if (o.hWnd) if (o.hWnd)
{ {
StopAllOpenVPN(); StopAllOpenVPN();

View File

@ -1283,8 +1283,8 @@ OnTimeout(connection_t *c, UNUSED char *msg)
c->state = connecting; c->state = connecting;
if (!OpenManagement(c)) if (!OpenManagement(c))
{ {
MessageBoxEx(NULL, L"Failed to open management", _T(PACKAGE_NAME), MessageBoxExW(NULL, L"Failed to open management", _T(PACKAGE_NAME),
MB_OK|MB_SETFOREGROUND|MB_ICONERROR, GetGUILanguage()); MB_OK | MB_SETFOREGROUND | MB_ICONERROR | MBOX_RTL_FLAGS, GetGUILanguage());
StopOpenVPN(c); StopOpenVPN(c);
} }
return; return;
@ -1316,8 +1316,8 @@ OnStop(connection_t *c, UNUSED char *msg)
SetForegroundWindow(c->hwndStatus); SetForegroundWindow(c->hwndStatus);
ShowWindow(c->hwndStatus, SW_SHOW); ShowWindow(c->hwndStatus, SW_SHOW);
} }
MessageBox(c->hwndStatus, LoadLocalizedString(IDS_NFO_CONN_TERMINATED, c->config_file), MessageBoxExW(c->hwndStatus, LoadLocalizedString(IDS_NFO_CONN_TERMINATED, c->config_file),
_T(PACKAGE_NAME), MB_OK); _T(PACKAGE_NAME), MB_OK | MBOX_RTL_FLAGS, GetGUILanguage());
SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); SendMessage(c->hwndStatus, WM_CLOSE, 0, 0);
break; break;
@ -1340,7 +1340,8 @@ OnStop(connection_t *c, UNUSED char *msg)
SetForegroundWindow(c->hwndStatus); SetForegroundWindow(c->hwndStatus);
ShowWindow(c->hwndStatus, SW_SHOW); ShowWindow(c->hwndStatus, SW_SHOW);
} }
MessageBox(c->hwndStatus, LoadLocalizedString(msg_id, c->config_name), _T(PACKAGE_NAME), MB_OK); MessageBoxExW(c->hwndStatus, LoadLocalizedString(msg_id, c->config_name),
_T(PACKAGE_NAME), MB_OK | MBOX_RTL_FLAGS, GetGUILanguage());
SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); SendMessage(c->hwndStatus, WM_CLOSE, 0, 0);
break; break;
@ -1764,7 +1765,7 @@ OnNeedOk (connection_t *c, char *msg)
} }
const char *fmt; const char *fmt;
if (MessageBoxW (NULL, wstr, L""PACKAGE_NAME, MB_OKCANCEL) == IDOK) if (MessageBoxExW(NULL, wstr, L""PACKAGE_NAME, MB_OKCANCEL | MBOX_RTL_FLAGS, GetGUILanguage()) == IDOK)
{ {
fmt = "needok \'%s\' ok"; fmt = "needok \'%s\' ok";
} }
@ -2124,8 +2125,8 @@ ThreadOpenVPNStatus(void *p)
if (!OpenManagement(c)) if (!OpenManagement(c))
{ {
MessageBoxEx(NULL, L"Failed to open management", _T(PACKAGE_NAME), MessageBoxExW(NULL, L"Failed to open management", _T(PACKAGE_NAME),
MB_OK|MB_SETFOREGROUND|MB_ICONERROR, GetGUILanguage()); MB_OK | MB_SETFOREGROUND | MB_ICONERROR | MBOX_RTL_FLAGS, GetGUILanguage());
StopOpenVPN(c); StopOpenVPN(c);
} }

View File

@ -96,7 +96,7 @@ add_option(options_t *options, int i, TCHAR **p)
LoadLocalizedStringBuf(caption, _countof(caption), IDS_NFO_USAGECAPTION); LoadLocalizedStringBuf(caption, _countof(caption), IDS_NFO_USAGECAPTION);
LoadLocalizedStringBuf(msg, _countof(msg), IDS_NFO_USAGE); LoadLocalizedStringBuf(msg, _countof(msg), IDS_NFO_USAGE);
MessageBoxEx(NULL, msg, caption, MB_OK | MB_SETFOREGROUND, GetGUILanguage()); MessageBoxExW(NULL, msg, caption, MB_OK | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage());
exit(0); exit(0);
} }
else if (streq(p[0], _T("connect")) && p[1]) else if (streq(p[0], _T("connect")) && p[1])