2013-03-10 78 views
3

我試圖創建一個程序,我可以將進程的進程ID(可能是firefox,即記事本等)發送到滾動進程窗口的方法。如何使用Win32API在其他進程中滾動窗口

我一直在嘗試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

林不知道我做錯了什麼。我該如何解決這個問題?

回答

3

你可以發送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的發送是一個點,實際上是在滾動區域上方,而其他如記事本不會。

+0

謝謝。我會稍後再試! :) – 2013-03-12 09:21:12

+0

尋找這方面的信息似乎有點難。你的例子很好用。既然你似乎是我所知道的少數人知道的事情之一,你從哪裏得到這些信息?我想進一步概括這個,所以它不僅僅是記事本。我不知道「編輯」來自哪裏。那是什麼?我怎樣才能找到其他程序的等價物? – 2013-03-13 22:56:16

+0

「編輯」是記事本中需要將滾動發送到的控件。許多瀏覽器不會要求它被髮送到控件 - 例如,我只用FindWindow嘗試(null,「當前頁面名稱 - Opera」);和滾動工作正常。我過去使用過WM_MOUSEWHEEL,並且知道在低級別的鼠標鉤子中使用它需要什麼。如果你想得到一個需要發送到其他窗口的控件,可以查看EnumChildWindows或者使用WinSpy ++。 欲瞭解更多信息: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx – Jammerx2 2013-03-14 20:26:44

2

如果您要滾動另一個進程的窗口,實際上需要模擬滾動條或按鍵上的點擊。最簡單的方法是使用UI Automation,它具有.NET和本機接口。

通過詢問滾動條信息,您只需獲取有關如何顯示滾動條的信息。這不會給你一種滾動窗口內容的方法。您必須讓目標應用程序通過讓用戶認爲用戶正在操作滾動條來滾動內容。

+0

這聽起來像一個更通用的方式來做到這一點。肯定會研究它。謝謝!! :) – 2013-03-12 09:22:10

相關問題