一、 原始输入线程(系统初始化时建立):
鼠标和键盘 à 设备驱动程序 à 系统硬件输入队列(System Hardware Input Queue,SHIQ)à 原始输入线程(Raw Input Thread, RIT)à VIQ à 线程的THREADINFO。
RIT如何分发:
鼠标:RIT确定哪个窗口(有焦点),调用GetWindowThreadProcessId确定线程;
键盘:任何时刻,只有一个线程(Foreground Thread,前台)同RIT连接。RIT处理特殊组合键(ALT+TAB等)以切换窗口。
二、 局部输入状态(哪个窗口有焦点;鼠标光标形状;可见性):
a) 键盘:
SetFocus();
HWND SetActiveWindow(HWND hwnd);// 激活窗口、设定焦点
HWND Get ActiveWindow();// 获取活动窗口句柄,GetFocus();
改变窗口Z序(Z-order)、活动状态、焦点的函数:
BOOL SetWindowPos(……);
BOOL BringWindowToTop(HWND hwnd);// 调用SetWindowPos(HWND_TOP)
SetForegroundWindow // 将窗口移到前台;如不允许,该窗口标题闪烁
SystemParametersInfo 和 SPI_SETFOREGROUNDFLASHCOUNT // 控制闪烁
允许某个线程调用SetForegroundWindow:
BOOL AllowSetForegroundWindow(DWORD dwProcessId); // ASFW_ANY任何进程
不允许(锁定)线程调用SetForegroundWindow:
BOOL LockSetForegroundWindow(UINT uLockCode);// LSFW_(UN)LOCK
查询是否某个键被按下(也适用于鼠标VK_LBUTTON等):
SHORT GetAsyncKeyState(int nVKey);// nVKey为虚拟键码,按下时结果的高位=1
b) 鼠标:
捕获鼠标:SetCapture;释放:ReleaseCapture。
限定光标在矩形内,其他窗口激活时失效:BOOL ClipCursor(CONST RECT* prt);
三、 将虚拟输入队列同局部输入状态挂接:
让多个线程共享一组局部输入状态变量及一个虚拟输入队列(避免使用):
BOOL AttachThreadInput(DWORD idAttach, DWORD idTo, BOOL fAttach); // 使idAttach线程共享idTo线程的变量和队列;fAttach=TRUE挂接,FALSE分开。
注意:挂接在一起的线程中某一个被挂起,其他线程也不能接收输入!
使用的情况:日志记录挂钩、子窗口。
四、 其他:
获取鼠标位置:
x = LOWORD(GetMessagePos());y = HIWORD(GetMessagePos());
获取鼠标位置的窗口:
ChildWindowFromPointEx(GetDesktopWindow(), pt, CWP_SKIPINVISIBLE);
GetWindowThreadProcessId(HWND, NULL); // 获取窗口的线程(进程)ID。
使用资源:MAKEINTRESOURCE(IDD_DLG);