So I have this code:
Private Sub button28_Click(sender As Object, e As EventArgs) Handles button28.Click
Dim bounds As Rectangle
Dim screenshot As System.Drawing.Bitmap
Dim graph As Graphics
bounds = PicOuterBorder.Bounds
screenshot = New System.Drawing.Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
graph = Graphics.FromImage(screenshot)
graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy)
picFinal.Image = screenshot
'this takes a screenshot
End Sub
PicOuterBorder is a picturebox on my form. PicFinal is another display picturebox. But this code gets me this: Which is basically a screenshot of a window in the size of PicOuterBorder starting from the origin of my screen. However, Me.Bounds instead of PicOuterBorder.Bounds works and gets a perefect screenshot of just my form. I want picFinal to have a screenshot of just PicOuterBorder
Try below code. You have to map the control coordinates to screen coordinates using PointToScreen. I have placed PicOuterBorder inside the panel PanelPicture. PanelPicture is without any border, while PicOuterBorder can have any type of border style. Below code takes the snapshot of the panel.
Private Sub button28_Click(sender As Object, e As EventArgs) Handles button28.Click
Dim graph As Graphics = Nothing
Dim bounds As Rectangle = Nothing
Dim screenshot As System.Drawing.Bitmap
Dim location As Drawing.Point = PanelPicture.PointToScreen(Drawing.Point.Empty)
screenshot = New System.Drawing.Bitmap(PanelPicture.Width, PanelPicture.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
graph = Graphics.FromImage(screenshot)
graph.CopyFromScreen(location.X, location.Y, 0, 0, PanelPicture.Size, CopyPixelOperation.SourceCopy)
picFinal.Image = screenshot
graph.Dispose()
End Sub
Adapt your code for something like this:
Public Sub SaveImage(filename As String, image As Image, Encoder As ImageCodecInfo, EncParam As EncoderParameter)
Dim path As String = System.IO.Path.Combine(My.Application.Info.DirectoryPath, filename & ".jpg")
Dim mySource As New Bitmap(image.Width, image.Height)
Dim grfx As Graphics = Graphics.FromImage(mySource)
grfx.DrawImageUnscaled(image, Point.Empty)
grfx.Dispose()
mySource.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg)
mySource.Dispose()
End Sub
Related
I'm trying to do the following activity in visual basic:
Take a screenshot of my desktop and hold it in picture box.
Save it on my folder
Send a mail to someone with the image attached
Rename the image and Delete it from the folder
This is a recurring activity for every one hour. So far I have coded for all the steps above but when the script tries to rename the file on the folder I get an error message.
Error code
The code goes something like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim theTime As DateTime
theTime = Now.ToLongTimeString
Dim regDate As Date = DateTime.Now()
strDate = regDate.ToString("ddMMMyyyy HH:mm:ss")
'MsgBox(theTime)
'currentfolder = "C:\Users\user\Desktop" + strDate
'My.Computer.FileSystem.CreateDirectory(currentfolder)
If theTime >= #8:00:00 AM# Then
Timer1.Interval = 100
Timer1.Start()
'Timer starts functioning
End If
End Sub
Function Takescreenshot()
Dim bounds As Rectangle
Dim screenshot As System.Drawing.Bitmap
Dim graph As Graphics
Dim FileToDelete As String
FileToDelete = "C:\Users\user\Desktop\1.png"
If System.IO.File.Exists(FileToDelete) = True Then
PictureBox1.Image = Nothing
My.Computer.FileSystem.RenameFile("C:\Users\user\Desktop\1.png", "2.png")
System.IO.File.Delete("C:\Users\user\Desktop\2.png")
End If
bounds = Screen.PrimaryScreen.Bounds
screenshot = New System.Drawing.Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
graph = Graphics.FromImage(screenshot)
graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy)
PictureBox1.Image = screenshot
SaveImage("C:\Users\user\Desktop\1.png", PictureBox1.Image)
'Send Email
Second = 0
Timer1.Start()
End Function
Public Sub SaveImage(filename As String, image As Image)
Dim path As String = System.IO.Path.Combine(My.Application.Info.DirectoryPath, filename & ".png")
Dim mySource As New Bitmap(image.Width, image.Height)
Dim grfx As Graphics = Graphics.FromImage(mySource)
grfx.DrawImageUnscaled(image, Point.Empty)
grfx.Dispose()
mySource.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg)
mySource.Dispose()
End Sub
I need to delete the current image and then save a fresh copy of it. Please help.
Ok I found out a solution for this problem. I actually found out what was the process that was really holding the script from deleting the image.
It was the mail function which I have not added for security reasons. I had to dispose the image that was being added to the email body after the work was done so
img1.Dispose()
solved the issue
So I am making a documentation program for a physical therapy environment, and am trying to encorporate the ability to export the form with the data on it to a pdf or image of some sort. My form looks like this:
I have tried using the following code to create an image from it
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim bmpScreenshot As Bitmap = New Bitmap(Width, Height, PixelFormat.Format32bppArgb)
' Create a graphics object from the bitmap
Dim gfxScreenshot As Graphics = Graphics.FromImage(bmpScreenshot)
' Take a screenshot of the entire Form1
gfxScreenshot.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, Me.Size, CopyPixelOperation.SourceCopy)
' Save the screenshot
bmpScreenshot.Save("C:\Student.jpg", ImageFormat.Jpeg)
End Sub
But every time it comes back as only part of the form.
Any help would be appreciated!
You can use this code:
Private Function GetFormImage(ByVal include_borders As Boolean) As Bitmap
' Make the bitmap.
Dim wid As Integer = Me.Width
Dim hgt As Integer = Me.Height
Dim bm As New Bitmap(wid, hgt)
' Draw the form onto the bitmap.
Me.DrawToBitmap(bm, New Rectangle(0, 0, wid, hgt))
' Make a smaller bitmap without borders.
wid = Me.ClientSize.Width
hgt = Me.ClientSize.Height
Dim bm2 As New Bitmap(wid, hgt)
' Get the offset from the window's corner to its client
' area's corner.
Dim pt As New Point(0, 0)
pt = PointToScreen(pt)
Dim dx As Integer = pt.X - Me.Left
Dim dy As Integer = pt.Y - Me.Top
' Copy the part of the original bitmap that we want
' into the bitmap.
Dim gr As Graphics = Graphics.FromImage(bm2)
gr.DrawImage(bm, 0, 0, New Rectangle(dx, dy, wid, hgt), GraphicsUnit.Pixel)
Return bm
End Function
From https://social.msdn.microsoft.com/Forums/vstudio/en-US/3d258c2b-64b9-431f-9df8-398a7866de40/vbnet-save-windows-form-as-an-image-getformimage?forum=vbgeneral
And then call the function as so:
GetFormImage(*True to include the borders*).Save("C:\Student.jpg", ImageFormat.Jpeg)
I've encountered a very bizarre problem when trying to get a screenshot of a TableLayoutPanel in my form.
I have this code (taken from another question (How to get a screenshot, only for a picturebox); code courtesy of user "Chase Rocker"):
Dim s As Size = TableLayoutPanel1.Size
Dim memoryImage = New Bitmap(s.Width, s.Height)
Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
Dim ScreenPos As Point = Me.TableLayoutPanel1.PointToScreen(New Point(0, 0))
memoryGraphics.CopyFromScreen(ScreenPos.X, ScreenPos.Y, 0, 0, s)
Form3.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize
Form3.PictureBox1.BringToFront()
Form3.PictureBox1.Image = memoryImage
Now, here comes my problem. This code gives me a blank picture. It takes the screenshot apparently, but all I can see is white. Now, I was trying to see if the size was correct, so I was messing with MsgBox. I add this line to the code:
MsgBox("Random Message")
Getting
Dim s As Size = TableLayoutPanel1.Size
MsgBox("Random Message")
Dim memoryImage = New Bitmap(s.Width, s.Height)
Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
Dim ScreenPos As Point = Me.TableLayoutPanel1.PointToScreen(New Point(0, 0))
memoryGraphics.CopyFromScreen(ScreenPos.X, ScreenPos.Y, 0, 0, s)
Form3.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize
Form3.PictureBox1.BringToFront()
Form3.PictureBox1.Image = memoryImage
By some reason I don't know, the screenshot now works. I don't see white anymore, but the actual screenshot of the TableLayoutPanel. For me is very weird that the code only works with a MsgBox. Maybe I'm missing something. Does anyone know why this happens? Thank you!
How about if you try to make the TableLayoutPanel draw itself to a bitmap instead? This can be done using the Control.DrawToBitmap() method.
Dim s As Size = TableLayoutPanel1.Size
Dim memoryImage As New Bitmap(s.Width, s.Height)
TableLayoutPanel1.DrawToBitmap(memoryImage, New Rectangle(New Point(0, 0), s))
Form3.PictureBox1.Image = memoryImage
If the TableLayoutPanel fill happens in the same event handler where you grab the image then Windows has not draw the UI for the elements added to the TableLayoutPanel. Only when you exit from the event handler, the winforms engine has the opportunity to draw everything.
Adding a MessageBox changes everything because calling Show (a modal call that interrupts your code and pass control back to window) allows the Winform engine to draw the pending updates and your code works.
You can add a Timer control and put the code that execute the ScreenShoot in the Timer event.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
......
' code that fills the TableLayoutPanel
......
Dim tim1 = new System.Windows.Forms.Timer()
tim1.Interval = 1
AddHandler tim1.Tick, AddressOf tim1Ticked
tim1.Start()
End Sub
Private Sub tim1Ticked(sender As Object, e As EventArgs)
......
' Code that execute the screenshoot.
......
Dim t = DirectCast(sender, System.Windows.Forms.Timer)
t.Stop()
End Sub
I'm using a picture box as a 'preview' screen for a webbrowser control on a another winform. It works well apart from that in order to update the picturebox control I'm finding that the code needs to run twice (double click the button) linked to the below code. Any ideas why the picturebox isn't updating in the first pass to show the newly navigated page?
Private Sub mOutput_Click(sender As Object, e As EventArgs) Handles mOutput.Click
If Not mFiles.SelectedItem Is Nothing Then
Formloading.fDisplay.WebBrowser1.Navigate(folderloc.ToString & "\" & mFiles.SelectedItem.ToString)
End If
Dim Bounds As System.Drawing.Rectangle
Dim outputscreen As System.Drawing.Bitmap
Dim graph As System.Drawing.Graphics
Dim LO As Integer = 0
With Bounds
.Height = fDisplay.WebBrowser1.Height
.Width = fDisplay.WebBrowser1.Width
.X = Formloading.fDisplay.Location.X
.Y = Formloading.fDisplay.Location.Y
.Size = Formloading.fDisplay.Size
End With
outputscreen = New System.Drawing.Bitmap(Bounds.Width, Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb)
graph = System.Drawing.Graphics.FromImage(outputscreen)
graph.CopyFromScreen(Bounds.X, Bounds.Y, 0, 0, Bounds.Size, Drawing.CopyPixelOperation.SourceCopy)
PictureBox1.Image = outputscreen
End Sub
I'm using a timer to take screen captures after an amount of time and save the images to a specific path.
Private Sub tmrPS1_Tick(sender As Object, e As EventArgs) Handles tmrPS1.Tick
Dim bounds As Rectangle
Dim screenshot As System.Drawing.Bitmap
Dim graph As Graphics
bounds = Screen.PrimaryScreen.Bounds
screenshot = New System.Drawing.Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
graph = Graphics.FromImage(screenshot)
graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy)
PictureBox1.Image = screenshot
PictureBox1.Image.Save("C:\ImagesFolder\1.jpg")
tmrPS1.Enabled = False
End Sub
And I want another timer to delete them after I sent them with mail because I will have to take new ones. My question is how do I delete the images knowing the path?
Delete/recreate the folder when you are done with it?
If IO.Directory.Exists(DestinationFolder) Then IO.Directory.Delete(DestinationFolder, True)
Application.DoEvents()
IO.Directory.CreateDirectory(DestinationFolder)
This code cleans up files in "Temp" with the same extension as the file I'm saving.
With My.Computer.FileSystem
Dim s As String = Environ("temp")
For Each foundFile As String In .GetFiles(s, FileIO.SearchOption.SearchTopLevelOnly, "*.tmp.kml")
.DeleteFile(foundFile) ' clean up old output
Next
End With