如何使用Win32API在其他进程中滚动Window

我试图创建一个程序,我可以将一个进程的进程ID(可能是firefox,即记事本等)发送到滚动进程窗口的方法。

我一直在尝试使用GetScrollBarInfo和SetScrollPos,我在pinvoke找到了没有任何成功。 我不确定这是不是正确的方法。 我开始玩GetScrollBarInfo,但它似乎不起作用。

我尝试了http://www.pinvoke.net/default.aspx/user32.getscrollbarinfo上的代码

[StructLayout(LayoutKind.Sequential)] public struct SCROLLBARINFO { public int cbSize; public Rectangle rcScrollBar; public int dxyLineButton; public int xyThumbTop; public int xyThumbBottom; public int reserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public int[] rgstate; } private const uint OBJID_HSCROLL = 0xFFFFFFFA; private const uint OBJID_VSCROLL = 0xFFFFFFFB; private const uint OBJID_CLIENT = 0xFFFFFFFC; private int Scroll(int ProcessID) { IntPtr handle = Process.GetProcessById(ProcessID).MainWindowHandle; SCROLLBARINFO psbi = new SCROLLBARINFO(); psbi.cbSize = Marshal.SizeOf(psbi); int nResult = GetScrollBarInfo(handle, OBJID_CLIENT, ref psbi); if (nResult == 0) { int nLatError = Marshal.GetLastWin32Error(); } } 

GetLastWin32Error()返回错误代码122,这意味着“传递给系统调用的数据区域太小”,根据http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs。 85)的.aspx

我不确定我做错了什么。 我怎么解决这个问题?

您可以发送WM_MOUSEWHEEL消息来执行您想要的操作。 例如,使用C ++在新的记事本窗口中向下滚动一次:

 HWND hwnd = FindWindowEx(FindWindow(NULL, "Untitled - Notepad"), NULL, "Edit", NULL); RECT r; GetClientRect(hwnd, &r); SendMessage(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA * -1), MAKELPARAM(r.right / 2, r.bottom / 2)); 

要使其适应C#,您可以执行以下操作:

 [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, ref Point lParam); private void ScrollWindow(IntPtr hwnd, Point p, int scrolls = -1) { SendMessage(hwnd, WM_MOUSEWHEEL, (WHEEL_DELTA * scrolls) << 16, ref p); } 

这可以用于在新的记事本窗口中向下滚动一次,如下所示:

 //Imports [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); ... //Actual code IntPtr hwnd = FindWindowEx(FindWindow(null, "Untitled - Notepad"), IntPtr.Zero, "Edit", null); Point p = new Point(0, 0); ScrollWindow(hwnd, p); 

有些程序要求发送的lParam是一个实际位于滚动区域上方的点,而其他程序如记事本则不会。

如果您正在尝试滚动其他进程的窗口,则实际上需要模拟滚动条或按键上的单击。 最简单的方法是使用UI Automation ,它同时具有.NET和本机接口。

通过询问滚动条信息,您只需获取有关滚动条显示方式的信息。 这不会给你一种滚动窗口内容的方法。 您必须让目标应用程序通过让用户认为用户正在操作滚动条来滚动内容。