ventanas ventana una otra navegacion entre dentro abrir wpf window hwnd

otra - Cargando una ventana de WPF sin mostrarlo



abrir una ventana dentro de otra wpf (11)

Creé el método de extensión para mostrar la ventana invisible, luego Show llamadas se comportará bien.

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; } }

Creo una tecla rápida global para mostrar una ventana mediante Invocar RegisterHotKey() . Pero para hacer esto necesito HWND esa ventana, que no existe hasta que se cargue la ventana, eso significa que se muestra por primera vez. Pero no quiero mostrar la ventana antes de poder configurar la tecla de acceso rápido. ¿Hay alguna manera de crear un HWND para esa ventana que sea invisible para el usuario?


Este es un truco sucio, pero debería funcionar, y no tiene los inconvenientes de cambiar la opacidad:

  • establecer el WindowStartupLocation en Manual
  • establecer las propiedades Top e Left en algún lugar fuera de la pantalla
  • establece ShowInTaskbar en falso para que el usuario no se dé cuenta de que hay una nueva ventana
  • Show y Hide la ventana

Ahora debería poder recuperar el HWND

EDITAR: otra opción, probablemente mejor: establezca ShowInTaskBar en falso y WindowState en Minimized , luego muéstrelo: no será visible en absoluto


Haga que el tamaño de la ventana sea de 0 x 0 px, ponga ShowInTaskBar en falso, muéstrelo y luego cambie el tamaño cuando sea necesario.


La clase WindowInteropHelper debería permitirle obtener HWND para la ventana de WPF.

MyWindow win = new MyWindow(); WindowInteropHelper helper = new WindowInteropHelper(win); IntPtr hwnd = helper.Handle;

Documentación de MSDN


Me di cuenta de que lo último que sucede cuando se inicializa la ventana es el cambio de WindowState , si difiere de lo normal. Entonces, puedes usarlo:

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(); } }

Eso funciona bastante bien para mí. Y no requiere trabajar con ningún manipulador ni nada, y, lo que es más importante, no requiere tener una clase personalizada para una ventana. Lo cual es genial para XAML cargado dinámicamente. Y también es una gran manera si estás haciendo una aplicación de pantalla completa. Ni siquiera necesita cambiar su estado a normal o establecer el ancho y la altura adecuados. Solo ve con

protected bool isStateChangeFirst = true; protected void OnBackgroundStateChanged(object sender, EventArgs e) { if (isStateChangeFirst) { isStateChangeFirst = false; window.ShowInTaskbar = true; window.Opacity = 1; window.Activate(); } }

Y tu estas listo.

E incluso si me equivoco al suponer que el último cambio de estado se realiza cuando se carga la ventana, aún puede cambiar a cualquier otro evento, realmente no importa.


No sé absolutamente nada sobre WPF, pero ¿podría crear una ventana de solo mensaje utilizando otros medios (PInvoke, por ejemplo) para recibir el mensaje WM_HOTKEY? En caso afirmativo, una vez que reciba el WM_HOTKEY, puede abrir la ventana de WPF desde allí.


Nunca intenté hacer lo que está haciendo, pero si necesita mostrar la ventana para obtener el HWND, pero no desea mostrarlo , configure Opacidad de ventana en 0. Esto también evitará que ocurra cualquier prueba de detección. . Entonces podría tener un método público en la Ventana para cambiar la Opacidad a 100 cuando quiera hacerla visible.


Otra opción similar a establecer la opacidad en 0 es establecer el tamaño en 0 y configurar la posición para que esté fuera de la pantalla. Esto no requerirá AllowsTransparency = True.

También recuerde que una vez que lo haya mostrado una vez, puede ocultarlo y obtener el hwnd.


Si tiene como objetivo .NET 4.0, puede utilizar el nuevo método EnsureHandle disponible en WindowInteropHelper :

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

(Gracias a Thomas Levesque por señalar esto ) .

Si se dirige a una versión anterior de .NET Framework, la forma más fácil es mostrar la ventana para acceder al HWND mientras configura algunas propiedades para asegurarse de que la ventana sea invisible y no se robe el foco:

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

Una vez que desee mostrar la ventana real, puede configurar el contenido, el tamaño y cambiar el estilo a una ventana normal.


También puede cambiar la ventana a la llamada ventana de solo mensaje. Como este tipo de ventana no admite elementos gráficos, nunca se mostrará. Básicamente se trata de llamar:

SetParent(hwnd, (IntPtr)HWND_MESSAGE);

Cree una ventana de mensaje dedicada que siempre estará oculta, o use la ventana de GUI real y cámbiela a una ventana normal cuando quiera mostrarla. Vea el código a continuación para obtener un ejemplo más completo.

[DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hwnd, IntPtr hwndNewParent); private const int HWND_MESSAGE = -3; private IntPtr hwnd; private IntPtr oldParent; protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; if (hwndSource != null) { hwnd = hwndSource.Handle; oldParent = SetParent(hwnd, (IntPtr)HWND_MESSAGE); Visibility = Visibility.Hidden; } } private void OpenWindowMenuItem_Click(object sender, RoutedEventArgs e) { SetParent(hwnd, oldParent); Show(); Activate(); }

Para mí, la solución de establecer el ancho, la altura a cero y el estilo a ninguno no funcionó, ya que aún mostraba una pequeña ventana, con una sombra molesta de lo que parece ser el borde alrededor de una ventana de 0x0 (probado en Windows 7 ) Por lo tanto, estoy proporcionando esta opción alternativa.


Ya había publicado una respuesta a esa pregunta, pero acabo de encontrar una mejor solución.

Si solo necesita asegurarse de que se creó el HWND, sin mostrar realmente la ventana, puede hacer esto:

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

(en realidad, el método EnsureHandle no estaba disponible cuando se publicó la pregunta, se introdujo en .NET 4.0)