Capture a hidden window without making it top level?

thomas10001

Well-known member
Joined
Jun 22, 2003
Messages
57
Location
Samoa & Sweden
I need to capture the image of a hidden window. Can this be done without making it the top level window?


(I have already code to capture an image of the top level window. But that involves a lot of hiding and showing windows and creates problem with flickering and that the whole area is not redrawn and I do not always capture what I want.)
 
Ill tell you what I know, which isnt much.

In Windows generally the image for a window is only that which is stored on the screen, which means that if all or part of a window isnt visible, the image for the concealed portion does not exist. There must be a way, however, to have a form draw itself somewhere other than the screen because Microsoft offers an alt-tab replacement program which shows the image of the window you are tabbing to, even if it isnt visible (or completely visible).
 
Everyone uses bitblt, but there is the printWindow API too (which works for off-screen and hidden forms). One thing that you cant do though is create a form that is bigger than the available working screen space.

Code:
    Private Declare Function PrintWindow Lib "user32.dll" (ByVal _
               hwnd As IntPtr, ByVal hdcBlt As IntPtr, ByVal nFlags As _
               UInt32) As Boolean
    Dim WithEvents t As New Timer

    Dim screenCapture As Bitmap
    Dim otherForm As New Form

    Private Sub CaptureScreen()
        Me.Text = "capturing, " & Me.Location.X & "," & Me.Location.Y
        screenCapture = New Bitmap(Me.Width, Me.Height)
        Dim g As Graphics = Graphics.FromImage(screenCapture)
        Dim hdc As IntPtr = g.GetHdc
        Form1.PrintWindow(Me.Handle, hdc, Nothing)
        g.ReleaseHdc(hdc)
        g.Flush()
        g.Dispose()

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
         uncomment to test capturing various hidden forms:

        1- hidden off screen -> works!
        Me.Location = New Point(-500, -500)

        2- Minimizes - works but just takes a capture of the small minimized form...
        Me.WindowState = FormWindowState.Minimized

        3- big form laid over the top
        otherForm.Size = New Size(4000, 4000)
        otherForm.Show()

        t.Interval = 1000
        t.Start()
    End Sub



    Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
        CaptureScreen()
        If IO.File.Exists("C:\\ScreenCapBlah.bmp") Then
            IO.File.Delete("C:\\ScreenCapBlah.bmp")
        End If
        screenCapture.Save("c:\\ScreenCapBlah.bmp")
        Me.Text = ""

        1 - move the form back
         Me.Location = New Point(0, 0)

        2- maximize again
         Me.WindowState = FormWindowState.Maximized

        3 - hide otherForm
        otherForm.Hide()
        t.Stop()
    End Sub
 
Last edited by a moderator:
PrintWindow

It seems that I should use PrintWindow

I found the following code that I modified a bit.

public static Bitmap captureHiddenWindow(IntPtr hwnd)
{
Bitmap bitmap = null;

// Takes a snapshot of the window hwnd, stored in the memory device context hdcMem
IntPtr hdc = PlatformInvokeGDI32.GetWindowDC(hwnd);
if (hdc != IntPtr.Zero)
{
IntPtr hdcMem = PlatformInvokeGDI32.CreateCompatibleDC(hdc);
if (hdcMem != IntPtr.Zero)
{
Rectangle rc;
PlatformInvokeGDI32.GetWindowRect(hwnd,out rc);
IntPtr hbitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hdc, rc.Width, rc.Height);
if (hbitmap != IntPtr.Zero)
{
PlatformInvokeGDI32.SelectObject(hdcMem, hbitmap);
Win32.PrintWindow(hwnd, hdcMem, 0);
bitmap = System.Drawing.Image.FromHbitmap(hdcMem);
PlatformInvokeGDI32.DeleteObject(hbitmap);
}
PlatformInvokeGDI32.DeleteObject(hdcMem);
}
PlatformInvokeGDI32.ReleaseDC(hwnd, hdc);
}
return bitmap;
}



I added the bitmap = System.Drawing.Image.FromHbitmap(hdcMem);
because I need a bitmap returned. I got an exception when I tried it due
to (I guess) hdcMem was negative. What do I do wrong here?

Is there another way to use the dc that I am not aware of?
 
Back
Top