2010-02-26 14 views
6

Por lo tanto, pensé que esto sería simple y, además, estaba equivocado. Aquí hay una descripción simplificada del problema:Como encontrar de forma fiable la ventana en primer plano cuando no tiene el foco

Estoy escribiendo una pequeña aplicación para nuestra gente de fabricación que tomará una captura de pantalla de todo el escritorio, así como la ventana de primer plano cuando hagan clic en el icono de la aplicación en la bandeja del sistema. Actualmente, estoy usando el método Win32 "GetforegroundWindow" en el evento MouseMove de NotifyIcon para guardar el identificador de ventana de primer plano y tomar la captura de pantalla en el evento Click.

Esto funciona a veces, pero si hago clic en el icono muy rápidamente que realmente captura la barra de tareas en lugar de la ventana en primer plano. No estoy seguro de por qué sucede esto (entiendo que la barra de tareas sea una ventana, no entiendo por qué a veces parece tener foco en MouseMove antes de hacer clic), y he tenido poca suerte usando el método EnumWindows también, probablemente porque no entiendo completamente cómo funciona.

Parecería que, si yo fuera capaz de obtener la posición z de cada ventana utilizando sólo el identificador de ventana, esto sería un problema fácil de resolver utilizando EnumWindows. Sin embargo, no he encontrado un método para hacerlo.

Por lo tanto, pido a ustedes; ¿Cómo escribirías un método para ubicar la ventana de primer plano de manera confiable, dado que puede no tener foco en ese momento? O mi google-fu me está fallando o la información sobre esto es escasa. Gracias por adelantado.

Respuesta

1

La barra de tareas es tan válida una ventana de primer plano como cualquier otro. Cuando hace clic en él, será temporalmente la ventana de primer plano. Y si hace clic en Inicio y presiona Escape por ejemplo, será la ventana de primer plano hasta que haga clic fuera de él.

Probablemente pueda usar GetWindow con HWND_NEXT pasando en el identificador de ventana de la barra de tareas.

No importa, dado que la barra de tareas es una ventana superior, GetWindow (o GetNextWindow, etc.) funcionará de manera diferente. Sugiero volver a visitar la solución EnumWindows, que es probablemente su mejor opción.

+0

Correcto, entiendo que la barra de tareas es una ventana, pero eso es exactamente lo que estoy tratando de evitar. Necesito obtener el hWnd de la ventana lógica en primer plano. Intentaré pasar HWND_NEXT y ver si eso siempre me devuelve lo que busco. Gracias. –

+0

Por supuesto, ahora necesito poder encontrar el controlador en la barra de tareas = P.eso probablemente se definió en algún lugar para mí, miraré (sé que el escritorio es 0). –

+0

Bueno, en realidad ya tienes el mango en ese punto. Solo necesita usar GetClassName para determinar si ese identificador es la barra de tareas o no. Si tiene instalado Spy ++, puede usarlo para encontrar el nombre de la clase. No lo sé de mano. http://msdn.microsoft.com/en-us/library/ms633582(VS.85).aspx – Josh

0

Si la forma que desea que la instantánea de es la misma que la forma ligada a la barra de tareas, que realmente no es necesario utilizar GetForegroundWindow. Simplemente use Form.hWnd y páselo a la función para obtener la instantánea. Es posible que necesite para que sea la ventana superior llamando

[DllImport("user32.dll")] 
public static extern IntPtr SetForegroundWindow(IntPtr hWnd); 

o

[DllImport("user32.dll")] 
public static extern bool BringWindowToTop(HandleRef hWnd); 

Si desea todo el escritorio, entonces es probable que sólo tiene que poner en un Thread.Sleep para asegurarse de que el primer plano ventana ha tenido suficiente para llegar a la cima antes de obtener la instantánea de escritorio.

poner el src de mi comentario aquí para una mejor impresión

[DllImport("user32.dll")] 
public static extern IntPtr GetForegroundWindow(); 

[DllImport("user32.dll")] 
public static extern IntPtr GetActiveWindow(); 

// this or the next line not both 
IntPtr curWindow = GetActiveWindow(); 
IntPtr curWindow = GetForegroundWindow(); 

BringWindowToTop(window); 
System.Threading.Thread.Sleep(500); 

Cuando el hilo spleep da la ventana de tiempo suficiente para llegar a la parte superior de la orden Z.

+0

No es así, necesito tomar una ventana arbitraria que está en la parte superior. Gracias sin embargo. –

+0

Piense en un programa de captura de pantalla que solo agarra la ventana superior, sea lo que sea. El escritorio es fácil y esa parte funciona bien actualmente. –

+0

También agregaría que ni la ventana GetActiveWindow ni GetForegroung funcionarán. Como dije en mi publicación inicial, la ventana no tendrá foco. –

Cuestiones relacionadas