WPF에서 창을 앞으로 가져 오기


214

WPF 응용 프로그램을 데스크탑 전면으로 가져 오려면 어떻게해야합니까? 지금까지 나는 시도했다 :

SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);

SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);

어느 것도 작업을 수행하지 않습니다 ( Marshal.GetLastWin32Error()이러한 작업이 성공적으로 완료되었다고 말하고 각 정의에 대한 P / Invoke 속성에 있음 SetLastError=true).

새 빈 WPF 응용 프로그램을 만들고 SwitchToThisWindow타이머를 사용하여 호출 하면 예상대로 정확하게 작동하므로 원래 사례에서 왜 작동하지 않는지 잘 모르겠습니다.

편집 : 나는 글로벌 핫키와 함께 이것을하고 있습니다.


MainWindow가 원하는 창인지 확인 했습니까? MSDN에서 : MainWindow는 AppDomain에서 인스턴스화 할 첫 번째 Window 개체에 대한 참조로 자동 설정됩니다.
Todd White

좋은 생각이지만 응용 프로그램에서 유일한 창입니다.
Factor Mystic

좀 더 컨텍스트 코드를 줄 수 있습니까?
Todd White

답변:


314
myWindow.Activate();

창을 전경으로 가져 와서 활성화합니다.

내가 오해하지 않고 항상 맨 위의 동작을 원하지 않는 한 트릭을 수행해야합니다. 이 경우에는 다음을 원합니다.

myWindow.TopMost = true;

14
나는 단순히 myWindow.Show ()를 사용하고 있었고 때로는 상단에 없었습니다. 그 후 즉시 myWindow.Activate ()를 호출하여 작동했습니다.
Bermo

4
Windows XP에서는 때때로 활성화가 작동하지 않습니다. @Matthew Xavier의 답변을 권장합니다.
Lex Li

기본적으로 ShowActivated가 설정되어 있기 때문에 조금 이상합니다.
greenoldman

1
첫 번째 대답은 좋습니다. 감사합니다. 그러나 Topmost속성을 사용하는 두 번째 코드 줄은 다른 팝업 대화 상자를 가리고 예기치 않은 동작을 할 수 있기 때문에 나쁜 습관입니다.
조나단 페리

2
실제로 이것은 다음과 같이 수행 할 수 있습니다 : if (myWindow.WindowState == WindowState.Minimized) myWindow.WindowState = WindowState.Normal;이상하게도 최대화 된 창을 유지하고 창을 일반 상태로 되 돌리지 않습니다.
r41n

168

창을 맨 위로 가져 오는 솔루션을 찾았지만 일반 창처럼 작동합니다.

if (!Window.IsVisible)
{
    Window.Show();
}

if (Window.WindowState == WindowState.Minimized)
{
    Window.WindowState = WindowState.Normal;
}

Window.Activate();
Window.Topmost = true;  // important
Window.Topmost = false; // important
Window.Focus();         // important

1
좋은 힌트! TopMost는 윈도우가 이미 열려 있지만 다른 윈도우 아래에있는 경우 Windows 7에서 마법을 발생시킵니다.
gsb

이것은 나에게도 속임수를 썼다. TopMost의 이상한 사용에 대한 추가 의견을 주신 gsb에게 감사드립니다!
Jen

1
고마워-수정이 짧고 달콤했습니다.
code4life

2
필자의 경우 Window.Activate () 및 Window.Focus ()로 충분했습니다. Setting Window.TopMost는 불필요합니다.
악의

6
사용하지 마십시오 Window.Focus(). 이렇게하면 사용자가 텍스트 상자에 현재 입력하고있는 내용에서 포커스를 빼앗아 최종 사용자에게는 실망 할 것입니다. 위의 코드는 그것없이 잘 작동합니다.
Contango

32

창을 처음로드 할 때 맨 앞에 있어야하는 경우 다음을 사용해야합니다.

private void Window_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
}

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

1
C #에서 Launchy ( launchy.net ) 와 비슷한 것을 개발 하면이 대답이 거의 쓸모가 없다는 것을 알아야합니다.
Lex Li

