我已经制作了一个应用程序,当鼠标悬停在静态控件上方时,需要将光标的外观更改为手,否则将其重置为普通光标.
我的初始应用程序是全屏模式,但最近条款已更改,并且必须具有可调整大小的窗口.
这意味着WM_SETCURSOR
必须重写我的处理程序以反映新引入的更改.
游标被加载WM_CREATE
,我已经定义了类游标,如下所示:
// cursors
case WM_CREATE:
hCursorHand = LoadCursor( NULL, IDC_HAND );
hCursorArrow = LoadCursor( NULL, IDC_ARROW );
// other stuff
Run Code Online (Sandbox Code Playgroud)
在我班上:
WNDCLASSEX wc;
// ...
wc.hCursor = hCursorArrow;
//...
Run Code Online (Sandbox Code Playgroud)
这是我的旧WM_CURSOR
处理程序(为简化起见,代码已简化):
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
SetCursor(hCursorHand);
else
SetCursor(hCursorArrow);
return TRUE;
Run Code Online (Sandbox Code Playgroud)
如果光标悬停在静态控件之上,那么我的处理程序将其更改为手动,否则将其设置为默认光标(箭头).
Bellow是我在Paint中绘制的图片,当它悬停在静态控件上方时显示所需的光标外观,它位于客户端区域,当用户调整窗口大小时.
如果需要额外的代码片段,请询问,我将编辑我的帖子,但是现在,它们被省略以保持帖子简洁明了.
我在Windows XP上工作,使用MS Visual Studio C++和纯Win32 API.
贝娄是我尝试过的代码片段,但它们都失败了:
第一个片段:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
return TRUE;
}
else
return DefWindowProc( hWnd, msg, lParam, wParam );
Run Code Online (Sandbox Code Playgroud)
第二个片段:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
return TRUE;
}
break; // based on MSDN example
Run Code Online (Sandbox Code Playgroud)
第三个片段:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
return TRUE;
}
else
return FALSE;
Run Code Online (Sandbox Code Playgroud)
无论它在哪里,它们都会将光标设置为手.
如果我WM_SETCURSOR
保持我的处理程序不变,我得到的唯一问题是,当我将鼠标悬停在边框上时,我会获得常规箭头(如光标的外观),而不是调整箭头大小,但窗口可以调整大小.
如果我注释掉我的WM_SETCURSOR
处理程序,大小调整箭头和光标箭头会正确显示,但是当鼠标悬停在静态控件之上时光标不会变成手(这是合乎逻辑的,因为没有WM_SETCURSOR
处理程序可以更改它).
我浏览了SO存档,查看了MSDN,CodeProject,DaniWeb,Cprogramming和CodeGuru,但没有成功.
通过这些,我找到了一个例子,人们比较低 lParam
命中测试代码.
通过MSDN我找到了命中测试值的链接(http://msdn.microsoft.com/en-us/library/windows/desktop/ms645618%28v=vs.85%29.aspx),我找到了链接游标类型(http://msdn.microsoft.com/en-us/library/windows/desktop/ms648391%28v=vs.85%29.aspx).
目前我正在阅读它们,因为我认为我将不得不加载额外的游标资源,对命中测试值进行几次比较,然后使用这些资源来相应地设置游标外观.
我真的希望我的WM_SETCURSOR
处理程序看起来像这样:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
return TRUE;
}
else
// reset cursor's look to default
Run Code Online (Sandbox Code Playgroud)
所以我请社区指导我如何做到这一点.
如果这是不可能的,那么我将考虑使用多个if
语句来检查命中测试代码,并相应地设置光标的外观.
当然,如果我的问题有更好的解决方案,请提出建议,我也会考虑.
谢谢.
问候.
通常,如果您处理WM_SETCURSOR
消息,您必须要么
SetCursor()
设置光标,然后返回TRUE
,或FALSE
默认处理,或DefWindowProc()
我认为MSDN文档中没有明确说明最后两点.
鼠标指针下的窗口获取第一条WM_SETCURSOR
消息.如果它处理它并在那时返回,则不会发生任何其他事情.如果它调用DefWindowProc()
,则DWP将消息转发到窗口的父级以进行处理.如果父选择不处理它,它可以返回FALSE
并且DefWindowProc处理将继续.
但这仅适用于消息来自之前对DWP的调用.如果消息来自窗口本身而不是子节点,则返回TRUE
或FALSE
不设置光标意味着光标将根本不被设置.
另一件事:虽然你的问题没有说明,但我假设您使用GetDlgItem()
顶级窗口是一个对话框.如果这是真的,你不能只返回TRUE
或FALSE
留言 - 你需要使用返回值SetWindowLongPtr()
并存储返回值DWLP_MSGRESULT
.FALSE
从对话框程序返回表示您根本没有处理该消息 - 这相当于将消息传递给DefWindowProc()
.
因此,我认为在您的顶级窗口中正确处理您的情况:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}
return FALSE;
Run Code Online (Sandbox Code Playgroud)
如果您的顶级窗口实际上不是对话框,您可以这样做:
case WM_SETCURSOR:
if( (HWND)wParam == GetDlgItem( hwnd, 4000 ) )
{
SetCursor(hCursorHand);
return TRUE;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
Run Code Online (Sandbox Code Playgroud)