2

タイトルでこれを説明するのは非常に難しいです。誰かがそれを変更したいのであれば、それは大丈夫です。

WPFで、プログラマーに対して透過的な「非表示」ウィンドウを作成する状況があります。つまり、このウィンドウは静的コンストラクターで作成され、非表示にして画面の外に移動され、幅と高さは0です。これは、このウィンドウを使用していくつかの相互運用操作を実行し、すべてのハンドラーの一種を許可しているためです。誰かが要求する可能性のある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:

あなたの答えに答えるために、いいえ、私は私のライブラリを使用するプログラマーによる介入を避けたいので、理想的な解決策は、私のライブラリでいくつかのApplication.Exitイベントをサブスクライブしてウィンドウを閉じることです、明らかに私はApplicationを使用できません。ウィンドウが閉じないためにアプリケーションが閉じないため、終了します

たぶん、アプリケーションに属するすべてのウィンドウを計算する方法はありますか?私もそれで何かできる

4

3 に答える 3

3

メインウィンドウがある場合、Application.ShutdownModeOnMainWindowCloseに設定できませんか?

デフォルト値はOnLastWindowCloseです。これが、この動作が見られる理由である可能性が最も高いです。

于 2011-07-16T23:09:04.903 に答える
2

安いハックですが、これであなたが求めているものを達成できると思います。

libで、xamlの依存関係(PresentationCore、PresentationFramework、System.Xaml、およびWindowsBase)を参照する必要があります。

libの静的コンストラクターで、次のようなものを追加できます。

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

static void MainWindow_Closed(object sender, EventArgs e)
{
    Dispose();
}

ここで、disposeはウィンドウを閉じ(_Instance.Close())、その他のクリーンアップ呼び出しを処理します

于 2011-07-17T20:55:04.773 に答える
1

概念的には、頭に浮かぶのはイベントメッセージ通知サービスだけです。このサービスでは、2番目のウィンドウがメッセージをリッスンまたは待機しており、最初のウィンドウがメッセージを送信して閉じます。これには、MVVMパターンを使用する必要もあります。これについては完全にはわかりません。また、これが他のプログラマーに知らせないというあなたの考えに当てはまるかどうかもわかりません。

これに関するブログ記事は次のとおり です。WPFMVVMアプリケーションでの通知の送信

于 2011-07-16T21:27:41.003 に答える