2011-07-16 2 views
2

제목을 변경하려고하면 제목을 설명하기가 어렵습니다.WPF : "프로그래머"개입없이 응용 프로그램 종료시 보조 창 닫기

나는 WPF에서 프로그래머에게 투명 인 "숨겨진"창을 생성하는 상황이 있습니다. 내 말은이 창은 정적 생성자에서 만들어지고 숨겨지고 화면 바깥으로 이동되며 너비와 높이가 0입니다.이 때문에 일부 interop 작업을 수행하고 누군가가 요구할 수있는 모든 WndProcs 재정의 (WndProc를 재정의해야하는 메서드를 처리하는 대리자 목록이 있음)

내가 말했던 것을 이해하기를 바랍니다 (쉬운 일이 아닙니다.) 제 문제는 WPF 프로젝트를 만들고 시작할 때, 메인 윈도우를 닫으면 (이 투명하지 않음) 프로그래머에게), 나는 그 응용 프로그램을 종료 싶습니다. 그러나 내가 작성한 코드를 사용하면 Application.Current.Shutdown();

이 메서드를 호출하지 않고이 문제를 해결할 수있는 방법이 있습니까? 다른 프로그래머들도 눈치 채지 말아야 할 투명한 방식을 원합니다 (lib 형식이므로 이런 방식으로 작동하는 프로그램의 동작을 변경해서는 안됩니다).

감사 어떤 제안을 위해, 여기에 일부 코드 조각 볼 수 있습니다

lib 디렉토리에 의해 생성 된 창

public class InteropWindow : Window 
{ 
    public HwndSource Source { get; protected set; } 

    private static InteropWindow _Instance; 

    static InteropWindow() 
    { 
     _WndProcs = new LinkedList<WndProcHandler>(); 
     _Instance = new InteropWindow(); 
    } 

    private static WindowInteropHelper _InteropHelper; 
    public static WindowInteropHelper InteropHelper 
    { 
     get 
     { 
      if (_InteropHelper == null) 
      { 
       _InteropHelper = new WindowInteropHelper(_Instance); 
       _InteropHelper.EnsureHandle(); 
      } 
      return _InteropHelper; 
     } 
    } 

    public static IntPtr Handle { get { return InteropHelper.Handle; } } 

    private InteropWindow() 
    { 
     Opacity = 0.0; 
     //We have to "show" the window in order to obtain hwnd to process WndProc messages in WPF 
     Top = -10; 
     Left = -10; 
     Width = 0; 
     Height = 0; 
     WindowStyle = WindowStyle.None; 
     ShowInTaskbar = false; 
     ShowActivated = false; 
     Show(); 
     Hide(); 
    } 

    private static LinkedList<WndProcHandler> _WndProcs; 
    public static void AddWndProcHandler(WndProcHandler handler) 
    { 
     _WndProcs.AddLast(handler); 
    } 
    public static void RemoveWndProcHandler(WndProcHandler handler) 
    { 
     _WndProcs.Remove(handler); 
    } 

    private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     IntPtr result = IntPtr.Zero; 
     foreach (WndProcHandler handler in _WndProcs) 
     { 
      IntPtr tmp = handler(hwnd, msg, wParam, lParam, ref handled); 
      if (tmp != IntPtr.Zero) 
      { 
       if (result != IntPtr.Zero) 
        throw new InvalidOperationException(string.Format("result should be zero if tmp is non-zero:\nresult: {0}\ntmp: {1}", result.ToInt64().ToString(), tmp.ToInt64().ToString())); 
       result = tmp; 
      } 
     } 
     return result; 
    } 

    protected override void OnSourceInitialized(EventArgs e) 
    { 
     base.OnSourceInitialized(e); 
     Source = PresentationSource.FromVisual(this) as HwndSource; 
     Source.AddHook(WndProc); 
     OnWindowInitialized(null, e); 
    } 

    protected override void OnClosed(EventArgs e) 
    { 
     base.OnClosed(e); 
     if (Source != null) 
      Source.RemoveHook(WndProc); 
     OnWindowClosed(null, e); 
    } 

    private static void OnWindowInitialized(object sender, EventArgs e) 
    { 
     if (WindowInitialized != null) WindowInitialized(sender, e); 
    } 

    private static void OnWindowClosed(object sender, EventArgs e) 
    { 
     if (WindowClosed != null) WindowClosed(sender, e); 
    } 

    public static event EventHandler WindowInitialized; 

    public static event EventHandler WindowClosed; 
} 

WPF (프로젝트에서 만든 기본 화면)로 만든 일반 창

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     ExClipboard.ClipboardUpdate += new RoutedEventHandler(ExClipboard_ClipboardUpdate); 
     Closed += new EventHandler(MainWindow_Closed); 
    } 

    private void MainWindow_Closed(object sender, EventArgs e) 
    { 
     //InteropWindow.Dispose(); 
     App.Current.Shutdown(0); 
    } 
} 

업데이트 1 :

대답에 대답하려면, 아니요. 내 라이브러리를 사용하는 프로그래머가 어떤 intervetion을 피하기를 원합니다. 이상적인 해결책은 제 lib에서 일부 Application.Exit 이벤트를 구독하고 내 창을 닫는 것입니다. 응용 프로그램이 닫히지 않아서 응용 프로그램이 닫히지 않기 때문에 Application.Exit을 사용하지 마십시오.

응용 프로그램에 속한 모든 창을 계산하는 방법이 있습니까? 나는 그걸로 뭔가를 할 수 있습니다

답변

2

저렴한 해킹이지만, 이것이 당신이 겪은 것을 달성 할 수 있다고 생각합니다.당신의 lib에

당신은

Application.Current.MainWindow.Closed += new EventHandler(MainWindow_Closed); 

static void MainWindow_Closed(object sender, EventArgs e) 
{ 
    Dispose(); 
} 
같은 것을 추가 할 수 있습니다, 귀하의 lib 디렉토리에 대한 정적 생성자에서 XAML 종속성 (PresentationCore, PresentationFramework, System.Xaml 및 WindowsBase)

를 참조해야합니다

dispose가 창 (_Instance.Close())을 닫고 다른 정리 호출을 처리합니다.

+0

좋은 직장 동료 인 여러분의 해킹이 크게 효과를 보았습니다. 정확하게 찾고 있던 것이 었습니다. –

+0

응용 프로그램에서 ShutDownMode를 설정하십시오. xaml에서 OnMainWindow로 닫기. –

+0

@JesseSeger 아이디어 (이 경우)는 lib 내에서 처리하고 최종 개발자 개입에 의존하지 말아야했습니다. 이 질문에 대해 제공된 다른 대답은 정상적으로 수행하는 가장 좋은 방법이지만이 특정 경우에는 수행하지 않는 것이 좋습니다. – fatty

1

개념적으로 말하면, 두 번째 창은 수신 대기 중이거나 닫을 메시지를 기다리는 이벤트 메시지 알림 서비스뿐입니다. 첫 번째 창은 그것은 닫혀 야합니다. 또한 MVVM 패턴을 사용해야합니다. 이 점에 대해서는 잘 모르겠다. 다른 프로그래머에게 알려주지 않는다는 생각에 넘어갈 지 확신 할 수 없다. Sending notifications in WPF MVVM applications

3

당신은 메인 윈도우가있는 경우, 당신은 OnMainWindowCloseApplication.ShutdownMode을 설정할 수 없습니다 : 여기

그것에 블로그 기사인가?

기본값은 OnLastWindowClose이며이 동작을하는 이유는 무엇입니까?