6

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

我一直在尝试使用我在 pinvoke 找到的 GetScrollBarInfo 和 SetScrollPos,但没有任何成功。我不确定这是否是正确的方法。我开始玩 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();
    }
}

根据http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs. 85).aspx

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

4

3 回答 3

6

你可以发送一条 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 是实际位于滚动区域上方的点,而其他程序(例如记事本)则不会。

于 2013-03-11T09:54:33.000 回答
3

如果您尝试滚动另一个进程的窗口,您实际上需要模拟滚动条上的点击或按键操作。最简洁的方法是使用UI Automation,它同时具有 .NET 和本机接口。

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

于 2013-03-10T22:09:04.237 回答
0

http://forums.codeguru.com/showthread.php?446352-How-to-scroll-active-window-SendMessage&p=1686041#post1686041

最终代码

class Program
{
        [DllImport("user32.dll")]
        static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);


        [DllImport("user32.dll")]
        public static extern int SetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar, int nPos, bool bRedraw);


        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);


        public struct GUITHREADINFO
        {
            public int cbSize;
            public int flags;
            public IntPtr hwndActive;
            public IntPtr hwndFocus;
            public IntPtr hwndCapture;
            public IntPtr hwndMenuOwner;
            public IntPtr hwndMoveSize;
            public IntPtr hwndCaret;
            public System.Drawing.Rectangle rcCaret;
        }


        const Int32 WM_VSCROLL = 0x0115;
        const Int32 SB_LINERIGHT = 1;


        static void Main(string[] args)
        {
            //create process in focus
            Process.Start("notepad++", "Source.cpp");
            Thread.Sleep(1000);
            GUITHREADINFO threadInfo = new GUITHREADINFO();
            threadInfo.cbSize = Marshal.SizeOf(threadInfo);

            GetGUIThreadInfo(0, ref threadInfo);
            SendMessage(threadInfo.hwndFocus, WM_VSCROLL, SB_LINERIGHT, 0);
            //SetScrollPos not work. Change only scrollbar without scroll window
            //SetScrollPos(threadInfo.hwndFocus, System.Windows.Forms.Orientation.Vertical, 10, true);           
        }
    }
于 2019-04-03T21:19:30.823 回答