我正在使用SetCursor将系统光标设置为我自己的图像。 代码看起来像这样:
// member on some class HCURSOR _cursor; // at init time _cursor = LoadCursorFromFile("somefilename.cur"); // in some function SetCursor(_cursor);
当我这样做时,光标确实会改变,但在第一个鼠标移动消息时,它会变回默认的系统箭头光标。 这是设置光标的项目中唯一的代码。 我需要做什么来使光标保持我设置的方式?
看来我有两个选择。 第一个是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
否则直到下一次鼠标移动,光标才会更新。
您需要响应Windows消息WM_SETCURSOR 。
您需要使您的HCURSOR手柄不超出范围。 当鼠标移动时,窗口消息开始在整个地方飞行,并将擦除你的手柄(在上面的例子中)。
使HCURSOR成为该类的私有成员,并在调用LoadCursor …()和SetCursor()时使用该句柄。 完成之后,不要忘记将其释放并清理干净,否则最终会导致资源泄漏。
这种行为是为了这样。 我认为最简单的解决方案是:当创建您的窗口类( RegisterClass || RegisterClassEx
),设置WNDCLASS.hCursor || WNDCLASSEX.hCursor
WNDCLASS.hCursor || WNDCLASSEX.hCursor
成员为NULL
。
正如@ 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()
为true时,您将不会调用父级的实现。 可能你总是希望游标不会被父类的行为所取代,所以你只需要一个更短的方法:
BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { return FALSE; }
头文件中的方法声明是:
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);