获取另一个窗口/应用程序的滚动方向

时间:2018-11-14 07:25:10

标签: c# windows winapi ui-automation microsoft-ui-automation

我想检测另一个应用程序的滚动方向。如果用户通过挂钩滚动鼠标滚轮或键盘(上/下/左/右键),则可以这样做。但是当用户使用Chrome之类的应用程序中存在的滚动条时,我无法捕获相同的内容。

我已经尝试了以下本机方法,但是它不适用于chrome等许多应用程序,并且不适用于Notepad ++,因为它无法检测chrome的滚动条。我想要一种适用于所有应用程序的东西。

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

我进行了大量研究,但找不到任何可以为我提供页面滚动方向的信息。 请让我知道是否需要进一步的信息。

更新

我正在尝试使用UI自动化来获取Chrome的滚动条信息。

这是怎么回事?

我使用EnumChildWindows收集了Windows Gui矩形窗口,该窗口也检索了子控件。根据鼠标位置,选择其Gui矩形包含我的鼠标位置的窗口手柄。我获得的手柄具有Gui Rectangle = chrome的客户区域。

问题:

下面是代码。对于Chrome,它在elementCollection中为我提供了一个空集合,对于Notepad ++,它成功返回了2个滚动条元素。

var element = AutomationElement.FromHandle(handle);
if(element != null)
{
    Condition condition = 
       new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ScrollBar);

    // Find all children that match the specified conditions.
    AutomationElementCollection elementCollection =
        element.FindAll(TreeScope.SubTree, condition);
 }

1 个答案:

答案 0 :(得分:0)

您需要做的是调用GetScrollInfo方法两次并比较这些值以找出答案;是否滚动控件并计算(上一个<当前)方向。只要您想继续监视滚动方向,就需要重复此过程。

现在,您应该创建某种工作者类来很好地处理事情,出于这个问题的目的,我使用了一个简单的Console应用程序,该应用程序使用while循环轮询句柄的SCROLLINFO结构:< / p>

static void Main(string[] args)
{
    var handle = (IntPtr)0x35087C; // notepad textbox handle

    var prevInfo = default(SCROLLINFO);
    int iterations = 1000;

    while (iterations > 0)
    {
        var curInfo = new SCROLLINFO();
        curInfo.cbSize = Marshal.SizeOf(curInfo);
        curInfo.fMask = (int)ScrollInfoMask.SIF_ALL;

        if (GetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref curInfo))
        {
            var dir = curInfo.nPos < prevInfo.nPos ? "Up" : "Down";
            dir = curInfo.nPos == prevInfo.nPos ? "Unchanged" : dir;

            Console.WriteLine(dir);

            prevInfo = curInfo;
        }
        else
        {
            Console.WriteLine($"No scrolling.. {Marshal.GetLastWin32Error()}");
        }

        System.Threading.Thread.Sleep(100);
        iterations--;
    }

    Console.ReadLine();
}

请注意,handle变量包含指向记事本进程文本框的指针(与记事本进程的句柄不同)。我已经使用WinSpy++从记事本过程中检索了句柄。

我已经使用GetScrollInfo MSDN page来了解API调用本身,GetScrollInfo Pinvoke.NET page来获取所有必需的结构/枚举。