Question: Saving form as jpeg or gif automatically

V

VB Programmer

Briefly, how do you save the current form to a jpeg or gif?

Details: I have a form with a speedometer control on it. It continually
loops through a table in a db that has different current "speeds". I want
to "set" the speedometer to the current speed, then save the form as a
picture, then go to the next one, etc... The end result would be a gif or
jpeg that has a "snapshot" of the gauge. (This would eventually show up on
a aspx webform in an image control.)

Any ideas?

Thanks!
 
F

Fergus Cooney

Hi VBP

The code below will capture the given Control's imagery and return a
BitMap.

You can the use bmp.Save (sFilePath, Imaging.ImageFormat.Whatever)

Credit to Armin for this one - I think I got it from one of his posts
elsewhere.

Regards,
Fergus

<code>
Public Declare Function BitBlt Lib "gdi32" ( _
ByVal hDestDC As IntPtr, _
ByVal x As Integer, _
ByVal y As Integer, _
ByVal nWidth As Integer, _
ByVal nHeight As Integer, _
ByVal hSrcDC As IntPtr, _
ByVal xSrc As Integer, _
ByVal ySrc As Integer, _
ByVal dwRop As Integer _
) As Integer

'===================================================================
Public Function CaptureControl(ByVal c As Control) As Bitmap

Dim bmp As Bitmap
Dim gDest, gSource As Graphics
Dim hdcSource, hdcDest As IntPtr

bmp = New Bitmap(c.Width, c.Height)

gSource = c.CreateGraphics
Try
gDest = Graphics.FromImage(bmp)
Try
hdcSource = gSource.GetHdc
Try
hdcDest = gDest.GetHdc
Try
BitBlt( _
hdcDest, 0, 0, _
c.Width, c.Height, _
hdcSource, 0, 0, SRCCOPY _
)
Finally
gDest.ReleaseHdc(hdcDest)
End Try
Finally
gSource.ReleaseHdc(hdcSource)
End Try
Finally
gDest.Dispose()
End Try
Finally
gSource.Dispose()
End Try

Return bmp
End Function
</code>
 
V

VB Programmer

3 quick questions...

I put a button on my winform and tried to call your CaptureControl function
but it kept giving me a "Invalid parameter used" error (unhandled exception
in system.drawing.dll) for the Dim line. Here's the code:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim x As New Bitmap("zzz.bmp")
x = CaptureControl(Me)
End Sub

1. Any ideas? Am I invoking this correctly?
2. Also, it says I have to declare SRCCOPY. Do I just declare it as an
integer?
3. What is BitBlt? I don't see any code? Where is the code?

Thanks.
 
F

Fergus Cooney

Hi VBP,

Sorry, I forgot to copy SRCCOPY across.
Const SRCCOPY As Integer = &HCC0020

BitBlt is part of the WinApi, specifically the GDI dll.
This is shown by the declaration:
Public Declare Function BitBlt Lib "gdi32" ( ...) As Integer
The Declare part tells the compiler that there's going to be mention of a
function BitBlt but that the code isn't going to be given at this time. The
Lib "gdi32" part tells it to find the actual routine externally.

Try this.
Dim x As New Bitmap 'Just to say that you want a BitMap
x = CaptureControl(Me)
x.Save ("zzz.bmp", Imaging.ImageFormat.Bmp)

Regards,
Fergus
 
H

Herfried K. Wagner [MVP]

VB Programmer said:
Details: I have a form with a speedometer control on it. It continually
loops through a table in a db that has different current "speeds". I want
to "set" the speedometer to the current speed, then save the form as a
picture, then go to the next one, etc... The end result would be a gif or
jpeg that has a "snapshot" of the gauge. (This would eventually show up on
a aspx webform in an image control.)

<http://www.mvps.org/dotnet/dotnet/samples/windowsandforms/downloads/Screenshot.zip>
 
H

Herfried K. Wagner [MVP]

Fergus Cooney said:
function BitBlt but that the code isn't going to be given at this time. The
Lib "gdi32" part tells it to find the actual routine externally.

