Creo una tecla de acceso directo global para mostrar una ventana mediante PInvoking RegisterHotKey()
. Pero para hacer esto necesito esa ventana HWND
, 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 es invisible para el usuario?Cargando una ventana de WPF sin mostrarlo
Respuesta
Si el idioma de .NET 4.0 se puede hacer uso del nuevo método EnsureHandle
disponible en el WindowInteropHelper
:
public void InitHwnd()
{
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
}
(gracias a Thomas Levesque para pointing this out.)
Si el idioma de una versión anterior de .NET Framework, la forma más fácil es para mostrar la ventana para llegar a la HWND al establecer algunas propiedades para asegurarse de que la ventana es invisible y no se roba 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 desea mostrar la ventana real a continuación, puede establecer el contenido, el tamaño y cambiar el estilo de nuevo a una ventana normal.
La clase WindowInteropHelper debería permitirle obtener el HWND para la ventana de WPF.
MyWindow win = new MyWindow();
WindowInteropHelper helper = new WindowInteropHelper(win);
IntPtr hwnd = helper.Handle;
Eso es lo que estoy haciendo, pero de esta manera, la ventana no tiene un HWND todavía, entonces helper.Handle es 0, que no es lo que necesito. – svick
Nunca he tratado de hacer lo que está haciendo, pero si usted necesita para mostrar la ventana para obtener el HWND, pero no quiere mostrar , establezca el Opacidad de la ventana a 0. Esto también evitará que ocurra cualquier prueba de impacto. Entonces podría tener un método público en la Ventana para cambiar la Opacidad a 100 cuando quiera hacerla visible.
Esto es una especie de hack sucio, pero funcionará con seguridad. –
Desafortunadamente, para que la configuración de Opacidad sea efectiva, AllowsTransparency debe establecerse en true y esto a su vez fuerza a WindowStyle a WindowStyle.None, que no es lo que quiero. Además, AllowsTransparency no se puede cambiar después de que se muestre la ventana, por lo que no puedo volver a configurarlo después. – svick
Otra opción similar a configurar la opacidad en 0 es establecer el tamaño en 0 y configurar la posición para que no esté en la pantalla. Esto no requerirá AllowsTransparency = True.
También recuerde que una vez que lo haya mostrado una vez, puede ocultarlo y seguir obteniendo el hwnd.
Este es un truco sucio, pero debería funcionar, y no tiene las desventajas de cambiar la opacidad:
- establecer el
WindowStartupLocation
aManual
Top
establezca las propiedades yLeft
a algún lugar fuera la pantallaShowInTaskbar
establece en false para que el usuario no se da cuenta que hay una ventana nuevaShow
yHide
º ventana de correo
Ahora debería ser capaz de recuperar el HWND
EDIT: otra opción, probablemente mejor: set ShowInTaskBar
false y WindowState
a Minimized
, a continuación, mostrar que: no será visible en todo
+1 ShowInTaskBar = falso y WindowState = Minimized funciona. –
Con su otra opción, puedo ver la ventana minimizada en la esquina inferior izquierda de la pantalla. Pero el primero parece prometedor. – svick
@svick: ¿qué SO estás usando? En Windows 7 la ventana minimizada no está visible –
Haga que el tamaño de la ventana sea de 0 x 0 px, ponga ShowInTaskBar en falso, muéstrelo y luego ajústelo cuando sea necesario.
No sé absolutamente nada sobre WPF, pero ¿podría crear un message only window 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í.
+1, puede usar una Ventana de Winforms en otro hilo si desea hacer esto. –
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 a:
SetParent(hwnd, (IntPtr)HWND_MESSAGE);
bien crear una ventana de mensaje específico que se encontrará siempre oculto, o utilizar la ventana de interfaz gráfica de usuario real y cambiarlo de nuevo a una ventana normal cuando se quiere mostrarlo. 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 estilo a ninguno no funcionó, ya que todavía mostraba una pequeña ventana, con una sombra molesta de lo que parece ser la frontera en torno a una Ventana 0x0 (probado en Windows 7). Por lo tanto, estoy proporcionando esta opción alternativa.
Esta parece ser la única solución al 100%. –
Gracias por este gran consejo.Realmente me ayudó, porque todas las otras soluciones aquí causaron algunos efectos secundarios que no fueron bonitos. Pero tu también lo hace, por desgracia. Obtuve una MetroWindow (usando Fluent Ribbon Suite). Luego, la ventana tiene un borde de ventana típico, que normalmente no es visible para esas MetroWindows ... ¿Alguna idea de cómo resolver esto? – SharpShade
Perfecto. Solo necesita: ShowActivated = false; después de Visibilidad, porque sin él parpadea. – blez
Ya había publicado una respuesta a esa pregunta, pero acabo de encontrar una solución mejor.
Si sólo tiene que asegurarse de que se crea el HWND, sin llegar a mostrar la ventana, usted puede hacer esto:
public void InitHwnd()
{
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
}
(en realidad el método EnsureHandle
no estaba disponible cuando la pregunta fue publicada, se introdujo en .NET 4.0)
muy bien hecho Thomas – tofutim
esto probablemente debería ser la respuesta aceptada ahora, o debería actualizar mi respuesta para incluir esto también? no estoy seguro de cuál es la práctica respetada para las diferencias de la versión del marco. –
@PatrickKlug, no sé tampoco ... Puede incluir esto en su respuesta, o simplemente hacer referencia a mi respuesta, lo que crea que es mejor. –
He creado el método de extensión para mostrar la ventana invisible, las próximas Show
llamadas se comportarán 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;
}
}
- 1. Ventana sin bordes en WPF
- 2. Cargue un formulario sin mostrarlo
- 3. Comenzar la actividad sin mostrarlo
- 4. Forma de hacer que una ventana WPF sin ventana sea arrastrable sin obtener InvalidOperationException
- 5. Tener una ventana wpf dentro de otra ventana wpf
- 6. Delphi: ¿Cómo imprimir un PDF sin mostrarlo?
- 7. WPF/XAML: ¿Cómo dimensiono una ventana sin borde?
- 8. Probando el control WPF sin agregarlo a una ventana
- 9. ¿Cómo implemento una ventana sin bordes con WPF?
- 10. Razor: añadiendo variable en bucle sin mostrarlo
- 11. Cargando iconos de una ruta determinada para mostrar en la ventana de WPF
- 12. ¿Minimiza una ventana en WPF?
- 13. Precarga de ventana WPF
- 14. android convertir vista XML a mapa de bits sin mostrarlo
- 15. diseño de WPF en una ventana
- 16. cerrar una ventana de otro en WPF
- 17. Cómo rotar una ventana de WPF?
- 18. Cargando una imagen en un hilo de fondo en WPF
- 19. Posición de ventana de WPF
- 20. Tamaño de ventana de WPF
- 21. Cargando imágenes grandes sin OutOfMemoryError
- 22. WPF Ventana establecida Enfoque
- 23. WPF ventana emergente
- 24. WPF - Desplazar sin foco
- 25. Crear una aplicación sin una ventana
- 26. Cómo renderizar un UserControl de WPF en un mapa de bits sin crear una ventana
- 27. Cambiar la ubicación de inicio de una ventana de WPF
- 28. Agregue un control de usuario a una ventana de wpf
- 29. WPF - Traer ventana al frente
- 30. ¿Cómo obtener una referencia estática a una ventana de WPF?
Sí, esto funciona, gracias. Establecer WindowState incluso no es necesario. Además, establezco el contenido de la ventana en XAML, pero eso no es importante. Otra cosa es que WindowStartupLocation = CenterScreen no funciona correctamente de esta manera, pero eso es fácil de arreglar. – svick
eliminado el setter WindowState ... gracias por informarme. –
Agregaría 'ResizeMode = ResizeMode.NoResize' también, porque elimina el borde de la ventana para cambiar el tamaño. – schnaader