programing

WPF 창을 내 앱의 다른 모든 창 위에 표시하는 방법(시스템 전체가 아님)?

lastcode 2023. 5. 7. 11:28
반응형

WPF 창을 내 앱의 다른 모든 창 위에 표시하는 방법(시스템 전체가 아님)?

프로그램의 다른 모든 창 위에만 창을 표시합니다.창의 TopMost 속성을 설정하면 창이 모든 응용 프로그램의 모든 창 맨 위에 표시되므로 원하지 않습니다.

창의 소유자 속성을 설정해야 합니다.

주 창을 차단하기 위해 showdialog를 통해 창을 표시하거나, 일반 창을 표시하여 소유자를 차단하지 않고 소유자 위에 둘 수 있습니다.

다음은 파트 뒤에 있는 코드의 코드 예입니다. 저는 모든 명백한 것을 생략했습니다.

namespace StackoverflowExample
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();
    }
    void NewWindowAsDialog(object sender, RoutedEventArgs e)
    {
      Window myOwnedDialog = new Window();
      myOwnedDialog.Owner = this;
      myOwnedDialog.ShowDialog();
    }
    void NormalNewWindow(object sender, RoutedEventArgs e)
    {
      Window myOwnedWindow = new Window();
      myOwnedWindow.Owner = this;
      myOwnedWindow.Show();
    }
  }
}

대신에 항상 맨 위에 있는 팝업을 사용하여 창과 비슷하게 꾸미고 응용 프로그램에서 기본 창의 위치 변경 이벤트를 처리하고 팝업의 IsOpen 속성을 false로 설정할 수 있습니다.

편집:

다음과 같은 것을 원하시기 바랍니다.

    Window1 window;

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        window = new Window1();
        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        window.Topmost = true;
        this.LocationChanged+=OnLocationchanged;
        window.Show();
    }
     
    private void OnLocationchanged(object sender, EventArgs e)
    {
          if(window!=null)
              window.Close();
    }

도움이 되길 바랍니다!!!

CustomWindow cw = new CustomWindow();

cw.Owner = Application.Current.MainWindow;

cw.ShowInTaskbar = false;

cw.ShowDialog() ; 

XAML로 하는 것은 간단하며, 아직 아무도 이 답변을 게시하지 않은 것에 놀랐습니다.다음 예제에서는Window에 정의되어 있습니다.ResourceLibrary((으)로 x:Key), 이 XAML 실행형, XAML 바인딩에서도 할 수 Page 리소스style WPF 파일입니다.

<Window x:Key="other_window" 
        Topmost="{Binding Source={x:Static Application.Current},Path=MainWindow.IsActive,Mode=OneWay}">
    <TextBlock Text="OTHER WINDOW" />
</Window>

Activate() 메서드를 사용합니다.그러면 창이 전경으로 이동하여 활성화됩니다(예: Window wnd = new xyz(); wnd).활성화();

팝업 창에서 Show() 메서드를 매개 변수로 오버로드합니다.

Public Overloads Sub Show(Caller As Window)
    Me.Owner = Caller
    MyBase.Show()
End Sub

그런 다음 메인 창에서 오버로드된 메서드를 Show():

Dim Popup As PopupWindow

Popup = New PopupWindow
Popup.Show(Me)

저도 당신과 매우 비슷한 상황에 부딪혔습니다.제가 발견한 대부분의 검색은 기본 창 또는 표시라고 하는 창에서 맨 위에 있고 싶은 창의 소유자를 설정하는 것만 하면 된다고 명시했습니다.

아무튼 저에게 잘 맞는 솔루션을 올려보도록 하겠습니다.

Window용 이벤트 핸들러를 만들었습니다.활성화 및 창.내 애플리케이션과 관련하여 가장 상위에 있어야 하는 창에서 비활성화되었습니다.

private void Window_Activated(object sender, EventArgs e)
{
    Topmost = true;
}

private void Window_Deactived(object sender, EventArgs e)
{
    if(Owner == null || Owner.IsActive)
        return;
    bool hasActiveWindow = false;
    foreach(Window ownedWindow in Owner.OwnedWindows)
    {
        if(ownedWindow.IsActive)
            hasActiveWindow = true; 
    }

    if(!hasActiveWindow)
        Topmost = false;
}

그것은 저에게 아주 잘 맞습니다.바라건대 이것이 저 밖의 다른 누군가에게 유용하기를 바랍니다.

가장 좋은 방법은 이 두 가지 이벤트를 앱의 모든 창에 설정하는 것입니다.

GotKeyboardFocus
LostKeyboardFocus

다음과 같은 방식으로:

WiondowOfMyApp_GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    windowThatShouldBeTopMost.TopMost = true;
}

