UI 자동화 요소를 구현하지 않는 프로그램의 UI로 작업해야하는 응용 프로그램을 만들고 있습니다 (Inspect.Exe는 기본 창과 아이들 없음).스레드 입력을 대상 프로세스에 연결 한 후 SendInput이 작동하지 않습니다.
그래서 필요한 기능을 구현하는 가장 좋은 방법은 무엇인지 조사하고 sendInput()이 keybd_event()와 mouse_event()의 최신 버전임을 확인했습니다.
그러나 키보드 포커스가 필요하고 타겟 윈도우를 포어 그라운드로 설정할 여유가 없으므로 (실행하는 동안 사용자를 괴롭히지 않도록) 나는 this answer을 찾을 때까지 검색을 계속했습니다. 나는 Skurmedel이 말한 것을했고, 내 응용 프로그램의 스레드를 대상의 창 스레드에 연결했습니다. 그러나 이제 SetFocus()를 대상으로 보낸 다음 SendInput()을 실행하더라도 대상 창이 영향을받지 않습니다.
제 질문은 "왜이 기능이 작동하지 않습니까?"입니다. 또는 "? 내가 뭘 잘못하고있는 중이 야",하지만 난 코드 예제이 밖으로 정렬 도움이 될 것 같아요
ThreadHandler 클래스
class ThreadHandler
{
#region P/Invoking and constants definition
const uint WM_GETTEXT = 0x000D;
[DllImport("user32.dll")]
static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, uint lpdwProcessId = 0);
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
IntPtr lParam);
[DllImport("user32.dll")]
static extern bool AttachThreadInput(int idAttach, int idAttachTo, bool fAttach);
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, StringBuilder lParam);
#endregion
public readonly string ProcessName, WindowName;
protected readonly int TargetThreadID, CurrentThreadID;
protected readonly IntPtr TargetWindowHandle;
public ThreadHandler(string processName, string windowName)
{
CurrentThreadID = GetCurrentThreadId();
ProcessName = processName;
WindowName = windowName;
object[] objs = GetWindowThread(processName, windowName);
if (objs == null)
{
throw new ArgumentException("Could not find the specified process/window.");
}
TargetThreadID = (int)objs[0];
TargetWindowHandle = (IntPtr)objs[1];
}
public ThreadHandler(string processName)
{
CurrentThreadID = GetCurrentThreadId();
ProcessName = processName;
var processes = Process.GetProcessesByName(ProcessName);
if (processes.Length == 0)
{
throw new ArgumentException("Could not find the specified process.");
}
var appProc = processes[0];
WindowName = appProc.MainWindowTitle;
TargetThreadID = GetWindowThreadProcessId(appProc.MainWindowHandle);
TargetWindowHandle = appProc.MainWindowHandle;
}
public bool AttachThreadInput()
{
return AttachThreadInput(CurrentThreadID, TargetThreadID, true);
}
public bool DetachThreadInput()
{
return AttachThreadInput(CurrentThreadID, TargetThreadID, false);
}
public void SetFocus()
{
SetFocus(TargetWindowHandle);
}
static object[] GetWindowThread(string processName, string windowName)
{
var processes = Process.GetProcessesByName(processName);
if (processes.Length > 0)
{
//Fill a list of handles
var handles = new List<IntPtr>();
foreach (ProcessThread thread in processes[0].Threads)
EnumThreadWindows(thread.Id,
(hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
//Create a stringbuilder to function as storage unit
StringBuilder nameBuffer = new StringBuilder(64);
foreach (var hWnd in handles)
{
//And finally compare the caption of the window with the requested name
nameBuffer.Clear();
SendMessage(hWnd, WM_GETTEXT, nameBuffer.Capacity, nameBuffer);
if (nameBuffer.ToString() == windowName)
{
return new object[2] { GetWindowThreadProcessId(hWnd), hWnd };
}
}
}
return null;
}
}
응용 프로그램의Main 메서드
SendInput()의 비밀스런 기술에 대해 설명해 주시면 미리 감사드립니다.
어떻게 마침내 해결 했습니까? PostMessage를 사용하여 창에 키를 보냅니다. – SMUsamaShah
@ LifeH2O 슬프게도 나는 그것을 풀어 본 적이 없다고 생각합니다. PostMessage를 사용하려면 응용 프로그램에서 Windows 이벤트 루프를 실행해야하지만 상호 작용하려는 창에 포커스가 없으면 IIRC가 작동하지 않습니다. – KappaG3