We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Is there any way to create an 'image' of a website?

Medium Priority
512 Views
Last Modified: 2007-12-19
Hi,
this is going in the languages section, as I'm using c# (so a solution in that would be ideal) but I think any relevant programming is more low-level so c/c++ stuff would be useful as well.
Right, I need a way to take a url and return an image - as in a Bitmap.
This is driving me crazy - is there actually any way?

I've looked into creating an instance of Internet Explorer (SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorerClass();)
and capturing the screen...

int hWindowDC, hOffscreenDC, hBMP, hBMPOld, r;
const int SRCCOPY = 13369376;
hWindowDC = GetWindowDC(hWnd);
hOffscreenDC = CreateCompatibleDC(hWindowDC);
hBMP = CreateCompatibleBitmap(hWindowDC, 800, 600);
hBMPOld = SelectObject(hOffscreenDC, hBMP);
r = BitBlt(hOffscreenDC, 0, 0, 800, 600, hWindowDC, 0, 0, SRCCOPY);
hBMP = SelectObject(hOffscreenDC, hBMPOld);
r = DeleteDC(hWindowDC);
r = DeleteDC(hOffscreenDC);
Bitmap ret = Image.FromHbitmap(new IntPtr(hBMP));
DeleteObject(hBMP);
ret.Save("C:\\capturescreentest.bmp");

but this really isn't the ideal approach - for one I don't want the explorer window on top, which is of course vital if I'm capturing the screen. Is there any way I can do it 'behind the scenes'? Is there any way to do it without opening internet explorer for that matter?

Thanks for your time.
Comment
Watch Question

Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
If that doesn't work, the MSDN web site also mentions a WM_PRINT message that takes the same arguments.  MSDN documents it exactly the same way, so I'm not sure what the difference is.

Author

Commented:
ah, ok, since I posted I have changed to using a WebBrowser control like you said.
The code I have is a Form which conatins a WebBrowser control.  The browser is navigated to a url, and when the DownloadComplete Event happens, I want to capture the screen.
This WM_PRINT stuff appears to be exactly what I'm looking for so thank you, but I'm unsure how to implement it in C#.
I've looked at http://www.fengyuan.com/article/wmprint.html and worked out the following code...

Graphics grfxScreen = Graphics.FromHwnd(hWnd);
MyBitmap = new Bitmap((int) this.Width, (int) this.Height, grfxScreen);
Graphics grfxBitmap = Graphics.FromImage(MyBitmap);
IntPtr hdcBitmap = grfxBitmap.GetHdc();
Message printClientMessage = Message.Create(hWnd, WM_PRINTCLIENT, hdcBitmap, new IntPtr(PRF_CHILDREN | PRF_CLIENT));  
DefWndProc(ref printClientMessage);

However, as the article in the link above says, this only gets a blank screen.  The article shows how to add/change code to OnPaint and LRESULT CALLBACK WndProc0, but I have no idea how to do this in C#.

Any ideas?
Cheers.

If anyone comes up with the appropriate c# code by the way (I can't imagine it'd be too hard to translate using the above link) I'd be more than happy to increase the points - I can sense the answer getting closer!

Commented:
Take a look at the following URL.  Not sure, but it sounds like it might address some of your questions.

http://www.codeproject.com/csharp/ImageCapture.asp?target=image%7Ccapture

Author

Commented:
No, this demonstrates the techniques I know about - using BitBlt to capture screen.
The WM_PRINT stuff is definitely the way to go... if I can get it working, but thanks anyway.

Incidentally, I now have...

protected override void WndProc(ref Message m)
{
      switch ((Win32.Msgs)m.Msg)
      {
            case Win32.Msgs.WM_PRINTCLIENT:
                  SendMessage(m.HWnd, m.Msg, m.WParam, m.LParam);
                  break;

            case Win32.Msgs.WM_PAINT:
// Not sure if following two commented out lines would achieve the same result or not - they'd probably be better, because they use c# graphics instead of c++ pointers, but don't know
                  //Graphics g = Graphics.FromHdc(m.WParam);
                  //OnPaint(new PaintEventArgs(g, g.ClipBounds));
                  OnPaint(m.HWnd,m.WParam);
                  break;

            default:
                  // unhandled window message
                  base.WndProc(ref m);
                  break;
      }
}

I then need to have an OnPaint method - but this is where I get stuck in the translation to C# - any ideas? The C++ version from the article on that link I mentioned in a previous comment is...

void OnPaint(HWND hWnd, WPARAM wParam)
{
    PAINTSTRUCT ps;
    HDC         hDC;
    if ( wParam==0 )
        hDC = BeginPaint(hWnd, & ps);
    else
        hDC = (HDC) wParam;
    OnDraw(hWnd, hDC);
    if ( wParam==0 )
        EndPaint(hWnd, & ps);
}

What's the C# equivalent for OnDraw? And can I rewrite this Onpaint method if it takes a PaintEventArgs such as that from my commented out code in the WndProc method?
The article you're referring to looks neat, but I think that stuff is too low-level to implement in C#.  Not knowing C# myself, though, I can't say for sure and I'm afraid I can't be a lot of help with such stuff.  Even if you do get it to work, though, the article says it doesn't work in Win95/98/ME, so that's something to beware of.

If you need more help, try posting another question, maybe in the .NET area.

Author

Commented:
Hi,

I've just cracked it! I created a separate message to deal with what I thought was a separate issue, but it all ties in really, so if anyone's interested, see...
https://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_20939542.html
The actual capturing of a screen hidden from view is done using WM_PRINT, and I think my code for that is on the other message thread as well. For some reason it wouldn't work when converted it to C# graphics, so I just used lots of dllimports. The only other issue (which kept me frustrated for a VERY long time) was that even when every event signified that the browser had finished downloading, painting etc, there was a slight time lag between the final events firing and the screen being suitable for capture. All this is on the other message thread.

Thanks for all the help - I don't think I would have ever found out about WM_PRINT otherwise (I'm on a steep learning curve). Cheers.
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.