微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Win32 中暂时切换到等待光标的正确方法是什么? 或者:如何正确触发 WM_SETCURSOR?

如何解决在 Win32 中暂时切换到等待光标的正确方法是什么? 或者:如何正确触发 WM_SETCURSOR?

这是我遇到的问题:

  • 我需要将光标切换到(比如说)IDC_WAIT,直到我完成了一些操作。

  • SetCursor 只在鼠标移动前有效。

  • WM_SETCURSOR 仅在鼠标移动后有效。

你会认为我可以只做上述两个,同时调用 SetCursor修改 WM_SETCURSOR 的行为,以便我让光标改变直到某个点未来。

但我不能就那样做。为什么?因为 SetCursor 是应用程序范围的,但随机窗口不知道(也不应该知道)整个应用程序的正确光标是什么。它需要执行正确的命中测试才能将 WM_SETCURSOR 发送到实际位于光标下的窗口,目前尚不清楚正确的方法是什么。

在 Win32 中切换光标并返回的正确方法是什么?我看到的每个例子都是微不足道的,忽略了这些问题。

解决方法

1_ 与禁用输入结合使用时,实现繁忙游标是最简单的。首先禁用输入EnableWindow( hwnd,FALSE );,然后设置忙光标SetCursor( LoadCursor( 0,IDC_WAIT ) );。现在您可以进行一些操作(最好不要超过 5 秒)。之后启用输入EnableWindow( hwnd,TRUE );。当您的操作时间超过 5 秒时,窗口会出现“重影”,因此会丢失标题栏上的繁忙光标和调整边框。

2_如果窗口在显示忙光标时需要接受输入,则不仅要在顶级窗口的窗口过程中处理 WM_SETCURSOR 消息,还要处理其所有子窗口(简单的 STATIC 控件是个例外)。这需要对这些子项进行子类化 (SetWindowSubclass),除非您可以使用某些高级框架,否则这可能是一项任务。

在子类化窗口过程中,只需设置忙光标并返回TRUE。对于 DefWindowProc 情况,请勿调用 DefSubclassProcWM_SETCURSOR

switch ( message )
{
case WM_SETCURSOR:
    SetCursor( MyCursor );
    return TRUE;
...
}

子类化可以在每个子创建时完成,也可以在以后通过枚举它们来完成。

有趣的是,它甚至适用于带有弹出列表的菜单和组合框。

3_ 另一种选择是隐藏光标 ShowCursor( FALSE ); 并显示具有一些点击功能的半透明窗口跟踪鼠标光标位置。就我个人而言,我会从只显示在当前光标位置上方或下方几个像素的窗口开始。

也许状态栏上的进度条或主窗口上的简单动画(沙漏?)会更容易。

,

我想我找到了一个合理有效的解决方案。它并不完美(我仍然看到一些粗糙的边缘),但我认为到目前为止对我来说还可以,并且考虑到所有的权衡,它的行为比懒惰的方法更合理。

应用的复杂程度可能会有所不同。

以下是我建议对处于类似情况的人做的事情:

  1. 定义应用范围的消息,例如WM_UPDATECURSOR = WM_APP + 0

  2. 通过触发 WM_UPDATECURSOR 使您的主 (GUI) 线程处理 WM_SETCURSOR

    一个。使用 GetCursorPosWindowFromPoint 获取光标下的线程。

    B.使用 GetWindowThreadProcessId 检查进程和线程 ID。

    c.如果它处于不同的进程中,请停止。

    d。如果它与您的进程在不同的线程中,请PostThreadMessage(thread_id,WM_UPDATECURSOR) 到它,然后停止。 (这是不寻常且通常很糟糕的做法;我只是为了完整性才提到它。)

    e.如果它是用于您自己的线程,则使用 WM_NCHITTEST,如果成功,请找出(如下所述)正确 光标应该是什么(如果有)。如果有的话,用 SetCursor 设置它;如果没有,SendMessage(WM_SETCURSOR)

  3. 保留与您认为“可堆叠”的不同游标相对应的计数器列表。较早的元素较低优先级。不在列表中的任何内容都不会在以后被覆盖或考虑。

  4. 每当您想更改任何线程上的光标时,如果需要,可以原子地增加或减少其相应的计数器。 (假设此游标在可堆叠游标列表中。)
    然后以与上述 WM_UPDATECURSOR 相同的方式触发游标更新。

  5. 要判断某个游标是否已在任何一点堆叠,请反向遍历列表,找到第一个正计数器对应的游标。如果没有,则返回NULL;没有堆叠光标。

  6. 在主窗口/对话框的 WM_SETCURSOR 处理程序中,按照上一步中的说明从全局列表中评估光标,并使用 SetCursor 对其进行设置。但是,返回 FALSE 以便子窗口(如编辑控件)在需要时仍会覆盖它。

如果我发现更多问题,我会更新它,但我认为总体上它表现得不错。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。