windows SetCursor 在鼠标移动后恢复
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/169155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SetCursor reverts after a mouse move
提问by Joe Ludwig
I am using SetCursor to set the system cursor to my own image. The code looks something like this:
我正在使用 SetCursor 将系统光标设置为我自己的图像。代码如下所示:
// member on some class
HCURSOR _cursor;
// at init time
_cursor = LoadCursorFromFile("somefilename.cur");
// in some function
SetCursor(_cursor);
When I do this the cursor does change, but on the first mouse move message it changes back to the default system arrow cursor. This is the only code in the project that is setting the cursor. What do I need to do to make the cursor stay the way I set it?
当我这样做时,光标确实会发生变化,但是在第一次鼠标移动消息时,它会变回默认的系统箭头光标。这是项目中设置光标的唯一代码。我需要做什么才能使光标保持我设置的方式?
回答by Joe Ludwig
It seems that I have two options. The first is the one that Mark Ransom suggested here, which is to respond to the windows WM_SETCURSOR
message and call SetCursor at that time based on where the mouse is. Normally windows will only send you WM_SETCURSOR
when the cursor is over your window, so you would only set the cursor in your window.
看来我有两个选择。第一个是Mark Ransom这里建议的,就是响应windowsWM_SETCURSOR
消息,根据鼠标所在的位置调用当时的SetCursor。通常,窗口只会WM_SETCURSOR
在光标悬停在您的窗口上时才会发送给您,因此您只需将光标设置在您的窗口中即可。
The other option is to set the default cursor for the window handle at the same time as I call SetCursor
. This changes the cursor set by the default handler to WM_SETCURSOR
. That code would look something like this:
另一个选项是在我调用SetCursor
. 这会将默认处理程序设置的光标更改为WM_SETCURSOR
。该代码如下所示:
// defined somewhere
HWND windowHandle;
HCURSOR cursor;
SetCursor(cursor);
SetClassLong(windowHandle, GCL_HCURSOR, (DWORD)cursor);
If you use the second method you have to call both SetCursor
and SetClassLong
or your cursor will not update until the next mouse move.
如果您使用第二种方法,您必须同时调用这两种方法SetCursor
,SetClassLong
否则您的光标在下一次鼠标移动之前不会更新。
回答by Mark Ransom
You need to respond to the Windows message WM_SETCURSOR.
您需要响应 Windows 消息WM_SETCURSOR。
回答by LarryF
You need to make your HCURSOR handle not go out of scope. When the mouse moves, windows messages start flying all over the place, and it will wipe out your handle (in the example above).
您需要使您的 HCURSOR 句柄不会超出范围。当鼠标移动时,windows 消息开始到处飞,它会擦掉你的句柄(在上面的例子中)。
Make an HCURSOR a private member of the class, and use that handle when you call LoadCursor...() and SetCursor(). When you are done, do not forget to free it, and clean it up, or you will end up with a resource leak.
使 HCURSOR 成为类的私有成员,并在调用 LoadCursor...() 和 SetCursor() 时使用该句柄。完成后,不要忘记释放它,并清理它,否则最终会导致资源泄漏。
回答by Heinz Traub
This behavior is intended to be this way. I think the most simple solution is: When creating your window class (RegisterClass || RegisterClassEx
), set the WNDCLASS.hCursor || WNDCLASSEX.hCursor
member to NULL
.
这种行为就是这样的。我认为最简单的解决方案是:在创建窗口类 ( RegisterClass || RegisterClassEx
) 时,将WNDCLASS.hCursor || WNDCLASSEX.hCursor
成员设置为NULL
.
回答by sergiol
As @Heinz Traub said the problem comes from the cursor defined on the RegisterClass
or RegisterClassEx
call. You probably have code like:
正如@Heinz Traub 所说,问题来自在RegisterClass
orRegisterClassEx
调用上定义的游标。你可能有这样的代码:
BOOL CMyWnd::RegisterWindowClass()
{
WNDCLASS wndcls;
// HINSTANCE hInst = AfxGetInstanceHandle();
HINSTANCE hInst = AfxGetResourceHandle();
if (!(::GetClassInfo(hInst, _T("MyCtrl"), &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = _T("MyCtrl");
if (!AfxRegisterClass(&wndcls))
{
AfxThrowResourceException();
return FALSE;
}
}
return TRUE;
}
where the wndcls.hCursor
says what cursor will be used when WM_SETCURSOR
message is thrown; it happens every time it occurs a mouse move and not only.
哪里wndcls.hCursor
表示WM_SETCURSOR
抛出消息时将使用什么游标;每次发生鼠标移动时都会发生这种情况,而不仅仅是。
I solved a similar problem this way:
我以这种方式解决了类似的问题:
In the class' message map add an entry for the WM_SETCURSOR
message:
在类的消息映射中为WM_SETCURSOR
消息添加一个条目:
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
//... other messages
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
Add the method OnSetCursor
, which will override the parent class' implementation:
添加方法OnSetCursor
,它将覆盖父类的实现:
BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (SomeCondition())
return FALSE;
return __super::OnSetCursor(pWnd, nHitTest, message);
}
Explanation: when SomeCondition()
is true, you will not call parent's implementation. May be you want always to have a cursor not superseded with parent class behavior, so you just need an even shorter method:
说明:当SomeCondition()
为真时,您将不会调用父级的实现。可能您希望始终拥有一个不被父类行为取代的游标,所以您只需要一个更短的方法:
BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
return FALSE;
}
And the declaration of the method in the header file is:
而头文件中方法的声明是:
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);