programing

항상 맨 위에 있는 WPF

mailnote 2023. 5. 6. 15:18
반응형

항상 맨 위에 있는 WPF

다른 응용 프로그램이 전체 화면에서 실행 중인 경우에도 창을 항상 맨 위로 유지할 수 있습니까?지금 사용 중입니다.TopMost = true그러나 다른 응용 프로그램이 전체 화면에서 실행되면 내 응용 프로그램은 보이지 않게 됩니다.그건…WindowStyle = None창가 쪽에

편집: 물론 다른 창이 최소화되지 않도록 합니다.

이것이 100% 효과가 있는 것은 아니지만 상황을 어느 정도 개선시킬 것입니다.설정할 수 있습니다.Topmost = true이벤트 핸들러에서:

private void Window_Deactivated(object sender, EventArgs e)
{
    Window window = (Window)sender;
    window.Topmost = true;
}

Deactivated프로그램이 초점을 잃을 때마다 이벤트가 호출됩니다(종종 다른 프로그램이 요청할 때).Topmost이렇게 하면 응용프로그램이 초기화됩니다.

MSDN의 이 솔루션을 사용해 보십시오. 효과가 있을 것입니다.에서Window Activated Event다음 코드를 추가합니다.

this.Width   = System.Windows.SystemParameters.PrimaryScreenWidth;
this.Height  = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Topmost = true;
this.Top  = 0;
this.Left = 0;

DeActivated Event다음 코드를 추가합니다.

this.Topmost = true;
this.Activate();

MSDN의 원본 게시물

위의 어떤 해결책도 저에게 효과가 없었기 때문에, 제가 하게 된 것은 다음과 같습니다.그것은 저에게 완벽하게 효과가 있었습니다.

기본적으로 위에 유지하려면 초점 손실 이벤트를 다시 위로 이동하도록 설정하면 됩니다.

XAML:

PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"
    

코드 이면:

private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
      var window = (Window)sender;
      window.Topmost = true;
}

응용 프로그램을 EVERYTHING(이전의 "Metro"로 알려진 Windows 8의 시작 인터페이스 포함) 위에 유지하려면 UiAccess=를 지정할 수 있습니다."매니페스트 파일에 "True"가 있습니다.일반적으로 화면 키보드와 같은 내게 필요한 옵션 응용 프로그램에서 사용됩니다.

기억에서 당신은 3가지 일을 해야 합니다.

  1. UiAccess= 요청"참"
  2. 인증된 인증서로 응용프로그램의 exe 파일에 서명합니다.저는 오픈소스 프로젝트이기 때문에 Certum에서 무료 코드 서명 자격증을 취득했습니다.
  3. 프로그램 파일 디렉터리인 "신뢰할 수 있는 위치"에 응용 프로그램을 설치합니다.제가 찾을 수 있는 "신뢰할 수 있는 위치"에 대한 공식적인 정의가 없습니다.

그래서 저는 최근에 같은 요구사항에 부딪혔습니다.저는 두 번째뿐만 아니라 최고 등급의 답변도 제대로 작동하지 않은 것 같습니다.MVVM을 사용하여 완벽하게 작동하고 모범 사례를 준수하는 솔루션을 찾았습니다.

아래를 사용하면 창이 맨 위로 이동하고 다른 솔루션과 마찬가지로 변경 사항이 적용되지 않습니다.

1단계: 기본 클라이언트 창에 대한 간단한 상태 관리자 클래스를 만들었습니다.알림을 사용했습니다.창에 대한 직접 바인딩을 사용할 때 속성이 동기화되도록 속성이 변경되었습니다.(매우 중요)

public class ClientStateManager : INotifyPropertyChanged
{
    #region Private Variables
    private bool isForceToTop;
    private bool isClientEnabled;
    #endregion

    #region Public Properties
    public bool IsForceToTop
    {
        get { return isForceToTop; }
        set
        {
            isForceToTop = value;
            NotifyPropertyChanged();
        }
    }
    public bool IsClientEnabled
    {
        get { return isClientEnabled; }
        set
        {
            isClientEnabled = value;
            NotifyPropertyChanged();
        }
    }       
    #endregion

