From 9d5efc686b6fc5c0842131f3bc9c2573b563b63f Mon Sep 17 00:00:00 2001 From: lx-s Date: Tue, 18 Aug 2026 14:54:59 +0200 Subject: [PATCH] Reworked settings UI. --- Translations/lang-de.json | 21 +- Translations/lang-en.json | 21 +- Translations/lang-es.json | 21 +- Translations/lang-fr.json | 21 +- Translations/lang-it.json | 21 +- Translations/lang-ko.json | 21 +- Translations/lang-lv.json | 21 +- Translations/lang-nl.json | 21 +- Translations/lang-ro.json | 21 +- Translations/lang-ru.json | 21 +- Translations/lang-zh_Hans.json | 21 +- WinMute/SettingsDlg.cpp | 538 ++++++++++++++++++------ WinMute/Settings_BluetoothDlg.cpp | 6 +- WinMute/Settings_GeneralDlg.cpp | 416 +++++++++++------- WinMute/Settings_ManageEndpointsDlg.cpp | 138 +++--- WinMute/Settings_MuteDlg.cpp | 119 +++--- WinMute/Settings_QuietHoursDlg.cpp | 3 - WinMute/Settings_WifiDlg.cpp | 14 +- WinMute/WinMute.rc | 264 ++++++------ WinMute/resource.h | 14 +- 20 files changed, 1116 insertions(+), 627 deletions(-) diff --git a/Translations/lang-de.json b/Translations/lang-de.json index 192848b..f8b2f82 100644 --- a/Translations/lang-de.json +++ b/Translations/lang-de.json @@ -61,11 +61,19 @@ "settings.btn-edit": "Bearbeiten", "settings.btn-remove": "Entfernen", "settings.btn-remove-all": "Alle entfernen", - "settings.tab.general": "Allgemein", - "settings.tab.mute": "Stummschalten", - "settings.tab.quiet-hours": "Ruhezeit", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Allgemein", + "settings.nav.general.language": "Sprache", + "settings.nav.general.startup": "Start & Updates", + "settings.nav.general.hotkeys": "Tastenkürzel", + "settings.nav.general.logging": "Protokollierung", + "settings.nav.muting": "Stummschalten", + "settings.nav.muting.events": "Ereignisse", + "settings.nav.muting.endpoints": "Audiogeräte", + "settings.nav.muting.media": "Mediensteuerung", + "settings.nav.triggers": "Auslöser", + "settings.nav.triggers.quiet-hours": "Ruhezeit", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Bluetooth-Gerät hinzufügen", "settings.bluetooth.add-edit.edit-title": "Bluetooth-Gerät bearbeiten", "settings.bluetooth.add-edit.device-name-label": "Bluetooth Gerätename:", @@ -80,10 +88,8 @@ "settings.bluetooth.enable-muting": "\"Bluetooth Stummschalten\" aktivieren", "settings.bluetooth.enable-muting-filter": "Nur für die folgenden Geräte aktivieren:", "settings.bluetooth-disabled-info": "Info: Bluetooth ist auf diesem Gerät nicht verfügbar.\nEinige Optionen wurden deaktiviert.", - "settings.mute.general-title": "Allgemein", "settings.mute.show-mute-event-notifications": "Zeige Benachrichtigungen an", "settings.mute.manage-endpoints-individually": "Verwalte Audiogeräte individuell", - "settings.mute.btn-manage-endpoints": "Audiogeräte verwalten...", "settings.mute.mute-with-restore.title": "Stummschalten mit Lautstärkewiederherstellung, wenn...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... der PC gesperrt wird", "settings.mute.mute-with-restore.when-screen-turns-off": "... der Bildschirm in Standby geht", @@ -120,7 +126,6 @@ "settings.wifi.add-edit.edit-title": "WLAN Netzwerk bearbeiten", "settings.wifi.add-edit.ssid-name-label": "SSID/WLAN-Name:", "settings.wifi.add-edit.enter-device-name-placeholder": "Bitte geben sie einen WLAN Netzwerknamen ein", - "settings.mute.manage-endpoints.title": "Audiogeräte verwalten", "settings.mute.manage-endpoints.list-behaviour.title": "Allgemein", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Nur gespeicherte Audiogeräte stummschalten", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Alle bis auf die gespeicherten Audiogeräte stummschalten", diff --git a/Translations/lang-en.json b/Translations/lang-en.json index 85f5ab2..61eb12c 100644 --- a/Translations/lang-en.json +++ b/Translations/lang-en.json @@ -67,11 +67,19 @@ "settings.btn-edit": "Edit", "settings.btn-remove": "Remove", "settings.btn-remove-all": "Remove all", - "settings.tab.general": "General", - "settings.tab.mute": "Mute", - "settings.tab.quiet-hours": "Quiet Hours", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "General", + "settings.nav.general.language": "Language", + "settings.nav.general.startup": "Startup & Updates", + "settings.nav.general.hotkeys": "Hotkeys", + "settings.nav.general.logging": "Logging", + "settings.nav.muting": "Muting", + "settings.nav.muting.events": "Mute events", + "settings.nav.muting.endpoints": "Audio devices", + "settings.nav.muting.media": "Media control", + "settings.nav.triggers": "Triggers", + "settings.nav.triggers.quiet-hours": "Quiet Hours", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Add Bluetooth device", "settings.bluetooth.add-edit.edit-title": "Edit Bluetooth device", "settings.bluetooth.add-edit.device-name-label": "Bluetooth device name:", @@ -90,10 +98,8 @@ "settings.bluetooth.enable-muting": "Enable Bluetooth-based muting", "settings.bluetooth.enable-muting-filter": "Enable only for these devices:", "settings.bluetooth.bluetooth-disabled-info": "Note: Bluetooth is not available on this device.\nSome options have been disabled.", - "settings.mute.general-title": "General", "settings.mute.show-mute-event-notifications": "Show mute event notifications", "settings.mute.manage-endpoints-individually": "Manage audio devices individually", - "settings.mute.btn-manage-endpoints": "Manage devices...", "settings.mute.mute-with-restore.title": "Mute with volume restore, when...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... the computer is locked", "settings.mute.mute-with-restore.when-screen-turns-off": "... the screen turns off", @@ -131,7 +137,6 @@ "settings.wifi.add-edit.edit-title": "Edit WiFi network", "settings.wifi.add-edit.ssid-name-label": "SSID/WiFi Name:", "settings.wifi.add-edit.enter-device-name-placeholder": "Please enter a SSID/WiFi name", - "settings.mute.manage-endpoints.title": "Manage audio devices", "settings.mute.manage-endpoints.list-behaviour.title": "General", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Mute only listed devices", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Mute all but listed devices", diff --git a/Translations/lang-es.json b/Translations/lang-es.json index b2651db..b146342 100644 --- a/Translations/lang-es.json +++ b/Translations/lang-es.json @@ -55,11 +55,19 @@ "settings.btn-edit": "Editar", "settings.btn-remove": "Quitar", "settings.btn-remove-all": "Quitar todo", - "settings.tab.general": "General", - "settings.tab.mute": "Silencio", - "settings.tab.quiet-hours": "Horas de silencio", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "General", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "Silencio", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "Administrar dispositivos de audio", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "Horas de silencio", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Añade un dispositivo Bluetooth", "settings.bluetooth.add-edit.edit-title": "Editar dispositivo Bluetooth", "settings.bluetooth.add-edit.device-name-label": "Nombre del dispositivo Bluetooth:", @@ -72,10 +80,8 @@ "settings.bluetooth.enable-muting": "Activar el silenciamiento basado en Bluetooth", "settings.bluetooth.enable-muting-filter": "Activar sólo para estos dispositivos:", "settings.bluetooth-disabled-info": "", - "settings.mute.general-title": "General", "settings.mute.show-mute-event-notifications": "Mostrar notificaciones de eventos silenciados", "settings.mute.manage-endpoints-individually": "Gestiona individualmente los dispositivos de audio", - "settings.mute.btn-manage-endpoints": "Gestiona los dispositivos...", "settings.mute.mute-with-restore.title": "Silencio con restauración del volumen, cuando...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... el ordenador está bloqueado", "settings.mute.mute-with-restore.when-screen-turns-off": "... la pantalla se apaga", @@ -106,7 +112,6 @@ "settings.wifi.add-edit.edit-title": "Editar red WiFi", "settings.wifi.add-edit.ssid-name-label": "Nombre SSID/WiFi:", "settings.wifi.add-edit.enter-device-name-placeholder": "Por favor proporcione un nombre de SSID/WiFi", - "settings.mute.manage-endpoints.title": "Administrar dispositivos de audio", "settings.mute.manage-endpoints.list-behaviour.title": "General", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Silenciar solo los dispositivos listados", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Silenciar todo excepto los dispositivos listados", diff --git a/Translations/lang-fr.json b/Translations/lang-fr.json index d3aeaa6..f01f7b0 100644 --- a/Translations/lang-fr.json +++ b/Translations/lang-fr.json @@ -61,11 +61,19 @@ "settings.btn-edit": "Éditer", "settings.btn-remove": "Retirer", "settings.btn-remove-all": "Retirer tout", - "settings.tab.general": "Menu Général", - "settings.tab.mute": "Muet", - "settings.tab.quiet-hours": "Réglages pendant la coupure", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Menu Général", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "Muet", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "Gérer les périphériques audio", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "Réglages pendant la coupure", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Ajouter un périphérique Bluetooth", "settings.bluetooth.add-edit.edit-title": "Modifier le périphérique Bluetooth", "settings.bluetooth.add-edit.device-name-label": "Nom du périphérique Bluetooth :", @@ -82,10 +90,8 @@ "settings.bluetooth.enable-muting": "Activer la coupure de son via Bluetooth", "settings.bluetooth.enable-muting-filter": "Activer seulement pour ces périphériques :", "settings.bluetooth.bluetooth-disabled-info": "Remarque : le Bluetooth n'est pas disponible sur ce périphérique.\nCertaines options ont été désactivées.", - "settings.mute.general-title": "Général", "settings.mute.show-mute-event-notifications": "Afficher les notifications d'événements en sourdine", "settings.mute.manage-endpoints-individually": "Gérer les périphériques audio individuellement", - "settings.mute.btn-manage-endpoints": "Gérer les périphériques...", "settings.mute.mute-with-restore.title": "Couper le son avec restauration du volume, si...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... l'ordinateur est verrouillé", "settings.mute.mute-with-restore.when-screen-turns-off": "... l'écran s'éteint", @@ -116,7 +122,6 @@ "settings.wifi.add-edit.edit-title": "Modifier le réseau WiFi", "settings.wifi.add-edit.ssid-name-label": "SSID/Nom Wi-Fi :", "settings.wifi.add-edit.enter-device-name-placeholder": "Veuillez saisir un nom SSID/WiFi", - "settings.mute.manage-endpoints.title": "Gérer les périphériques audio", "settings.mute.manage-endpoints.list-behaviour.title": "Général", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Couper le son seulement des périphériques répertoriés", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Couper le son de tous les périphériques sauf ceux répertoriés", diff --git a/Translations/lang-it.json b/Translations/lang-it.json index b214237..ff58802 100644 --- a/Translations/lang-it.json +++ b/Translations/lang-it.json @@ -55,11 +55,19 @@ "settings.btn-edit": "Modifica", "settings.btn-remove": "Rimuovi", "settings.btn-remove-all": "Rimuovi tutto", - "settings.tab.general": "Generale", - "settings.tab.mute": "Disattiva audio", - "settings.tab.quiet-hours": "Ore silenzio", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Generale", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "Disattiva audio", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "Gestisci dispositivi audio", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "Ore silenzio", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Aggiungi dispositivo Bluetooth", "settings.bluetooth.add-edit.edit-title": "Modifica dispositivo Bluetooth", "settings.bluetooth.add-edit.device-name-label": "Nome dispositivo Bluetooth:", @@ -72,10 +80,8 @@ "settings.bluetooth.enable-muting": "Abilita disabilitazione audio basata su hardware Bluetooth", "settings.bluetooth.enable-muting-filter": "Abilita solo per questi dispositivi:", "settings.bluetooth.bluetooth-disabled-info": "Nota: il Bluetooth non è disponibile nel dispositivo, quindi alcune opzioni sono state disabilitate.", - "settings.mute.general-title": "Generale", "settings.mute.show-mute-event-notifications": "Visualizza notifiche eventi disattivazione", "settings.mute.manage-endpoints-individually": "Gestisci i dispositivi audio individualmente", - "settings.mute.btn-manage-endpoints": "Gestisci dispositivi audio...", "settings.mute.mute-with-restore.title": "Disattiva audio con ripristino del volume, quando...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... il computer viene bloccato", "settings.mute.mute-with-restore.when-screen-turns-off": "... lo schermo viene spento", @@ -105,7 +111,6 @@ "settings.wifi.add-edit.edit-title": "Modifica rete WiFi", "settings.wifi.add-edit.ssid-name-label": "Nome SSID/WiFi:", "settings.wifi.add-edit.enter-device-name-placeholder": "Inserisci un nome SSID/WiFi", - "settings.mute.manage-endpoints.title": "Gestisci dispositivi audio", "settings.mute.manage-endpoints.list-behaviour.title": "Generale", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Disattiva solo i dispositivi audio elencati", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Disattiva tutti i dispositivi audio tranne quelli elencati", diff --git a/Translations/lang-ko.json b/Translations/lang-ko.json index 20ad56a..9cc9912 100644 --- a/Translations/lang-ko.json +++ b/Translations/lang-ko.json @@ -61,11 +61,19 @@ "settings.btn-edit": "편집", "settings.btn-remove": "삭제", "settings.btn-remove-all": "모두 삭제", - "settings.tab.general": "일반", - "settings.tab.mute": "음소거", - "settings.tab.quiet-hours": "무음 시간", - "settings.tab.bluetooth": "블루투스", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "일반", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "음소거", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "오디오 장치 관리", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "무음 시간", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "블루투스", "settings.bluetooth.add-edit.add-title": "블루투스 장치 추가", "settings.bluetooth.add-edit.edit-title": "블루투스 장치 편집", "settings.bluetooth.add-edit.device-name-label": "블루투스 장치명:", @@ -83,10 +91,8 @@ "settings.bluetooth.enable-muting": "블루투스 기반 음소거 활성화", "settings.bluetooth.enable-muting-filter": "다음 장치에만 활성화:", "settings.bluetooth.bluetooth-disabled-info": "참고: 이 기기에서는 블루투스를 사용할 수 없습니다.\n일부 옵션이 비활성화되었습니다.", - "settings.mute.general-title": "일반", "settings.mute.show-mute-event-notifications": "음소거 이벤트 알림 표시", "settings.mute.manage-endpoints-individually": "오디오 장치를 개별적으로 관리", - "settings.mute.btn-manage-endpoints": "장치 관리...", "settings.mute.mute-with-restore.title": "다음 상황에서 음소거 후 볼륨 복원...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... 컴퓨터가 잠길 때", "settings.mute.mute-with-restore.when-screen-turns-off": "... 화면 꺼질 때", @@ -117,7 +123,6 @@ "settings.wifi.add-edit.edit-title": "WiFi 네트워크 편집", "settings.wifi.add-edit.ssid-name-label": "SSID/WiFi 이름:", "settings.wifi.add-edit.enter-device-name-placeholder": "SSID/WiFi 이름을 입력해주세요", - "settings.mute.manage-endpoints.title": "오디오 장치 관리", "settings.mute.manage-endpoints.list-behaviour.title": "일반", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "목록의 장치만 음소거", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "목록에 있는 장치만 전체 음소거", diff --git a/Translations/lang-lv.json b/Translations/lang-lv.json index 2f83f0f..8937126 100644 --- a/Translations/lang-lv.json +++ b/Translations/lang-lv.json @@ -60,11 +60,19 @@ "settings.btn-edit": "Labot", "settings.btn-remove": "Noņemt", "settings.btn-remove-all": "", - "settings.tab.general": "Vispārīgie", - "settings.tab.mute": "", - "settings.tab.quiet-hours": "", - "settings.tab.bluetooth": "", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Vispārīgie", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "", "settings.bluetooth.add-edit.add-title": "Pievienot Bluetooth ierīci", "settings.bluetooth.add-edit.edit-title": "", "settings.bluetooth.add-edit.device-name-label": "Bluetooth ierīces nosaukums:", @@ -81,10 +89,8 @@ "settings.bluetooth.enable-muting": "", "settings.bluetooth.enable-muting-filter": "", "settings.bluetooth.bluetooth-disabled-info": "", - "settings.mute.general-title": "", "settings.mute.show-mute-event-notifications": "", "settings.mute.manage-endpoints-individually": "", - "settings.mute.btn-manage-endpoints": "", "settings.mute.mute-with-restore.title": "", "settings.mute.mute-with-restore.when-workstation-is-locked": "", "settings.mute.mute-with-restore.when-screen-turns-off": "", @@ -115,7 +121,6 @@ "settings.wifi.add-edit.edit-title": "", "settings.wifi.add-edit.ssid-name-label": "SSID/Wi-Fi nosaukums:", "settings.wifi.add-edit.enter-device-name-placeholder": "", - "settings.mute.manage-endpoints.title": "", "settings.mute.manage-endpoints.list-behaviour.title": "", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "", diff --git a/Translations/lang-nl.json b/Translations/lang-nl.json index 1349200..fe71ad9 100644 --- a/Translations/lang-nl.json +++ b/Translations/lang-nl.json @@ -55,11 +55,19 @@ "settings.btn-edit": "Wijzigen", "settings.btn-remove": "Verwijderen", "settings.btn-remove-all": "Verwijder alles", - "settings.tab.general": "Algemeen", - "settings.tab.mute": "Dempen", - "settings.tab.quiet-hours": "Stille uren", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Algemeen", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "Dempen", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "Stille uren", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Bluetoothapparaat toevoegen", "settings.bluetooth.add-edit.edit-title": "Bluetoothapparaat wijzigen", "settings.bluetooth.add-edit.device-name-label": "Naam Bluetoothapparaat:", @@ -72,10 +80,8 @@ "settings.bluetooth.enable-muting": "Schakel Bluetoothgebaseerde demping in", "settings.bluetooth.enable-muting-filter": "Enkel inschakelen voor deze apparaten:", "settings.bluetooth.bluetooth-disabled-info": "Let op: Bluetooth is niet beschikbaar op dit apparaat.\nSommige opties zijn uitgeschakeld.", - "settings.mute.general-title": "Algemeen", "settings.mute.show-mute-event-notifications": "Toon dempgebeurtenisnotificaties", "settings.mute.manage-endpoints-individually": "Beheer audioapparaten individueel", - "settings.mute.btn-manage-endpoints": "Beheer apparaten...", "settings.mute.mute-with-restore.title": "Demp met herstel van volume, als...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... De computer afgesloten is", "settings.mute.mute-with-restore.when-screen-turns-off": "... het scherm uitvalt", @@ -105,7 +111,6 @@ "settings.wifi.add-edit.edit-title": "", "settings.wifi.add-edit.ssid-name-label": "", "settings.wifi.add-edit.enter-device-name-placeholder": "", - "settings.mute.manage-endpoints.title": "", "settings.mute.manage-endpoints.list-behaviour.title": "", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "", diff --git a/Translations/lang-ro.json b/Translations/lang-ro.json index 776b70f..0b007c5 100644 --- a/Translations/lang-ro.json +++ b/Translations/lang-ro.json @@ -60,11 +60,19 @@ "settings.btn-edit": "", "settings.btn-remove": "", "settings.btn-remove-all": "", - "settings.tab.general": "", - "settings.tab.mute": "", - "settings.tab.quiet-hours": "", - "settings.tab.bluetooth": "", - "settings.tab.wifi": "", + "settings.nav.general": "", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "", + "settings.nav.triggers.wifi": "", + "settings.nav.triggers.bluetooth": "", "settings.bluetooth.add-edit.add-title": "", "settings.bluetooth.add-edit.edit-title": "", "settings.bluetooth.add-edit.device-name-label": "", @@ -81,10 +89,8 @@ "settings.bluetooth.enable-muting": "", "settings.bluetooth.enable-muting-filter": "", "settings.bluetooth.bluetooth-disabled-info": "", - "settings.mute.general-title": "", "settings.mute.show-mute-event-notifications": "", "settings.mute.manage-endpoints-individually": "", - "settings.mute.btn-manage-endpoints": "", "settings.mute.mute-with-restore.title": "", "settings.mute.mute-with-restore.when-workstation-is-locked": "", "settings.mute.mute-with-restore.when-screen-turns-off": "", @@ -115,7 +121,6 @@ "settings.wifi.add-edit.edit-title": "", "settings.wifi.add-edit.ssid-name-label": "", "settings.wifi.add-edit.enter-device-name-placeholder": "", - "settings.mute.manage-endpoints.title": "", "settings.mute.manage-endpoints.list-behaviour.title": "", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "", diff --git a/Translations/lang-ru.json b/Translations/lang-ru.json index 38d08de..7ba34c8 100644 --- a/Translations/lang-ru.json +++ b/Translations/lang-ru.json @@ -61,11 +61,19 @@ "settings.btn-edit": "Изменить", "settings.btn-remove": "Удалить", "settings.btn-remove-all": "Удалить все", - "settings.tab.general": "Основные", - "settings.tab.mute": "Выключить звук", - "settings.tab.quiet-hours": "Тихие часы", - "settings.tab.bluetooth": "Bluetooth", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "Основные", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "Выключить звук", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "Управление аудиоустройствами", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "Тихие часы", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "Bluetooth", "settings.bluetooth.add-edit.add-title": "Добавить устройство Bluetooth", "settings.bluetooth.add-edit.edit-title": "Изменить устройство Bluetooth", "settings.bluetooth.add-edit.device-name-label": "Название устройства Bluetooth:", @@ -82,10 +90,8 @@ "settings.bluetooth.enable-muting": "Включить выключение звука на основе Bluetooth", "settings.bluetooth.enable-muting-filter": "Включить только для этих устройств:", "settings.bluetooth.bluetooth-disabled-info": "Примечание: Bluetooth недоступен на этом устройстве.\nНекоторые параметры отсутствуют.", - "settings.mute.general-title": "Общие", "settings.mute.show-mute-event-notifications": "Показывать уведомления о событиях отключения звука", "settings.mute.manage-endpoints-individually": "Управление аудиоустройствами по отдельности", - "settings.mute.btn-manage-endpoints": "Управление устройствами...", "settings.mute.mute-with-restore.title": "Выключение звука с восстановлением громкости, когда...", "settings.mute.mute-with-restore.when-workstation-is-locked": "... компьютер заблокирован", "settings.mute.mute-with-restore.when-screen-turns-off": "... экран выключается", @@ -116,7 +122,6 @@ "settings.wifi.add-edit.edit-title": "Изменить сеть WiFi", "settings.wifi.add-edit.ssid-name-label": "Название SSID/WiFi:", "settings.wifi.add-edit.enter-device-name-placeholder": "Введите название SSID/WiFi", - "settings.mute.manage-endpoints.title": "Управление аудиоустройствами", "settings.mute.manage-endpoints.list-behaviour.title": "Общие", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "Выключить звук только для перечисленных устройств", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "Выключить звук для всех, кроме перечисленных устройств", diff --git a/Translations/lang-zh_Hans.json b/Translations/lang-zh_Hans.json index 14a9483..07704d4 100644 --- a/Translations/lang-zh_Hans.json +++ b/Translations/lang-zh_Hans.json @@ -61,11 +61,19 @@ "settings.btn-edit": "编辑", "settings.btn-remove": "移除", "settings.btn-remove-all": "全部移除", - "settings.tab.general": "常规", - "settings.tab.mute": "静音", - "settings.tab.quiet-hours": "免打扰时间", - "settings.tab.bluetooth": "蓝牙", - "settings.tab.wifi": "WLAN", + "settings.nav.general": "常规", + "settings.nav.general.language": "", + "settings.nav.general.startup": "", + "settings.nav.general.hotkeys": "", + "settings.nav.general.logging": "", + "settings.nav.muting": "静音", + "settings.nav.muting.events": "", + "settings.nav.muting.endpoints": "管理音频设备", + "settings.nav.muting.media": "", + "settings.nav.triggers": "", + "settings.nav.triggers.quiet-hours": "免打扰时间", + "settings.nav.triggers.wifi": "WLAN", + "settings.nav.triggers.bluetooth": "蓝牙", "settings.bluetooth.add-edit.add-title": "添加蓝牙设备", "settings.bluetooth.add-edit.edit-title": "编辑蓝牙设备", "settings.bluetooth.add-edit.device-name-label": "蓝牙设备名称:", @@ -82,10 +90,8 @@ "settings.bluetooth.enable-muting": "启用基于蓝牙的静音功能", "settings.bluetooth.enable-muting-filter": "仅对以下设备启用:", "settings.bluetooth.bluetooth-disabled-info": "注意:蓝牙在此设备上不可用。\n部分选项已被禁用。", - "settings.mute.general-title": "常规", "settings.mute.show-mute-event-notifications": "显示静音事件通知", "settings.mute.manage-endpoints-individually": "单独管理音频设备", - "settings.mute.btn-manage-endpoints": "管理设备…", "settings.mute.mute-with-restore.title": "在以下情况静音并恢复音量…", "settings.mute.mute-with-restore.when-workstation-is-locked": "…计算机锁定时", "settings.mute.mute-with-restore.when-screen-turns-off": "…屏幕关闭时", @@ -116,7 +122,6 @@ "settings.wifi.add-edit.edit-title": "编辑 Wi-Fi 网络", "settings.wifi.add-edit.ssid-name-label": "SSID/Wi-Fi 名称:", "settings.wifi.add-edit.enter-device-name-placeholder": "请输入 SSID/Wi-Fi 名称", - "settings.mute.manage-endpoints.title": "管理音频设备", "settings.mute.manage-endpoints.list-behaviour.title": "常规", "settings.mute.manage-endpoints.list-behaviour.mute-only-listed": "仅静音已列出的设备", "settings.mute.manage-endpoints.list-behaviour.mute-all-but-listed": "静音除已列出设备外的所有设备", diff --git a/WinMute/SettingsDlg.cpp b/WinMute/SettingsDlg.cpp index f5185f4..79e0ac9 100644 --- a/WinMute/SettingsDlg.cpp +++ b/WinMute/SettingsDlg.cpp @@ -33,93 +33,384 @@ POSSIBILITY OF SUCH DAMAGE. #include "common.h" -enum SettingsTabsIDs { - SETTINGS_TAB_GENERAL = 0, - SETTINGS_TAB_MUTE, - SETTINGS_TAB_QUIETHOURS, - SETTINGS_TAB_BLUETOOTH, - SETTINGS_TAB_WIFI, - SETTINGS_TAB_COUNT +extern INT_PTR CALLBACK Settings_LanguageDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_UpdatesDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_HotkeysDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_LoggingDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_MuteDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND, UINT, WPARAM, + LPARAM); +extern INT_PTR CALLBACK Settings_MediaDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_QuietHoursDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_WifiDlgProc(HWND, UINT, WPARAM, LPARAM); +extern INT_PTR CALLBACK Settings_BluetoothDlgProc(HWND, UINT, WPARAM, LPARAM); + +extern HINSTANCE hglobInstance; + +// The settings pages, in the order the navigation tree lists them. Every +// group below covers a contiguous run of this enum, so a group only has to +// name its first page and how many pages follow. +enum SettingsPageId { + SETTINGS_PAGE_LANGUAGE = 0, + SETTINGS_PAGE_UPDATES, + SETTINGS_PAGE_HOTKEYS, + SETTINGS_PAGE_LOGGING, + SETTINGS_PAGE_MUTE, + SETTINGS_PAGE_ENDPOINTS, + SETTINGS_PAGE_MEDIA, + SETTINGS_PAGE_QUIETHOURS, + SETTINGS_PAGE_WIFI, + SETTINGS_PAGE_BLUETOOTH, + SETTINGS_PAGE_COUNT }; -struct SettingsDlgData { - HWND hTabCtrl; - HWND hTabs[SETTINGS_TAB_COUNT]; +struct SettingsPageDesc { + int templateId; + DLGPROC dlgProc; + const char* titleId; +}; - HWND hActiveTab; - WMSettings* settings; +struct SettingsGroupDesc { + const char* titleId; + int firstPage; + int pageCount; +}; - explicit SettingsDlgData(WMSettings* settings) - : settings(settings), hTabCtrl(nullptr), hActiveTab(nullptr) - { - ZeroMemory(hTabs, sizeof(hTabs)); - } +static const SettingsPageDesc SETTINGS_PAGES[SETTINGS_PAGE_COUNT] = { + {IDD_SETTINGS_LANGUAGE, Settings_LanguageDlgProc, + "settings.nav.general.language"}, + {IDD_SETTINGS_UPDATES, Settings_UpdatesDlgProc, + "settings.nav.general.startup"}, + {IDD_SETTINGS_HOTKEYS, Settings_HotkeysDlgProc, + "settings.nav.general.hotkeys"}, + {IDD_SETTINGS_LOGGING, Settings_LoggingDlgProc, + "settings.nav.general.logging"}, + {IDD_SETTINGS_MUTE, Settings_MuteDlgProc, "settings.nav.muting.events"}, + {IDD_SETTINGS_ENDPOINTS, Settings_ManageEndpointsDlgProc, + "settings.nav.muting.endpoints"}, + {IDD_SETTINGS_MEDIA, Settings_MediaDlgProc, "settings.nav.muting.media"}, + {IDD_SETTINGS_QUIETHOURS, Settings_QuietHoursDlgProc, + "settings.nav.triggers.quiet-hours"}, + {IDD_SETTINGS_WIFI, Settings_WifiDlgProc, "settings.nav.triggers.wifi"}, + {IDD_SETTINGS_BLUETOOTH, Settings_BluetoothDlgProc, + "settings.nav.triggers.bluetooth"}, }; -extern INT_PTR CALLBACK Settings_QuietHoursDlgProc(HWND, UINT, WPARAM, LPARAM); -extern INT_PTR CALLBACK Settings_GeneralDlgProc(HWND, UINT, WPARAM, LPARAM); -extern INT_PTR CALLBACK Settings_MuteDlgProc(HWND, UINT, WPARAM, LPARAM); -extern INT_PTR CALLBACK Settings_BluetoothDlgProc(HWND, UINT, WPARAM, LPARAM); -extern INT_PTR CALLBACK Settings_WifiDlgProc(HWND, UINT, WPARAM, LPARAM); +static const SettingsGroupDesc SETTINGS_GROUPS[] = { + {"settings.nav.general", SETTINGS_PAGE_LANGUAGE, 4}, + {"settings.nav.muting", SETTINGS_PAGE_MUTE, 3}, + {"settings.nav.triggers", SETTINGS_PAGE_QUIETHOURS, 3}, +}; -extern HINSTANCE hglobInstance; +// lParam of a tree item that only groups other items and has no page of its +// own. +static constexpr LPARAM SETTINGS_NAV_GROUP = -1; + +// ============================================================================= +// Page host +// +// A plain scrolling viewport: it holds exactly one visible page dialog at a +// time and moves it up and down behind its own client area. The pages keep +// the fixed layout of their dialog template, so only their height matters +// here -- a page taller than the viewport gets a scroll bar, everything else +// is shown as-is. + +static const wchar_t* SETTINGS_HOST_CLASS = L"WinMuteSettingsPageHost"; + +struct PageHostData { + HWND hPage = nullptr; + int pageHeight = 0; // natural height of hPage in pixels + int scrollPos = 0; // pixels of hPage scrolled off the top + int lineHeight = 0; // scroll step of one wheel/arrow line +}; + +static PageHostData* GetPageHostData(HWND hHost) +{ + return reinterpret_cast( + GetWindowLongPtr(hHost, GWLP_USERDATA)); +} + +// Re-applies the current scroll position and stretches the page to the width +// of the viewport. Call whenever the page or the viewport size changes. +static void PageHostUpdateLayout(HWND hHost) +{ + PageHostData* host = GetPageHostData(hHost); + if (host == nullptr) { + return; + } + + RECT clientRect = {0}; + GetClientRect(hHost, &clientRect); + const int clientHeight = clientRect.bottom - clientRect.top; + + const int maxScroll = (std::max)(0, host->pageHeight - clientHeight); + host->scrollPos = std::clamp(host->scrollPos, 0, maxScroll); -static void InsertTabItem(HWND hTabCtrl, UINT id, const wchar_t* itemName) + // Windows hides the scroll bar on its own once the page covers the whole + // range, which also gives the width used below. + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; + si.nMax = (host->pageHeight > 0) ? host->pageHeight - 1 : 0; + si.nPage = clientHeight; + si.nPos = host->scrollPos; + SetScrollInfo(hHost, SB_VERT, &si, TRUE); + + if (host->hPage != nullptr) { + GetClientRect(hHost, &clientRect); + SetWindowPos(host->hPage, nullptr, 0, -host->scrollPos, + clientRect.right - clientRect.left, host->pageHeight, + SWP_NOZORDER | SWP_NOACTIVATE); + } +} + +static void PageHostScrollTo(HWND hHost, int newPos) { - constexpr int bufSize = 50; - wchar_t buf[bufSize]; - TC_ITEM tcItem; - ZeroMemory(&tcItem, sizeof(tcItem)); - tcItem.mask |= TCIF_TEXT; - StringCchCopyW(buf, bufSize, itemName); - tcItem.pszText = buf; - tcItem.cchTextMax = bufSize; - - TabCtrl_InsertItem(hTabCtrl, id, &tcItem); + PageHostData* host = GetPageHostData(hHost); + if (host == nullptr || host->hPage == nullptr) { + return; + } + + RECT clientRect = {0}; + GetClientRect(hHost, &clientRect); + const int clientHeight = clientRect.bottom - clientRect.top; + const int maxScroll = (std::max)(0, host->pageHeight - clientHeight); + newPos = std::clamp(newPos, 0, maxScroll); + if (newPos == host->scrollPos) { + return; + } + + const int delta = host->scrollPos - newPos; + host->scrollPos = newPos; + SetScrollPos(hHost, SB_VERT, host->scrollPos, TRUE); + ScrollWindowEx(hHost, 0, delta, nullptr, nullptr, nullptr, nullptr, + SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE); + UpdateWindow(hHost); } -static void SwitchTab(SettingsDlgData* dlgData, HWND hNewTab) +static void PageHostSetPage(HWND hHost, HWND hPage, int pageHeight) { - if (dlgData->hActiveTab != nullptr) { - ShowWindow(dlgData->hActiveTab, SW_HIDE); + PageHostData* host = GetPageHostData(hHost); + if (host == nullptr || host->hPage == hPage) { + return; + } + + if (host->hPage != nullptr) { + ShowWindow(host->hPage, SW_HIDE); + } + host->hPage = hPage; + host->pageHeight = pageHeight; + host->scrollPos = 0; + PageHostUpdateLayout(hHost); + if (host->hPage != nullptr) { + ShowWindow(host->hPage, SW_SHOW); } - dlgData->hActiveTab = hNewTab; - ShowWindow(dlgData->hActiveTab, SW_SHOW); - // SetFocus(dlgData->hActiveTab); } -static void ResizeTabs(HWND hTabCtrl, HWND* hTabs, int tabCount) +static LRESULT CALLBACK PageHostWndProc(HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam) { - RECT tabCtrlRect = {0}; - GetWindowRect(hTabCtrl, &tabCtrlRect); - POINT tabCtrlPos = {0}; - tabCtrlPos.x = tabCtrlRect.left; - tabCtrlPos.y = tabCtrlRect.top; - ScreenToClient(GetParent(hTabCtrl), &tabCtrlPos); - - GetClientRect(hTabCtrl, &tabCtrlRect); - TabCtrl_AdjustRect(hTabCtrl, FALSE, &tabCtrlRect); - tabCtrlRect.left += tabCtrlPos.x; - tabCtrlRect.top += tabCtrlPos.y; - - HDWP hdwp = BeginDeferWindowPos(tabCount); - if (hdwp == nullptr) { - ShowWindowsError(L"BeginDeferWindowPos", GetLastError()); - } else { - for (int i = 0; i < tabCount; ++i) { - HDWP newHdwp = DeferWindowPos( - hdwp, hTabs[i], HWND_TOP, tabCtrlRect.left, tabCtrlRect.top, - tabCtrlRect.right - tabCtrlRect.left, - tabCtrlRect.bottom - tabCtrlRect.top, 0); - if (newHdwp == nullptr) { - ShowWindowsError(L"DeferWindowPos", GetLastError()); + PageHostData* host = GetPageHostData(hWnd); + switch (msg) { + case WM_CREATE: { + PageHostData* newHost = new PageHostData; + const CREATESTRUCT* cs = + reinterpret_cast(lParam); + newHost->lineHeight = + static_cast(reinterpret_cast(cs->lpCreateParams)); + SetWindowLongPtr(hWnd, GWLP_USERDATA, + reinterpret_cast(newHost)); + return 0; + } + case WM_NCDESTROY: + delete host; + SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); + break; + case WM_SIZE: + PageHostUpdateLayout(hWnd); + return 0; + case WM_VSCROLL: { + if (host == nullptr) { break; - } else { - hdwp = newHdwp; } + RECT clientRect = {0}; + GetClientRect(hWnd, &clientRect); + const int page = clientRect.bottom - clientRect.top; + int newPos = host->scrollPos; + switch (LOWORD(wParam)) { + case SB_LINEUP: + newPos -= host->lineHeight; + break; + case SB_LINEDOWN: + newPos += host->lineHeight; + break; + case SB_PAGEUP: + newPos -= page; + break; + case SB_PAGEDOWN: + newPos += page; + break; + case SB_TOP: + newPos = 0; + break; + case SB_BOTTOM: + newPos = host->pageHeight; + break; + case SB_THUMBTRACK: + case SB_THUMBPOSITION: { + // The 16 bit wParam position tops out at 65535, so ask for + // the full one. + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS; + if (GetScrollInfo(hWnd, SB_VERT, &si)) { + newPos = si.nTrackPos; + } + break; + } + default: + break; + } + PageHostScrollTo(hWnd, newPos); + return 0; } - EndDeferWindowPos(hdwp); + case WM_MOUSEWHEEL: { + if (host == nullptr) { + break; + } + UINT scrollLines = 3; + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0); + RECT clientRect = {0}; + GetClientRect(hWnd, &clientRect); + const int step = + (scrollLines == WHEEL_PAGESCROLL) + ? (clientRect.bottom - clientRect.top) + : static_cast(scrollLines) * host->lineHeight; + const int delta = GET_WHEEL_DELTA_WPARAM(wParam); + PageHostScrollTo( + hWnd, host->scrollPos - MulDiv(delta, step, WHEEL_DELTA)); + return 0; + } + default: + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +static bool RegisterPageHostClass() +{ + static bool registered = false; + if (registered) { + return true; + } + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpfnWndProc = PageHostWndProc; + wc.hInstance = hglobInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = SETTINGS_HOST_CLASS; + if (RegisterClassEx(&wc) == 0) { + ShowWindowsError(L"RegisterClassEx", GetLastError()); + return false; + } + registered = true; + return true; +} + +// ============================================================================= +// Settings dialog + +struct SettingsDlgData { + HWND hTree = nullptr; + HWND hHost = nullptr; + HWND hPages[SETTINGS_PAGE_COUNT] = {nullptr}; + int pageHeights[SETTINGS_PAGE_COUNT] = {0}; + WMSettings* settings = nullptr; + + explicit SettingsDlgData(WMSettings* settings) : settings(settings) + { } +}; + +static HTREEITEM InsertNavItem(HWND hTree, HTREEITEM hParent, + const std::wstring& text, LPARAM data) +{ + TVINSERTSTRUCTW tvis = {0}; + tvis.hParent = (hParent == nullptr) ? TVI_ROOT : hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_PARAM; + tvis.item.pszText = const_cast(text.c_str()); + tvis.item.lParam = data; + return TreeView_InsertItem(hTree, &tvis); +} + +// Returns the tree item of the given page, so the initial selection can be +// made once the whole tree exists. +static HTREEITEM BuildNavTree(HWND hTree, int selectPage) +{ + WMi18n& i18n = WMi18n::GetInstance(); + HTREEITEM hSelect = nullptr; + + for (const auto& group : SETTINGS_GROUPS) { + const HTREEITEM hGroup = + InsertNavItem(hTree, nullptr, i18n.GetTranslationW(group.titleId), + SETTINGS_NAV_GROUP); + for (int i = 0; i < group.pageCount; ++i) { + const int page = group.firstPage + i; + const HTREEITEM hItem = InsertNavItem( + hTree, hGroup, + i18n.GetTranslationW(SETTINGS_PAGES[page].titleId), page); + if (page == selectPage) { + hSelect = hItem; + } + } + TreeView_Expand(hTree, hGroup, TVE_EXPAND); + } + return hSelect; +} + +// Places the page viewport in the gap the dialog template leaves to the right +// of the navigation tree. +static HWND CreatePageHost(HWND hDlg, HWND hTree) +{ + if (!RegisterPageHostClass()) { + return nullptr; + } + + RECT dlgRect = {0}; + GetClientRect(hDlg, &dlgRect); + + RECT treeRect = {0}; + GetWindowRect(hTree, &treeRect); + MapWindowPoints(nullptr, hDlg, reinterpret_cast(&treeRect), 2); + + // Same gap between tree and pages as between tree and dialog border. + RECT unit = {0, 0, 6, 8}; + MapDialogRect(hDlg, &unit); + const int gap = unit.right; + const int left = treeRect.right + gap; + + const HWND hHost = CreateWindowEx( + WS_EX_CONTROLPARENT, SETTINGS_HOST_CLASS, nullptr, + WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_VSCROLL, left, + treeRect.top, dlgRect.right - treeRect.left - left, + treeRect.bottom - treeRect.top, hDlg, nullptr, hglobInstance, + reinterpret_cast(static_cast(unit.bottom))); + if (hHost == nullptr) { + ShowWindowsError(L"CreateWindowEx", GetLastError()); + } + return hHost; +} + +static void SwitchPage(SettingsDlgData* dlgData, int page) +{ + if (page < 0 || page >= SETTINGS_PAGE_COUNT) { + return; + } + PageHostSetPage(dlgData->hHost, dlgData->hPages[page], + dlgData->pageHeights[page]); } INT_PTR CALLBACK SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, @@ -137,47 +428,43 @@ INT_PTR CALLBACK SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, SetWindowLongPtr(hDlg, DWLP_USER, reinterpret_cast(dlgData)); - dlgData->hTabCtrl = GetDlgItem(hDlg, IDC_SETTINGS_TAB); - SetWindowText(hDlg, i18n.GetTranslationW("settings.title").c_str()); - i18n.SetItemText(hDlg, IDOK, "settings.btn-save"); i18n.SetItemText(hDlg, IDCANCEL, "settings.btn-cancel"); - InsertTabItem(dlgData->hTabCtrl, SETTINGS_TAB_GENERAL, - i18n.GetTranslationW("settings.tab.general").c_str()); - InsertTabItem(dlgData->hTabCtrl, SETTINGS_TAB_MUTE, - i18n.GetTranslationW("settings.tab.mute").c_str()); - InsertTabItem( - dlgData->hTabCtrl, SETTINGS_TAB_QUIETHOURS, - i18n.GetTranslationW("settings.tab.quiet-hours").c_str()); - InsertTabItem( - dlgData->hTabCtrl, SETTINGS_TAB_BLUETOOTH, - i18n.GetTranslationW("settings.tab.bluetooth").c_str()); - InsertTabItem(dlgData->hTabCtrl, SETTINGS_TAB_WIFI, - i18n.GetTranslationW("settings.tab.wifi").c_str()); - - dlgData->hTabs[SETTINGS_TAB_GENERAL] = CreateDialogParam( - hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS_GENERAL), hDlg, - Settings_GeneralDlgProc, reinterpret_cast(settings)); - dlgData->hTabs[SETTINGS_TAB_MUTE] = CreateDialogParam( - hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS_MUTE), hDlg, - Settings_MuteDlgProc, reinterpret_cast(settings)); - dlgData->hTabs[SETTINGS_TAB_QUIETHOURS] = CreateDialogParam( - hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS_QUIETHOURS), hDlg, - Settings_QuietHoursDlgProc, reinterpret_cast(settings)); - dlgData->hTabs[SETTINGS_TAB_WIFI] = CreateDialogParam( - hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS_WIFI), hDlg, - Settings_WifiDlgProc, reinterpret_cast(settings)); - dlgData->hTabs[SETTINGS_TAB_BLUETOOTH] = CreateDialogParam( - hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS_BLUETOOTH), hDlg, - Settings_BluetoothDlgProc, reinterpret_cast(settings)); - - // Init tab pages - ResizeTabs(dlgData->hTabCtrl, dlgData->hTabs, SETTINGS_TAB_COUNT); - for (int i = 0; i < SETTINGS_TAB_COUNT; ++i) { - HWND hCurTab = dlgData->hTabs[i]; - ShowWindow(hCurTab, SW_HIDE); + dlgData->hTree = GetDlgItem(hDlg, IDC_SETTINGS_TREE); + SetWindowTheme(dlgData->hTree, L"Explorer", nullptr); + TreeView_SetExtendedStyle(dlgData->hTree, TVS_EX_DOUBLEBUFFER, + TVS_EX_DOUBLEBUFFER); + + dlgData->hHost = CreatePageHost(hDlg, dlgData->hTree); + if (dlgData->hHost == nullptr) { + EndDialog(hDlg, 1); + return TRUE; + } + + for (int i = 0; i < SETTINGS_PAGE_COUNT; ++i) { + const SettingsPageDesc& desc = SETTINGS_PAGES[i]; + HWND hPage = CreateDialogParam( + hglobInstance, MAKEINTRESOURCE(desc.templateId), + dlgData->hHost, desc.dlgProc, + reinterpret_cast(settings)); + if (hPage == nullptr) { + ShowWindowsError(L"CreateDialogParam", GetLastError()); + continue; + } + RECT pageRect = {0}; + GetWindowRect(hPage, &pageRect); + dlgData->hPages[i] = hPage; + dlgData->pageHeights[i] = pageRect.bottom - pageRect.top; + ShowWindow(hPage, SW_HIDE); + } + + const HTREEITEM hSelect = + BuildNavTree(dlgData->hTree, SETTINGS_PAGE_LANGUAGE); + SwitchPage(dlgData, SETTINGS_PAGE_LANGUAGE); + if (hSelect != nullptr) { + TreeView_SelectItem(dlgData->hTree, hSelect); } HICON hIcon = LoadIcon(GetModuleHandle(nullptr), @@ -185,35 +472,50 @@ INT_PTR CALLBACK SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, SendMessageW(hDlg, WM_SETICON, ICON_BIG, reinterpret_cast(hIcon)); - SwitchTab(dlgData, dlgData->hTabs[SETTINGS_TAB_GENERAL]); return TRUE; } case WM_COMMAND: + if (dlgData == nullptr) { + return FALSE; + } if (LOWORD(wParam) == IDOK) { - for (int i = 0; i < SETTINGS_TAB_COUNT; ++i) { - SendMessage(dlgData->hTabs[i], WM_SAVESETTINGS, 0, 0); - EndDialog(dlgData->hTabs[i], 0); + for (int i = 0; i < SETTINGS_PAGE_COUNT; ++i) { + if (dlgData->hPages[i] != nullptr) { + SendMessage(dlgData->hPages[i], WM_SAVESETTINGS, 0, 0); + } } EndDialog(hDlg, 0); } else if (LOWORD(wParam) == IDCANCEL) { - for (int i = 0; i < SETTINGS_TAB_COUNT; ++i) { - EndDialog(dlgData->hTabs[i], 0); - } EndDialog(hDlg, 1); } return 0; case WM_NOTIFY: { + // The tree already notifies while the dialog manager is building + // the dialog, so this runs before WM_INITDIALOG. + if (dlgData == nullptr) { + return FALSE; + } const LPNMHDR lpnmhdr = reinterpret_cast(lParam); + if (lpnmhdr->hwndFrom != dlgData->hTree) { + return 0; + } #pragma warning(push) #pragma warning( \ - disable : 26454) // Disable arithmetic overflow warning for TCN_SELCHANGE - if (lpnmhdr->code == TCN_SELCHANGE && - lpnmhdr->hwndFrom == dlgData->hTabCtrl) - { + disable : 26454) // Disable arithmetic overflow warning for TVN_SELCHANGED + if (lpnmhdr->code == TVN_SELCHANGED) { #pragma warning(pop) - const int curSel = TabCtrl_GetCurSel(dlgData->hTabCtrl); - if (curSel >= 0 && curSel < SETTINGS_TAB_COUNT) { - SwitchTab(dlgData, dlgData->hTabs[curSel]); + const LPNMTREEVIEW nmtv = + reinterpret_cast(lParam); + if (nmtv->itemNew.lParam == SETTINGS_NAV_GROUP) { + // Group items carry no page of their own; show the first + // page below them instead. + const HTREEITEM hChild = + TreeView_GetChild(dlgData->hTree, nmtv->itemNew.hItem); + if (hChild != nullptr) { + TreeView_SelectItem(dlgData->hTree, hChild); + } + } else { + SwitchPage(dlgData, static_cast(nmtv->itemNew.lParam)); } } return 0; diff --git a/WinMute/Settings_BluetoothDlg.cpp b/WinMute/Settings_BluetoothDlg.cpp index 0cf5f23..f0edd59 100644 --- a/WinMute/Settings_BluetoothDlg.cpp +++ b/WinMute/Settings_BluetoothDlg.cpp @@ -184,13 +184,14 @@ static std::vector ExportBluetoothDeviceList(HWND hList) static bool IsBluetoothAvailable() noexcept { - HANDLE btHandle; + HANDLE btHandle = nullptr; BLUETOOTH_FIND_RADIO_PARAMS bfrp = {sizeof(BLUETOOTH_FIND_RADIO_PARAMS)}; HBLUETOOTH_RADIO_FIND hRadiosFind = BluetoothFindFirstRadio(&bfrp, &btHandle); if (hRadiosFind == nullptr) { return false; } + CloseHandle(btHandle); BluetoothFindRadioClose(hRadiosFind); return true; } @@ -222,9 +223,6 @@ INT_PTR CALLBACK Settings_BluetoothDlgProc(HWND hDlg, UINT msg, WPARAM wParam, { switch (msg) { case WM_INITDIALOG: { - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } LoadBluetoothDlgTranslation(hDlg); WMSettings* settings = reinterpret_cast(lParam); diff --git a/WinMute/Settings_GeneralDlg.cpp b/WinMute/Settings_GeneralDlg.cpp index 0d386c0..a6c1f52 100644 --- a/WinMute/Settings_GeneralDlg.cpp +++ b/WinMute/Settings_GeneralDlg.cpp @@ -31,6 +31,9 @@ POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ +// The pages below the "General" node of the settings navigation tree: +// Language, Startup & Updates, Hotkeys and Logging. + #include "common.h" namespace fs = std::filesystem; @@ -38,13 +41,21 @@ namespace fs = std::filesystem; extern void ShowLogDialog(HWND hParent); extern HINSTANCE hglobInstance; -struct SettingsGeneralData { +static WMSettings* GetPageSettings(HWND hDlg) +{ + return reinterpret_cast(GetWindowLongPtr(hDlg, DWLP_USER)); +} + +// ============================================================================= +// Language + +struct SettingsLanguageData { WMSettings* settings = nullptr; std::vector langModules; }; static void FillLanguageList(HWND hLanguageList, - const SettingsGeneralData& dlgData) + const SettingsLanguageData& dlgData) { SendMessage(hLanguageList, CB_INITSTORAGE, static_cast(dlgData.langModules.size() + 1), @@ -66,7 +77,7 @@ static void FillLanguageList(HWND hLanguageList, WMi18n::GetInstance().GetCurrentLanguageName().c_str()); } -static void LoadSettingsGeneralDlgTranslation(HWND hDlg) +static void LoadLanguageDlgTranslation(HWND hDlg) { WMi18n& i18n = WMi18n::GetInstance(); @@ -80,80 +91,132 @@ static void LoadSettingsGeneralDlgTranslation(HWND hDlg) SetDlgItemText(hDlg, IDC_LINK_HELP_TRANSLATING, helpTranslateLink.c_str()); i18n.SetItemText(hDlg, IDC_SELECT_LANGUAGE_LABEL, "settings.general.select-language-label"); +} + +INT_PTR CALLBACK Settings_LanguageDlgProc(HWND hDlg, UINT msg, WPARAM wParam, + LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + + switch (msg) { + case WM_INITDIALOG: { + LoadLanguageDlgTranslation(hDlg); + + SettingsLanguageData* dlgData = new SettingsLanguageData; + dlgData->langModules = + WMi18n::GetInstance().GetAvailableLanguages(); + dlgData->settings = reinterpret_cast(lParam); + assert(dlgData->settings != nullptr); + SetWindowLongPtr(hDlg, DWLP_USER, + reinterpret_cast(dlgData)); + + FillLanguageList(GetDlgItem(hDlg, IDC_LANGUAGE), *dlgData); + + return TRUE; + } + case WM_DESTROY: { + delete reinterpret_cast( + GetWindowLongPtr(hDlg, DWLP_USER)); + SetWindowLongPtr(hDlg, DWLP_USER, 0); + return FALSE; + } + case WM_NOTIFY: { + const PNMLINK pNmLink = reinterpret_cast(lParam); +#pragma warning(push) +#pragma warning(disable : 26454) // Disable arithmetic overflow warning for + // NM_CLICK and NM_RETURN + if (pNmLink->hdr.code == NM_CLICK || pNmLink->hdr.code == NM_RETURN) + { +#pragma warning(pop) + const UINT_PTR ctrlId = pNmLink->hdr.idFrom; + const LITEM item = pNmLink->item; + if ((ctrlId == IDC_LINK_HELP_TRANSLATING) && item.iLink == 0) { + LaunchBrowser(hDlg, item.szUrl); + } + } + return TRUE; + } + case WM_SAVESETTINGS: { + SettingsLanguageData* dlgData = + reinterpret_cast( + GetWindowLongPtr(hDlg, DWLP_USER)); + assert(dlgData != nullptr); + + HWND hLanguageSelector = GetDlgItem(hDlg, IDC_LANGUAGE); + const auto curLangSel = ComboBox_GetCurSel(hLanguageSelector); + if (curLangSel != CB_ERR) { + const wchar_t* selectedLang = reinterpret_cast( + ComboBox_GetItemData(hLanguageSelector, curLangSel)); + if (selectedLang != nullptr) { + if (!WMi18n::GetInstance().LoadLanguage(selectedLang)) { + TaskDialog(hDlg, hglobInstance, PROGRAM_NAME, + L"Failed to load selected language.", + L"Please report this error to the WinMute " + L"issue tracker.", + TDCBF_OK_BUTTON, TD_ERROR_ICON, nullptr); + } else { + dlgData->settings->SetValue(SettingsKey::APP_LANGUAGE, + selectedLang); + } + } + } + return 0; + } + default: + break; + } + return FALSE; +} + +// ============================================================================= +// Startup & Updates + +static void LoadUpdatesDlgTranslation(HWND hDlg) +{ + WMi18n& i18n = WMi18n::GetInstance(); + i18n.SetItemText(hDlg, IDC_RUNONSTARTUP, "settings.general.run-on-startup"); i18n.SetItemText(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP, "settings.general.check-for-updates-on-start"); i18n.SetItemText(hDlg, IDC_CHECK_FOR_BETA_UPDATES, "settings.general.check-for-beta-updates-on-start"); - i18n.SetItemText(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY, - "settings.general.enable-global-mute-hotkey"); - i18n.SetItemText(hDlg, IDC_ENABLELOGGING, - "settings.general.enable-logging"); - i18n.SetItemText(hDlg, IDC_OPENLOG, "settings.general.btn-open-log-file"); i18n.SetItemText(hDlg, IDC_UPDATE_OPTIONS_DISABLED, "settings.general.updates-handled-externally"); - i18n.SetItemText(hDlg, IDC_OPENLOGDLG, - "settings.general.btn-open-log-window"); } -INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, +INT_PTR CALLBACK Settings_UpdatesDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { + LoadUpdatesDlgTranslation(hDlg); + + WMSettings* settings = reinterpret_cast(lParam); + assert(settings != nullptr); + SetWindowLongPtr(hDlg, DWLP_USER, + reinterpret_cast(settings)); + HWND hAutostart = GetDlgItem(hDlg, IDC_RUNONSTARTUP); HWND hUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP); HWND hBetaUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES); - HWND hLogging = GetDlgItem(hDlg, IDC_ENABLELOGGING); - HWND hOpenLog = GetDlgItem(hDlg, IDC_OPENLOG); HWND hUpdatesDisabledNotice = GetDlgItem(hDlg, IDC_UPDATE_OPTIONS_DISABLED); - HWND hEnableGlobalMuteHotkey = - GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY); - HWND hGlobalMuteHotkey = GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY); - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } - LoadSettingsGeneralDlgTranslation(hDlg); - - SettingsGeneralData* dlgData = new SettingsGeneralData; - dlgData->langModules = - WMi18n::GetInstance().GetAvailableLanguages(); - dlgData->settings = reinterpret_cast(lParam); - assert(dlgData->settings != nullptr); - - SetWindowLongPtr(hDlg, DWLP_USER, - reinterpret_cast(dlgData)); - - FillLanguageList(GetDlgItem(hDlg, IDC_LANGUAGE), *dlgData); - - DWORD enabled = dlgData->settings->IsAutostartEnabled(); + DWORD enabled = settings->IsAutostartEnabled(); Button_SetCheck(hAutostart, enabled ? BST_CHECKED : BST_UNCHECKED); - enabled = - !!dlgData->settings->QueryValue(SettingsKey::CHECK_FOR_UPDATE); + enabled = !!settings->QueryValue(SettingsKey::CHECK_FOR_UPDATE); Button_SetCheck(hUpdateCheck, enabled ? BST_CHECKED : BST_UNCHECKED); EnableWindow(hBetaUpdateCheck, enabled); - enabled = !!dlgData->settings->QueryValue( - SettingsKey::CHECK_FOR_BETA_UPDATE); + enabled = + !!settings->QueryValue(SettingsKey::CHECK_FOR_BETA_UPDATE); Button_SetCheck(hBetaUpdateCheck, enabled ? BST_CHECKED : BST_UNCHECKED); - // Hotkey - const auto hotkey = - dlgData->settings->QueryValue(SettingsKey::GLOBAL_MUTE_HOTKEY); - SendMessage(hGlobalMuteHotkey, HKM_SETHOTKEY, hotkey, 0); - enabled = !!dlgData->settings->QueryValue( - SettingsKey::ENABLE_GLOBAL_MUTE_HOTKEY); - Button_SetCheck(hEnableGlobalMuteHotkey, - enabled ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(hGlobalMuteHotkey, enabled); - // If the disable-update file is present, then also hide all options UpdateChecker updateChecker; if (updateChecker.IsUpdateCheckDisabledViaFile()) { @@ -166,148 +229,183 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, ShowWindow(hUpdatesDisabledNotice, SW_HIDE); } - enabled = - !!dlgData->settings->QueryValue(SettingsKey::LOGGING_ENABLED); - Button_SetCheck(hLogging, enabled ? BST_CHECKED : BST_UNCHECKED); - Button_Enable(hOpenLog, enabled); - if (enabled) { - WMLog& log = WMLog::GetInstance(); - const std::wstring filePath = log.GetLogFilePath().c_str(); - SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, 0, - reinterpret_cast(filePath.c_str())); - - } else { - SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, 0, - reinterpret_cast(L"")); - } - - return TRUE; - } - case WM_DESTROY: { - SettingsGeneralData* dlgData = - reinterpret_cast( - GetWindowLongPtr(hDlg, DWLP_USER)); - if (dlgData != nullptr) { - delete dlgData; - SetWindowLongPtr(hDlg, DWLP_USER, 0); - } - return FALSE; - } - case WM_NOTIFY: { - const PNMLINK pNmLink = reinterpret_cast(lParam); -#pragma warning(push) -#pragma warning(disable : 26454) // Disable arithmetic overflow warning for - // NM_CLICK and NM_RETURN - if (pNmLink->hdr.code == NM_CLICK || pNmLink->hdr.code == NM_RETURN) - { -#pragma warning(pop) - const UINT_PTR ctrlId = pNmLink->hdr.idFrom; - const LITEM item = pNmLink->item; - if ((ctrlId == IDC_LINK_HELP_TRANSLATING) && item.iLink == 0) { - LaunchBrowser(hDlg, item.szUrl); - } - } return TRUE; } case WM_COMMAND: { - if (LOWORD(wParam) == IDC_ENABLELOGGING) { - DWORD checked = - Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLELOGGING)); - Button_Enable(GetDlgItem(hDlg, IDC_OPENLOG), - checked == BST_CHECKED); - if (checked == BST_CHECKED) { - WMLog& log = WMLog::GetInstance(); - const std::wstring filePath = log.GetLogFilePath().c_str(); - SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, - 0, reinterpret_cast(filePath.c_str())); - - } else { - SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, - 0, reinterpret_cast(L"")); - } - } else if (LOWORD(wParam) == IDC_ENABLE_GLOBAL_MUTE_HOTKEY) { - const auto checked = Button_GetCheck( - GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY)); - EnableWindow(GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY), checked); - } else if (LOWORD(wParam) == IDC_OPENLOGDLG) { - ShowLogDialog(hDlg); - } else if (LOWORD(wParam) == IDC_CHECK_FOR_UPDATES_ON_STARTUP) { + if (LOWORD(wParam) == IDC_CHECK_FOR_UPDATES_ON_STARTUP) { const int enabled = Button_GetCheck( GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP)); EnableWindow(GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES), enabled); - } else if (LOWORD(wParam) == IDC_OPENLOG) { - WMLog& log = WMLog::GetInstance(); - const std::wstring filePath = log.GetLogFilePath().c_str(); - ShellExecuteW(nullptr, L"open", filePath.c_str(), nullptr, - nullptr, SW_SHOW); } return 0; } case WM_SAVESETTINGS: { - SettingsGeneralData* dlgData = - reinterpret_cast( - GetWindowLongPtr(hDlg, DWLP_USER)); - assert(dlgData != nullptr); + WMSettings* settings = GetPageSettings(hDlg); + assert(settings != nullptr); HWND hAutostart = GetDlgItem(hDlg, IDC_RUNONSTARTUP); - HWND hLogging = GetDlgItem(hDlg, IDC_ENABLELOGGING); HWND hUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP); HWND hBetaUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES); - HWND hEnableGlobalMuteHotkey = - GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY); - HWND hGlobalMuteHotkey = GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY); - - const int enableLog = Button_GetCheck(hLogging) == BST_CHECKED; - dlgData->settings->SetValue(SettingsKey::LOGGING_ENABLED, - enableLog); - WMLog::GetInstance().EnableLogFile(enableLog); - - HWND hLanguageSelector = GetDlgItem(hDlg, IDC_LANGUAGE); - const auto curLangSel = ComboBox_GetCurSel(hLanguageSelector); - if (curLangSel != CB_ERR) { - const wchar_t* selectedLang = reinterpret_cast( - ComboBox_GetItemData(hLanguageSelector, curLangSel)); - if (selectedLang != nullptr) { - if (!WMi18n::GetInstance().LoadLanguage(selectedLang)) { - TaskDialog(hDlg, hglobInstance, PROGRAM_NAME, - L"Failed to load selected language.", - L"Please report this error to the WinMute " - L"issue tracker.", - TDCBF_OK_BUTTON, TD_ERROR_ICON, nullptr); - } else { - dlgData->settings->SetValue(SettingsKey::APP_LANGUAGE, - selectedLang); - } - } - } const int enableUpdateCheck = Button_GetCheck(hUpdateCheck) == BST_CHECKED; - dlgData->settings->SetValue(SettingsKey::CHECK_FOR_UPDATE, - enableUpdateCheck); + settings->SetValue(SettingsKey::CHECK_FOR_UPDATE, + enableUpdateCheck); const int enableBetaUpdateCheck = Button_GetCheck(hBetaUpdateCheck) == BST_CHECKED; - dlgData->settings->SetValue(SettingsKey::CHECK_FOR_BETA_UPDATE, - enableBetaUpdateCheck); + settings->SetValue(SettingsKey::CHECK_FOR_BETA_UPDATE, + enableBetaUpdateCheck); - if (Button_GetCheck(hAutostart) == BST_CHECKED) { - dlgData->settings->EnableAutostart(true); - } else { - dlgData->settings->EnableAutostart(false); + settings->EnableAutostart(Button_GetCheck(hAutostart) == + BST_CHECKED); + + return 0; + } + default: + break; + } + return FALSE; +} + +// ============================================================================= +// Hotkeys + +INT_PTR CALLBACK Settings_HotkeysDlgProc(HWND hDlg, UINT msg, WPARAM wParam, + LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: { + WMi18n::GetInstance().SetItemText( + hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY, + "settings.general.enable-global-mute-hotkey"); + + WMSettings* settings = reinterpret_cast(lParam); + assert(settings != nullptr); + SetWindowLongPtr(hDlg, DWLP_USER, + reinterpret_cast(settings)); + + HWND hEnableGlobalMuteHotkey = + GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY); + HWND hGlobalMuteHotkey = GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY); + + const auto hotkey = + settings->QueryValue(SettingsKey::GLOBAL_MUTE_HOTKEY); + SendMessage(hGlobalMuteHotkey, HKM_SETHOTKEY, hotkey, 0); + const DWORD enabled = + !!settings->QueryValue(SettingsKey::ENABLE_GLOBAL_MUTE_HOTKEY); + Button_SetCheck(hEnableGlobalMuteHotkey, + enabled ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(hGlobalMuteHotkey, enabled); + + return TRUE; + } + case WM_COMMAND: { + if (LOWORD(wParam) == IDC_ENABLE_GLOBAL_MUTE_HOTKEY) { + const auto checked = Button_GetCheck( + GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY)); + EnableWindow(GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY), checked); } + return 0; + } + case WM_SAVESETTINGS: { + WMSettings* settings = GetPageSettings(hDlg); + assert(settings != nullptr); + + HWND hEnableGlobalMuteHotkey = + GetDlgItem(hDlg, IDC_ENABLE_GLOBAL_MUTE_HOTKEY); + HWND hGlobalMuteHotkey = GetDlgItem(hDlg, IDC_GLOBAL_MUTE_HOTKEY); const int enableGlobalMuteHotkey = Button_GetCheck(hEnableGlobalMuteHotkey) == BST_CHECKED; - dlgData->settings->SetValue(SettingsKey::ENABLE_GLOBAL_MUTE_HOTKEY, - enableGlobalMuteHotkey); + settings->SetValue(SettingsKey::ENABLE_GLOBAL_MUTE_HOTKEY, + enableGlobalMuteHotkey); const auto hotkey = SendMessage(hGlobalMuteHotkey, HKM_GETHOTKEY, 0, 0); - dlgData->settings->SetValue(SettingsKey::GLOBAL_MUTE_HOTKEY, - static_cast(hotkey)); + settings->SetValue(SettingsKey::GLOBAL_MUTE_HOTKEY, + static_cast(hotkey)); + + return 0; + } + default: + break; + } + return FALSE; +} + +// ============================================================================= +// Logging + +static void UpdateLogFilePath(HWND hDlg, bool loggingEnabled) +{ + const std::wstring filePath = loggingEnabled + ? WMLog::GetInstance().GetLogFilePath() + : std::wstring(); + SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, 0, + reinterpret_cast(filePath.c_str())); +} + +static void LoadLoggingDlgTranslation(HWND hDlg) +{ + WMi18n& i18n = WMi18n::GetInstance(); + + i18n.SetItemText(hDlg, IDC_ENABLELOGGING, + "settings.general.enable-logging"); + i18n.SetItemText(hDlg, IDC_OPENLOG, "settings.general.btn-open-log-file"); + i18n.SetItemText(hDlg, IDC_OPENLOGDLG, + "settings.general.btn-open-log-window"); +} + +INT_PTR CALLBACK Settings_LoggingDlgProc(HWND hDlg, UINT msg, WPARAM wParam, + LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: { + LoadLoggingDlgTranslation(hDlg); + + WMSettings* settings = reinterpret_cast(lParam); + assert(settings != nullptr); + SetWindowLongPtr(hDlg, DWLP_USER, + reinterpret_cast(settings)); + + HWND hLogging = GetDlgItem(hDlg, IDC_ENABLELOGGING); + const DWORD enabled = + !!settings->QueryValue(SettingsKey::LOGGING_ENABLED); + Button_SetCheck(hLogging, enabled ? BST_CHECKED : BST_UNCHECKED); + Button_Enable(GetDlgItem(hDlg, IDC_OPENLOG), enabled); + UpdateLogFilePath(hDlg, !!enabled); + + return TRUE; + } + case WM_COMMAND: { + if (LOWORD(wParam) == IDC_ENABLELOGGING) { + const DWORD checked = + Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLELOGGING)); + Button_Enable(GetDlgItem(hDlg, IDC_OPENLOG), + checked == BST_CHECKED); + UpdateLogFilePath(hDlg, checked == BST_CHECKED); + } else if (LOWORD(wParam) == IDC_OPENLOGDLG) { + ShowLogDialog(hDlg); + } else if (LOWORD(wParam) == IDC_OPENLOG) { + const std::wstring filePath = + WMLog::GetInstance().GetLogFilePath(); + ShellExecuteW(nullptr, L"open", filePath.c_str(), nullptr, + nullptr, SW_SHOW); + } + return 0; + } + case WM_SAVESETTINGS: { + WMSettings* settings = GetPageSettings(hDlg); + assert(settings != nullptr); + + const int enableLog = + Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLELOGGING)) == + BST_CHECKED; + settings->SetValue(SettingsKey::LOGGING_ENABLED, enableLog); + WMLog::GetInstance().EnableLogFile(enableLog); return 0; } diff --git a/WinMute/Settings_ManageEndpointsDlg.cpp b/WinMute/Settings_ManageEndpointsDlg.cpp index 7e8b3cd..c16e097 100644 --- a/WinMute/Settings_ManageEndpointsDlg.cpp +++ b/WinMute/Settings_ManageEndpointsDlg.cpp @@ -53,7 +53,7 @@ struct EndpointAddCtx { // selection index on its own says nothing about which device was picked. static constexpr LONG_PTR ENDPOINT_ITEM_LEGACY_NAME = -1; -// State of the endpoint list dialog. The list box only renders friendly +// State of the endpoint page. The list box only renders friendly // names, so the endpoint ids have to be tracked alongside it. struct ManageEndpointsDlgState { WMSettings* settings = nullptr; @@ -190,9 +190,8 @@ static void LoadManageEndpointsDlgTranslation(HWND hDlg) { WMi18n& i18n = WMi18n::GetInstance(); - SetWindowText( - hDlg, - i18n.GetTranslationW("settings.mute.manage-endpoints.title").c_str()); + i18n.SetItemText(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY, + "settings.mute.manage-endpoints-individually"); i18n.SetItemText(hDlg, IDC_GROUP_LIST_BEHAVIOUR, "settings.mute.manage-endpoints.list-behaviour.title"); i18n.SetItemText( @@ -208,8 +207,32 @@ static void LoadManageEndpointsDlgTranslation(HWND hDlg) i18n.SetItemText(hDlg, IDC_ENDPOINT_EDIT, "settings.btn-edit"); i18n.SetItemText(hDlg, IDC_ENDPOINT_REMOVE, "settings.btn-remove"); i18n.SetItemText(hDlg, IDC_ENDPOINT_REMOVEALL, "settings.btn-remove-all"); - i18n.SetItemText(hDlg, IDOK, "settings.btn-save"); - i18n.SetItemText(hDlg, IDCANCEL, "settings.btn-cancel"); +} + +// The list only means anything while endpoints are managed individually, so +// the master check box gates the whole page. +static void UpdateEndpointControlStates(HWND hDlg) +{ + const bool individual = + Button_GetCheck(GetDlgItem( + hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY)) == BST_CHECKED; + HWND hList = GetDlgItem(hDlg, IDC_ENDPOINT_LIST); + const bool hasSelection = ListBox_GetCurSel(hList) != LB_ERR; + const bool hasItems = ListBox_GetCount(hList) > 0; + + static constexpr int gatedItems[] = { + IDC_GROUP_LIST_BEHAVIOUR, IDC_ENDPOINT_LIST_IS_ALLOWLIST, + IDC_ENDPOINT_LIST_IS_BLOCKLIST, IDC_GROUP_ENDPOINTS, IDC_ENDPOINT_LIST, + IDC_ENDPOINT_ADD}; + for (const int itemId : gatedItems) { + EnableWindow(GetDlgItem(hDlg, itemId), individual); + } + EnableWindow(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), + individual && hasSelection); + EnableWindow(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), + individual && hasSelection); + EnableWindow(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVEALL), + individual && hasItems); } INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, @@ -217,9 +240,6 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, { switch (msg) { case WM_INITDIALOG: { - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } LoadManageEndpointsDlgTranslation(hDlg); WMSettings* settings = reinterpret_cast(lParam); @@ -229,6 +249,12 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, SetWindowLongPtr(hDlg, DWLP_USER, reinterpret_cast(state)); + Button_SetCheck( + GetDlgItem(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY), + settings->QueryValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS) + ? BST_CHECKED + : BST_UNCHECKED); + DWORD endpointMode = settings->QueryValue( SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS_MODE); if (endpointMode == MUTE_ENDPOINT_MODE_INDIVIDUAL_ALLOW_LIST) { @@ -251,8 +277,7 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, HWND hList = GetDlgItem(hDlg, IDC_ENDPOINT_LIST); state->entries = settings->GetManagedAudioEndpoints(); RebuildEndpointList(hList, state->entries); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVEALL), - ListBox_GetCount(hList) > 0); + UpdateEndpointControlStates(hDlg); return TRUE; } @@ -268,24 +293,14 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, if (state == nullptr) { return FALSE; } - if (LOWORD(wParam) == IDC_ENDPOINT_LIST) { - HWND hList = GetDlgItem(hDlg, IDC_ENDPOINT_LIST); + if (LOWORD(wParam) == IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY) { + UpdateEndpointControlStates(hDlg); + } else if (LOWORD(wParam) == IDC_ENDPOINT_LIST) { if (HIWORD(wParam) == LBN_SELCHANGE || - HIWORD(wParam) == LBN_SELCANCEL) + HIWORD(wParam) == LBN_SELCANCEL || + HIWORD(wParam) == LBN_KILLFOCUS) { - const bool entrySelected = - (ListBox_GetCurSel(hList) != LB_ERR); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), - entrySelected); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), - entrySelected); - } else if (HIWORD(wParam) == LBN_KILLFOCUS) { - const bool entrySelected = - (ListBox_GetCurSel(hList) != LB_ERR); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), - entrySelected); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), - entrySelected); + UpdateEndpointControlStates(hDlg); } } else if (LOWORD(wParam) == IDC_ENDPOINT_ADD) { ManagedEndpoint epData; @@ -305,11 +320,7 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, state->entries.push_back(epData); RebuildEndpointList(GetDlgItem(hDlg, IDC_ENDPOINT_LIST), state->entries); - HWND hRemoveAll = - GetDlgItem(hDlg, IDC_ENDPOINT_REMOVEALL); - if (!IsWindowEnabled(hRemoveAll)) { - Button_Enable(hRemoveAll, TRUE); - } + UpdateEndpointControlStates(hDlg); } } } else if (LOWORD(wParam) == IDC_ENDPOINT_EDIT) { @@ -347,12 +358,8 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, RebuildEndpointList(hList, state->entries); if (static_cast(sel) < state->entries.size()) { ListBox_SetCurSel(hList, sel); - } else { - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), - FALSE); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), - FALSE); } + UpdateEndpointControlStates(hDlg); } } } else if (LOWORD(wParam) == IDC_ENDPOINT_REMOVE) { @@ -364,38 +371,39 @@ INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND hDlg, UINT msg, state->entries.erase(state->entries.begin() + sel); // Nothing is selected after the rebuild. RebuildEndpointList(hList, state->entries); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), FALSE); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), FALSE); - if (ListBox_GetCount(hList) == 0) { - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVEALL), - FALSE); - } + UpdateEndpointControlStates(hDlg); } } else if (LOWORD(wParam) == IDC_ENDPOINT_REMOVEALL) { state->entries.clear(); ListBox_ResetContent(GetDlgItem(hDlg, IDC_ENDPOINT_LIST)); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_EDIT), FALSE); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVE), FALSE); - Button_Enable(GetDlgItem(hDlg, IDC_ENDPOINT_REMOVEALL), FALSE); - } else if (LOWORD(wParam) == IDOK) { - WMSettings* settings = state->settings; - settings->StoreManagedAudioEndpoints(state->entries); - if (Button_GetCheck( - GetDlgItem(hDlg, IDC_ENDPOINT_LIST_IS_ALLOWLIST))) - { - settings->SetValue( - SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS_MODE, - MUTE_ENDPOINT_MODE_INDIVIDUAL_ALLOW_LIST); - } else if (Button_GetCheck(GetDlgItem( - hDlg, IDC_ENDPOINT_LIST_IS_BLOCKLIST))) - { - settings->SetValue( - SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS_MODE, - MUTE_ENDPOINT_MODE_INDIVIDUAL_BLOCK_LIST); - } - EndDialog(hDlg, 0); - } else if (LOWORD(wParam) == IDCANCEL) { - EndDialog(hDlg, 0); + UpdateEndpointControlStates(hDlg); + } + return 0; + } + case WM_SAVESETTINGS: { + auto* state = reinterpret_cast( + GetWindowLongPtr(hDlg, DWLP_USER)); + if (state == nullptr) { + return FALSE; + } + WMSettings* settings = state->settings; + + settings->SetValue( + SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS, + Button_GetCheck(GetDlgItem( + hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY)) == + BST_CHECKED); + settings->StoreManagedAudioEndpoints(state->entries); + if (Button_GetCheck( + GetDlgItem(hDlg, IDC_ENDPOINT_LIST_IS_ALLOWLIST))) + { + settings->SetValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS_MODE, + MUTE_ENDPOINT_MODE_INDIVIDUAL_ALLOW_LIST); + } else if (Button_GetCheck( + GetDlgItem(hDlg, IDC_ENDPOINT_LIST_IS_BLOCKLIST))) + { + settings->SetValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS_MODE, + MUTE_ENDPOINT_MODE_INDIVIDUAL_BLOCK_LIST); } return 0; } diff --git a/WinMute/Settings_MuteDlg.cpp b/WinMute/Settings_MuteDlg.cpp index dc7e6c6..d5aee32 100644 --- a/WinMute/Settings_MuteDlg.cpp +++ b/WinMute/Settings_MuteDlg.cpp @@ -31,10 +31,11 @@ POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ -#include "common.h" +// The "Mute events" and "Media control" pages below the "Muting" node of the +// settings navigation tree. The endpoint list lives in +// Settings_ManageEndpointsDlg.cpp. -extern INT_PTR CALLBACK Settings_ManageEndpointsDlgProc(HWND, UINT, WPARAM, - LPARAM); +#include "common.h" static void SetCheckButton(HWND hBtn, const WMSettings& settings, SettingsKey key) @@ -49,17 +50,20 @@ static void SetOption(HWND hBtn, WMSettings& settings, SettingsKey key) settings.SetValue(key, enable); } +static WMSettings* GetPageSettings(HWND hDlg) +{ + return reinterpret_cast(GetWindowLongPtr(hDlg, DWLP_USER)); +} + +// ============================================================================= +// Mute events + static void LoadMuteDlgTranslation(HWND hDlg) { WMi18n& i18n = WMi18n::GetInstance(); - i18n.SetItemText(hDlg, IDC_GROUP_GENERAL, "settings.mute.general-title"); i18n.SetItemText(hDlg, IDC_SHOWNOTIFICATIONS, "settings.mute.show-mute-event-notifications"); - i18n.SetItemText(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY, - "settings.mute.manage-endpoints-individually"); - i18n.SetItemText(hDlg, IDC_MANAGE_ENDPOINTS, - "settings.mute.btn-manage-endpoints"); i18n.SetItemText(hDlg, IDC_GROUP_MUTE_WITH_RESTORE, "settings.mute.mute-with-restore.title"); @@ -89,11 +93,6 @@ static void LoadMuteDlgTranslation(HWND hDlg) i18n.SetItemText( hDlg, IDC_MUTE_WHEN_RDP_SESSION, "settings.mute.mute-without-restore.when-rdp-session-starts"); - - i18n.SetItemText(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA, - "settings.mute.try-pause-media-on-mute"); - i18n.SetItemText(hDlg, IDC_MUTE_TRY_RESUME_MEDIA, - "settings.mute.try-resume-media-on-unmute"); } INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, @@ -103,15 +102,9 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, switch (msg) { case WM_INITDIALOG: { - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } - LoadMuteDlgTranslation(hDlg); HWND hNotify = GetDlgItem(hDlg, IDC_SHOWNOTIFICATIONS); - HWND hManageEndpoints = - GetDlgItem(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY); HWND hMuteOnLock = GetDlgItem(hDlg, IDC_MUTE_WHEN_WS_LOCKED); HWND hMuteOnScreenOff = GetDlgItem(hDlg, IDC_MUTE_WHEN_SCREEN_OFF); @@ -123,21 +116,13 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, HWND hMuteOnSleep = GetDlgItem(hDlg, IDC_MUTE_WHEN_SLEEP); HWND hMuteOnLogout = GetDlgItem(hDlg, IDC_MUTE_WHEN_LOGOUT); - HWND hTryPauseMedia = GetDlgItem(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA); - HWND hTryResumeMedia = GetDlgItem(hDlg, IDC_MUTE_TRY_RESUME_MEDIA); - WMSettings* settings = reinterpret_cast(lParam); assert(settings != nullptr); SetWindowLongPtr(hDlg, DWLP_USER, reinterpret_cast(settings)); - // General SetCheckButton(hNotify, *settings, SettingsKey::NOTIFICATIONS_ENABLED); - SetCheckButton(hManageEndpoints, *settings, - SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS); - Button_Enable(GetDlgItem(hDlg, IDC_MANAGE_ENDPOINTS), - Button_GetCheck(hManageEndpoints) == BST_CHECKED); const DWORD muteDelay = settings->QueryValue(SettingsKey::MUTE_DELAY); SetDlgItemInt(hDlg, IDC_MUTEDELAY, (muteDelay < 0) ? 0 : muteDelay, @@ -161,38 +146,13 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, SetCheckButton(hMuteOnLogout, *settings, SettingsKey::MUTE_ON_LOGOUT); - SetCheckButton(hTryPauseMedia, *settings, - SettingsKey::MUTE_TRY_PAUSE_MEDIA); - SetCheckButton(hTryResumeMedia, *settings, - SettingsKey::MUTE_TRY_RESUME_MEDIA); - return TRUE; } - case WM_COMMAND: - if (LOWORD(wParam) == IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY) { - int isEnabled = Button_GetCheck( - GetDlgItem(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY)); - Button_Enable(GetDlgItem(hDlg, IDC_MANAGE_ENDPOINTS), - isEnabled); - } else if (LOWORD(wParam) == IDC_MANAGE_ENDPOINTS) { - WMSettings* settings = reinterpret_cast( - GetWindowLongPtr(hDlg, DWLP_USER)); - if (!DialogBoxParam(nullptr, - MAKEINTRESOURCE(IDD_MANAGE_ENDPOINTS), hDlg, - Settings_ManageEndpointsDlgProc, - reinterpret_cast(settings)) == 0) - { - ShowWindowsError(L"DialogBoxParam", GetLastError()); - } - } - return 0; case WM_SAVESETTINGS: { - WMSettings* settings = reinterpret_cast( - GetWindowLongPtr(hDlg, DWLP_USER)); + WMSettings* settings = GetPageSettings(hDlg); + assert(settings != nullptr); HWND hNotify = GetDlgItem(hDlg, IDC_SHOWNOTIFICATIONS); - HWND hManageEndpoints = - GetDlgItem(hDlg, IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY); HWND hMuteOnLock = GetDlgItem(hDlg, IDC_MUTE_WHEN_WS_LOCKED); HWND hMuteOnScreenOff = GetDlgItem(hDlg, IDC_MUTE_WHEN_SCREEN_OFF); @@ -204,13 +164,7 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, HWND hMuteOnSleep = GetDlgItem(hDlg, IDC_MUTE_WHEN_SLEEP); HWND hMuteOnLogout = GetDlgItem(hDlg, IDC_MUTE_WHEN_LOGOUT); - HWND hTryPauseMedia = GetDlgItem(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA); - HWND hTryResumeMedia = GetDlgItem(hDlg, IDC_MUTE_TRY_RESUME_MEDIA); - - // General SetOption(hNotify, *settings, SettingsKey::NOTIFICATIONS_ENABLED); - SetOption(hManageEndpoints, *settings, - SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS); const DWORD muteDelay = GetDlgItemInt(hDlg, IDC_MUTEDELAY, nullptr, TRUE); settings->SetValue(SettingsKey::MUTE_DELAY, @@ -232,10 +186,49 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, SetOption(hMuteOnSleep, *settings, SettingsKey::MUTE_ON_SUSPEND); SetOption(hMuteOnLogout, *settings, SettingsKey::MUTE_ON_LOGOUT); - // Media - SetOption(hTryPauseMedia, *settings, + return 0; + } + default: + break; + } + return FALSE; +} + +// ============================================================================= +// Media control + +INT_PTR CALLBACK Settings_MediaDlgProc(HWND hDlg, UINT msg, WPARAM wParam, + LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + + switch (msg) { + case WM_INITDIALOG: { + WMi18n& i18n = WMi18n::GetInstance(); + i18n.SetItemText(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA, + "settings.mute.try-pause-media-on-mute"); + i18n.SetItemText(hDlg, IDC_MUTE_TRY_RESUME_MEDIA, + "settings.mute.try-resume-media-on-unmute"); + + WMSettings* settings = reinterpret_cast(lParam); + assert(settings != nullptr); + SetWindowLongPtr(hDlg, DWLP_USER, + reinterpret_cast(settings)); + + SetCheckButton(GetDlgItem(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA), + *settings, SettingsKey::MUTE_TRY_PAUSE_MEDIA); + SetCheckButton(GetDlgItem(hDlg, IDC_MUTE_TRY_RESUME_MEDIA), + *settings, SettingsKey::MUTE_TRY_RESUME_MEDIA); + + return TRUE; + } + case WM_SAVESETTINGS: { + WMSettings* settings = GetPageSettings(hDlg); + assert(settings != nullptr); + + SetOption(GetDlgItem(hDlg, IDC_MUTE_TRY_PAUSE_MEDIA), *settings, SettingsKey::MUTE_TRY_PAUSE_MEDIA); - SetOption(hTryResumeMedia, *settings, + SetOption(GetDlgItem(hDlg, IDC_MUTE_TRY_RESUME_MEDIA), *settings, SettingsKey::MUTE_TRY_RESUME_MEDIA); return 0; diff --git a/WinMute/Settings_QuietHoursDlg.cpp b/WinMute/Settings_QuietHoursDlg.cpp index 6184883..240640a 100644 --- a/WinMute/Settings_QuietHoursDlg.cpp +++ b/WinMute/Settings_QuietHoursDlg.cpp @@ -361,9 +361,6 @@ INT_PTR CALLBACK Settings_QuietHoursDlgProc(HWND hDlg, UINT msg, WPARAM wParam, SetWindowLongPtr(hDlg, DWLP_USER, reinterpret_cast(qhdata)); - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } LoadQuietHoursDlgTranslation(hDlg); const DWORD qhEnabled = diff --git a/WinMute/Settings_WifiDlg.cpp b/WinMute/Settings_WifiDlg.cpp index ba0b898..c29428c 100644 --- a/WinMute/Settings_WifiDlg.cpp +++ b/WinMute/Settings_WifiDlg.cpp @@ -137,13 +137,20 @@ static std::vector ExportSsidListItems(HWND hList) static bool IsWlanAvailable() noexcept { - HANDLE wlanHandle; + HANDLE wlanHandle = nullptr; DWORD vers = 2; if (WlanOpenHandle(vers, nullptr, &vers, &wlanHandle) != ERROR_SUCCESS) { return false; } + + bool available = false; + PWLAN_INTERFACE_INFO_LIST ifList = nullptr; + if (WlanEnumInterfaces(wlanHandle, nullptr, &ifList) == ERROR_SUCCESS) { + available = ifList->dwNumberOfItems > 0; + WlanFreeMemory(ifList); + } WlanCloseHandle(wlanHandle, nullptr); - return true; + return available; } static BOOL CALLBACK ShowChildWindow(HWND hWnd, LPARAM lParam) @@ -173,9 +180,6 @@ INT_PTR CALLBACK Settings_WifiDlgProc(HWND hDlg, UINT msg, WPARAM wParam, { switch (msg) { case WM_INITDIALOG: { - if (IsAppThemed()) { - EnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } LoadWifiDlgTranslation(hDlg); WMSettings* settings = reinterpret_cast(lParam); assert(settings != nullptr); diff --git a/WinMute/WinMute.rc b/WinMute/WinMute.rc index fc9f538..520aa13 100644 --- a/WinMute/WinMute.rc +++ b/WinMute/WinMute.rc @@ -62,57 +62,79 @@ BEGIN PUSHBUTTON "OK",IDOK,242,246,64,16 END -IDD_SETTINGS DIALOGEX 0, 0, 275, 334 +IDD_SETTINGS DIALOGEX 0, 0, 370, 261 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW CAPTION "Settings" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CONTROL "",IDC_SETTINGS_TAB,"SysTabControl32",0x0,7,7,261,303 - DEFPUSHBUTTON "OK",IDOK,165,313,50,14 - PUSHBUTTON "Cancel",IDCANCEL,218,313,50,14 + CONTROL "",IDC_SETTINGS_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_TRACKSELECT | TVS_DISABLEDRAGDROP | WS_BORDER | WS_TABSTOP,7,7,100,226 + DEFPUSHBUTTON "OK",IDOK,257,240,50,14 + PUSHBUTTON "Cancel",IDCANCEL,313,240,50,14 END -IDD_SETTINGS_GENERAL DIALOGEX 0, 0, 243, 258 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +IDD_SETTINGS_LANGUAGE DIALOGEX 0, 0, 234, 51 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "Language",IDC_SELECT_LANGUAGE_LABEL,7,14,41,10 - COMBOBOX IDC_LANGUAGE,51,12,87,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Language",IDC_SELECT_LANGUAGE_LABEL,7,9,50,10 + COMBOBOX IDC_LANGUAGE,60,7,167,120,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP CONTROL "Help translating",IDC_LINK_HELP_TRANSLATING, - "SysLink",WS_TABSTOP,153,15,83,14 + "SysLink",WS_TABSTOP,7,30,220,14 +END + +IDD_SETTINGS_UPDATES DIALOGEX 0, 0, 234, 82 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN CONTROL "Run WinMute when this user logs on",IDC_RUNONSTARTUP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34,229,17 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 CONTROL "Check for updates on startup",IDC_CHECK_FOR_UPDATES_ON_STARTUP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,50,229,17 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,23,220,12 CONTROL "Also check for beta-updates",IDC_CHECK_FOR_BETA_UPDATES, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,65,199,17 - LTEXT "Options disabled. Updates are handled externally.\nLine2",IDC_UPDATE_OPTIONS_DISABLED,29,83,204,19 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,20,39,207,12 + LTEXT "Options disabled. Updates are handled externally.\nLine2",IDC_UPDATE_OPTIONS_DISABLED,20,55,207,20 +END + +IDD_SETTINGS_HOTKEYS DIALOGEX 0, 0, 234, 45 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN CONTROL "Enable global mute-hotkey",IDC_ENABLE_GLOBAL_MUTE_HOTKEY, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,103,219,17 - CONTROL "",IDC_GLOBAL_MUTE_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,29,122,196,14 - CONTROL "Save log to file",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,141,229,15 - PUSHBUTTON "Open log file...",IDC_OPENLOG,29,156,104,16 - PUSHBUTTON "Show log...",IDC_OPENLOGDLG,133,156,94,16 - LTEXT "[log file path]",IDC_LOGFILEPATH,33,177,203,27 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 + CONTROL "",IDC_GLOBAL_MUTE_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,20,24,207,14 END -IDD_SETTINGS_QUIETHOURS DIALOGEX 0, 0, 246, 204 +IDD_SETTINGS_LOGGING DIALOGEX 0, 0, 234, 78 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "During Quiet Hours WinMute automatically mutes your PC volumes and unmutes it afterwards.",IDC_QUIET_HOURS_DESCRIPTION,7,9,232,22 - CONTROL "Enable Quiet Hours",IDC_ENABLEQUIETHOURS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,31,120,15 - CONTROL "",IDC_QUIET_HOURS_TIMES,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,22,47,155,72 - PUSHBUTTON "Add",IDC_QUIET_HOURS_ADD,183,46,56,16 - PUSHBUTTON "Edit",IDC_QUIET_HOURS_EDIT,183,65,56,16 - PUSHBUTTON "Remove",IDC_QUIET_HOURS_REMOVE,183,84,56,16 - PUSHBUTTON "Remove All",IDC_QUIET_HOURS_REMOVEALL,183,103,56,16 - CONTROL "Force unmute",IDC_FORCEUNMUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,123,216,16 - LTEXT "If force unmute is enabled, WinMute will unmute your workstation when quiet hours end and not take into account if your workstation was already muted before quiet hours started.",IDC_QUIET_HOURS_FORCE_UNMUTE_DESCRIPTION,33,140,204,37 + CONTROL "Save log to file",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 + PUSHBUTTON "Open log file...",IDC_OPENLOG,20,23,100,16 + PUSHBUTTON "Show log...",IDC_OPENLOGDLG,127,23,100,16 + LTEXT "[log file path]",IDC_LOGFILEPATH,20,44,207,27 +END + +IDD_SETTINGS_QUIETHOURS DIALOGEX 0, 0, 234, 198 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "During Quiet Hours WinMute automatically mutes your PC volumes and unmutes it afterwards.",IDC_QUIET_HOURS_DESCRIPTION,7,7,220,22 + CONTROL "Enable Quiet Hours",IDC_ENABLEQUIETHOURS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,31,220,12 + CONTROL "",IDC_QUIET_HOURS_TIMES,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,20,47,143,72 + PUSHBUTTON "Add",IDC_QUIET_HOURS_ADD,171,46,56,16 + PUSHBUTTON "Edit",IDC_QUIET_HOURS_EDIT,171,65,56,16 + PUSHBUTTON "Remove",IDC_QUIET_HOURS_REMOVE,171,84,56,16 + PUSHBUTTON "Remove All",IDC_QUIET_HOURS_REMOVEALL,171,103,56,16 + CONTROL "Force unmute",IDC_FORCEUNMUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,123,207,12 + LTEXT "If force unmute is enabled, WinMute will unmute your workstation when quiet hours end and not take into account if your workstation was already muted before quiet hours started.",IDC_QUIET_HOURS_FORCE_UNMUTE_DESCRIPTION,32,139,195,37 CONTROL "Show quiet hours notifications",IDC_SHOWNOTIFICATIONS, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,175,180,21 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,179,207,12 END IDD_ABOUT_LICENSE DIALOGEX 0, 0, 300, 181 @@ -135,56 +157,80 @@ BEGIN EDITTEXT IDC_ABOUTTEXT,7,14,182,144,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER END -IDD_SETTINGS_MUTE DIALOGEX 0, 0, 253, 274 +IDD_SETTINGS_MUTE DIALOGEX 0, 0, 234, 196 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - GROUPBOX "General",IDC_GROUP_GENERAL,7,7,239,61 CONTROL "Show mute event notifications",IDC_SHOWNOTIFICATIONS, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,15,227,18 - CONTROL "Manage audio endpoints individually",IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,28,227,18 - PUSHBUTTON "Manage endpoints...",IDC_MANAGE_ENDPOINTS,26,46,97,15 - GROUPBOX "Mute with volume restore, when...",IDC_GROUP_MUTE_WITH_RESTORE,7,71,239,84 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 + GROUPBOX "Mute with volume restore, when...",IDC_GROUP_MUTE_WITH_RESTORE,7,25,220,86 CONTROL "... the workstation is locked.",IDC_MUTE_WHEN_WS_LOCKED, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,83,214,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,38,206,10 CONTROL "... the screen turns off.",IDC_MUTE_WHEN_SCREEN_OFF, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,97,205,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,51,206,10 CONTROL "... the laptop lid closes.",IDC_MUTE_WHEN_LID_CLOSE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,110,205,10 - CONTROL "Restore volume afterwards.",IDC_RESTOREVOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,124,221,10 - EDITTEXT IDC_MUTEDELAY,13,136,30,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER - LTEXT "seconds delay before muting.",IDC_DELAY_MUTING_LABEL,47,139,187,8 - GROUPBOX "Mute without volume restore, when...",IDC_GROUP_MUTE_WITHOUT_RESTORE,7,157,239,67 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,64,206,10 + CONTROL "Restore volume afterwards.",IDC_RESTOREVOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,78,206,10 + EDITTEXT IDC_MUTEDELAY,14,90,30,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + LTEXT "seconds delay before muting.",IDC_DELAY_MUTING_LABEL,48,93,172,8 + GROUPBOX "Mute without volume restore, when...",IDC_GROUP_MUTE_WITHOUT_RESTORE,7,117,220,72 CONTROL "... the computer shuts down.",IDC_MUTE_WHEN_SHUTDOWN, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,168,220,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,130,206,10 CONTROL "... the computer goes into sleep/hibernate.",IDC_MUTE_WHEN_SLEEP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,182,214,10 - CONTROL "... you log out.",IDC_MUTE_WHEN_LOGOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,196,214,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,144,206,10 + CONTROL "... you log out.",IDC_MUTE_WHEN_LOGOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,158,206,10 CONTROL "... when WinMute is started within a RDP session.",IDC_MUTE_WHEN_RDP_SESSION, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,210,220,10 - GROUPBOX "Media",IDC_GROUP_MUTE_MEDIA_CONTROL,7,223,239,42 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,172,206,10 +END + +IDD_SETTINGS_MEDIA DIALOGEX 0, 0, 234, 42 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN CONTROL "Try pausing currently played media when muting.",IDC_MUTE_TRY_PAUSE_MEDIA, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,234,219,10 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 CONTROL "Try resuming media when unmuting.",IDC_MUTE_TRY_RESUME_MEDIA, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,248,214,10 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,23,220,12 +END + +IDD_SETTINGS_ENDPOINTS DIALOGEX 0, 0, 234, 207 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Manage audio endpoints individually",IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,220,12 + GROUPBOX "List behaviour",IDC_GROUP_LIST_BEHAVIOUR,7,25,220,42 + CONTROL "Mute only listed endpoints",IDC_ENDPOINT_LIST_IS_ALLOWLIST, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,14,38,206,10 + CONTROL "Mute all but the listed endpoints",IDC_ENDPOINT_LIST_IS_BLOCKLIST, + "Button",BS_AUTORADIOBUTTON,14,51,206,10 + GROUPBOX "Endpoints",IDC_GROUP_ENDPOINTS,7,72,220,128 + LISTBOX IDC_ENDPOINT_LIST,14,85,140,108,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ENDPOINT_ADD,161,85,59,16 + PUSHBUTTON "Edit",IDC_ENDPOINT_EDIT,161,104,59,16 + PUSHBUTTON "Remove",IDC_ENDPOINT_REMOVE,161,123,59,16 + PUSHBUTTON "Remove all",IDC_ENDPOINT_REMOVEALL,161,177,59,16 END -IDD_SETTINGS_WIFI DIALOGEX 0, 0, 242, 216 +IDD_SETTINGS_WIFI DIALOGEX 0, 0, 234, 218 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "Description\nDescription\nDescription\nDescription",IDC_WIFI_INTRO,7,7,228,37 - CONTROL "Enable WLAN based muting",IDC_ENABLE_WIFI_MUTE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,44,228,14 + LTEXT "Description\nDescription\nDescription\nDescription",IDC_WIFI_INTRO,7,7,220,37 + CONTROL "Enable WLAN based muting",IDC_ENABLE_WIFI_MUTE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,46,220,14 CONTROL "Mute if connected WLAN is in list",IDC_WLAN_LIST_IS_ALLOWLIST, - "Button",BS_AUTORADIOBUTTON,17,60,209,10 + "Button",BS_AUTORADIOBUTTON | WS_GROUP,17,63,210,10 CONTROL "Mute if connected WLAN is not in list",IDC_WLAN_LIST_IS_BLOCKLIST, - "Button",BS_AUTORADIOBUTTON,17,73,207,10 - LISTBOX IDC_WIFI_LIST,7,88,166,121,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Add",IDC_WIFI_ADD,179,87,56,16 - PUSHBUTTON "Edit",IDC_WIFI_EDIT,179,106,56,16 - PUSHBUTTON "Remove",IDC_WIFI_REMOVE,179,125,56,16 - PUSHBUTTON "Remove all",IDC_WIFI_REMOVEALL,179,193,56,16 + "Button",BS_AUTORADIOBUTTON,17,76,210,10 + LISTBOX IDC_WIFI_LIST,7,91,157,120,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_WIFI_ADD,171,90,56,16 + PUSHBUTTON "Edit",IDC_WIFI_EDIT,171,109,56,16 + PUSHBUTTON "Remove",IDC_WIFI_REMOVE,171,128,56,16 + PUSHBUTTON "Remove all",IDC_WIFI_REMOVEALL,171,195,56,16 END IDD_SETTINGS_WIFI_ADD DIALOGEX 0, 0, 201, 62 @@ -198,21 +244,21 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,144,41,50,14 END -IDD_SETTINGS_BLUETOOTH DIALOGEX 0, 0, 244, 222 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +IDD_SETTINGS_BLUETOOTH DIALOGEX 0, 0, 234, 222 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "Description\nDescription\nDescription\nDescription\nDescription\nDescription",IDC_BLUETOOTH_DESCRIPTION_LABEL,7,7,230,51 + LTEXT "Description\nDescription\nDescription\nDescription\nDescription\nDescription",IDC_BLUETOOTH_DESCRIPTION_LABEL,7,7,220,51 CONTROL "Enable Bluetooth based muting",IDC_ENABLE_BLUETOOTH_MUTE, - "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,62,228,14 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,62,220,14 CONTROL "Enable only for these devices:",IDC_ENABLE_BLUETOOTH_MUTE_DEVICE_LIST, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,20,79,215,12 - LISTBOX IDC_BLUETOOTH_LIST,7,95,168,120,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Add",IDC_BLUETOOTH_ADD,181,94,56,16 - PUSHBUTTON "Edit",IDC_BLUETOOTH_EDIT,181,113,56,16 - PUSHBUTTON "Remove",IDC_BLUETOOTH_REMOVE,181,132,56,16 - PUSHBUTTON "Remove all",IDC_BLUETOOTH_REMOVEALL,181,199,56,16 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,20,79,207,12 + LISTBOX IDC_BLUETOOTH_LIST,7,95,157,120,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_BLUETOOTH_ADD,171,94,56,16 + PUSHBUTTON "Edit",IDC_BLUETOOTH_EDIT,171,113,56,16 + PUSHBUTTON "Remove",IDC_BLUETOOTH_REMOVE,171,132,56,16 + PUSHBUTTON "Remove all",IDC_BLUETOOTH_REMOVEALL,171,199,56,16 END IDD_SETTINGS_BLUETOOTH_ADD DIALOGEX 0, 0, 201, 62 @@ -226,26 +272,6 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,144,41,50,14 END -IDD_MANAGE_ENDPOINTS DIALOGEX 0, 0, 246, 201 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Manage Endpoints" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - GROUPBOX "List behaviour",IDC_GROUP_LIST_BEHAVIOUR,7,7,232,41 - CONTROL "Mute only listed endpoints",IDC_ENDPOINT_LIST_IS_ALLOWLIST, - "Button",BS_AUTORADIOBUTTON,13,19,209,10 - CONTROL "Mute all but the listed endpoints",IDC_ENDPOINT_LIST_IS_BLOCKLIST, - "Button",BS_AUTORADIOBUTTON,13,32,207,10 - GROUPBOX "Endpoints",IDC_GROUP_ENDPOINTS,7,48,232,128 - LISTBOX IDC_ENDPOINT_LIST,13,60,156,110,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Add",IDC_ENDPOINT_ADD,176,60,59,16 - PUSHBUTTON "Edit",IDC_ENDPOINT_EDIT,176,78,59,16 - PUSHBUTTON "Remove",IDC_ENDPOINT_REMOVE,176,97,59,16 - PUSHBUTTON "Remove all",IDC_ENDPOINT_REMOVEALL,176,155,59,16 - DEFPUSHBUTTON "Save",IDOK,133,180,50,14 - PUSHBUTTON "Cancel",IDCANCEL,189,180,50,14 -END - IDD_MANAGE_ENDPOINTS_ADD DIALOGEX 0, 0, 201, 62 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Add Endpoint" @@ -303,15 +329,6 @@ BEGIN BOTTOMMARGIN, 327 END - IDD_SETTINGS_GENERAL, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 236 - VERTGUIDE, 29 - TOPMARGIN, 7 - BOTTOMMARGIN, 251 - HORZGUIDE, 66 - END IDD_SETTINGS_QUIETHOURS, DIALOG BEGIN @@ -378,13 +395,6 @@ BEGIN BOTTOMMARGIN, 55 END - IDD_MANAGE_ENDPOINTS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 239 - TOPMARGIN, 7 - BOTTOMMARGIN, 194 - END IDD_MANAGE_ENDPOINTS_ADD, DIALOG BEGIN @@ -432,11 +442,6 @@ BEGIN 0 END -IDD_SETTINGS_GENERAL AFX_DIALOG_LAYOUT -BEGIN - 0 -END - IDD_SETTINGS_QUIETHOURS AFX_DIALOG_LAYOUT BEGIN 0 @@ -458,27 +463,52 @@ BEGIN 0 END -IDD_SETTINGS_WIFI AFX_DIALOG_LAYOUT +IDD_SETTINGS_LANGUAGE AFX_DIALOG_LAYOUT BEGIN 0 END -IDD_SETTINGS_WIFI_ADD AFX_DIALOG_LAYOUT +IDD_SETTINGS_UPDATES AFX_DIALOG_LAYOUT BEGIN 0 END -IDD_SETTINGS_BLUETOOTH AFX_DIALOG_LAYOUT +IDD_SETTINGS_HOTKEYS AFX_DIALOG_LAYOUT BEGIN 0 END -IDD_SETTINGS_BLUETOOTH_ADD AFX_DIALOG_LAYOUT +IDD_SETTINGS_LOGGING AFX_DIALOG_LAYOUT BEGIN 0 END -IDD_MANAGE_ENDPOINTS AFX_DIALOG_LAYOUT +IDD_SETTINGS_MEDIA AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_SETTINGS_ENDPOINTS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_SETTINGS_WIFI AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_SETTINGS_WIFI_ADD AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_SETTINGS_BLUETOOTH AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_SETTINGS_BLUETOOTH_ADD AFX_DIALOG_LAYOUT BEGIN 0 END diff --git a/WinMute/resource.h b/WinMute/resource.h index 84fed3f..ede4fa1 100644 --- a/WinMute/resource.h +++ b/WinMute/resource.h @@ -20,7 +20,6 @@ #define IDD_SETTINGS_BLUETOOTH 131 #define IDD_DIALOG1 133 #define IDD_SETTINGS_BLUETOOTH_ADD 133 -#define IDD_MANAGE_ENDPOINTS 135 #define IDD_DIALOG2 137 #define IDD_MANAGE_ENDPOINTS_ADD 137 #define IDI_APP_UPDATE 141 @@ -28,6 +27,12 @@ #define IDD_LOG 142 #define IDD_EDIT_QUIET_HOURS_ENTRY 144 #define IDD_SETTINGS_QUIETHOURS_ADD 144 +#define IDD_SETTINGS_LANGUAGE 146 +#define IDD_SETTINGS_UPDATES 147 +#define IDD_SETTINGS_HOTKEYS 148 +#define IDD_SETTINGS_LOGGING 149 +#define IDD_SETTINGS_ENDPOINTS 150 +#define IDD_SETTINGS_MEDIA 151 #define IDC_LINK_HOMEPAGE 1001 #define IDC_LINK_SUPPORT 1002 #define IDC_LINK_PROJECT 1002 @@ -39,8 +44,6 @@ #define IDC_SHOWNOTIFICATIONS 1007 #define IDC_TREE1 1008 #define IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY 1008 -#define IDC_TAB1 1010 -#define IDC_SETTINGS_TAB 1010 #define IDC_CHECK1 1011 #define IDC_RUNONSTARTUP 1011 #define IDC_MUTE_WHEN_WS_LOCKED 1011 @@ -136,6 +139,7 @@ #define IDC_QUIET_HOURS_REMOVEALL 1082 #define IDC_HOTKEY1 1082 #define IDC_GLOBAL_MUTE_HOTKEY 1082 +#define IDC_SETTINGS_TREE 1083 #define ID_TRAYMENU_INFO 40001 #define ID_TRAYMENU_ 40002 #define ID_TRAYMENU_MUTEON 40003 @@ -184,9 +188,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 146 +#define _APS_NEXT_RESOURCE_VALUE 152 #define _APS_NEXT_COMMAND_VALUE 40044 -#define _APS_NEXT_CONTROL_VALUE 1083 +#define _APS_NEXT_CONTROL_VALUE 1084 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif -- 2.43.0