Ein WPF-Fenster laden, ohne es anzuzeigen



wpf tutorial deutsch (9)

Ich erstelle einen globalen Hotkey zum Anzeigen eines Fensters durch PInvoking RegisterHotKey() . Aber dafür brauche ich die HWND dieses Fensters, die erst beim Laden des Fensters existiert, also zum ersten Mal angezeigt wird. Ich möchte das Fenster jedoch nicht anzeigen, bevor ich den Hotkey einstellen kann. Gibt es eine Möglichkeit, eine HWND für dieses Fenster zu erstellen, die für den Benutzer nicht sichtbar ist?


Ich kenne absolut nichts über WPF, aber könnten Sie mit anderen Mitteln (z. B. PInvoke) ein Nachrichtenfenster erstellen, um die WM_HOTKEY-Nachricht zu erhalten? Wenn ja, können Sie nach Erhalt des WM_HOTKEY das WPF-Fenster von dort starten.


Eine andere Option in ähnlicher Weise zur Einstellung der Deckkraft auf 0 ist die Einstellung der Größe auf 0 und die Einstellung der Position außerhalb des Bildschirms. Dies erfordert nicht die AllowsTransparency = True.

Denken Sie auch daran, wenn Sie es einmal gezeigt haben, können Sie es ausblenden und trotzdem das Hwnd erhalten.


Die WindowInteropHelper-Klasse sollte es Ihnen ermöglichen, die HWND für das WPF-Fenster abzurufen.

MyWindow win = new MyWindow();
WindowInteropHelper helper = new WindowInteropHelper(win);

IntPtr hwnd = helper.Handle;

MSDN-Dokumentation


Ich habe eine Erweiterungsmethode zum Anzeigen von unsichtbaren Fenstern erstellt. Nächste Anrufe anzeigen verhalten sich OK.

public static class WindowHelper
{
    public static void ShowInvisible(this Window window)
    {
        // saving original settings
        bool needToShowInTaskbar = window.ShowInTaskbar;
        WindowState initialWindowState = window.WindowState;

        // making window invisible
        window.ShowInTaskbar = false;
        window.WindowState = WindowState.Minimized;

        // showing and hiding window
        window.Show();
        window.Hide();

        // restoring original settings
        window.ShowInTaskbar = needToShowInTaskbar;
        window.WindowState = initialWindowState;
    }
}

Ich hatte bereits eine Antwort auf diese Frage gepostet, fand aber gerade eine bessere Lösung.

Wenn Sie nur sicherstellen müssen, dass die HWND erstellt wird, ohne das Fenster tatsächlich anzuzeigen, können Sie Folgendes tun:

    public void InitHwnd()
    {
        var helper = new WindowInteropHelper(this);
        helper.EnsureHandle();
    }

( EnsureHandle war die EnsureHandle Methode nicht verfügbar, als die Frage gepostet wurde. Sie wurde in .NET 4.0 eingeführt.)


Stellen Sie die Größe des Fensters auf 0 x 0 px, setzen Sie ShowInTaskBar auf false, zeigen Sie es an und passen Sie es bei Bedarf an.


Ich habe bemerkt, dass das letzte, was passiert, wenn das Fenster initialisiert wird, die Änderung von WindowState , wenn es sich von der normalen unterscheidet. Sie können es also tatsächlich nutzen:

public void InitializeWindow(Window window) {
    window.Top = Int32.MinValue;
    window.Left = Int32.MinValue;

    window.Width = 0;
    window.Height = 0;

    window.ShowActivated = false;
    window.ShowInTaskbar = false;
    window.Opacity = 0;

    window.StateChanged += OnBackgroundStateChanged;

    window.WindowStyle = WindowStyle.None;
}

public void ShowWindow(Window window) {
    window.Show();
    window.WindowState = WindowState.Maximized;
}

protected bool isStateChangeFirst = true;
protected void OnBackgroundStateChanged(object sender, EventArgs e) {
    if (isStateChangeFirst) {
        isStateChangeFirst = false;

        window.Top = 300;
        window.Left = 200;

        window.Width = 760;
        window.Height = 400;

        window.WindowState = WindowState.Normal;

        window.ShowInTaskbar = true;
        window.Opacity = 1;
        window.Activate();
    }
}

Das geht mir gut. Und es erfordert keine Arbeit mit irgendwelchen Ziehpunkten und Sachen und, was noch wichtiger ist, keine benutzerdefinierte Klasse für ein Fenster. Das ist ideal für dynamisch geladene XAML. Dies ist auch eine großartige Möglichkeit, wenn Sie eine Vollbild-App erstellen. Sie müssen nicht einmal den Status wieder in den normalen Zustand zurückversetzen oder die richtige Breite und Höhe einstellen. Geh einfach mit

protected bool isStateChangeFirst = true;
protected void OnBackgroundStateChanged(object sender, EventArgs e) {
    if (isStateChangeFirst) {
        isStateChangeFirst = false;

        window.ShowInTaskbar = true;
        window.Opacity = 1;
        window.Activate();
    }
}

Und du bist fertig.

Und selbst wenn ich falsch bin, dass die Änderung des Zustands das letzte ist, wenn das Fenster geladen wird, können Sie immer noch zu einem anderen Ereignis wechseln.


Wenn Sie auf .NET 4.0 abzielen, können Sie die neue EnsureHandle Methode verwenden, die für den EnsureHandle verfügbar ist:

public void InitHwnd()
{
    var helper = new WindowInteropHelper(this);
    helper.EnsureHandle();
}

(Danke an Thomas Levesque für diesen Hinweis. )

Wenn Sie auf eine ältere Version von .NET Framework abzielen, zeigen Sie am einfachsten das Fenster, um zum HWND zu gelangen, und legen Sie einige Eigenschaften fest, um sicherzustellen, dass das Fenster unsichtbar ist und den Fokus nicht stiehlt:

var window = new Window() //make sure the window is invisible
{
    Width = 0,
    Height = 0,
    WindowStyle = WindowStyle.None,
    ShowInTaskbar = false,
    ShowActivated = false
};
window.Show();

Wenn Sie das tatsächliche Fenster anzeigen möchten, können Sie den Inhalt und die Größe festlegen und den Stil wieder in ein normales Fenster ändern.


Ich habe nie versucht, das zu tun, was Sie tun, aber wenn Sie das Fenster anzeigen müssen, um die HWND zu erhalten, es aber nicht anzeigen möchten, setzen Sie die Fenster-Opazität auf 0. Dadurch werden auch keine Trefferprüfungen durchgeführt . Dann könnten Sie eine öffentliche Methode im Fenster verwenden, um die Deckkraft auf 100 zu ändern, wenn Sie sie sichtbar machen möchten.





hwnd