Recently, when I was writing a program, I suddenly felt that Google Chrome's webpage thumbnail is quite fun, But Chrome is its own kernel. Of course its own things are convenient. What should I do with webbrowser?
The first thing that comes to mind is the most common screen replication, that is, the well-known bitblt, which is replicated from the DC of webbrowser to the DC of Bitmap. this method has many limitations: 1. to copy the image correctly, make sure that the webbrowser is at the front of the window (that is, there is no shadow) When copying the screen. Otherwise, the copied image has a shadow. 2. even if there is no cover, the copied images often contain 3d border and scroll, which is necessary in the standard webbrowser. however, for thumbnail photos on webpages, this is disgusting.
So some people think of an iviewobject2 interface in ActiveX, and webbrowser also implements this interface. You only need to query interface (...) from the webbrowser object (...) you can enumerate this interface. iwebbrowser2 * pwb2 =... // obtain the webbrowser interface, pwb2-> QueryInterface (iid_iviewobject2, (void **) & pviewobj2); then, you can use the draw method in iviewobject2 to paint the content of the web page in webbrowser, well, you can draw a window even if it is hidden. However, if you try this method, you will find that this is still unsatisfactory. because you can only get the page thumbnails of the webbrowser window, but cannot get the thumbnail of the entire page. meanwhile, 3D border and Scroll still torture us. someone proposed the following code, which can be mitigated to some extent. Let's take a look:
Ihtmlbodyelement * pbody = 0; <br/> ihtmlelement * pbodyelem; <br/> hrtest_e (gethtmldocument2 ()-> get_body (& pbodyelem )); <br/> hrtest_e (pbodyelem-> QueryInterface (iid_ihtmlbodyelement, (void **) & pbody); </P> <p> ihtmlstyle * pstyle; <br/> hrtest_e (pbodyelem-> get_style (& pstyle); <br/> hrtest_e (pstyle-> put_borderstyle (bsborderstyle = :: sysallocstring (L "NONE"); </P> <p> // hide scrollbars <br/> hrtest_e (pbody-> put_scroll (bsscrollstyle = :: sysallocstring (L "no"); <br/> // resize the browser component to the size of the HTML content <br/> ihtmlelement2 * pbodyelement2; <br/> hrtest_e (pbody-> QueryInterface (iid_ihtmlelement2, (void **) & pbodyelement2); <br/> long iscrollwidth = 0; <br/> hrtest_e (pbodyelement2-> get_scrollwidth (& iscrollwidth); <br/> long iscrollheight = 0; <br/> hrtest_e (pbodyelement2-> get_scrollheight (& iscrollheight); <br/> rect rc = {0, iscrollwidth, iscrollheight}; <br/> :: setwindowpos (gethwnd (), null, 0, 0, iscrollwidth, iscrollheight, swp_noredraw); <br/> setwebrect (& rc );
Ignoring the strange macro, we can find that this idea is to use the body to close border and scroll, which is useful in some cases, but in most cases, if the page is too large (such as exceeding the screen size), scroll will still appear. border will not disappear because it has nothing to do with the body element.
Is there really no solution? Of course, otherwise I will not write so many things. There is a well-known good thing. Interface: idochostuihandler. He has a method: gethostinfo (dochostuiinfo * pinfo ); you can change the webbrowser display mode. there is no need to use the body to close the thankless methods like border and scroll. to remove border, we only need to write scroll as follows:
Hresult <br/> cshadowwebwindow: gethostinfo (dochostuiinfo * pinfo) <br/>{< br/> pinfo-> cbsize = sizeof (dochostuiinfo ); <br/> pinfo-> dwflags = dochostuiflag_dialog | <br/> dochostuiflag_theme | <br/> dochostuiflag_no3dborder | <br/> success; <br/> return s_ OK; <br/>}
Here, dochostuiflag_no3dborder and dochostuiflag_scroll_no are exactly what we need. Next we need to draw the entire web page. We only need to set the container size of webbrowser to the HTML size, so that we can draw a thumbnail of the web page.
Of course, we strongly recommend that you use an invisible webbrowser to implement page thumbnails. After all, a window is too large or small, which is not a good user experience.
Finally, sort out the code:
I use the cshadowwebwindow class to implement webbrowser. This is an invisible window.
The following is the key code (ignore the strange macro)
Void <br/> cshadowwebwindow: documentcomplete (idispatch * Pdisp, variant * URL) <br/>{</P> <p> webbrowserwindow: documentcomplete (Pdisp, URL ); </P> <p> pwstr npwnewbmp filepath = NULL; <br/> iwebbrowser2 * pwb2 = getwebbrowser2 (); <br/> iviewobject2 * pviewobject2 = NULL; <br/> hrtest_e (pwb2-> QueryInterface (iid_iviewobject2, (void **) & pviewobject2); <br/> ihtmlelement * pbodyelem; <br/> hrtest_e (gethtmldocument2 () -> get_body (& pbodyelem); </P> <p> // resize the browser component to the size of the HTML content <br/> ihtmlelement2 * pbodyelement2; <br/> hrtest_e (pbodyelem-> QueryInterface (iid_ihtmlelement2, (void **) & pbodyelement2); <br/> long iscrollwidth = 0; <br/> hrtest_e (pbodyelement2-> get_scrollwidth (& iscrollwidth); <br/> long iscrollheight = 0; <br/> hrtest_e (pbodyelement2-> get_scrollheight (& iscrollheight); <br/> // adjust the webbrowser size to be the same as the webpage size <br/> rect rc = {0, 0, iscrollwidth, iscrollheight };< br/>: setwindowpos (gethwnd (), null, 0, 0, iscrollwidth, iscrollheight, swp_noredraw); <br/> setwebrect (& rc ); </P> <p> hbitmap =: createcompatiblebitmap (getdc (gethwnd (), rectwidth (RC), rectheight (RC); <br/> HDC hbitmapdc =:: createcompatibledc (getdc (gethwnd (); <br/>: SelectObject (hbitmapdc, hbitmap); </P> <p> rectl rctl = {RC. left, RC. top, RC. right, RC. bottom }; <br/> // draw the web content in webbrowser <br/> // gethwnd () return webbrowser container window handle <br/> hrtest_e (pviewobject2-> draw (dvaspect_content, 1, null, null,: getdc (gethwnd (), hbitmapdc, & rctl, null, null, 0); <br/> // write the BMP file <br/> bitmap stbitmap; <br/> pbyte npdata; <br/> DWORD dwdatasize; <br/> DWORD dwbmp datasize; <br/> handle hbmpfile; <br/> DWORD dwwritten; <br/> nulltest_e (: getobjectw (hbitmap, sizeof (stbitmap ), (pvoid) & stbitmap); <br/> nulltest_e (npdata = <br/> New byte [dwdatasize = (sizeof (bitmapfileheader) + sizeof (bitmapinfoheader) + (dwbmp datasize = (stbitmap. bmwidth * 8 + 31)/32) * 4 * stbitmap. bmheight * 3)]); </P> <p> bitmapfileheader * pbmpfileheader = (bitmapfileheader *) (npdata); <br/> pbmpfileheader-> bftype = 0x4d42; // "BM" <br/> pbmpfileheader-> bfsize = dwdatasize; // sizeof (bitmapfileheader) + sizeof (bitmapinfoheader) + 0 + dwbmp datasize; <br/> pbmpfileheader-> bfreserved1 = 0; <br/> pbmpfileheader-> bfreserved2 = 0; <br/> pbmpfileheader-> bytes = sizeof (bitmapfileheader) + sizeof (bitmapinfoheader) + 0; <br/> bitmapinfoheader * pbmpinfoheader = (bitmapinfoheader *) (npdata + sizeof (bitmapfileheader); <br/> pbmpinfoheader-> bisize = sizeof (bitmapinfoheader ); <br/> pbmpinfoheader-> biwidth = stbitmap. bmwidth; <br/> pbmpinfoheader-> biheight = stbitmap. bmheight; <br/> pbmpinfoheader-> biplanes = 1; <br/> pbmpinfoheader-> bibitcount = 24; <br/> pbmpinfoheader-> bicompression = bi_rgb; <br/> pbmpinfoheader-> bisizeimage = 0; <br/> pbmpinfoheader-> bixpelspermeter = 0; <br/> pbmpinfoheader-> biypelspermeter = 0; <br/> pbmpinfoheader-> biclrused = 0; <br/> pbmpinfoheader-> biclrimportant = 0; <br/> nulltest_e (: getdibits (hbitmapdc, hbitmap, 0, stbitmap. bmheight, npdata + sizeof (bitmapfileheader) + sizeof (bitmapinfoheader), (bitmapinfo *) (npdata + sizeof (bitmapfileheader), dib_rgb_colors )); </P> <p> // create a file and write the file <br/> valuetest_e (hbmpfile =: createfilew (L "E: // test.bmp", generic_write, 0, null, create_always, file_attribute_normal, null), invalid_handle_value); <br/> falsetest_e (: writefile (hbmpfile, npdata, dwdatasize, & dwwritten, null); <br/>:: closehandle (hbmpfile); </P> <p> return: <br/> deletearray (npwnewbmp filepath); <br/> return; <br/>}< br/> hresult <br/> cshadowwebwindow: gethostinfo (dochostuiinfo * pinfo) <br/>{< br/> pinfo-> cbsize = sizeof (dochostuiinfo ); <br/> pinfo-> dwflags = dochostuiflag_dialog | <br/> dochostuiflag_theme | <br/> dochostuiflag_no3dborder | <br/> success; <br/> return s_ OK; <br/>}
So far, we have implemented a snapshot (or thumbnail) of the web page ). it is comparable to Chrome's implementation. I hope to help you. I have seen such flaws on the Internet. The implementation in the next step should be a little more perfect. I hope it will help you.
If my article is helpful to you, please leave a message to express your feelings. This is a great encouragement to me. Thank you!