How to scroll Window in other process with Win32API
c#, winapi
Solution
You could send a WM_MOUSEWHEEL message to do what you want. For example, to scroll down once in a new notepad window using 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));
To adapt that to C#, you could do something such as this:
[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);
}
Which could be used to scroll down once in a new notepad window like this:
//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);
Some programs will require the lParam sent to be a point that's actually above the scrolled area, while others such as notepad will not.
Problem
Im trying to create a program where I can send some process id of a process (that may be firefox, ie, notepad etc) to a method that scrolls window of the process. I have been trying with GetScrollBarInfo and SetScrollPos which I found at pinvoke without any success. Im not sure if this is the right way or not. I started playing with GetScrollBarInfo, but it doesn't seem to work. I tried the code found at 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() returns errorcode 122 which means "The data area passed to a system call is too small", according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx Im not sure what I do wrong. How can I solve this?