21

이것을 빠른 복사-붙여 넣기 방법으로 만들기 -
이 클래스의 DoOnProcess메소드를 사용 하여 프로세스의 메인 윈도우를 포 그라운드로 옮기십시오 (그러나 다른 윈도우에서 포커스를 훔치지는 않습니다)

public class MoveToForeground
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);

    const int SWP_NOMOVE        = 0x0002;
    const int SWP_NOSIZE        = 0x0001;            
    const int SWP_SHOWWINDOW    = 0x0040;
    const int SWP_NOACTIVATE    = 0x0010;
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

    public static void DoOnProcess(string processName)
    {
        var allProcs = Process.GetProcessesByName(processName);
        if (allProcs.Length > 0)
        {
            Process proc = allProcs[0];
            int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
            // Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
            SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
        }
    }
}

HTH


6
+1 이것은 나에게 유용한 유일한 대답입니다. 하나의 마스터와 여러 개의 부동 슬레이브 창이있는 응용 프로그램이 있습니다. 이들 중 하나를 활성화하면 다른 모든 창도 앞쪽으로 가져와야합니다. 그러나 대부분의 답변에서 알 수 있듯이 활성화 / 초점을 얻지 못했습니다. 갑자기 다른 창에 초점이 맞춰져 현재 클릭 한 창을 클릭 할 수 없게 만드는 것은 재앙입니다.
stijn

사용하지 않는 이유는 process.MainWindowHandle무엇입니까?
Sriram Sakthivel

필자의 경우 기본 창을 원하지 않았지만 동의하는 다른 방법이 hWnd있습니다. FWIW는 HwndSource개체가 잘 작동.
tobriand

21

나는이 질문이 다소 오래되었다는 것을 알고 있지만이 정확한 시나리오를 보았고 구현 한 솔루션을 공유하고 싶었습니다.

이 페이지의 의견에서 언급했듯이 제안 된 여러 솔루션은 XP에서 작동하지 않으므로 시나리오에서 지원해야합니다. @Matthew Xavier의 의견에 동의하지만 일반적으로 이것이 나쁜 UX 관행이라는 사실에 동의하지만, 전적으로 그럴듯한 UX 인 경우가 있습니다.

WPF 창을 맨 위로 가져 오는 솔루션은 실제로 글로벌 핫키를 제공하는 데 사용하는 동일한 코드로 제공되었습니다. Joseph Cooney의 블로그 기사 에는 원래 코드가 포함 된 코드 샘플에 대한 링크 가 포함되어 있습니다.

코드를 약간 정리하고 수정했으며 System.Windows.Window에 대한 확장 메서드로 구현했습니다. XP 32 비트 및 Win7 64 비트에서 이것을 테스트했으며 둘 다 올바르게 작동합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace System.Windows
{
    public static class SystemWindows
    {
        #region Constants

        const UInt32 SWP_NOSIZE = 0x0001;
        const UInt32 SWP_NOMOVE = 0x0002;
        const UInt32 SWP_SHOWWINDOW = 0x0040;

        #endregion

        /// <summary>
        /// Activate a window from anywhere by attaching to the foreground window
        /// </summary>
        public static void GlobalActivate(this Window w)
        {
            //Get the process ID for this window's thread
            var interopHelper = new WindowInteropHelper(w);
            var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);

            //Get the process ID for the foreground window's thread
            var currentForegroundWindow = GetForegroundWindow();
            var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);

            //Attach this window's thread to the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);

            //Set the window position
            SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

            //Detach this window's thread from the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);

            //Show and activate the window
            if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
            w.Show();
            w.Activate();
        }

        #region Imports

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        [DllImport("user32.dll")]
        private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        #endregion
    }
}

이 코드가이 문제를 겪는 다른 사람들에게 도움이되기를 바랍니다.


저기 봐! 나는 이것을 몇 달 동안 고투 해왔다! 이것은 두 가지 상황 모두에서 작동합니다. 대박! (Windows 7 x64)
mdiehl13