Try this.
Dim x As New Bitmap 'Just to say that you want a BitMap

I still don't understand why you declare 'x' as 'New Bitmap'.
 
F

Fergus Cooney

Hi Herfried,

Got to keep that garbage collector on its toes!! ;-)

VBP had this.
Dim x As New Bitmap("zzz.bmp")

I took off the (..) but forgot to remove the New too.

Regards,
Fergus
 
V

VB Programmer

Something weird is happening. It captures whatever is directly BEHIND the
control, rather than the control itself. For example, if I launch it using
Windows Explorer a jpg will be create but it will be of a portion of
Explorer (directly behind the control, and the same size)!

Any ideas?

Here's how I call the capture code (just test code)...
Dim MyBitmap As Bitmap
MyBitmap = CaptureControl(grpGauge)
MyBitmap.Save("c:\zzzz.jpeg", Imaging.ImageFormat.Jpeg)

Here is the CaptureControl code...
Public Declare Function BitBlt Lib "gdi32" ( _
ByVal hDestDC As IntPtr, _
ByVal x As Integer, _
ByVal y As Integer, _
ByVal nWidth As Integer, _
ByVal nHeight As Integer, _
ByVal hSrcDC As IntPtr, _
ByVal xSrc As Integer, _
ByVal ySrc As Integer, _
ByVal dwRop As Integer _
) As Integer

Public Function CaptureControl(ByVal c As Control) As Bitmap
Dim bmp As Bitmap
Dim gDest, gSource As Graphics
Dim hdcSource, hdcDest As IntPtr
Const SRCCOPY As Integer = &HCC0020
bmp = New Bitmap(c.Width, c.Height)

gSource = c.CreateGraphics
Try
gDest = Graphics.FromImage(bmp)
Try
hdcSource = gSource.GetHdc
Try
hdcDest = gDest.GetHdc
Try
BitBlt( _
hdcDest, 0, 0, _
c.Width, c.Height, _
hdcSource, 0, 0, SRCCOPY _
)
Finally
gDest.ReleaseHdc(hdcDest)
End Try
Finally
gSource.ReleaseHdc(hdcSource)
End Try
Finally
gDest.Dispose()
End Try
Finally
gSource.Dispose()
End Try
Return bmp
End Function
 
V

VB Programmer

NM I think the problem is that the first set of code was in Form_load rather
than being called from a button. When I did this it worked. Don't
understand it yet, but, oh well... it works!
 
F

Fergus Cooney

Hi VBP,

There will only be background visible during Form_Load because the Form
hasn't been shown yet. This happens when Form_Load returns. You can, however,
call Me.Show explicitly within Form_Load - and then do your capture. You might
have to add a Me.Refresh too, I haven't tested it.

Regards,
Fergus
 
H

Herfried K. Wagner [MVP]

* "VB Programmer said:
NM I think the problem is that the first set of code was in Form_load rather
than being called from a button. When I did this it worked. Don't
understand it yet, but, oh well... it works!

You can only capture visible parts of the window. If the window isn't
visible ('Form_Load'), it won't be captured.
 
V

VB Programmer

Quick question....

This seems to work well if the form has the focus. But, if I switch to
another application the images that are captured are in the correct
"location", but the picture is of whatever application has the focus. Any
ideas on how to FORCE the capture on the correct form?

Thanks!
 
F

Fergus Cooney

Hi VBP,

Do you mean that the 'focus' application (or some other window) is lying
across the capture area and thus getting picked up?

I believe that this capture works by going to the screen bitmap, so it
doesn't actually care about who's who and what's what. I think it's just a
dumb 'Gimme a Rect, I'll give you some bits' type of operator.

I imagine that you'll have to get that target window out from under before
doing the capture.

Let me know if I'm wrong though, this is the kind of thing where that
would be useful. ;-)

Regards,
Fergus
 
V

VB Programmer

You are exactly right Fergus.

This application is going to continuously run on a PC. Which means I would
preferably like it to run in the background so I can do other things. Any
ideas how I can get around it? I tried to "Active" the form before I
captured it, but this doesn't work too well.

Thanks!!!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top