2009-04-05 14 views
9

Desidero inviare l'input da tastiera a una finestra in un altro processo, senza portare quella finestra in primo piano. Posso usare PostMessage per simulare il WM_KEYDOWN e WM_KEYUP; tutto quello che devo sapere è quale maniglia della finestra dovrebbe ricevere l'input da tastiera, ad esempio GetFocus, ma per un'altra applicazione non attiva.Chiamare GetGUIThreadInfo tramite P/Invoke

L'API GetGUIThreadInfo sembra promettente - restituisce un hwndFocus per un'altra app. Ma non ho avuto fortuna a farlo funzionare da C# sul mio sistema operativo a 64 bit. Ho copiato (e poi ulteriormente ottimizzato) le dichiarazioni da pinvoke.net, ma tutto quello che riesco a recuperare è un codice di errore generico (maggiori dettagli di seguito).

Sto impostando cbSize prima chiamo GetGUIThreadInfo, quindi ho evitato il più ovvio potenziale problema.

Sto utilizzando Vista a 64 bit, quindi non so se il problema è che non sto usando l'API correttamente, o che funziona diversamente a 64-bit - Devo ancora trovare un esempio di codice che dice specificatamente che funziona correttamente con Win64.

Ecco il codice di esempio. Sto utilizzando GetWindowThreadProcessId as recommended, quindi non credo che il problema ha a che fare con la miscelazione ID filo con filo maniglie:

[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 è un handle di finestra valida; GetWindowThreadProcessId restituisce un handle di thread diverso da zero. Ma la chiamata a GetGUIThreadInfo restituisce sempre false e il messaggio di eccezione è sempre "Il parametro non è corretto".

Nel caso in cui il problema era che GetGUIThreadInfo in qualche modo non ha una versione a 64-bit, ho provato a cambiare tutte le 8 byte IntPtr s nelle GuiThreadInfo dichiarazione a 4 byte int s, ma ho ancora avuto lo stesso errore.

Qualcuno ha un campione C# di lavoro di GetGUIThreadInfo su Win64? Oppure esiste un altro modo per trovare quale sarebbe l'handle della finestra figlio focalizzata in un'altra app, senza rendere attiva quell'app?

risposta

4

Non l'ho guardato troppo da vicino ma una cosa salta fuori. Nella tua chiamata GetGUIThreadInfo tu passi la struttura GUIThreadInfo per ref ma la hai definita come una classe, quindi stai inviando un riferimento per ref, in altre parole un puntatore a un puntatore. Cambiare GUIThreadInfo in una struct o rimuovere il ref sul parametro e aggiungere gli attributi [In, Out].

+1

Ouch. Hai ragione - non posso credere di averlo perso. Punto di galateo: questo risolveva il problema immediato, ma poi si presentava un altro problema; quindi il mio obiettivo finale di "maneggiare l'attenzione in altri processi" è ancora aperto. Dovrei modificare questa domanda o accettare questa risposta e scrivere una nuova domanda? –

+0

In questo caso, la domanda riguarda davvero pInvocare GetGUIThreadInfo, quindi dovresti probabilmente votarlo come utile e contrassegnarlo come risposta. Potresti anche voler modificare il titolo per descrivere in modo più ristretto questa domanda. Quindi aggiungi una nuova domanda sul problema più generale che include cosa ... –

+0

... il tuo requisito di base è e quello che hai provato fino ad ora. In generale, è necessario modificare una domanda per aggiungere informazioni o chiarezza per non modificare ciò che viene chiesto. –

Problemi correlati