From: Mike Williams on 22 Sep 2009 07:43 "Eduardo" <mm(a)mm.com> wrote in message news:h9a43e$l6s$1(a)aioe.org... > I've been playing with the code... >> then it fails to work if the >> WebBrowser Control has the focus > It happens with some pages, so I had to leave > the command button. Have a look at the response I posted a couple of hours ago in which I posted a more detailed description of that problem and also a solution to it, which is a simple case of setting the focus to another control (the PictureBox in this case) at the top of the routine that creates the bitmap and setting it back again (if necessary) immediately afterwards. > Here is my last code, that saves the page with > its actual size: Thanks. That looks extremely interesting Eduardo. I see that you have obtained the size of the page using the WebBrowser.Document property, which is something I mentioned in a recent response to Shotgun Thom in which I told him I didn't actually know how to do that using the WebBrowser.Docuement properties but that it was probably something similar to the way Olaf did it (using a browser Olaf had loaded in code) at the link I posted. As I've mentioned, I don't actually know anything about the WebBrowser (being interested in the graphics side of the OP's question myself) and your code to get the page size details from the VB6 WebBrowser Control is very interesting and I'll put it in my list of useful projects if you don't mind. > (I've found that there is a limit for control sizes, the max height > is 16383 pixels. The result is that too long pages are cut.) Yes. That's not a problem as far as the PictureBox is concerned though because you can always ditch the PictureBox and instead create a DC and a bitmap to put into it (CreateCompatibleDC and CreateCompatibleBitmap). This will allow you to create screen width bitmaps much more than 16,383 pixels high, in fact more than 100,000 pixels high even on modest machines. If that isn't enough then you can create even larger bitmaps if you use DIBSections instead of screen compatible bitmaps. I'm not sure whether DIBSections would work with the WM_PAINT etc messages, but even if they don't a 100,000 pixel high screen compatible bitmap is enough for even very long web pages, and there are always other ways of getting around such things if it is not. The VB6 WebBrowser Control would probably present a problem though, because that too is limited to 16383 pixels, although I imagine you could get around that one (if it actually was a problem) by creating a browser in code as in Olaf's suggestion in the thread I was involved in a few years ago (see my previous post for details of that one). Not that 16383 pixels would present a problem for most web pages of course, but there would appear to be a solution if there are some web pages you need to get that are larger than that. Mike
From: Mike Williams on 22 Sep 2009 08:12 "Schmidt" <sss(a)online.de> wrote in message news:%23HJH$j3OKHA.1876(a)TK2MSFTNGP06.phx.gbl... > :-) ... glad you digged that older post out again. Just > copied the code over into a Form, after putting a > reference to Eduardos OleLib into the test-project - > and it yet works here on two XP-machines (having > IE6 installed), even against such "Monster-URLs" as > slashdot.org, resulting in a Bitmap of about > 800 x 11000 pixels. If that works also on newer > OS-versions (with an actual IE), then it should be > wrappable also in a small ActiveX-Dll . . . Would be > nice, if somebody with a Vista-system could > test the code too and confirm if it works - or not. Thanks for the info, Olaf. I had only a vague memory in my head about being involved in a similar thread three years ago, and it's sheer luck really that I managed to Google my way to it, especially now that the Google Groups archive seems to have gone belly up. The only machine I've got access to at the moment is my own desktop, a Vista Home Premium with IE8 installed. I've just pasted the code into a project (with the required reference to olelib.tlb) and it works fine. It renders an image of 800 x 5943 pixels from slashdot.org on my machine, but it seems to contain the full page. I'm glad I dug it out now. Looks really interesting. If I get time later I'll try it on my laptop (a more lowly machine but with Vista Business installed, although I can't remember offhand what version of IE it has). It might be some time though because all this digging into things I don't know about (browsers and stuff) is making my head spin ;-) Mike
From: Schmidt on 22 Sep 2009 08:32 "Mike Williams" <Mike(a)WhiskyAndCoke.com> schrieb im Newsbeitrag news:%23A7RH43OKHA.352(a)TK2MSFTNGP02.phx.gbl... > "Schmidt" <sss(a)online.de> wrote in message > news:%23HJH$j3OKHA.1876(a)TK2MSFTNGP06.phx.gbl... > >. . . Would be nice, if somebody with a Vista-system could > > test the code too and confirm if it works - or not. > > It renders an image of 800 x 5943 pixels from slashdot.org on > my machine, but it seems to contain the full page. I'm glad > I dug it out now. Looks really interesting. Thanks for the "Vista-check"... Just for others who want to adapt the code to their needs... All the Controls.Add-stuff (used for the PicBox-Buffer and the IE-Control) can be omitted of course - you can also place these Controls "normally" on a Form and work with the normal Event-Handlers of the Controls - that was just, to make the Form-Code more "Copy'nPaste-friendly". The main-lines of interest (avoiding all the WM_Paint-stuff) are probably the somewhat "enhanced" Document-Complete- Event-Handling: If Info.Name = "DocumentComplete" Then IEExt.Tag = "DC" '<--just set a Flag here and do nothing End If If Info.Name = "ProgressChange" Then If IEExt.Tag = "DC" And Info.EventParameters.Item(0).Value = 0 Then IEExt.Tag = "" '<-- reset the Flag now within ProgressChange-Event Me.Caption = "Document complete - now we start rendering!" ....translated into "normal EventHandling-Code" that means, that one has to set a Flag (I used the Tag-Property) - and wait for an additional Event - ProgressChange - (after setting the DocComplete-Flag) to occur - if the First Param of ProgressChange is Zero, then the Document is "really complete" (involving the loading of SubFrames from additional URLs on that page - stuff like that). Then one can start the copying of the fully rendered Document with a ClassType, defined in Eduardo Morcillos Typelib: Dim ViewObject As IViewObject2 '...after adjusting some Rectangle-Structs .... Set ViewObject = IE.Document 'just do a ObjType-Cast here ViewObject.Draw 1, -1, ByVal 0&, ByVal 0&, BBuf.hdc, _ BBuf.hdc, Rct, Rct, ByVal 0&, 0 So, the ViewObject.Draw-Method does the copy-over in that approach - not that dependent then on Win-Paint-Messages. That's it basically. Olaf
From: Eduardo on 22 Sep 2009 11:56 Mike Williams escribi�: >> Here is my last code, that saves the page with >> its actual size: > > Thanks. That looks extremely interesting Eduardo. I see that you have > obtained the size of the page using the WebBrowser.Document property, > which is something I mentioned in a recent response to Shotgun Thom in > which I told him I didn't actually know how to do that using the > WebBrowser.Docuement properties but that it was probably something > similar to the way Olaf did it (using a browser Olaf had loaded in code) > at the link I posted. As I've mentioned, I don't actually know anything > about the WebBrowser (being interested in the graphics side of the OP's > question myself) and your code to get the page size details from the VB6 > WebBrowser Control is very interesting and I'll put it in my list of > useful projects if you don't mind. I took ideas from this code: http://web.archive.org/web/20040615094139/msdn.microsoft.com/workshop/author/dhtml/reference/methods/getclientrects.asp >> (I've found that there is a limit for control sizes, the max height >> is 16383 pixels. The result is that too long pages are cut.) > > Yes. That's not a problem as far as the PictureBox is concerned though > because you can always ditch the PictureBox and instead create a DC and > a bitmap to put into it (CreateCompatibleDC and CreateCompatibleBitmap). > This will allow you to create screen width bitmaps much more than 16,383 > pixels high, in fact more than 100,000 pixels high even on modest machines. > > If that isn't enough then you can create even larger bitmaps if you use > DIBSections instead of screen compatible bitmaps. I'm not sure whether > DIBSections would work with the WM_PAINT etc messages, but even if they > don't a 100,000 pixel high screen compatible bitmap is enough for even > very long web pages, and there are always other ways of getting around > such things if it is not. > > The VB6 WebBrowser Control would probably present a problem though, > because that too is limited to 16383 pixels, Yes, it's also limited (all the controls must limited in the same way, I suppose), and we need it displaying all the area that we need to print (if I make the control shorter than the page, it just prints the part that is displayed in the webbrowser). So it's a problem, but just if it's going to be used with large pages. > although I imagine you > could get around that one (if it actually was a problem) by creating a > browser in code as in Olaf's suggestion in the thread I was involved in > a few years ago (see my previous post for details of that one). It seems to be a more professional approach, without the need of a webbrowser control.
From: Shotgun Thom on 22 Sep 2009 15:16
On Sep 22, 2:06 am, Eduardo <m...(a)mm.com> wrote: > I've been playing with the code... > > > then it fails to work if the > > WebBrowser Control has the focus > > It happens with some pages, so I had to leave the command button. > > Here is my last code, that saves the page with its actual size: > > (I've found that there is a limit for control sizes, the max height is > 16383 pixels. The result is that too long pages are cut.) > > Option Explicit > > Private Declare Function SendMessage Lib "user32" Alias _ > "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _ > ByVal wParam As Long, ByVal lParam As Long) As Long > Private Declare Function GetWindow Lib "user32" _ > (ByVal hwnd As Long, ByVal wCmd As Long) As Long > Private Declare Function GetClassName Lib "user32" _ > Alias "GetClassNameA" (ByVal hwnd As Long, _ > ByVal lpClassName As String, ByVal nMaxCount As Long) _ > As Long > Private Declare Function GetSystemMetrics Lib "user32" _ > (ByVal nIndex As Long) As Long > > Private Const WM_PAINT = &HF > Private Const WM_PRINT = &H317 > Private Const PRF_CHILDREN = &H10& > Private Const PRF_CLIENT = &H4& > Private Const PRF_OWNED = &H20& > Private Const GW_CHILD = 5 > Private Const GW_HWNDNEXT = 2 > Private Const SM_CXVSCROLL = 2 > > Private Sub Form_Load() > Picture1.BorderStyle = vbBSNone > Picture1.AutoRedraw = True > Picture1.Visible = False > Me.ScaleMode = vbTwips > WebBrowser1.Navigate "http://www.yahoo.co.uk" > Caption = "Loading page . . ." > End Sub > > Private Sub SaveWebBrowserPicture() > Dim myWindow As Long, childWindow As Long > Dim myClass As String, clsName As String * 256 > Dim s1 As String > Dim iP As IPicture > > Command1.SetFocus > myClass = "Shell Embedding" > childWindow = GetWindow(Me.hwnd, GW_CHILD) > Do > GetClassName childWindow, clsName, 256 > If Left$(clsName, Len(myClass)) = myClass Then > myWindow = childWindow > Exit Do > End If > childWindow = GetWindow(childWindow, GW_HWNDNEXT) > Loop While childWindow <> 0 > If myWindow <> 0 Then > SendMessage myWindow, WM_PAINT, Picture1.hDC, 0 > SendMessage myWindow, WM_PRINT, Picture1.hDC, _ > PRF_CHILDREN + PRF_CLIENT + PRF_OWNED > > Set iP = Picture1.Image > Picture1.Cls > Picture1.Width = Picture1.Width - ScaleX(4, vbPixels, vbTwips) > Picture1.Height = Picture1.Height - ScaleY(4, vbPixels, vbTwips) > Picture1.PaintPicture iP, 0, 0, , , ScaleX(2, vbPixels, vbTwips), _ > ScaleY(2, vbPixels, vbTwips) > > Picture1.Picture = Picture1.Image > s1 = "d:\webpic1.bmp" ' or whatever is required > SavePicture Picture1.Picture, s1 > Caption = "Web page saved as " & s1 > End If > End Sub > > Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As _ > Object, URL As Variant) > Dim iWidth As Long > Dim iHeight As Long > > If URL = WebBrowser1.LocationURL Then > iWidth = WebBrowser1.Document.Body.scrollWidth > If iWidth < 800 Then iWidth = 800 > iWidth = iWidth + GetSystemMetrics(SM_CXVSCROLL) + 4 > iHeight = WebBrowser1.Document.Body.scrollHeight > If iHeight < 600 Then iHeight = 600 > iHeight = iHeight + 4 > > WebBrowser1.Move 0, 0, ScaleX(iWidth, vbPixels, _ > vbTwips), ScaleY(iHeight, vbPixels, vbTwips) > Picture1.Move 0, 0, WebBrowser1.Width - _ > ScaleX(GetSystemMetrics(SM_CXVSCROLL), _ > vbPixels, vbTwips), WebBrowser1.Height > > SaveWebBrowserPicture > End If > End Sub Perfect, Eduardo. That's exactly what I was looking for in regards to sizing. Thank you! Tom |