From 2d70899d1300d8cec424d7b92fbec0dad52e6bb4 Mon Sep 17 00:00:00 2001 From: lx-s Date: Sun, 8 Oct 2023 11:29:31 +0200 Subject: [PATCH] Added WMi18n-class. Added default language table --- Translations/wm_de/resource.h | 4 +- Translations/wm_de/wm_de.rc | Bin 2904 -> 3050 bytes WinMute/Settings_GeneralDlg.cpp | 31 ++--------- WinMute/WMSettings.cpp | 95 +++++++++++++------------------- WinMute/WMSettings.h | 8 +-- WinMute/WinMain.cpp | 29 +++++++++- WinMute/WinMute.cpp | 9 +-- WinMute/WinMute.h | 4 +- WinMute/WinMute.rc | 11 ++++ WinMute/WinMute.vcxproj | 2 + WinMute/WinMute.vcxproj.filters | 6 ++ WinMute/common.h | 4 +- WinMute/resource.h | 4 +- 13 files changed, 103 insertions(+), 104 deletions(-) diff --git a/Translations/wm_de/resource.h b/Translations/wm_de/resource.h index afeb27a..93eadb0 100644 --- a/Translations/wm_de/resource.h +++ b/Translations/wm_de/resource.h @@ -1,12 +1,14 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by wm_de.rc +// +#define IDI_LANG_NAME 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/Translations/wm_de/wm_de.rc b/Translations/wm_de/wm_de.rc index 164dec452a6eab8fbdb7c853bc9144c7e6231882..389ad11191902fd8baeccb9d0126c0c57f000249 100644 GIT binary patch delta 128 zcmca1_DXz%28U=cLkL3 z23H0JtWXK4K9!-Ap@gBBA(5W-3DwLoP!iLmq?X GetTranslationSearchString() -{ - wchar_t wmPath[MAX_PATH + 1]{ 0 }; - if (GetModuleFileNameW(nullptr, wmPath, MAX_PATH) <= 0) { - WMLog::GetInstance().WriteWindowsError(L"GetModuleFileNameW", GetLastError()); - return std::nullopt; - } - return fs::path{ wmPath } / L"lang" / "*.dll"; -} - -static std::vector GetLanguageList() -{ - const auto langPath = GetTranslationSearchString(); - if (!langPath.has_value()) { - return {}; - } - WIN32_FIND_DATAW wfd{ 0 }; - FindFirstFileExW( - langPath->c_str(), - FindExInfoBasic, - &wfd, - FindExSearchNameMatch, - nullptr, - FIND_FIRST_EX_CASE_SENSITIVE); -} +struct LanguageDll { + std::wstring langName; + std::wstring file; +}; INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { diff --git a/WinMute/WMSettings.cpp b/WinMute/WMSettings.cpp index e616a0b..aaf4c62 100644 --- a/WinMute/WMSettings.cpp +++ b/WinMute/WMSettings.cpp @@ -119,6 +119,9 @@ static const wchar_t* KeyToStr(SettingsKey key) case SettingsKey::NOTIFICATIONS_ENABLED: keyStr = L"ShowNotifications"; break; + case SettingsKey::APP_LANGUAGE: + keyStr = L"AppLanguage"; + break; } return keyStr; } @@ -166,6 +169,8 @@ static DWORD GetDefaultSetting(SettingsKey key) return 0; case SettingsKey::NOTIFICATIONS_ENABLED: return 0; + case SettingsKey::APP_LANGUAGE: + return 0; } return 0; } @@ -324,7 +329,6 @@ void WMSettings::Unload() noexcept hWifiKey_ = nullptr; RegCloseKey(hBluetoothKey_); hBluetoothKey_ = nullptr; - UnloadLanguage(); } HKEY WMSettings::OpenAutostartKey(REGSAM samDesired) @@ -423,6 +427,17 @@ DWORD WMSettings::QueryValue(SettingsKey key) const return value; } +std::optional WMSettings::QueryStrValue(SettingsKey key) const +{ + std::wstring val; + auto keyStr = KeyToStr(key); + assert(keyStr != nullptr); + if (!ReadStringFromRegistry(hSettingsKey_, keyStr, val)) { + return std::nullopt; + } + return val; +} + bool WMSettings::SetValue(SettingsKey key, DWORD value) { auto keyStr = KeyToStr(key); @@ -443,6 +458,28 @@ bool WMSettings::SetValue(SettingsKey key, DWORD value) return true; } +bool WMSettings::SetValue(SettingsKey key, const std::wstring &value) +{ + auto keyStr = KeyToStr(key); + assert(keyStr != nullptr); + + BYTE *strValue = reinterpret_cast(const_cast(value.c_str())); + DWORD strLen = static_cast((value.length() + 1) * sizeof(wchar_t)); + DWORD regError = RegSetValueExW( + hSettingsKey_, + keyStr, + 0, + REG_SZ, + strValue, + strLen); + if (regError != ERROR_SUCCESS) { + PrintWindowsError(L"RegSetValueExW", regError); + return false; + } + + return true; +} + bool WMSettings::StoreWifiNetworks(std::vector& networks) { // Clear all stored keys @@ -730,60 +767,4 @@ std::vector WMSettings::GetManagedAudioEndpoints() const NormalizeStringList(devices); return devices; } -// https://learn.microsoft.com/en-us/windows/win32/intl/creating-a-multilingual-user-interface-application - -bool WMSettings::SetLanguage(const std::wstring &dllName) -{ - if (dllName.empty()) { - UnloadLanguage(); - return true; - } else { - wchar_t winMutePath[MAX_PATH + 1]; - GetModuleFileNameW(GetModuleHandleW(nullptr), winMutePath, ARRAY_SIZE(winMutePath)); - fs::path langPath{winMutePath}; - langPath /= L"lang"; - langPath /= dllName; - if (!fs::exists(langPath)) { - // TODO: Error - } else { - auto newLangModule = LoadLibraryExW( - langPath.c_str(), nullptr, - LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE); - if (newLangModule == nullptr) { - // TODO: Error - } else { - UnloadLanguage(); - textModule_ = newLangModule; - return true; - } - } - } - return false; -} - -void WMSettings::UnloadLanguage() -{ - if (textModule_ != nullptr) { - FreeLibrary(textModule_); - textModule_ = nullptr; - } -} -std::wstring WMSettings::GetString(UINT strId) -{ - HMODULE strModule = (textModule_ == nullptr) ? hglobInstance : textModule_; - wchar_t strBuffer[2048 + 1]{ 0 }; - int strLength = LoadStringW(strModule, strId, strBuffer, 0); - if (strLength == 0) { - return L""; - } else if (strLength < 2048) { - LoadStringW(strModule, strId, strBuffer, ARRAY_SIZE(strBuffer)); - return std::wstring(strBuffer, strBuffer + strLength); - } else { - wchar_t *largeBuffer = new wchar_t[strLength + 1]; - LoadStringW(strModule, strId, largeBuffer, strLength + 1); - std::wstring ret(strBuffer, largeBuffer + strLength); - delete[] largeBuffer; - return ret; - } -} diff --git a/WinMute/WMSettings.h b/WinMute/WMSettings.h index db901fb..af5b561 100644 --- a/WinMute/WMSettings.h +++ b/WinMute/WMSettings.h @@ -64,6 +64,7 @@ enum class SettingsKey { , QUIETHOURS_END , NOTIFICATIONS_ENABLED , LOGGING_ENABLED + , APP_LANGUAGE }; class WMSettings { @@ -93,8 +94,8 @@ public: DWORD QueryValue(SettingsKey key) const; bool SetValue(SettingsKey key, DWORD value); - bool SetLanguage(const std::wstring &dllName); - std::wstring GetString(UINT strId); + std::optional QueryStrValue(SettingsKey key) const; + bool SetValue(SettingsKey key, const std::wstring &value); private: HKEY hSettingsKey_; @@ -102,9 +103,6 @@ private: HKEY hBluetoothKey_; HKEY hAudioEndpointsKey_; - HMODULE textModule_; - bool MigrateSettings(); HKEY OpenAutostartKey(REGSAM samDesired); - void UnloadLanguage(); }; diff --git a/WinMute/WinMain.cpp b/WinMute/WinMain.cpp index dd8fb14..6b7b566 100644 --- a/WinMute/WinMain.cpp +++ b/WinMute/WinMain.cpp @@ -49,16 +49,39 @@ static bool SetWorkingDirectory() return false; } +static void LoadLanguage(WMSettings &settings, WMi18n &i18n) +{ + const auto langModule = settings.QueryStrValue(SettingsKey::APP_LANGUAGE); + if (langModule.has_value()) { + i18n.LoadLanguage(*langModule); + } +} + int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ PWSTR, _In_ int) { + WMSettings settings; + WMi18n& i18n = WMi18n::GetInstance(); + if (!settings.Init()) { + TaskDialog(nullptr, + nullptr, + PROGRAM_NAME, + L"Failed to initialize settings", + L"Critical error while initializing WinMute", + TDCBF_OK_BUTTON, + TD_ERROR_ICON, + nullptr); + return FALSE; + } + + LoadLanguage(settings, i18n); + HANDLE hMutex = CreateMutexW(nullptr, TRUE, L"LxSystemsWinMute"); if (hMutex == nullptr) { return FALSE; - } - if (GetLastError() == ERROR_ALREADY_EXISTS) { + } else if (GetLastError() == ERROR_ALREADY_EXISTS) { ReleaseMutex(hMutex); TaskDialog(nullptr, nullptr, @@ -111,7 +134,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, } MSG msg = { nullptr }; - WinMute program; + WinMute program(settings); if (program.Init()) { while (GetMessage(&msg, nullptr, 0, 0)) { HWND hwnd = GetForegroundWindow(); diff --git a/WinMute/WinMute.cpp b/WinMute/WinMute.cpp index 7cad7a9..cda8af3 100644 --- a/WinMute/WinMute.cpp +++ b/WinMute/WinMute.cpp @@ -143,11 +143,12 @@ WinMute::MuteConfig::MuteConfig() { } -WinMute::WinMute() : +WinMute::WinMute(WMSettings& settings) : hWnd_(nullptr), hTrayMenu_(nullptr), hAppIcon_(nullptr), - hTrayIcon_(nullptr) + hTrayIcon_(nullptr), + settings_(settings) { } @@ -235,10 +236,6 @@ bool WinMute::Init() hAppIcon_ = LoadIconW(hglobInstance, MAKEINTRESOURCE(IDI_APP)); - if (!settings_.Init()) { - return false; - } - #ifdef _DEBUG WMLog::GetInstance().SetEnabled(true); #else diff --git a/WinMute/WinMute.h b/WinMute/WinMute.h index 8aa747b..514979f 100644 --- a/WinMute/WinMute.h +++ b/WinMute/WinMute.h @@ -39,7 +39,7 @@ class WinAudio; class WinMute { public: - WinMute(); + explicit WinMute(WMSettings& settings); WinMute(const WinMute&) = delete; WinMute(WinMute&&) = delete; WinMute& operator=(const WinMute &) = delete; @@ -66,7 +66,7 @@ private: TrayIcon trayIcon_; WifiDetector wifiDetector_; - WMSettings settings_; + WMSettings& settings_; MuteControl muteCtrl_; QuietHoursTimer quietHours_; BluetoothDetector btDetector_; diff --git a/WinMute/WinMute.rc b/WinMute/WinMute.rc index 75a56b9..e100965 100644 --- a/WinMute/WinMute.rc +++ b/WinMute/WinMute.rc @@ -524,6 +524,17 @@ BEGIN END END + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDI_LANG_NAME "English" +END + #endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/WinMute/WinMute.vcxproj b/WinMute/WinMute.vcxproj index 2af7e7b..9dfba47 100644 --- a/WinMute/WinMute.vcxproj +++ b/WinMute/WinMute.vcxproj @@ -205,6 +205,7 @@ + @@ -240,6 +241,7 @@ + diff --git a/WinMute/WinMute.vcxproj.filters b/WinMute/WinMute.vcxproj.filters index bc4070f..c12cc05 100644 --- a/WinMute/WinMute.vcxproj.filters +++ b/WinMute/WinMute.vcxproj.filters @@ -101,6 +101,9 @@ Source Files\Controllers\Bluetooth + + Source Files\Base\Settings + @@ -188,5 +191,8 @@ Source Files\UI\Dialogs\Settings + + Source Files\Base\Settings + \ No newline at end of file diff --git a/WinMute/common.h b/WinMute/common.h index 58261c1..628df31 100644 --- a/WinMute/common.h +++ b/WinMute/common.h @@ -72,6 +72,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +namespace fs = std::filesystem; + #include #include #include @@ -95,6 +97,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "resource.h" +#include "WMi18n.h" #include "WMSettings.h" #include "WMLog.h" #include "TrayIcon.h" @@ -106,7 +109,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "WinMute.h" #include "VersionHelper.h" -namespace fs = std::filesystem; // Utility void PrintWindowsError(const wchar_t *functionName, DWORD lastError = -1); diff --git a/WinMute/resource.h b/WinMute/resource.h index 96e36eb..b6fe63e 100644 --- a/WinMute/resource.h +++ b/WinMute/resource.h @@ -4,6 +4,7 @@ // #define IDI_APP 5 #define IDD_ABOUT 9 +#define IDI_LANG_NAME 101 #define IDI_TRAY_BRIGHT 104 #define IDI_TRAY_DARK 105 #define IDR_TRAYMENU 106 @@ -86,7 +87,6 @@ #define IDC_ENDPOINT_REMOVEALL 1048 #define IDC_ENDPOINT_NAME 1049 #define IDC_MUTEDELAY 1050 -#define IDC_COMBO1 1051 #define IDC_LANGUAGE 1051 #define ID_TRAYMENU_INFO 40001 #define ID_TRAYMENU_ 40002 @@ -129,7 +129,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 139 +#define _APS_NEXT_RESOURCE_VALUE 140 #define _APS_NEXT_COMMAND_VALUE 40037 #define _APS_NEXT_CONTROL_VALUE 1052 #define _APS_NEXT_SYMED_VALUE 101 -- 2.43.0