실제로, 내가 이렇게하면 작동하는 것 같습니다 : App.mainWindow.Show (); SystemWindows.GlobalActivate (App.mainwindow); // 첫 번째 .show ()를 제거해도 앞에 나오지 않습니다
mdiehl13

SetWindowPos () +1, 다른 응용 프로그램을 방해하거나 포커스를 훔치지 않고 내 창을 앞으로 가져 오는 방법을 찾고있었습니다. this.Activate ()는 포커스를 훔칩니다.
prettyvoid

이것은 나를 위해 그것을했고, 내 경우의 요점은 사용자가 특정 요소와 상호 작용할 때 일어난 것처럼 초점을 훔치는 것이 었습니다. 고마워 이것은 일관되게 작동하는 것 같습니다! 전화 this.Activate()는 몇 번만 작동하는 것 같습니다.
Peter

13

사용자가 다른 응용 프로그램과 상호 작용하는 경우 사용자의 응용 프로그램을 맨 앞으로 가져올 수 없습니다. 일반적으로 프로세스는 해당 프로세스가 이미 포 그라운드 프로세스 인 경우에만 포 그라운드 창을 설정할 것으로 예상 할 수 있습니다. (Microsoft는 SetForegroundWindow () MSDN 항목 의 제한 사항을 설명합니다 .) 그 이유는 다음과 같습니다.

  1. 사용자는 포 그라운드를 "소유"합니다. 예를 들어, 사용자가 입력하는 동안 다른 프로그램이 포 그라운드를 훔 쳤을 때 최소한 워크 플로우를 방해하고 한 응용 프로그램의 키 입력이 변경 사항을 알 때까지 위반자가 잘못 해석하여 의도하지 않은 결과를 초래할 수 있습니다. .
  2. 두 프로그램 각각이 해당 창의 창이 전경인지 확인하고 그렇지 않은 경우이를 전경으로 설정하려고 시도한다고 상상해보십시오. 두 번째 프로그램이 실행 되 자마자 모든 작업 스위치에서 포 그라운드가 두 개 사이에서 바운스됨에 따라 컴퓨터가 쓸모 없게됩니다.

좋은 지적. 그러나 코드의 목적은 글로벌 핫키와 관련이 있었으며 다른 응용 프로그램에서도 그렇게합니다.
Factor Mystic

C #에서 PInvoke를 사용하여 codeproject.com/Tips/76427/
Lex Li

그렇다면 Visual Studio로 전환 할 때 Expression Blends 오류 팝업 대화 상자가 계속 표시되는 이유는 무엇입니까? :-/
Simon_Weaver

Simon, 나는 당신이 보는 오류 팝업이 "맨 위의"창이라고 생각한다. 사용자 입력을받는 전경 윈도우와 Z 순서의 "맨 위"윈도우에는 차이가 있습니다. 모든 창은 "맨 위"로 만들 수 있으며,이 창은 맨 위가 아닌 모든 창 위에 배치되지만 창 키보드 포커스 등을 제공하지는 않습니다.
Matthew Xavier

몇 가지 특수 창에는이 방법이 실패합니다. Visual Studio 및 명령 프롬프트 창에는 다른 창이 전경 창이되지 않도록하는 것이 있어야합니다.
Lex Li

9

나는 이것이 답이 늦다는 것을 알고 있습니다.

 if (!WindowName.IsVisible)
 {
     WindowName.Show();
     WindowName.Activate();
 }

9

이 페이지의 답변 중 일부가 틀린 이유는 무엇입니까?

  • 사용하는 답변 window.Focus()이 잘못되었습니다.

    • 왜? 알림 메시지가 표시 window.Focus()되면 사용자가 입력 한 내용에서 포커스를 빼십시오. 특히 팝업이 자주 발생하는 경우 최종 사용자에게는 실망 스럽습니다.
  • 사용하는 답변 window.Activate()이 잘못되었습니다.

    • 왜? 부모 창도 표시됩니다.
  • 생략 된 모든 대답 window.ShowActivated = false은 잘못되었습니다.
    • 왜? 메시지가 나올 때 다른 창에서 초점을 빼앗아 매우 성 가실 것입니다!
  • 사용하지 않는 답변 Visibility.Visible창을 숨기거나 표시하는 데 이 잘못되었습니다.
    • 왜? Citrix를 사용하는 경우 창을 닫을 때 창이 축소되지 않으면 화면에 이상한 검은 색 사각형이 유지됩니다. 따라서, 우리는 사용할 수 없습니다 window.Show()window.Hide().

