Chcę wysłać dane wejściowe z klawiatury do okna w innym procesie, bez wywoływania tego okna na pierwszy plan. Mogę użyć PostMessage
do sfałszowania WM_KEYDOWN
i WM_KEYUP
; wszystko, co muszę wiedzieć, to który uchwyt okna powinien otrzymać dane wejściowe z klawiatury - to jest coś takiego jak GetFocus, ale dla innej, nieaktywnej aplikacji.Wywołanie GetGUIThreadInfo przez P/Invoke
Interfejs API GetGUIThreadInfo wygląda obiecująco - zwraca inną hwndFocus
dla innej aplikacji. Ale nie miałem szczęścia, aby uruchomić go z C# na moim 64-bitowym systemie operacyjnym. Skopiowałem (a następnie jeszcze poprawiłem) deklaracje z pinvoke.net, ale wszystko, co kiedykolwiek otrzymałem, to ogólny kod błędu (więcej szczegółów poniżej).
Ustawiam cbSize przed wywołaniem GetGUIThreadInfo, więc uniknąłem najbardziej oczywistego potencjalnego problemu.
Używam 64-bitowego systemu Vista, więc nie wiem, czy problem polega na tym, że nie używam poprawnie interfejsu API, czy też działa on inaczej w wersji 64-bitowej - jeszcze nie znalazłem próbka kodu, która mówi, że działa poprawnie w Win64.
Oto przykładowy kod. Używam GetWindowThreadProcessId as recommended, więc nie sądzę, problem ma do czynienia z mieszaniem identyfikatory wątku nićmi uchwyty:
[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
jest prawidłowy uchwyt okna; GetWindowThreadProcessId
zwraca niezerowy uchwyt wątku. Jednak wywołanie GetGUIThreadInfo
zawsze zwraca false
, a komunikat o wyjątku jest zawsze "Parametr jest niepoprawny".
Tylko w przypadku problemem było to, że GetGUIThreadInfo
jakoś nie ma wersji 64-bitowej, Próbuję zmienić wszystkie 8-bajtowych IntPtr
S w GuiThreadInfo
deklaracja do 4-bajtowy int
s, ale nadal mam ten sam błąd.
Czy ktoś ma działającą próbkę C# z GetGUIThreadInfo
na Win64? Lub czy istnieje inny sposób na znalezienie tego, w jaki sposób ukierunkowana rączka okna potomnego znajdowałaby się w innej aplikacji, bez aktywowania tej aplikacji?
Ouch. Masz rację - nie mogę uwierzyć, że to przegapiłem. Punkt etykiety: naprawiono natychmiastowy problem, ale pojawił się kolejny problem; więc mój cel końcowy "zdobyć ukierunkowaną obsługę w innym procesie" jest nadal otwarty. Czy mogę edytować to pytanie, lub zaakceptować tę odpowiedź, a następnie napisać nowe pytanie? –
W tym przypadku, pytanie brzmi tak naprawdę o pInvoking GetGUIThreadInfo, więc prawdopodobnie powinieneś zagłosować jako pomocne i oznaczyć je jako odpowiedź. Możesz również edytować tytuł, aby dokładniej opisać to pytanie. Następnie dodaj nowe pytanie o bardziej ogólnym problemie, w tym o tym, co ... –
... Twoim podstawowym wymaganiem jest i co próbujesz do tej pory. Ogólnie rzecz biorąc, należy edytować pytanie, aby dodać informacje lub jasność, aby nie zmieniać tego, co jest zadawane. –