-
VB.NET - Screenshot to jpeg...
Im shure this will do the trick for many people.
VB Code:
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Private Const VK_SNAPSHOT As Short = &H2Cs
Public Function SaveScreen(ByVal theFile As String) As Boolean
Dim data As IDataObject
data = Clipboard.GetDataObject()
Dim bmap As Bitmap
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
bmap = CType(data.GetData(GetType(System.Drawing.Bitmap)), Bitmap)
Me.PictureBox1.Image = bmap
Me.PictureBox1.Image.Save(theFile, Imaging.ImageFormat.Jpeg)
End If
End Function
Private Sub Command2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Command2.Click
Call keybd_event(System.Windows.Forms.Keys.Snapshot, 0, 0, 0)
System.Threading.Thread.Sleep(200) ' To have time to catch the clipboard
SaveScreen("c:\test.jpg")
End Sub
-
With all respect, how come the jpeg is kind of fuzzy?
-
It might be that a jpeg file is a compressed bmp file and therefore might the compression corrupt the file a little bit. If you want to look deeper into this you will have to search for it. I am shure you can choose how much compression you want with coding, but for now the quality of the screenshot will due for me. :wave:
-
Quote:
Originally posted by Liquid Metal
With all respect, how come the jpeg is kind of fuzzy?
when the image opens ( usually in Windows PictureViewer ) , try clicking the actuall size button at the bottom ;) the picture should then be clear ( you are seeing a compressed version because it wont show as actuall size by default due to the size of a screenshot )
-
Re: VB.NET - Screenshot to jpeg...
wouldnt it be better to save to a PNG file if its a screenshot?
-
Re: VB.NET - Screenshot to jpeg...
This is a little smoother, and ts 100% framework (no API)...
VB Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Not SaveScreen(Application.StartupPath & "\screen.png") Then
MessageBox.Show("Sorry dude, couldn't do it.")
End If
End Sub
Public Function SaveScreen(ByVal theFile As String) As Boolean
Try
SendKeys.Send("%{PRTSC}") '<alt + printscreen>
Application.DoEvents()
Dim data As IDataObject = Clipboard.GetDataObject()
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
Dim bmp As Bitmap = CType(data.GetData(GetType(System.Drawing.Bitmap)), Bitmap)
bmp.Save(theFile, Imaging.ImageFormat.Png)
End If
Clipboard.SetDataObject(0) 'save memory by removing the image from the clipboard
Return True
Catch ex As Exception
Return False
End Try
End Function
-
Re: VB.NET - Screenshot to jpeg...
Follow up to WOSSMAN code.
works great except I keep getting a problem after doing about 8-10 screenshots ! I get an Exception error.
Further debugging reveals it happens during the .Save command
The Err.Message is
"Object reference not set to an instance of an object"
I would appreciate any feedback since I would love to use this really nice and compact code snippet to do screenshot capture, however I have to capture approximately 100-4000 Screenshots over the span of 60-120minutes.
Any suggestions would be welcome.
Sincerely
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by NSiggel
Follow up to WOSSMAN code.
works great except I keep getting a problem after doing about 8-10 screenshots ! I get an Exception error.
Further debugging reveals it happens during the .Save command
The Err.Message is
"Object reference not set to an instance of an object"
I would appreciate any feedback since I would love to use this really nice and compact code snippet to do screenshot capture, however I have to capture approximately 100-4000 Screenshots over the span of 60-120minutes.
Any suggestions would be welcome.
Sincerely
Wow, that's a lot of screenshots, worst case scenario by my calculations means 1.1 screenies per second. That is probably pushing it a bit. The thing about printscreen is that it is not a high-priority feature. If you want to take many snaps, then you would be much better off using the API. You would have much better performance (you would probably be able to do 2 or 3 snaps per second, depending on how fast you can save the data). But it would be at the cost of complexity. API would be a little harder to code, but it's probably worth it.
I don't have any samples for you at the moment, but the API functions you should check out are:
GetDC
BitBlt (The old favourite :D)
If you have API-Guide installed you can get some examples off there.
Hope that helps.
PS< Can you post the code that caused your error?
-
Re: VB.NET - Screenshot to jpeg...
I have looked at this thread and it seems that it could solve one of my problems but I need it to work as a windows service or at least in the background so the user is unaware it is running. the main problems seem to be caused by the send keys command and the IData objects not been recognised in services. Any Ideas.
-
Re: VB.NET - Screenshot to jpeg...
Ok Ihave added a reference to system.windows.forms which has solved my Clipboard problems i think, I just need it to recognise image formats.
-
Re: VB.NET - Screenshot to jpeg...
referencin system.drawing cleared some more errors but
Code:
Dim bmap As Bitmap
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
bmap = CType(data.GetData(GetType(System.Drawing.Bitmap)), Bitmap)
bmap.Save("L:/DeskSpy/" & Now & ".jpg", Imaging.ImageFormat.Jpeg)
End If
Underlined in blue is Bitmap and Imaging _ Name Imaging is not declared and type Bitmap is not defined????????
-
Re: VB.NET - Screenshot to jpeg...
Ok I have completed my transformation of it into a windows service - but it doesnt quite work, The service installs and starts but on debugging there is an error. That obeject reference not set to an instance of an object. line 86 (If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then) any suggestions please.
Code:
Option Strict Off
Imports System.ServiceProcess
Imports System.Timers
Imports System.Windows.Forms
Imports System.Drawing
Public Class TimerService
Inherits System.ServiceProcess.ServiceBase
#Region " Component Designer generated code "
Public Sub New()
MyBase.New()
' This call is required by the Component Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call
End Sub
'UserService overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' The main entry point for the process
<MTAThread()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
' More than one NT Service may run within the same process. To add
' another service to this process, change the following line to
' create a second service object. For example,
'
' ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
'
ServicesToRun = New System.ServiceProcess.ServiceBase() {New TimerService()}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
' NOTE: The following procedure is required by the Component Designer
' It can be modified using the Component Designer.
' Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.ServiceName = "TimerServiceTest"
End Sub
#End Region
' This fires every 10 seconds.
Private WithEvents ServiceTimer As New System.Timers.Timer(10000)
Private Counter As Integer
Protected Overrides Sub OnStart(ByVal args() As String)
ServiceTimer.Start()
End Sub
Protected Overrides Sub OnStop()
ServiceTimer.Stop()
End Sub
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Private Const VK_SNAPSHOT As Short = &H2CS
Private Sub DoWork(ByVal sender As Object, _
ByVal e As ElapsedEventArgs) Handles ServiceTimer.Elapsed
Counter += 1
Debug.WriteLine("Repetition #" & Counter.ToString())
Try
Call keybd_event(System.Windows.Forms.Keys.Snapshot, 0, 0, 0)
System.Threading.Thread.Sleep(200) ' To have time to catch the clipboard
Dim data As IDataObject
data = Clipboard.GetDataObject()
Dim bmap As Bitmap
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
bmap = CType(data.GetData(GetType(System.Drawing.Bitmap)), Bitmap)
bmap.Save("c:/SpyTest.jpg", Imaging.ImageFormat.Jpeg)
End If
Catch Err As Exception
Debug.WriteLine(Err.ToString())
End Try
End Sub
End Class
-
Re: VB.NET - Screenshot to jpeg...
FYI, I recently added screen-rectangle grabbing support to BlitterChip. See here, the attachment might be useful to you....
http://www.vbforums.com/showpost.php...63&postcount=2
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by FishGuy
That obeject reference not set to an instance of an object. line 86 (If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then)
Sounds like there was nothing on the clipboard.
-
Re: VB.NET - Screenshot to jpeg...
I dont understand why not unless its simply because a service cannot properly invoke Call keybd_event(System.Windows.Forms.Keys.Snapshot, 0, 0, 0)
-
Re: VB.NET - Screenshot to jpeg...
Wossname-
I ditched all my old code and used your Blitterchip class, which worked just as i wanted as a windows app but not as a windows service. any idea why? It executes ok and does take a screen grab except the screen grab is just black.
heres my code.
VB Code:
Option Strict On
Imports System.ServiceProcess
Imports System.Timers
Imports System.Drawing
Imports System.Windows.Forms
Public Class TimerService
Inherits System.ServiceProcess.ServiceBase
#Region " Component Designer generated code "
Public Sub New()
MyBase.New()
' This call is required by the Component Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call
End Sub
'UserService overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' The main entry point for the process
<MTAThread()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
' More than one NT Service may run within the same process. To add
' another service to this process, change the following line to
' create a second service object. For example,
'
' ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
'
ServicesToRun = New System.ServiceProcess.ServiceBase() {New TimerService}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
' NOTE: The following procedure is required by the Component Designer
' It can be modified using the Component Designer.
' Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container
Me.ServiceName = "TimerServiceTest"
End Sub
#End Region
' This fires every 10 seconds.
Private WithEvents ServiceTimer As New Timers.Timer(10000)
Private Counter As Integer
Protected Overrides Sub OnStart(ByVal args() As String)
ServiceTimer.Start()
End Sub
Protected Overrides Sub OnStop()
ServiceTimer.Stop()
End Sub
Private Sub DoWork(ByVal sender As Object, _
ByVal e As ElapsedEventArgs) Handles ServiceTimer.Elapsed
Counter += 1
Debug.WriteLine("Repetition #" & Counter.ToString())
Try
Dim i As Bitmap = BlitterChip.ScreenGrab(New Rectangle(0, 0, 1200, 800))
i.Save("c:/SpyTest1.jpg", Imaging.ImageFormat.Jpeg)
Catch Err As Exception
Debug.WriteLine(Err.ToString())
End Try
End Sub
End Class
-
Re: VB.NET - Screenshot to jpeg...
with all due respect it's alightly stupid to get a screenshot using print screen. You ruin the guy's clipboard data too :D I found this a few days before and it's in C# http://www.developerfusion.com/show/4630/
that gets the screen using APIs, I'm sure some of you gurus can rewrite that in VB:D
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by MrPolite
with all due respect it's alightly stupid to get a screenshot using print screen. You ruin the guy's clipboard data too :D I found this a few days before and it's in C#
http://www.developerfusion.com/show/4630/
that gets the screen using APIs, I'm sure some of you gurus can rewrite that in VB:D
Yes it is stupid. You should read post #16 :D API all the way baby, yeah!
That code on Developerfusion is a bit flabby imho. Why use 300 api functions when 2 will do? Blitterchip bungs the image straight into a bitmap for you so you can save it in any format supported by GDI+.
:)
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by FishGuy
Wossname-
I ditched all my old code and used your Blitterchip class, which worked just as i wanted as a windows app but not as a windows service. any idea why? It executes ok and does take a screen grab except the screen grab is just black.
You code looks OK to me. I wonder if Services are unable to query video memory? I have limited Services experience so I don't really know what to do about that, sorry.
-
Re: VB.NET - Screenshot to jpeg...
yeah I see it now. All your API are belong to me:)
umm one thing though, you are using GetDC(0) to get the desktop dc? is that a legitimate way of doing it?:D
would that always work?
-
Re: VB.NET - Screenshot to jpeg...
I got a problem with the code posted by wossname. I found that it only captured a corner of the screen. Could someone take a look? Help
-
Re: VB.NET - Screenshot to jpeg...
:( Thx for hijacking :ehh:
-
Re: VB.NET - Screenshot to jpeg...
Oh, so it was your code then. How do I capture the whole screen?
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by abhijit
Oh, so it was your code then. How do I capture the whole screen?
I mean hijacking the thread :)
And as far as i remember, the code i posted capture the whole screen. (havent been programming for a while) :sick:
-
Re: VB.NET - Screenshot to jpeg...
Oh I am sorry about that, but I still can't get this code to work properly.
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by MrPolite
with all due respect it's alightly stupid to get a screenshot using print screen. You ruin the guy's clipboard data too :D I found this a few days before and it's in C#
http://www.developerfusion.com/show/4630/
that gets the screen using APIs, I'm sure some of you gurus can rewrite that in VB:D
Can't you just back up the clipboard data then replace it when you're done?
Bill
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by conipto
Can't you just back up the clipboard data then replace it when you're done?
Bill
yeah sure
but when you can get the screenshots using apis, why not just do that instaed :)
-
Re: VB.NET - Screenshot to jpeg...
Quote:
Originally Posted by MrPolite
yeah sure
but when you can get the screenshots using apis, why not just do that instaed :)
Well, MS seems to think .NET users should be avoiding API calls.. and seems to be hinting around at their planned obsolesence...
Bill