我正在使用SetCursor将系统光标设置为我自己的图像。代码看起来像这样:
// member on some class
HCURSOR _cursor;
// at init time
_cursor = LoadCursorFromFile("somefilename.cur");
// in some function
SetCursor(_cursor);
当我这样做时,光标会改变,但在第一个鼠标移动消息上,它会变回默认的系统箭头光标。这是项目中设置光标的唯一代码。我需要做什么才能使光标保持原样?
答案 0 :(得分:10)
似乎我有两种选择。第一个是Mark Ransom在这里建议的,它是响应windows WM_SETCURSOR
消息,并根据鼠标所在的位置调用SetCursor。通常情况下,只有当光标在窗口上方时,窗口才会向您发送WM_SETCURSOR
,因此您只需在窗口中设置光标。
另一个选项是在我调用SetCursor
的同时设置窗口句柄的默认光标。这会将默认处理程序设置的游标更改为WM_SETCURSOR
。该代码看起来像这样:
// defined somewhere
HWND windowHandle;
HCURSOR cursor;
SetCursor(cursor);
SetClassLong(windowHandle, GCL_HCURSOR, (DWORD)cursor);
如果您使用第二种方法,则必须同时调用SetCursor
和SetClassLong
,否则在下一次鼠标移动之前,光标将不会更新。
答案 1 :(得分:5)
您需要回复Windows消息WM_SETCURSOR。
答案 2 :(得分:2)
你需要让你的HCURSOR手柄不要超出范围。当鼠标移动时,窗口消息开始飞到整个地方,它将擦除你的手柄(在上面的例子中)。
使HCURSOR成为该类的私有成员,并在调用LoadCursor ...()和SetCursor()时使用该句柄。完成后,不要忘记释放它,清理它,否则最终会导致资源泄漏。
答案 3 :(得分:1)
此行为旨在通过这种方式。我认为最简单的解决方案是:在创建窗口类(RegisterClass || RegisterClassEx
)时,将WNDCLASS.hCursor || WNDCLASSEX.hCursor
成员设置为NULL
。
答案 4 :(得分:0)
正如@Heinz Traub所说,问题来自RegisterClass
或RegisterClassEx
电话上定义的游标。您可能有以下代码:
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;
}
其中wndcls.hCursor
表示在抛出WM_SETCURSOR
消息时将使用什么游标;它发生在每次鼠标移动时都会发生,而不仅仅是。
在班级的消息地图中添加WM_SETCURSOR
消息的条目:
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
//... other messages
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
添加方法OnSetCursor
,它将覆盖父类的实现:
BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (SomeCondition())
return FALSE;
return __super::OnSetCursor(pWnd, nHitTest, message);
}
说明:当SomeCondition()
为真时,您不会调用父实现。可能您希望始终使游标不被父类行为取代,因此您只需要一个更短的方法:
BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
return FALSE;
}
头文件中方法的声明是:
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);