본질적으로 :

  • 창은 활성화 될 때 다른 창에서 포커스를 잡아서는 안됩니다.
  • 창이 표시 될 때 부모를 활성화하지 않아야합니다.
  • 이 창은 Citrix와 호환되어야합니다.

MVVM 솔루션

이 코드는 Citrix와 100 % 호환됩니다 (화면의 빈 영역 없음). 일반적인 WPF와 DevExpress로 테스트되었습니다.

이 답변은 항상 다른 창 앞에있는 작은 알림 창을 원할 때 사용합니다 (사용자가 환경 설정에서 이것을 선택하면).

이 답변이 다른 답변보다 더 복잡해 보이면 강력한 엔터프라이즈 급 코드이기 때문입니다. 이 페이지의 다른 답변 중 일부는 간단하지만 실제로 작동하지는 않습니다.

XAML-연결된 속성

이 첨부 된 특성을 UserControl창 내에서 추가하십시오 . 첨부 된 재산은 :

  • Loaded이벤트가 발생할 때까지 기다리십시오 (그렇지 않으면 부모 창을 찾기 위해 비주얼 트리를 찾을 수 없습니다).
  • 창이 표시되는지 확인하는 이벤트 핸들러를 추가하십시오.

어느 시점에서든 연결된 속성 값을 뒤집어 창을 앞쪽으로 설정하거나 해제 할 수 있습니다.

<UserControl x:Class="..."
         ...
         attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
             "{Binding EnsureWindowInForeground, Mode=OneWay}">

C #-도우미 방법

public static class HideAndShowWindowHelper
{
    /// <summary>
    ///     Intent: Ensure that small notification window is on top of other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoForeground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Visible)
            {
                window.Visibility = Visibility.Visible;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = true;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }

    /// <summary>
    ///     Intent: Ensure that small notification window can be hidden by other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoBackground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Collapsed)
            {
                window.Visibility = Visibility.Collapsed;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = false;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }
}

용법

이를 사용하려면 ViewModel에서 창을 만들어야합니다.

private ToastView _toastViewWindow;
private void ShowWindow()
{
    if (_toastViewWindow == null)
    {
        _toastViewWindow = new ToastView();
        _dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
    }
    ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
    HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}

private void HideWindow()
{
    if (_toastViewWindow != null)
    {
        HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
    }
}

추가 링크

알림 창이 항상 보이는 화면으로 되돌아 가도록하는 방법에 대한 팁은 내 답변 : WPF에서 화면이 꺼져있을 때 창을 화면으로 이동하는 방법을 참조하십시오 . .


5
"엔터프라이즈 레벨 코드"와 몇 줄 후에 catch (Exception) { }. 네 맞아요 그리고 그것은 _dialogService또는 같은 대답에 표시되지 않은 코드를 사용합니다 ShiftWindowOntoScreenHelper. 또한 viewmodel 쪽에서 창을 만들도록 요청합니다 (기본적으로 전체 MVVM 패턴이 깨짐).
Kryptos

@Kryptos 이것은 엔터프라이즈 레벨 코드입니다. 메모리에서 입력 한 결과,이 정확한 기술은 대규모 FTSE100 회사에서 사용됩니다. 실생활은 우리 모두가 목표로하는 완벽한 디자인 패턴에 비해 다소 덜 깨끗합니다.
Contango

크립토 스가 mvvm의 요점을 어기는 것으로 언급 한 것처럼 뷰 모델에서 창 인스턴스를 유지한다는 사실이 마음에 들지 않습니다. 대신 코드 숨김으로 수행되었을 수 있습니까?
Igor Meszaros

