//{{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
#include "common.h"
-
-
namespace fs = std::filesystem;
-static std::optional<fs::path> 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<std::wstring> 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)
{
case SettingsKey::NOTIFICATIONS_ENABLED:
keyStr = L"ShowNotifications";
break;
+ case SettingsKey::APP_LANGUAGE:
+ keyStr = L"AppLanguage";
+ break;
}
return keyStr;
}
return 0;
case SettingsKey::NOTIFICATIONS_ENABLED:
return 0;
+ case SettingsKey::APP_LANGUAGE:
+ return 0;
}
return 0;
}
hWifiKey_ = nullptr;
RegCloseKey(hBluetoothKey_);
hBluetoothKey_ = nullptr;
- UnloadLanguage();
}
HKEY WMSettings::OpenAutostartKey(REGSAM samDesired)
return value;
}
+std::optional<std::wstring> 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);
return true;
}
+bool WMSettings::SetValue(SettingsKey key, const std::wstring &value)
+{
+ auto keyStr = KeyToStr(key);
+ assert(keyStr != nullptr);
+
+ BYTE *strValue = reinterpret_cast<BYTE *>(const_cast<wchar_t *>(value.c_str()));
+ DWORD strLen = static_cast<DWORD>((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<std::wstring>& networks)
{
// Clear all stored keys
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;
- }
-}
, QUIETHOURS_END
, NOTIFICATIONS_ENABLED
, LOGGING_ENABLED
+ , APP_LANGUAGE
};
class WMSettings {
DWORD QueryValue(SettingsKey key) const;
bool SetValue(SettingsKey key, DWORD value);
- bool SetLanguage(const std::wstring &dllName);
- std::wstring GetString(UINT strId);
+ std::optional<std::wstring> QueryStrValue(SettingsKey key) const;
+ bool SetValue(SettingsKey key, const std::wstring &value);
private:
HKEY hSettingsKey_;
HKEY hBluetoothKey_;
HKEY hAudioEndpointsKey_;
- HMODULE textModule_;
-
bool MigrateSettings();
HKEY OpenAutostartKey(REGSAM samDesired);
- void UnloadLanguage();
};
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,
}
MSG msg = { nullptr };
- WinMute program;
+ WinMute program(settings);
if (program.Init()) {
while (GetMessage(&msg, nullptr, 0, 0)) {
HWND hwnd = GetForegroundWindow();
{
}
-WinMute::WinMute() :
+WinMute::WinMute(WMSettings& settings) :
hWnd_(nullptr),
hTrayMenu_(nullptr),
hAppIcon_(nullptr),
- hTrayIcon_(nullptr)
+ hTrayIcon_(nullptr),
+ settings_(settings)
{
}
hAppIcon_ = LoadIconW(hglobInstance, MAKEINTRESOURCE(IDI_APP));
- if (!settings_.Init()) {
- return false;
- }
-
#ifdef _DEBUG
WMLog::GetInstance().SetEnabled(true);
#else
class WinMute {
public:
- WinMute();
+ explicit WinMute(WMSettings& settings);
WinMute(const WinMute&) = delete;
WinMute(WinMute&&) = delete;
WinMute& operator=(const WinMute &) = delete;
TrayIcon trayIcon_;
WifiDetector wifiDetector_;
- WMSettings settings_;
+ WMSettings& settings_;
MuteControl muteCtrl_;
QuietHoursTimer quietHours_;
BluetoothDetector btDetector_;
END
END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDI_LANG_NAME "English"
+END
+
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
<ClInclude Include="BluetoothDetector.h" />
<ClInclude Include="common.h" />
<ClInclude Include="WiFiDetector.h" />
+ <ClInclude Include="WMi18n.h" />
<ClInclude Include="WMLog.h" />
<ClInclude Include="MMNotificationClient.h" />
<ClInclude Include="MuteControl.h" />
<ClCompile Include="Settings_MuteDlg.cpp" />
<ClCompile Include="Settings_WifiDlg.cpp" />
<ClCompile Include="WifiDetector.cpp" />
+ <ClCompile Include="WMi18n.cpp" />
<ClCompile Include="WMLog.cpp" />
<ClCompile Include="MMNotificationClient.cpp" />
<ClCompile Include="MuteControl.cpp" />
<ClInclude Include="BluetoothDetector.h">
<Filter>Source Files\Controllers\Bluetooth</Filter>
</ClInclude>
+ <ClInclude Include="WMi18n.h">
+ <Filter>Source Files\Base\Settings</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WinMute.rc">
<ClCompile Include="Settings_ManageEndpointsDlg.cpp">
<Filter>Source Files\UI\Dialogs\Settings</Filter>
</ClCompile>
+ <ClCompile Include="WMi18n.cpp">
+ <Filter>Source Files\Base\Settings</Filter>
+ </ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
#include <unordered_map>
#include <vector>
+namespace fs = std::filesystem;
+
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
+#include "WMi18n.h"
#include "WMSettings.h"
#include "WMLog.h"
#include "TrayIcon.h"
#include "WinMute.h"
#include "VersionHelper.h"
-namespace fs = std::filesystem;
// Utility
void PrintWindowsError(const wchar_t *functionName, DWORD lastError = -1);
//
#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
#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
//
#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