I am starting and resizing external applications(Microsoft Word/Excel/
Powerpoint Viewer Notepad, Acrobat Reader) to display some documents.
I have to scroll some off those windows, too. I think I need the Win32
API function FindWindowEX to find the scroll control or the Edit
control that implements it with WS_HSCROLL and/or WS_VSCROLL.
My problem is that I have no idea how to get the right handle. I am
using Microsof Managed Spy(http://msdn.microsoft.com/msdnmag/issues/
06/04/ManagedSpy/) to inspect the windows. Process and their windows
are clearly arranged:
exe-name program title [process id]
+ handle [Classes with subclasses]
handle [Just classes]
E.g. notepad.ex looks this
notepad PATH.txt - Editor
+ 655600 [Notepad]
327906 [Edit]
3408122 [msctls_statusbar32]
196948 [MSCTFIME UI]
786688 [IME]
I think that I have to get the _327906_ handle of the Edit class to be
able to do anything with it, but I can't get it with the following
code:
Public Const WM_VSCROLL As Int32 = &H115
Public Const SB_PAGEDOWN As Int32 = 3
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Public Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As
Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As
<MarshalAs(UnmanagedType.Bool)> Boolean
' No code here.
End Function
Public Class File
Private _path As String
Private _scrolltechnik As Scrolltechnik
Private _format As Format
Private _scrolltime As Integer ' in millisekunden
Private _show_always As Boolean
Private _file_viewer As SNK.Application
Friend sInfo As STARTUPINFO
Friend pInfo As PROCESS_INFORMATION
Public Sub New(ByVal path As String, ByVal app As SNK.Application,
Optional ByVal scrolltime As Integer = 2000, Optional ByVal scrolltec
As Scrolltechnik = SNK.Scrolltechnik.Zeilenweise, Optional ByVal form
As Format = SNK.Format.Hochformat)
_path = path
_scrolltechnik = scrolltec
_scrolltime = scrolltime
_format = form
_file_viewer = app
sInfo = New STARTUPINFO
pInfo = New PROCESS_INFORMATION
End Sub
End Class
Public Function Scroll(_current_file as File) As Boolean
Dim retValue As Boolean
Dim si As SCROLLINFO
Dim lRet As Integer
Dim windowHandle As IntPtr
Dim scrollbarHandle As IntPtr
si = New SCROLLINFO
Dim w As Integer = _current_file.pInfo.dwProcessId
'Dim w As Integer = _current_file.pInfo.dwThreadId
Dim h As Integer = 0
Dim lclassname As String = "Edit"
windowHandle = New IntPtr(w)
scrollbarHandle = New IntPtr(h)
scrollbarHandle = FindWindowEx(windowHandle, New IntPtr(0),
lclassname, "")
lRet = GetScrollInfo(scrollbarHandle, ScrollBarDirection.SB_VERT,
si)
If 0 = lRet Then
lRet =
System.Runtime.InteropServices.Marshal.GetLastWin32Error()
MsgBox("Last Win32-Errorcode: " & lRet.ToString)
Else
retValue = SendMessage(scrollbarHandle, WM_VSCROLL, _
New IntPtr(ScrollBarCommands.SB_PAGEDOWN), IntPtr.Zero)
End If
Return retValue
End Function
You can see that I am trying to get the handle of a class(lclassname)
with FindowWindowEx and I am passing the process ID to it. It doesn't
work to get the Edit handle directly, so I tried to get the handle of
the Notepad class instead, but I still don't get anything.
Do you see an error in my code or my thoughts? Do you know another way
to handle the problem?
Another problem occurs, when I grab the Edit handle with Managed Spy.
It can use it in Debug mode to initialize the scrollbar
handle(scrollbarHandle = New IntPtr(h) and skip FindWindowEx), but
nothing happens when I SendMessage the scroll message WM_VSCROLL to
it.
Can you explain that behaviour to me please?
Best Regards,
Thomas
I forgot to mention that SendMessage is returning true, when I send
the WM_VSCROLL directly to it, but it doesn't scroll.
It works now! I passed a wrong handle, but I still can't get the Edit
handle programatically. Can you please help me there with FindWindowEx
or another Win32 API function which I missed?
The full question again:
> Another problem occurs, when I grab the Edit handle with Managed Spy.
> It can use it in Debug mode to initialize the scrollbar
> handle(scrollbarHandle = New IntPtr(h) and skip FindWindowEx), but
> nothing happens when I SendMessage the scroll message WM_VSCROLL to
> it.
> Can you explain that behaviour to me please?
>
> Best Regards,
>
> Thomas
Sorry for any trouble. I am very new to API programming.
Look at this sample for listening scrolls:
http://www.vb-tips.com/Scroll.aspx
Thank you!
This is not what I am looking for. I don't want to listen to scroll
message, I want to send them to external applications. My problem is
that I cannot get the handle of the control which contains the scroll
bars, e.g. I have started notepad.exe showing a file with
CreateProcess, I have the process and thread information about it
stored in a PROCESSINFO structure and I am trying to use FindWindowEx
to get its window of the "Edit" class.
I have no idea how to get the handle of the Edit. Do you have any
ideas?
Thomas,
you may want to check FindWindowEx and similar functions which you
might need using p/invoke:
http://www.pinvoke.net/default.aspx/user32.FindWindowEx
Thank you I tried to use FindWindowEx with a handle from the
PROCESS_INFORMATION structure, but I didn't find a way to get the main
window handle of a process. Luckily I found out that the .Net class
Process can return the thread handle for MoveWindow which needs it -
it's in Process.Threads(0).id!
I am using now Process.mainWindowHandle as the starting point for
FindWindowEx.
I still have to find a way to make the Microsoft Word Viewer scroll a
document, but it is no big problem(I _hope_ so :)
Best regards,
Thomas
Hello, I just ran into a problem with FindWindowEx. I can't get to the
nested scroll bar in the Word Viewer:
WORDVIEW PATH.txt - Microsoft Word Viewer
329270 [OleDdeWndClass]
+ 460298 [OpusApp] <-- I have the handle of that one in
_process.MainWindowHandle
198174 [MsoCommandBarDock]
198178 [MsoCommandBarDock]
198176 [MsoCommandBarDock]
198180 [MsoCommandBarDock]
+ 460294 [_WwF]
+ 460350 [_WwB]
394812 [_WwC]
394768 [ScrollBar] <-- I need that one
198194 [_WwC]
198200 [ScrollBar]
198192 [_WwC]
198190 [_WwC]
525836 [_WwC]
196948 [MSCTFIME UI]
786688 [IME]
I tried it with this code:
Public Overrides Function GetScrollbarHandle() As IntPtr
Dim childHandle As IntPtr
childHandle = New IntPtr(0)
' the vertical scroll bar is nested a few layers
childHandle = FindWindowEx(_process.MainWindowHandle, New
IntPtr(0), "_WwF", "") ' <-- works!
If childHandle.ToInt32 <> IntPtr.Zero.ToInt32 Then
childHandle = FindWindowEx(childHandle, New IntPtr(0), "_WwB",
"") <-- This is returning 0
If childHandle.ToInt32 <> IntPtr.Zero.ToInt32 Then
childHandle = FindWindowEx(childHandle, New IntPtr(0),
"ScrollBar", "")
End If
End If
Return childHandle
End Function
Can you find any errors in my code? I am trying different things, but
it doesn't work.
Kindly,
Thomas