1
@Igor Meszaros 합의. 이제 더 많은 경험이 있으므로 다시해야 할 경우 동작을 추가 Func<>하고 ViewModel에 바인딩 된 것을 사용하여 제어 합니다.
Contango

7

Shell 개체를 통해 Access 응용 프로그램에서 호출되는 WPF 응용 프로그램과 비슷한 문제가 있습니다.

내 솔루션은 다음과 같습니다-XP 및 Win7 x64에서 x86 대상으로 컴파일 된 응용 프로그램에서 작동합니다.

alt-tab을 시뮬레이션하는 것보다이 작업을 수행하는 것이 좋습니다.

void Window_Loaded(object sender, RoutedEventArgs e)
{
    // make sure the window is normal or maximised
    // this was the core of the problem for me;
    // even though the default was "Normal", starting it via shell minimised it
    this.WindowState = WindowState.Normal;

    // only required for some scenarios
    this.Activate();
}

4

글쎄, 이것은 매우 인기있는 주제이기 때문에 여기에 나에게 도움이되는 것이 있습니다. 창을 볼 수 없으면 Activate ()가 오류를 발생시키기 때문에 이런 식으로하지 않으면 오류가 발생합니다.

Xaml :

<Window .... 
        Topmost="True" 
        .... 
        ContentRendered="mainWindow_ContentRendered"> .... </Window>

코드 비하인드 :

private void mainWindow_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
    this.Activate();
    _UsernameTextBox.Focus();
}

이것이 창을 맨 위에 표시하는 유일한 방법이었습니다. 그런 다음 마우스로 초점을 설정할 필요없이 상자에 입력 할 수 있도록 활성화하십시오. 창이 활성화되어 있지 않으면 control.Focus ()가 작동하지 않습니다.


2

글쎄, 나는 해결 방법을 알아 냈습니다. 핫키를 구현하는 데 사용되는 키보드 후크에서 전화를 겁니다. 일시 중지로 BackgroundWorker에 넣으면 통화가 예상대로 작동합니다. 그것은 kludge이지만, 그것이 원래 작동하지 않은 이유를 모르겠습니다.

void hotkey_execute()
{
    IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
    BackgroundWorker bg = new BackgroundWorker();
    bg.DoWork += new DoWorkEventHandler(delegate
        {
            Thread.Sleep(10);
            SwitchToThisWindow(handle, true);
        });
    bg.RunWorkerAsync();
}

관심 : Morten이 제안한 Window.Activate와 다른 제안을 시도 했습니까? 그들은 인정 된이 kludge보다 덜 해킹 된 것처럼 보인다.
Simon D.

이것은 꽤 오래 전에 이루어졌지만, 그렇습니다. 제가 시도했을 당시
Factor Mystic

Windows XP에서는 작동하지 않습니다. @Matthew Xavier의 답변을 권장합니다.
Lex Li

2

현재 열린 창을 표시하려면 해당 DLL을 가져옵니다.

public partial class Form1 : Form
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);
    [DllImportAttribute("User32.dll")]
    private static extern int SetForegroundWindow(int hWnd);

그리고 프로그램에서 우리는 지정된 제목을 가진 앱을 검색합니다 (첫 글자없이 제목을 쓰십시오 (색인> 0))

  foreach (Process proc in Process.GetProcesses())
                {
                    tx = proc.MainWindowTitle.ToString();
                    if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
                    {
                        tx = proc.MainWindowTitle;
                        hWnd = proc.Handle.ToInt32(); break;
                    }
                }
                hWnd = FindWindow(null, tx);
                if (hWnd > 0)
                {
                    SetForegroundWindow(hWnd);
                }

"첫 번째 편지없이 앱 제목" Oof, hacky hacky hacky. IndexOf대신 제대로 사용 하지 않는 이유는 무엇 입니까?
궤도에서 가벼움 레이스

1

문제는 후크에서 코드를 호출하는 스레드가 런타임에 의해 초기화되지 않아 런타임 메소드 호출이 작동하지 않을 수 있습니다.

아마도 호출을 수행하여 코드를 UI 스레드에 마샬링하여 창을 전경으로 가져 오는 코드를 호출 할 수 있습니다.