    #region Private Methods
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    #region Public Methods
    public void Lock() => this.IsClientEnabled = false;
    public void UnLock() => this.IsClientEnabled = true;
    public void SetTop() => this.IsForceToTop = true;
    public void UnSetTop() => this.IsForceToTop = false;
    #endregion

    #region Public Events
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion
}

2.1단계: 상태 관리자 클래스를 View Model에 추가했습니다.(MVVM)

  internal class MainWindowViewModel : INotifyPropertyChanged
  {
    #region Constructor
    public MainWindowViewModel() 
    {
        ClientStateManager = new ClientStateManager();
    }
    #endregion

    #region Public Properties  
    public ClientStateManager ClientStateManager { get; private set; }
    #endregion
  }

2.2단계: 그런 다음 창 데이터 컨텍스트를 뷰 모델로 설정합니다.

  private MainWindowViewModel model;
  private MainWindow()
  {
        InitializeComponent();
        this.model = new MainWindowViewModel();
        this.DataContext = model;
  }   

3단계: 데이터 바인딩을 창에 추가합니다.

  <Window x:Class="Intouch_Work.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ojects="clr-namespace:Framework.Object;assembly=Framework"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"     
    mc:Ignorable="d"
    Title="Intouch" Height="800" Width="1100"
    x:Name="mainWindow"
    Topmost="{Binding Path=ClientStateManager.IsForceToTop, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">

이제 View Model 내에서 초기화된 상태 관리자 개체를 사용하여 창 상태를 관리할 수 있습니다.상태 관리자에서 SetTop()을 호출하여 앞으로 밀거나 UnSetTop()을 호출하여 중지할 수 있습니다.이것이 같은 일을 하려는 모든 사람들에게 도움이 되기를 바랍니다.

는 산업 했는데, 이할 수 . 심지어 ▁even▁i▁should▁operators.Windows+D바탕 화면을 표시합니다.그리고 저는 그것을 달성하기 위한 가장 깨끗하고 간단한 방법이 다음을 통해 가능하다는 것을 알게 되었습니다.

  1. 설정을 할 수 있습니다.Width,Height,WindowStyle,WindowState그리고.Topmost특성.
  2. 이벤트 처리: 일부관이처리:StateChanged,Deactivated,LostFocuse,LostMouseCapture,LostKeyboardFocus그리고.PreviewLostKeyboardFocus.
  3. 으로 마감 ALT+F4또는 사용자 정의 버튼).

P/Invoke가 필요하지 않습니다. 다음은 전체 코드입니다.

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += OnLoaded;
            Closing += OnClosing;
            StateChanged += OnStateChanged;
            Deactivated += (sender, args) => Activate();
            LostFocus += (sender, args) => Focus();
            LostMouseCapture += (sender, args) => Mouse.Capture(this);
            LostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
            PreviewLostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Width = SystemParameters.PrimaryScreenWidth;
            Height = SystemParameters.PrimaryScreenHeight;
            WindowStyle = WindowStyle.None;
            WindowState = WindowState.Maximized;
            Topmost = true;
            // Other stuff here
        }

        private void OnClosing(object sender, CancelEventArgs e)
        {
            // You might want to allow only some users to close the app
            if (MessageBox.Show("Are you an admin?", "Admin Check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
               e.Cancel = true;
        }

        private void OnStateChanged(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
                WindowState = WindowState.Maximized;
        }
    }

이 중 일부를 XAML에 넣을 수도 있습니다.

<Window x:Class="FullScreen.MainWindow"
        ...
        Title="MainWindow"
        WindowState="Maximized"
        WindowStyle="None" 
        Topmost="True">
    <Grid>
        
    </Grid>
</Window>

모든 것 위에 유지하고 싶은 메인 창이 있었습니다(사용자가 "항상 맨 위에"를 선택한 경우).
이것은 저에게 효과가 있었습니다.이것이 누군가에게 도움이 되기를 바랍니다.

// If we want main to stay on top, we set the rest of the menus to Not be top 
if (mnuViewMainWindowAlwaysOnTopo.IsChecked)
{
    this.Topmost = true;
    
    foreach (var window in Application.Current.Windows)
        // Don't change for main window
        if (window.GetType().Name != this.GetType().Name)
            window.Topmost = false;
}
else this.Topmost = false;

언급URL : https://stackoverflow.com/questions/20050426/wpf-always-on-top

반응형