example - wpf tutorial deutsch




Ein WPF-Fenster laden, ohne es anzuzeigen (8)

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 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?


Dies ist ein schmutziger Hack, aber es sollte funktionieren und hat nicht die Nachteile, die Deckkraft zu ändern:

  • Setzen Sie die WindowStartupLocation auf Manual
  • Stellen Sie die Eigenschaften Top und Left außerhalb des Bildschirms ein
  • Setzen Sie ShowInTaskbar auf false, damit der Benutzer nicht erkennt, dass ein neues Fenster vorhanden ist
  • Das Fenster Show und Hide

Sie sollten jetzt in der Lage sein, die HWND abzurufen

BEARBEITEN: eine andere Option, wahrscheinlich besser: Setzen Sie ShowInTaskBar auf false und WindowState auf Minimized . Zeigen Sie es dann: es wird überhaupt nicht sichtbar


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.


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.)


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.


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.


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.





hwnd