WiondowOfMyApp_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    windowThatShouldBeTopMost.TopMost = false;
}
  • 그리고 당신이 원하는 모든 창은 앱의 다른 창에서 액세스할 수 있어야 합니다.저의 경우에는 기본 창과 기본 창 위에 있어야 하는 다른 창이 있습니다. 그래서 이것은 제 기본 창에 서로의 인스턴스가 있는 것에 나쁘지 않았습니다.

여러 개의 스레드가 있으며 "가장 높은" 태그도 있습니다.그것을 검색하거나, 좋아 보이는 이 게시물로 바로 이동하십시오.

응용프로그램의 다른 모든 창 위에만 창을 유지하려면 어떻게 해야 합니까?

제가 OP입니다.몇 가지 조사와 테스트를 거친 결과, 다음과 같은 답이 나왔습니다.

아니요, 정확히 그렇게 할 방법은 없습니다.

다음은 "가장 위에 있는" 창을 다른 창 GotFocus 및 LostFocus 이벤트에 가입시키고 다음을 이벤트 핸들러로 사용하는 방법입니다.

class TopMostWindow
{
    void OtherWindow_LostFocus(object sender, EventArgs e)
    {
        this.Topmost = false;
    }

    void OtherWindow_GotFocus(object sender, EventArgs e)
    {
        this.Topmost = true;
    }
}

창 태그에 추가할 수 있습니다.

WindowStartupLocation="CenterScreen"

그런 다음 계속 진행하기 위해 사용자에게 승인을 요청하는 경우에도 표시할 수 있습니다.

YourWindow.ShowDialog();

먼저 TopMost 매개 변수 없이 사용해 보고 결과를 확인합니다.

사용해 보십시오.

Popup.PlacementTarget = sender as UIElement;

htis는 어떻습니까?

Private Sub ArrangeWindows(Order As Window())
    For I As Integer = 1 To Order.Length -1
        Order(I).Owner = Order(I - 1)
    Next
End Sub

저도 같은 문제에 직면했고 구글을 따라 이 질문에 답했습니다.최근에 저는 다음과 같은 것들이 저에게 효과가 있다는 것을 알았습니다.

CustomWindow cw = new CustomWindow();
cw.Owner = this;
cw.ShowDialog();

저는 방금 같은 문제에 부딪혔습니다.WPF 창이 여러 개 있는 데스크톱 앱을 가지고 있으며, 앱의 다른 창 위에만 사용자 지정 스플래시 화면이 있어야 했습니다.시작 화면이 나타나면 다른 창이 열리지 않지만 인증 후 시작 화면에서 기본 창을 엽니다.그래서 저는 @GlenSlayden이 했던 것과 유사한 것을 했을 뿐이지만 코드 뒤에 있습니다. 제가 말했듯이 메인 윈도우는 제가 바인딩할 수 있는 것이 아닙니다.

private void SplashScreen_ContentRendered(object sender, EventArgs e)
{
    // User authentication...
    // ...

    MainWindow mainWindow = new MainWindow();
    SetBinding(SplashScreen.TopmostProperty, new Binding("IsVisible"))
    {
        Source = mainWindow,
        Mode = BindingMode.OneWay,
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    };
    mainWindow.Show();
}

프로그램이 기본 창에서 다른 모든 창을 로드하는 동안 스플래시 화면은 맨 위에 있지만 프로그램이 사용자를 인증하는 동안 맨 위에 있지 않으므로 다른 프로그램을 클릭하면 프로그램이 맨 뒤에 숨겨집니다.이 문제에 대한 해결책을 찾을 수 있는 가장 가까운 방법입니다.인증 후 프로그램이 로드되는 동안 다른 모든 응용 프로그램을 능가하기 때문에 완벽하지 않지만, 저의 경우에는 그렇게 오래 걸리지 않습니다.

저는 같은 문제에 부딪혔고 운영 중에 앱이 중단되지 않고 MVVM을 사용하여 소유자를 설정하는 데 문제가 있다는 것을 발견했습니다.창의 uri를 사용하여 창을 여는 명령이 포함된 창 관리자 뷰 모델을 가지고 있는데 소유자를 앱으로 설정할 수 없었습니다.앱이 손상되지 않은 메인 창.

그래서 - 소유자를 설정하는 대신 창의 TopMost 속성을 관리자 보기 모델에서 응용 프로그램이 현재 활성 상태인지 여부를 나타내는 속성에 바인딩했습니다. 애플리케이션이 활성화되어 있으면 원하는 대로 창이 위쪽에 있습니다. 활성화되지 않은 경우 다른 창에서 적용할 수 있습니다.

View 모델에 추가한 내용은 다음과 같습니다.

 public class WindowManagerVM : GalaSoft.MvvmLight.ViewModelBase
    {
        public WindowManagerVM()
        {
            App.Current.Activated += (s, e) => IsAppActive = true;
            App.Current.Deactivated += (s, e) => IsAppActive = false;
        }

        private bool _isAppActive = true;
        public bool IsAppActive
        {
            get => _isAppActive;
            set
            {
                if (_isAppActive != value)
                {
                    _isAppActive = value;
                    RaisePropertyChanged(() => IsAppActive);
                }
            }
        }
    }

