我正在编写一个非常简单的程序来将鼠标剪辑到指定的窗口.它从系统托盘运行,没有可见窗口.因为将存在同一窗口的多个实例,所以它用于EnumWindows()遍历每个顶级窗口并将其hwnd与之进行比较GetForegroundWindow().如果为true,则运行标准ClipCursor()代码. ClipCursor()返回TRUE,并且,我断言RECTset by GetClipCursor()与RECT传递给的完全相同ClipCursor().然而,光标可以自由移动到屏幕上的任何位置.
我已经检查RECT了窗口中的值是否是窗口的确切值,我已经在发布模式下编译了程序并使用管理员权限运行它,但仍然没有.下面的代码是我们发现后正是运行HWND的GetForegroundWindow():
// Get the window client area.
GetClientRect(hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(hwnd, &pt);
ClientToScreen(hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
clipped = true;
ClipCursor(&rc);
RECT rect;
GetClipCursor(&rect);
assert(rect.bottom == rc.bottom);
assert(rect.left == rc.left);
assert(rect.right == rc.right);
assert(rect.top == rc.top);
Run Code Online (Sandbox Code Playgroud)
我已经删除了很多检查,因为它们变得很烦人(我正在使用它MessageBox()),但是这个代码肯定会在它应该运行的时候运行.光标没有被修剪,我无法理解为什么.
由于光标是共享资源,因此您尝试剪切它的尝试将被其他任何调用ClipCursor解开光标的人覆盖.并且许多操作会自动解开光标(例如任何焦点更改).它被认为是背景窗口改变光标剪辑的不良形式.
好吧,我只花了几天时间就发现,尽管 Cursor 资源具有共享性质,但如果一个进程在我还不完全了解的某些情况下剪切光标(也许该进程必须是前台)应用程序?或类似的东西...我不太确定。)然后操作系统会自动将光标释放回完全剪切模式(或任何您所说的模式)。
无论如何,修复方法是执行低级鼠标挂钩并从那里调用 Clipcursor。这是一些概念代码的快速证明(经过测试并且有效,尽管我删除了不相关的内容,例如创建窗口或设置系统托盘等):
// Some variables we'll use
bool clipped = false; // Do we need to clip the mouse?
RECT rc; // The clip rect
HHOOK hMouseHook; // Low level mouse hook
// Low level mouse hook callback function
__declspec(dllexport) LRESULT CALLBACK MouseEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
// This part should be rewritten to make it not be a CPU-hog
// But works as a proof of concept
if ( clipped )
ClipCursor(&rc);
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// .... Blah blah blah ....
// Low level mouse hook
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MouseEvent, hInstance, 0);
// Only included to show that you set the hook before this,
// And unhook after this.
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Unhook the mouse
UnhookWindowsHookEx(hMouseHook);
return msg.wParam;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3018 次 |
| 最近记录: |