Scrolling Scrollbar in IE6
|
|
Thread rating:  |
Jack B. Pollack - 03 Sep 2008 13:21 GMT Hi,
Using VB6 and trying to interact with an instance of IE6.
I need my program to be able to scroll the scrollbars in IE. I suspect that I can use SetScrollPos API, but how do I get the hwnd of the scrollbar (I can get the hwnd of the main IE window, but not the Scrollbar)?
Thanks
mayayana - 03 Sep 2008 14:15 GMT You asked about accessing the window via API, but I wonder if you might prefer going through the document since you want to scroll the page. There are at least two ways I know of to get the document object. From there you should be able to use document.body.scrolltop to get/set the scroll position.
Method 1: Set a reference to Microsoft Shell Controls and Automation. Get a collection of open IE and Explorer windows from Shell.Windows. Each of those is returned as an IE object. (Even the folders!) Use properties like LocationURL to find your window in a For/Each loop and then access the IE.document object.
Method 2: Given your parent window hWnd, use EnumChildWindows to find the subwindow of class "Internet Explorer_Server". That's the actual browser. Send that hWnd to the following function to return the document object. (This function works with any window of class "Internet Explorer_Server" at least as far back as Win98.)
Two notes: 1) You need to set a reference to mshtml.tlb for DOM ops and objects. 2)IE7 introduced tabs so that you may have multiple "Internet Explorer_Server" windows in your Enum. Likewise if the page has frames.
'--- function to return document object from hWnd -----
Type UUID Data1 as Long Data2 as Integer Data3 as Integer Data4(0 to 7) as Byte End Type
Private Const SMTO_ABORTIFHUNG = &H2 Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" (ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, lParam As Any, ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long Private Declare Function ObjectFromLresult Lib "oleacc" (ByVal lResult As Long, riid As UUID, ByVal wParam As Long, ppvObject As Any) As Long
Private Function GetIEDoc(ByVal H1 As Long, Success As Boolean) As IHTMLDocument Dim IID_IHTMLDocument2 As UUID Dim LMsg As Long, LRes As Long, LRet As Long, H2 As Long Success = False H2 = GetIEWindow(H1) If (H2 = 0) Then Exit Function
LMsg = RegisterWindowMessage("WM_HTML_GETOBJECT") LRet = SendMessageTimeout(H2, LMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, LRes) If LRes = 0 Then Exit Function
With IID_IHTMLDocument2 .Data1 = &H332C4425 .Data2 = &H26CB .Data3 = &H11D0 .Data4(0) = &HB4 .Data4(1) = &H83 .Data4(2) = &H0 .Data4(3) = &HC0 .Data4(4) = &H4F .Data4(5) = &HD9 .Data4(6) = &H1 .Data4(7) = &H19 End With
LRet = ObjectFromLresult(LRes, IID_IHTMLDocument2, 0, GetIEDoc) If LRet = 0 Then Success = True End Function
> Using VB6 and trying to interact with an instance of IE6. > [quoted text clipped - 3 lines] > > Thanks Jack B. Pollack - 03 Sep 2008 14:24 GMT > You asked about accessing the window via API, but I > wonder if you might prefer going through the document [quoted text clipped - 82 lines] > > > > Thanks Thanks for your reply. I'll try this when I get back from this evening. I'll post back if I have problems
mayayana - 03 Sep 2008 15:47 GMT One note on that. I had copied and pasted the function from my own code and later realized that it was connected with a specific project. Notice there's a call to GetIEWindow. That's calling an EnumChildWindows function to get the Internet Explorer_Server subwindow. (The incoming H1 parameter was an IE window hWnd.) I'm posting here a corrected version where the incoming H1 parameter is the hWnd of the Internet Explorer_Server subwindow:
Private Function GetIEDoc(ByVal H1 As Long, Success As Boolean) As IHTMLDocument Dim IID_IHTMLDocument2 As UUID Dim LMsg As Long, LRes As Long, LRet As Long Success = False
LMsg = RegisterWindowMessage("WM_HTML_GETOBJECT") LRet = SendMessageTimeout(H1, LMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, LRes) If LRes = 0 Then Exit Function
With IID_IHTMLDocument2 .Data1 = &H332C4425 .Data2 = &H26CB .Data3 = &H11D0 .Data4(0) = &HB4 .Data4(1) = &H83 .Data4(2) = &H0 .Data4(3) = &HC0 .Data4(4) = &H4F .Data4(5) = &HD9 .Data4(6) = &H1 .Data4(7) = &H19 End With
LRet = ObjectFromLresult(LRes, IID_IHTMLDocument2, 0, GetIEDoc) If LRet = 0 Then Success = True End Function
There's also more involved sample code, if you need it, here. (It's part of a Shell Object/ ShellFolderView package of sample code.) :
www.jsware.net/jsware/vbcode.php5#shlop
> > '--- function to return document object from hWnd ----- > > [quoted text clipped - 57 lines] > Thanks for your reply. I'll try this when I get back from this evening. I'll > post back if I have problems Jack B. Pollack - 04 Sep 2008 01:09 GMT As you suspected, I am still having problems with the function GetIEDoc Wahat doed your EnumChildWindows function look like?
Thanks again
> One note on that. I had copied and pasted the function > from my own code and later realized that it was connected [quoted text clipped - 104 lines] > I'll > > post back if I have problems mayayana - 04 Sep 2008 03:07 GMT > As you suspected, I am still having problems with the function GetIEDoc > Wahat doed your EnumChildWindows function look like? You can see it all in the download I linked, though that project also has a few other things going on. EnumChildWindows uses a callback, so it's a bit awkward. In the following example I use two public variables that are visible from both the enum function and the callback function:
Public HCur As Long Public sClassName As String
You also need these declares:
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, lParam As Long) As Long
Then, assuming that you have an IE hWnd, you use the following to get the actual browser window from it:
Private Function GetIEServerWindow(ByVal H1 As Long) Dim LRet As Long HCur = 0 GetIEServerWindow = 0 sClassName = "Explorer_Server" ' "Internet Explorer_Server" LRet = EnumChildWindows(H1, AddressOf EnumChildProc, 0) GetIEServerWindow = HCur '-- either 0 or handle of browser. End Function
Public Function EnumChildProc(ByVal hWnd As Long, lParam As Long) As Long Dim s2 As String s2 = GetWinClass(hWnd) If InStr(1, s2, sClassName, 1) > 0 Then HCur = hWnd EnumChildProc = 0 Else EnumChildProc = 1 End If End Function
Those two functions work together. You send the IE hWnd into GetIEServerWindow, which calls EnumChildWindows on that. EnumChildProc is the callback function. EnumChildWindows will call EnumChildProc for each child window. EnumChildProc then gets the class name of that window. If the class name is "Internet Explorer_Server" it sets the public HCur to the hWnd of that window and returns 0, causing the enum to quit. Otherwise it returns 1, signaling the enum to continue. By the time it's done hCur is either a browser window hWnd or 0, if there was no I E_Server window in the hierarchy.
The following shows getting the class name of a window from the hWnd:
Public Function GetWinClass(ByVal H1 As Long) As String Dim sBuf As String Dim LRet As Long On Error Resume Next GetWinClass = "" sBuf = String$(256, 0) LRet = GetClassName(H1, sBuf, Len(sBuf)) If (LRet > 0) Then GetWinClass = Left$(sBuf, LRet) End Function
So you send the IE hWnd to GetIEServerWindow and if non-zero is returned then you send that to GetIEDoc. That then returns a document object and you're "ready to roll". :)
I'm assuming you have an IE hWnd to start. If not you'll need to use Shell Object or basic top-level window enumeration to get it.
If this all seems confusing you might try starting IE and then running Spy++. That will let you see the window hierarchy and see how the actual browser that has the document, Internet Explorer_Server, is not the top-level window. I think something like "IEFrame" is the class name of the top window with the chrome.
Jack B. Pollack - 04 Sep 2008 13:31 GMT > > As you suspected, I am still having problems with the function GetIEDoc > > Wahat doed your EnumChildWindows function look like? [quoted text clipped - 81 lines] > top-level window. I think something like "IEFrame" is > the class name of the top window with the chrome. Thanks. Think I got it.
|
|
|