2009-04-05 4 views
9

Deseo enviar una entrada de teclado a una ventana en otro proceso, sin llevar esa ventana al primer plano. Puedo usar PostMessage para falsificar WM_KEYDOWN y WM_KEYUP; todo lo que necesito saber es qué identificador de ventana debe recibir la entrada del teclado, es decir, algo así como GetFocus, pero para otra aplicación no activa.Llamando a GetGUIThreadInfo a través de P/Invoke

La API GetGUIThreadInfo parece prometedora: devuelve hwndFocus para otra aplicación. Pero no he tenido suerte de hacerlo funcionar desde C# en mi sistema operativo de 64 bits. He copiado (y luego modificado) las declaraciones de pinvoke.net, pero todo lo que recibo es un código de error genérico (más detalles a continuación).

Estoy configurando cbSize antes de llamar a GetGUIThreadInfo, por lo que he evitado el problema potencial más obvio.

Estoy ejecutando Vista de 64 bits, por lo que no sé si el problema es que no estoy usando la API correctamente, o que funciona de manera diferente en 64 bits - Todavía tengo que encontrar un muestra de código que dice específicamente que funciona con éxito en Win64.

Aquí hay un código de muestra. Estoy usando GetWindowThreadProcessId as recommended, así que no creo que el problema tiene que ver con la mezcla de los ID de hilo con hilo maneja:

[StructLayout(LayoutKind.Sequential)] 
internal struct Rect 
{ 
    public int Left; 
    public int Top; 
    public int Right; 
    public int Bottom; 
} 

[StructLayout(LayoutKind.Sequential)] 
internal class GuiThreadInfo 
{ 
    public int cbSize; 
    public uint flags; 
    public IntPtr hwndActive; 
    public IntPtr hwndFocus; 
    public IntPtr hwndCapture; 
    public IntPtr hwndMenuOwner; 
    public IntPtr hwndMoveSize; 
    public IntPtr hwndCaret; 
    public Rect rcCaret; 
} 

[DllImport("user32.dll")] 
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 
[DllImport("user32.dll", SetLastError = true)] 
internal static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); 

IntPtr GetFocusedHandleFromProcessWithWindow(IntPtr window) 
{ 
    var threadId = GetWindowThreadProcessId(window, IntPtr.Zero); 
    var info = new GuiThreadInfo(); 
    info.cbSize = Marshal.SizeOf(info); 
    if (!GetGUIThreadInfo(threadId, ref info)) 
     throw new Win32Exception(); 
    return info.hwndFocus; 
} 

window es un identificador de ventana válida; GetWindowThreadProcessId devuelve un identificador de hilo distinto de cero. Pero la llamada a GetGUIThreadInfo siempre devuelve false, y el mensaje de excepción siempre es "El parámetro es incorrecto".

Sólo en caso de que el problema era que GetGUIThreadInfo alguna manera no tiene una versión de 64 bits, He intentado cambiar todos los 8 bytes IntPtr s en los GuiThreadInfo declaración a 4 bytes int s, pero todavía tiene el mismo error.

¿Alguien tiene una muestra de C# en funcionamiento de GetGUIThreadInfo en Win64? O bien, ¿hay alguna otra manera de encontrar cuál sería el manejador de la ventana del niño enfocada en otra aplicación, sin activar esa aplicación?

Respuesta

4

No lo he mirado demasiado de cerca, pero una cosa salta. En su llamada GetGUIThreadInfo, pasa la estructura GUIThreadInfo por ref pero la ha definido como una clase, por lo que está enviando una referencia por ref, en otras palabras, un puntero a un puntero. Cambie su GUIThreadInfo por una estructura o elimine la referencia en el parámetro y agregue los atributos [In, Out].

+1

Ouch. Tienes razón, no puedo creer que me haya perdido eso. Punto de etiqueta: esto solucionó el problema inmediato, pero luego surgió otro problema; así que mi objetivo final de "obtener un control centrado en otros procesos" sigue abierto. ¿Debo editar esta pregunta, o aceptar esta respuesta y luego escribir una nueva pregunta? –

+0

En este caso, la pregunta es realmente acerca de invocar GetGUIThreadInfo, por lo que probablemente debería votar como útil y marcarla como la respuesta. Es posible que también desee editar el título para describir esta pregunta de manera más específica. A continuación, agregue una nueva pregunta sobre el problema más general, que incluye qué ... –

+0

... su requisito subyacente es y lo que ha intentado hasta ahora. En general, debe editar una pregunta para agregar información o claridad para no cambiar lo que se está pidiendo. –

Cuestiones relacionadas