From 577b2bcb5ae6f754295dbcdaa92551d144f54403 Mon Sep 17 00:00:00 2001 From: lx-s Date: Sat, 7 Oct 2023 08:01:28 +0200 Subject: [PATCH] #26 Added language loading functions to settings --- WinMute/Settings_GeneralDlg.cpp | 30 ++++++++++++++++ WinMute/WMSettings.cpp | 61 ++++++++++++++++++++++++++++++++- WinMute/WMSettings.h | 6 ++++ WinMute/WinMute.rc | 10 +++--- WinMute/common.h | 3 ++ WinMute/resource.h | 4 ++- 6 files changed, 108 insertions(+), 6 deletions(-) diff --git a/WinMute/Settings_GeneralDlg.cpp b/WinMute/Settings_GeneralDlg.cpp index ff06889..55fbbb1 100644 --- a/WinMute/Settings_GeneralDlg.cpp +++ b/WinMute/Settings_GeneralDlg.cpp @@ -33,6 +33,36 @@ POSSIBILITY OF SUCH DAMAGE. #include "common.h" + + +namespace fs = std::filesystem; + +static std::optional 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); +} + INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { diff --git a/WinMute/WMSettings.cpp b/WinMute/WMSettings.cpp index 9bac35d..e616a0b 100644 --- a/WinMute/WMSettings.cpp +++ b/WinMute/WMSettings.cpp @@ -47,6 +47,8 @@ static const wchar_t *LX_SYSTEMS_AUDIO_ENDPOINTS_SUBKEY static const wchar_t* LX_SYSTEMS_AUTOSTART_KEY = L"LX-Systems WinMute"; +extern HINSTANCE hglobInstance; + static const wchar_t* KeyToStr(SettingsKey key) { const wchar_t* keyStr = nullptr; @@ -168,7 +170,6 @@ static DWORD GetDefaultSetting(SettingsKey key) return 0; } - template static void NormalizeStringList(std::vector> &items) { @@ -323,6 +324,7 @@ void WMSettings::Unload() noexcept hWifiKey_ = nullptr; RegCloseKey(hBluetoothKey_); hBluetoothKey_ = nullptr; + UnloadLanguage(); } HKEY WMSettings::OpenAutostartKey(REGSAM samDesired) @@ -728,3 +730,60 @@ 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 94ac1ab..db901fb 100644 --- a/WinMute/WMSettings.h +++ b/WinMute/WMSettings.h @@ -93,12 +93,18 @@ public: DWORD QueryValue(SettingsKey key) const; bool SetValue(SettingsKey key, DWORD value); + bool SetLanguage(const std::wstring &dllName); + std::wstring GetString(UINT strId); + private: HKEY hSettingsKey_; HKEY hWifiKey_; HKEY hBluetoothKey_; HKEY hAudioEndpointsKey_; + HMODULE textModule_; + bool MigrateSettings(); HKEY OpenAutostartKey(REGSAM samDesired); + void UnloadLanguage(); }; diff --git a/WinMute/WinMute.rc b/WinMute/WinMute.rc index 327ff56..75a56b9 100644 --- a/WinMute/WinMute.rc +++ b/WinMute/WinMute.rc @@ -79,10 +79,12 @@ EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "Start WinMute on system startup",IDC_RUNONSTARTUP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,9,219,17 - CONTROL "Enable logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,31,219,15 - PUSHBUTTON "Open log file...",IDC_OPENLOG,22,50,58,15 - LTEXT "[log file path]",IDC_LOGFILEPATH,23,67,203,27 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,30,219,17 + CONTROL "Enable logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,52,219,15 + PUSHBUTTON "Open log file...",IDC_OPENLOG,22,71,58,15 + LTEXT "[log file path]",IDC_LOGFILEPATH,23,88,203,27 + LTEXT "Language",IDC_STATIC,7,14,41,10 + COMBOBOX IDC_LANGUAGE,51,12,87,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP END IDD_SETTINGS_QUIETHOURS DIALOGEX 0, 0, 246, 198 diff --git a/WinMute/common.h b/WinMute/common.h index 484b002..58261c1 100644 --- a/WinMute/common.h +++ b/WinMute/common.h @@ -62,6 +62,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -105,6 +106,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "WinMute.h" #include "VersionHelper.h" +namespace fs = std::filesystem; + // Utility void PrintWindowsError(const wchar_t *functionName, DWORD lastError = -1); bool GetWinMuteVersion(std::wstring &versNumber); diff --git a/WinMute/resource.h b/WinMute/resource.h index a63240e..96e36eb 100644 --- a/WinMute/resource.h +++ b/WinMute/resource.h @@ -86,6 +86,8 @@ #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 #define ID_TRAYMENU_MUTEON 40003 @@ -129,7 +131,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 139 #define _APS_NEXT_COMMAND_VALUE 40037 -#define _APS_NEXT_CONTROL_VALUE 1051 +#define _APS_NEXT_CONTROL_VALUE 1052 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif -- 2.43.0