1

이 코드는 항상 잘 작동합니다.

먼저 XAML에서 활성화 된 이벤트 핸들러를 설정하십시오.

Activated="Window_Activated"

기본 창 생성자 블록에 아래 행을 추가하십시오.

public MainWindow()
{
    InitializeComponent();
    this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}

그리고 활성화 된 이벤트 핸들러 내부에서 다음 코드를 복사하십시오.

private void Window_Activated(object sender, EventArgs e)
{
    if (Application.Current.Windows.Count > 1)
    {
        foreach (Window win in Application.Current.Windows)
            try
            {
                if (!win.Equals(this))
                {
                    if (!win.IsVisible)
                    {
                        win.ShowDialog();
                    }

                    if (win.WindowState == WindowState.Minimized)
                    {
                        win.WindowState = WindowState.Normal;
                    }

                    win.Activate();
                    win.Topmost = true;
                    win.Topmost = false;
                    win.Focus();
                }
            }
            catch { }
    }
    else
        this.Focus();
}

이 단계는 잘 작동하며 다른 모든 창을 부모 창으로 가져옵니다.


0

예를 들어 창을 최소화하려는 경우 창을 숨기려고하면

    this.Hide();

올바르게 숨기고 간단히

    this.Show();

그런 다음 창을 다시 최상위 항목으로 표시합니다.


0

이 질문에 다른 해결책을 추가하고 싶었습니다. 이 구현은 CaliBurn이 기본 창을 표시하는 시나리오에서 작동합니다.

protected override void OnStartup(object sender, StartupEventArgs e)
{
    DisplayRootViewFor<IMainWindowViewModel>();

    Application.MainWindow.Topmost = true;
    Application.MainWindow.Activate();
    Application.MainWindow.Activated += OnMainWindowActivated;
}

private static void OnMainWindowActivated(object sender, EventArgs e)
{
    var window = sender as Window;
    if (window != null)
    {
        window.Activated -= OnMainWindowActivated;
        window.Topmost = false;
        window.Focus();
    }
}

0

활성 창은 이벤트를 처리 한 창으로 다시 전환되므로 해당 창을 표시하는 코드를 PreviewMouseDoubleClick 핸들러 안에 넣지 마십시오. MouseDoubleClick 이벤트 핸들러에 넣거나 e.Handled를 True로 설정하여 버블 링을 중지하십시오.

내 경우에는 Listview에서 PreviewMouseDoubleClick을 처리하고 e.Handled = true를 설정하지 않고 MouseDoubleClick 이벤트 마녀가 원래 창으로 다시 초점을 맞췄습니다.


-1

쉽게 재사용 할 수 있도록 확장 방법을 만들었습니다.

using System.Windows.Forms;
    namespace YourNamespace{
        public static class WindowsFormExtensions {
            public static void PutOnTop(this Form form) {
                form.Show();
                form.Activate();
            }// END PutOnTop()       
        }// END class
    }// END namespace

폼 생성자에서 호출

namespace YourNamespace{
       public partial class FormName : Form {
       public FormName(){
            this.PutOnTop();
            InitalizeComponents();
        }// END Constructor
    } // END Form            
}// END namespace

안녕 마이크. 이 질문에 아주 늦게 대답하고 있습니다. 이 방법이이 질문에 대해 이미 게시 된 아주 좋은 답변과 다른 이유 (그리고 아마도 더 나은 이유)를 귀하의 답변에 설명해 주시겠습니까?
Noel Widmer

방금이 작업을 수행해야했던 늦게 만이 문제를 발견하고 다른 사람들이 사용하기를 원하는 경우 문제를 해결 한 방법을 공유하고 싶었습니다.
Mike

물론, 귀하의 게시물을 검토하기로 선택했으며 귀하를 알리고 싶었습니다. 커뮤니티에 좋은 기여를하고 있다고 생각되면 항상 새로운 답변을 제공하는 것이 좋습니다.
Noel Widmer

2
이 질문은 특히 WPF에 관한 것이지만 귀하의 솔루션은 WinForms입니다.
브라이언 라이 클
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.