我正在写一个非常简单的程序来将鼠标剪辑到指定的窗口。它从系统托盘运行,没有可见窗口。因为同一个窗口会有多个实例,所以它使用EnumWindows()
遍历每个顶级窗口并将其hwnd与GetForegroundWindow()
进行比较。如果为true,则运行标准ClipCursor()
代码。 ClipCursor()
返回TRUE
,并且我声称RECT
设置的GetClipCursor()
与传递给RECT
的{{1}}完全相同。然而,光标可以自由移动到屏幕上的任何位置。
我已经检查过ClipCursor()
中的值是窗口的确切值,我已经在发布模式下编译了程序并使用管理员权限运行它,但仍然没有。以下代码正是在我们找到RECT
的{{1}}之后运行的代码:
HWND
我已经删除了很多检查,因为它们变得很烦人(我使用的是GetForegroundWindow()
),但是这个代码肯定会在它应该运行的时候运行。光标没有被修剪,我无法理解为什么。
答案 0 :(得分:5)
由于光标是共享资源,因此任何调用ClipCursor
来解除光标的人都会覆盖您剪辑它的尝试。并且许多操作会自动解开光标(例如任何焦点更改)。对于更改光标剪辑的背景窗口,它被认为是不好的形式。
答案 1 :(得分:4)
好吧,我花了几天的时间才发现尽管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;
}