diff --git a/MediaSharer/MediaSharer/MainWindow.xaml.cs b/MediaSharer/MediaSharer/MainWindow.xaml.cs index ecbbe59..98e8b6f 100644 --- a/MediaSharer/MediaSharer/MainWindow.xaml.cs +++ b/MediaSharer/MediaSharer/MainWindow.xaml.cs @@ -1,24 +1,31 @@ using System; -using MediaSharer.Core; +using MediaSharer.Repositories.Interfaces; using MediaSharer.Strings; +using MediaSharer.Utils; using MediaSharer.Views; using MediaSharer.Windows; +using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media.Animation; -using WinRT; using WinUIEx; namespace MediaSharer { public sealed partial class MainWindow : Window { + private readonly string ICON_FILE_NAME = "icon.ico"; + private ProjectionWindow projectionWindow; + private ISettingsRepository settingsRepository; public MainWindow() { InitializeComponent(); - LoadIcon("icon.ico"); + + settingsRepository = App.Current.Services.GetService(); + + WinApi.LoadIcon(this, ICON_FILE_NAME); Navigate(typeof(DashboardPage)); RenderProjectionWindow(); @@ -50,25 +57,13 @@ private void RenderProjectionWindow() { projectionWindow = new ProjectionWindow(); projectionWindow.Title = LocalizedStrings.GetString("AppName"); - - SetProjectionWindowPosition(projectionWindow.As().WindowHandle); - projectionWindow.SetWindowPresenter(AppWindowPresenterKind.FullScreen); + projectionWindow.SetPosition(); + WinApi.LoadIcon(projectionWindow, ICON_FILE_NAME); + projectionWindow.Maximize(); + if (settingsRepository.IsProjectionWindowFullScreenEnabled) projectionWindow.SetWindowPresenter(AppWindowPresenterKind.FullScreen); projectionWindow.Activate(); } - private void SetProjectionWindowPosition(IntPtr hwnd) - { - var xPosition = DisplayArea.Primary.WorkArea.Width; - PInvoke.User32.SetWindowPos(hwnd, PInvoke.User32.SpecialWindowHandles.HWND_TOP, xPosition, 0, 0, 0, PInvoke.User32.SetWindowPosFlags.SWP_NOSIZE); - } - - private void LoadIcon(string iconName) - { - var hwnd = this.As().WindowHandle; - IntPtr hIcon = PInvoke.User32.LoadImage(IntPtr.Zero, iconName, PInvoke.User32.ImageType.IMAGE_ICON, 16, 16, PInvoke.User32.LoadImageFlags.LR_LOADFROMFILE); - PInvoke.User32.SendMessage(hwnd, PInvoke.User32.WindowMessage.WM_SETICON, (IntPtr)0, hIcon); - } - #endregion Private methods } } diff --git a/MediaSharer/MediaSharer/Repositories/Implementations/SettingsRepository.cs b/MediaSharer/MediaSharer/Repositories/Implementations/SettingsRepository.cs index b99dd2d..a5c0267 100644 --- a/MediaSharer/MediaSharer/Repositories/Implementations/SettingsRepository.cs +++ b/MediaSharer/MediaSharer/Repositories/Implementations/SettingsRepository.cs @@ -16,6 +16,18 @@ public bool AutoPlay set => TrySetLocalValue(nameof(AutoPlay), value); } + public bool IsProjectionWindowFullScreenEnabled + { + get => TryGetLocalValue(nameof(IsProjectionWindowFullScreenEnabled), false); + set => TrySetLocalValue(nameof(IsProjectionWindowFullScreenEnabled), value); + } + + public bool IsProjectionWindowAlwaysOnTopWhenSharing + { + get => TryGetLocalValue(nameof(IsProjectionWindowAlwaysOnTopWhenSharing), true); + set => TrySetLocalValue(nameof(IsProjectionWindowAlwaysOnTopWhenSharing), value); + } + #endregion Publics Properties #region Private Methods diff --git a/MediaSharer/MediaSharer/Repositories/Interfaces/ISettingsRepository.cs b/MediaSharer/MediaSharer/Repositories/Interfaces/ISettingsRepository.cs index 229da4a..42f55a6 100644 --- a/MediaSharer/MediaSharer/Repositories/Interfaces/ISettingsRepository.cs +++ b/MediaSharer/MediaSharer/Repositories/Interfaces/ISettingsRepository.cs @@ -3,5 +3,9 @@ public interface ISettingsRepository { bool AutoPlay { get; set; } + + bool IsProjectionWindowFullScreenEnabled { get; set; } + + bool IsProjectionWindowAlwaysOnTopWhenSharing { get; set; } } } diff --git a/MediaSharer/MediaSharer/Strings/en-US/Resources.resw b/MediaSharer/MediaSharer/Strings/en-US/Resources.resw index 07d53db..106ddde 100644 --- a/MediaSharer/MediaSharer/Strings/en-US/Resources.resw +++ b/MediaSharer/MediaSharer/Strings/en-US/Resources.resw @@ -132,6 +132,12 @@ On + + Always on top + + + Allow to put the projection screen in the front when sharing + AutoPlay @@ -141,6 +147,36 @@ External player controls + + Full screen + + + Allow to put the projection screen in full screen + + + Player + + + If both are needed, a workaround is to enable + + + Always on top + + + and in the + + + Taskbar + + + section of the Settings, disable + + + Show my taskbar on all screens + + + Projection screen + Settings diff --git a/MediaSharer/MediaSharer/Strings/fr-FR/Resources.resw b/MediaSharer/MediaSharer/Strings/fr-FR/Resources.resw index aeb0f7b..f6f2567 100644 --- a/MediaSharer/MediaSharer/Strings/fr-FR/Resources.resw +++ b/MediaSharer/MediaSharer/Strings/fr-FR/Resources.resw @@ -132,6 +132,12 @@ Activé + + Toujours au premier plan + + + Permet de mettre au premier plan l'écran de projection lors d'un partage + AutoPlay @@ -141,6 +147,36 @@ Commandes du player externe + + Plein écran + + + Permet de mettre l'écran de projection en plein écran + + + Player multimédia + + + Si les deux sont nécessaires, une solution de contournement consiste à activer + + + Toujours au premier plan + + + et dans la section + + + Barre des tâches + + + des Paramètres, désactiver + + + Afficher ma barre des tâches sur tous les affichages + + + Écran de projection + Paramètres diff --git a/MediaSharer/MediaSharer/Utils/WinApi.cs b/MediaSharer/MediaSharer/Utils/WinApi.cs new file mode 100644 index 0000000..1eb0ea7 --- /dev/null +++ b/MediaSharer/MediaSharer/Utils/WinApi.cs @@ -0,0 +1,17 @@ +using MediaSharer.Core; +using Microsoft.UI.Xaml; +using System; +using WinRT; + +namespace MediaSharer.Utils +{ + public static class WinApi + { + public static void LoadIcon(Window window, string iconName) + { + var hwnd = window.As().WindowHandle; + IntPtr hIcon = PInvoke.User32.LoadImage(IntPtr.Zero, iconName, PInvoke.User32.ImageType.IMAGE_ICON, 16, 16, PInvoke.User32.LoadImageFlags.LR_LOADFROMFILE); + PInvoke.User32.SendMessage(hwnd, PInvoke.User32.WindowMessage.WM_SETICON, (IntPtr)0, hIcon); + } + } +} diff --git a/MediaSharer/MediaSharer/Views/SettingsPage.xaml b/MediaSharer/MediaSharer/Views/SettingsPage.xaml index 4955d45..b584117 100644 --- a/MediaSharer/MediaSharer/Views/SettingsPage.xaml +++ b/MediaSharer/MediaSharer/Views/SettingsPage.xaml @@ -60,7 +60,7 @@ - @@ -92,6 +92,94 @@ Foreground="{StaticResource SettingSublabelColorBrush}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MediaSharer/MediaSharer/Views/SettingsPage.xaml.cs b/MediaSharer/MediaSharer/Views/SettingsPage.xaml.cs index a36c0db..1332790 100644 --- a/MediaSharer/MediaSharer/Views/SettingsPage.xaml.cs +++ b/MediaSharer/MediaSharer/Views/SettingsPage.xaml.cs @@ -1,4 +1,7 @@ -using MediaSharer.Core; +using System; +using MediaSharer.Core; +using Microsoft.UI.Xaml.Documents; +using Windows.System; namespace MediaSharer.Views { @@ -16,5 +19,11 @@ public SettingsPageViewModel PageViewModel => DataContext as SettingsPageViewModel; #endregion Properties + + #region Private methods + + private async void ProjectionWindowInfoLabelHyperlinkClick(Hyperlink sender, HyperlinkClickEventArgs args) => await Launcher.LaunchUriAsync(new Uri("ms-settings:taskbar")); + + #endregion Private methods } } diff --git a/MediaSharer/MediaSharer/Views/SettingsPageViewModel.cs b/MediaSharer/MediaSharer/Views/SettingsPageViewModel.cs index 37f721a..076b172 100644 --- a/MediaSharer/MediaSharer/Views/SettingsPageViewModel.cs +++ b/MediaSharer/MediaSharer/Views/SettingsPageViewModel.cs @@ -29,6 +29,36 @@ public bool AutoPlay } } + public bool IsProjectionWindowFullScreenEnabled + { + get => settingsRepository.IsProjectionWindowFullScreenEnabled; + set + { + if (value) + { + settingsRepository.IsProjectionWindowAlwaysOnTopWhenSharing = false; + OnPropertyChanged(nameof(IsProjectionWindowAlwaysOnTopWhenSharing)); + } + + settingsRepository.IsProjectionWindowFullScreenEnabled = value; + } + } + + public bool IsProjectionWindowAlwaysOnTopWhenSharing + { + get => settingsRepository.IsProjectionWindowAlwaysOnTopWhenSharing; + set + { + if (value) + { + settingsRepository.IsProjectionWindowFullScreenEnabled = false; + OnPropertyChanged(nameof(IsProjectionWindowFullScreenEnabled)); + } + + settingsRepository.IsProjectionWindowAlwaysOnTopWhenSharing = value; + } + } + public RelayCommand GoBackCommand => goBackCommand ?? (goBackCommand = new RelayCommand(() => GoBack())); diff --git a/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml b/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml index 2be7486..fc3586e 100644 --- a/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml +++ b/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml @@ -6,8 +6,11 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> - + + diff --git a/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml.cs b/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml.cs index 982ad55..eec29cd 100644 --- a/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml.cs +++ b/MediaSharer/MediaSharer/Windows/ProjectionWindow.xaml.cs @@ -10,22 +10,42 @@ using Windows.Media.Playback; using MediaSharer.Models; using Microsoft.UI.Xaml.Input; +using WinUIEx; +using MediaSharer.Core; +using WinRT; +using MediaSharer.Repositories.Interfaces; +using Microsoft.Extensions.DependencyInjection; namespace MediaSharer.Windows { public sealed partial class ProjectionWindow : Window { + private ISettingsRepository settingsRepository; private AppWindow m_appWindow; public ProjectionWindow() { - this.InitializeComponent(); + InitializeComponent(); + + settingsRepository = App.Current.Services.GetService(); m_appWindow = GetAppWindowForCurrentWindow(); + InitializeTitleBar(); WeakReferenceMessenger.Default.Register(this, StartItemSharingMessageReceived); WeakReferenceMessenger.Default.Register(this, StopItemSharingMessageReceived); } + #region Public methods + + public void SetPosition() + { + var hwnd = this.As().WindowHandle; + var xPosition = DisplayArea.Primary.WorkArea.Width; + PInvoke.User32.SetWindowPos(hwnd, PInvoke.User32.SpecialWindowHandles.HWND_TOP, xPosition, 0, 0, 0, PInvoke.User32.SetWindowPosFlags.SWP_NOSIZE); + } + + #endregion Public methods + #region Private methods private AppWindow GetAppWindowForCurrentWindow() @@ -36,13 +56,30 @@ private AppWindow GetAppWindowForCurrentWindow() return AppWindow.GetFromWindowId(myWndId); } + private void InitializeTitleBar() + { + ExtendsContentIntoTitleBar = true; + SetTitleBar(titleBar); + + var res = Application.Current.Resources; + res["WindowCaptionBackground"] = Colors.Transparent; + res["WindowCaptionBackgroundDisabled"] = Colors.Transparent; + res["WindowCaptionForeground"] = Colors.Transparent; + res["WindowCaptionForegroundDisabled"] = Colors.Transparent; + } + private void GridContainerDoubleTapped(object sender, DoubleTappedRoutedEventArgs e) { - m_appWindow.SetPresenter(m_appWindow.Presenter.Kind != AppWindowPresenterKind.FullScreen ? AppWindowPresenterKind.FullScreen : AppWindowPresenterKind.Default); + if (settingsRepository.IsProjectionWindowFullScreenEnabled) + { + m_appWindow.SetPresenter(m_appWindow.Presenter.Kind != AppWindowPresenterKind.FullScreen ? AppWindowPresenterKind.FullScreen : AppWindowPresenterKind.Default); + } } private void StartItemSharingMessageReceived(object recipient, StartItemSharingMessage message) { + if (settingsRepository.IsProjectionWindowAlwaysOnTopWhenSharing) this.SetIsAlwaysOnTop(true); + if (message.Item.ContentType == ContentType.Image) { imageElement.Visibility = Visibility.Visible; @@ -62,6 +99,8 @@ private void StartItemSharingMessageReceived(object recipient, StartItemSharingM private void StopItemSharingMessageReceived(object recipient, StopItemSharingMessage message) { + if (settingsRepository.IsProjectionWindowAlwaysOnTopWhenSharing) this.SetIsAlwaysOnTop(false); + imageElement.Visibility = Visibility.Collapsed; mediaPlayerElement.Visibility = Visibility.Collapsed; mediaPlayerElement?.MediaPlayer?.Dispose();