非激活窗口中响应鼠标滚动之理论篇

Posted cherishui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非激活窗口中响应鼠标滚动之理论篇相关的知识,希望对你有一定的参考价值。

在最近工作中有一个优化交互的需求,分析后得知,其核心功能为能在非激活窗口中响应鼠标滚动消息,先就该需求进行前期方案验证。

同类产品实现

参照现有软件行为,操作系统为Win7。以notepad++Chrome两款软件为例。

  • 当鼠标选中notepad++后,然后将鼠标转移到Chrome界面后,上下滚动鼠标,Chrome页面能够同步滚动。
  • 当鼠标选中Chrome后,然后将鼠标转移到Notepad++界面,上下滚动,Notepad++不能同步滚动。

猜测是Chrome对滚轮滚动消息进行了额外处理。既然现有软件支持该功能,那么在技术上就不是问题。接下来就是确定方案。在经过一番
搜索后,发现该需求的核心关键词是 scroll, inactive, hover

关联问题链接

  1. How to direct the mouse wheel input to control under cursor instead of focused?
  2. Windows上的焦点系统
  3. Mouse Wheel Scrolling not always working in Windows 10
  4. 微软鼠标指针交互文档
  5. On Windows 7, is there any way to make the scrollwheel‘s focus follow the mouse?

在Win10之前的版本,鼠标滚动会影响当前激活的窗口,而不影响鼠标当前悬停窗口。而Win10系统改变这种默认行为,当鼠标滚动时,会影响鼠标当前悬停窗口,而不是当前激活的窗口。该功能已经在Win10上得到验证,可通过以下来进行设置。

技术图片

鼠标滚轮处理流程

在Windows系统上,焦点决定了由哪个窗口或者控件接收键盘输入信息,对于用户来说,最直观的感觉是,有光标闪动的窗口或者被高亮的控件,就有焦点。更进一步,这里的焦点仅仅控制键盘输入,鼠标输入与焦点没有直接关系。系统的焦点模型决定了鼠标是如何使得一个窗口获得焦点的,主要有以下三种模型:

  1. click-to-focus模型
    鼠标点击的窗口可以获得焦点。这是Windows下最常见的一种模型,当用户点击鼠标时,鼠标当前位置下的窗口会被激活,并被置于所有窗口的最前面,可接受键盘输入。

  2. focus-follow-mouse模型

    鼠标当前位置下的窗口可以获取焦点。当鼠标移动到一个可以获得焦点的窗口范围内,用户无需点击窗口,即可激活该窗口,使得可以接收键盘输入。此时,该窗口不一定会置于最前方。当鼠标移出该窗口范围时,该窗口随之失去焦点。

  3. sloppy-focus模型
    该模式与focus-follow-mouse模型类似,不同之处在于,当鼠标移出该窗口范围时,该窗口不会失去焦点,直到鼠标移动到另外一个可以接收焦点的窗口时,输入焦点才会改变。

鼠标滚动消息是 WM_MOUSEWHEEL,官方解释如下:

Sent to the active window when the mouse's horizontal scroll wheel is tilted or rotated. 
The DefWindowProc function propagates the message to the window's parent. 
There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.

A window receives this message through its WindowProc function.

默认情况下,鼠标滚轮消息会发往当前有焦点的窗口,默认的窗口处理过程会将该消息往上传递,直到该消息被处理为止。

可行的解决方案

由于在Win10系统下,默认鼠标滚轮对非激活窗口是生效的,但为了兼容性考虑,程序自身还是要额外处理。下面列出以下两类方案:

  • 方案一
    使用第三方软件,不搜不知道,一搜才知道有这么多的小软件可以满足该需求。
  • 方案二
    自己搭轮子,利用鼠标钩子,将滚轮滚动消息传递给鼠标当前位置所在窗口即可。

以上是关于非激活窗口中响应鼠标滚动之理论篇的主要内容,如果未能解决你的问题,请参考以下文章

MFC中静态拆分窗口后,每个窗口的滚动条不支持鼠标滚动了,只能拖拉了,怎么回事,求解决啊!!!

为啥鼠标滚动条不起作用?

如何区分一个窗口是不是被鼠标点击激活?

还有的时候,会遇到DataGrid里面嵌套DataGrid(重叠嵌套),然后里面的鼠标滚轮无法响应外面的滚动,为此记录下解决方案

2019-11-29-WPF-非客户区的触摸和鼠标点击响应

当鼠标悬停在绝对 div 上时,jQuery 禁用滚动