이를 구현하는 XAML은 다음과 같습니다(Locator라는 앱에서 ViewModelLocator와 함께 MVVM 라이트를 정적 리소스로 사용).

<Window Topmost="{Binding WindowManager.IsAppActive, Source={StaticResource Locator}}"/>

이것이 저에게 도움이 되었습니다.

Window selector = new Window ();
selector.Show();
selector.Activate();
selector.Topmost = true;

이 질문에 대한 두 번째 답변입니다. 여러 개를 관리하는 데 매우 효과적인 다른 기술을 찾았습니다.Window한 사람에 속하는 예.Application

많은 사람들이 지적했듯이,Window.Owner속성이 키입니다.앱이 활성화될 때마다 창 중 하나를 의미합니다.IsActive--당신은 그것을 원합니다.Owner당신의 모든 창의 속성은 다음과 같습니다.null이를 통해 앱의 다양한 창을 동일하게 전환할 수 있습니다.

하지만 당신의 앱이 활성화되지 않을 때, 당신은 그것을 원합니다.Window.Owner 비거주자에 대한 자산MainWindow설정할 창MainWindow이렇게 하면 앱의 모든 창을 사용하여 다시 활성화할 수 있으며 모든 앱의 창이 다른 모든앞에 복원됩니다.

앱이 다시 활성화될 때마다Window.Owner에 대한 가치.null.그Application.OnActivated그리고.Application.OnDeactivated방법은 이것에 완벽합니다.

이 해결 방법을 사용하면 편리하지 않으므로 모든 창 목록을 별도로 보관해야 합니다.Window.OwnedWindows소유 재산MainWindow이러한 조정을 수행해야 할 때를 대비합니다.

public partial class MyApp : Application
{
    // not shown: keep this list of all your non-main windows updated...
    public List<Window> rgw = new List<Window>();

    protected override void OnActivated(EventArgs e)
    {
        // when app is ACTIVE, set all `Owner` values to null...
        rgw.ForEach(w => w.Owner = null);

        base.OnActivated(e);
    }

    protected override void OnDeactivated(EventArgs e)
    {
        // set `Owner` on all non-main Windows only when not-active
        rgw.ForEach(w => w.Owner = Current.MainWindow);  

        base.OnDeactivated(e);
    }

    // etc..
}

방금 C#을 배웠고 비슷한 상황을 마주쳤습니다.도움이 될 만한 해결책을 찾았죠여러분은 오래 전에 이것을 알아냈을지도 모릅니다.이것은 새로운 프로젝트를 시작할 때부터가 될 것이지만 당신은 그것을 어느 곳에서나 사용할 수 있습니다.

새 프로젝트를 시작합니다.

프로젝트로 이동한 다음 새 Windows 양식을 선택하고 Windows 양식 및 이름 스플래시를 선택합니다.

크기, 배경, 텍스트 등을 원하는 대로 설정합니다.

Splash.cs 양식 세트의 속성에서 시작 위치:중앙 화면 및 맨 위: true

form1에 "시스템 사용"을 추가합니다.스레드화;"

form1 하위 클래스에 "스플래시 스플래시 화면 = 새 스플래시();"를 추가합니다.

form1에 "discovery screen"을 추가합니다.표시();" 및 "응용 프로그램".이벤트 실행();"

form1 언더 이벤트>>포커스 >>>활성화되어 "스레드"를 추가합니다.절전 모드(4000), 스플래시 화면.닫기();"

Splash.cs 에서 "공개 스플래시" 아래에 "이것"을 추가합니다.백컬러 = 컬러.Aqua;" /모든 색상 사용 가능

10) Form1.cs 의 코드입니다.

public partial class Form1 : Form
{
    Splash splashscreen = new Splash();
    public Form1()
    {
        InitializeComponent();
        splashscreen.Show();
        Application.DoEvents();

    }

    private void Form1_Activated(object sender, EventArgs e)
    {
        Thread.Sleep(4000);
        splashscreen.Close();
    }
}

11) Splash.cs 의 코드입니다.

public partial class Splash : Form
{
    public Splash()
    {
        InitializeComponent();
        this.BackColor = Color.Aqua;
    }
}

12) 스플래시에서 작업을 수행하지 않으면 첫 번째 양식을 활성화해야 하는 시간 동안 화면이 상단에 유지되지 않습니다.스레드 수는 x초 후에 스플래시가 사라지므로 프로그램은 정상입니다.

언급URL : https://stackoverflow.com/questions/2546566/how-to-make-a-wpf-window-be-on-top-of-all-other-windows-of-my-app-not-system-wi

반응형