I want to capture the screen in my code to get an image - like using the 'print screen' button on the keyboard .
Does anyone have an idea how to do this? I have no starting point.
I want to capture the screen in my code to get an image - like using the 'print screen' button on the keyboard .
Does anyone have an idea how to do this? I have no starting point.
You can use the Graphics.CopyFromScreen()
method.
//Create a new bitmap.
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
// Save the screenshot to the specified path that the user has chosen.
bmpScreenshot.Save("Screenshot.png", ImageFormat.Png);
Screen.PrimaryScreen
to get the primary screen? You can use Screen.AllScreens
to get an array of them all. Screen.AllScreens[n].Bounds.Width
etc... –
Lelahleland I had two problems with the accepted answer.
Screen
class are incorrect when display scaling is used and your application is not declared per monitor dpiAware.Here's my updated solution using the Screen.AllScreens
static property and calling EnumDisplaySettings
using p/invoke to get the real screen resolution.
using System.Runtime.InteropServices;
const int ENUM_CURRENT_SETTINGS = -1;
foreach (Screen screen in Screen.AllScreens)
{
var dm = new DEVMODE();
dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);
using var bmp = new Bitmap(dm.dmPelsWidth, dm.dmPelsHeight);
using var g = Graphics.FromImage(bmp);
g.CopyFromScreen(dm.dmPositionX, dm.dmPositionY, 0, 0, bmp.Size);
bmp.Save(screen.DeviceName.Split('\\').Last() + ".png");
}
[DllImport("user32.dll")]
static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public ScreenOrientation dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
References:
https://mcmap.net/q/271030/-detect-if-non-dpi-aware-application-has-been-scaled-virtualized http://pinvoke.net/default.aspx/user32/EnumDisplaySettings.html?diff=y
// Use this version to capture the full extended desktop (i.e. multiple screens)
Bitmap screenshot = new Bitmap(SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height,
PixelFormat.Format32bppArgb);
Graphics screenGraph = Graphics.FromImage(screenshot);
screenGraph.CopyFromScreen(SystemInformation.VirtualScreen.X,
SystemInformation.VirtualScreen.Y,
0,
0,
SystemInformation.VirtualScreen.Size,
CopyPixelOperation.SourceCopy);
screenshot.Save("Screenshot.png", System.Drawing.Imaging.ImageFormat.Png);
Try this code
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics gr = Graphics.FromImage(bmp);
gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);
pictureBox1.Image = bmp;
bmp.Save("img.png",System.Drawing.Imaging.ImageFormat.Png);
Bitmap memoryImage;
//Set full width, height for image
memoryImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
Size s = new Size(memoryImage.Width, memoryImage.Height);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(0, 0, 0, 0, s);
string str = "";
try
{
str = string.Format(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
@"\Screenshot.png");//Set folder to save image
}
catch { };
memoryImage.save(str);
I had been wondering how to do the same thing in FORTRAN to save me a bunch of manual intervention using PrintScreen, paste to Paint etc. I just figured out how: I read the pixels using GETPIXEL_RGB for any section of the screen I want, and, having prepared a .bmp header and written it to the .bmp file, follow by writing the pixel data. However, I don't think it's going to capture 10 to 20 sctre
Multi Screen Capture Program by Smitty
The Form has
CheckBox2 - Checkbox - Button Style - Anchor = Top, Left
CB1 - ComboBox - Font size = 20 - Text = 1 - Anchor = Top, Left
PB1 - PictureBox - SizeMode = StretchImage - Anchor = Top, Right, Bottom, Left
This is the module1.vb code
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.Media
Imports System.Threading
Imports System.Management
Imports System.Runtime.InteropServices
Module Mod1
Dim x As Integer = Screen.AllScreens.Count
Public mon(x) As ScreenSpecs
<DllImport("gdi32.dll")>
Public Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("gdi32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)>
Public Function CreateDC(<MarshalAs(UnmanagedType.LPStr)> lpszDriver As String,
<MarshalAs(UnmanagedType.LPStr)> lpszDevice As String,
<MarshalAs(UnmanagedType.LPStr)> lpszOutput As String,
lpInitData As IntPtr) As IntPtr
End Function
Public Function BeforeLast(value As String, a As String) As String
If value = Nothing Then
Return value
Exit Function
End If
Dim posA As Integer = value.LastIndexOf(a)
If posA = -1 Then Return ""
Return value.Substring(0, posA)
End Function
Public Function BeforeFirst(value As String, a As String) As String
If value = Nothing Then
Return value
Exit Function
End If
Dim posA As Integer = value.IndexOf(a)
If posA = -1 Then Return ""
Return value.Substring(0, posA)
End Function
Public Function AfterFirst(value As String, a As String) As String
If value = Nothing Then
Return value
Exit Function
End If
Dim posA As Integer = value.IndexOf(a)
If posA = -1 Then Return ""
Dim adjustedPosA As Integer = posA + a.Length
If adjustedPosA >= value.Length Then Return ""
Return value.Substring(adjustedPosA)
End Function
Public Function AfterLast(value As String, a As String) As String
If value = Nothing Then
Return value
Exit Function
End If
Dim posA As Integer = value.LastIndexOf(a)
If posA = -1 Then Return ""
Dim adjustedPosA As Integer = posA + a.Length
If adjustedPosA >= value.Length Then Return ""
Return value.Substring(adjustedPosA)
End Function
Public Function GrabScreen(Index As Integer) As Bitmap
Dim MonWidth As Integer = mon(Index).Width
Dim MonHeight As Integer
If Form1.CheckBox2.Checked Then
MonHeight = mon(Index).Height
Else
MonHeight = mon(Index).HeightNtb
End If
Dim screenSize As Size = New Size(MonWidth, MonHeight)
Dim screenGrab As New Bitmap(MonWidth, MonHeight)
Dim g As Graphics = Graphics.FromImage(screenGrab)
g.CopyFromScreen(New Point(mon(Index).XStart, mon(Index).YStart), New Point(0, 0), screenSize)
Return screenGrab
End Function
Public Function GetScalleFactor(index As Integer) As Double
Dim desktop As IntPtr = CreateDC(Screen.AllScreens(index).DeviceName, Nothing, Nothing, IntPtr.Zero)
Return GetDeviceCaps(desktop, 118) / GetDeviceCaps(desktop, 8)
End Function
End Module
This is the ScreenSpec.vb Class I created
Public Class ScreenSpecs
Private BPPValue As Integer
Private IndexValue As Integer
Private NameValue As String
Private WidthValue As Integer
Private HeightValue As Integer
Private HeightNtbValue As Integer
Private ScaleValue As Double
Private XStartValue As Integer
Private YStartValue As Integer
Public Property BPP() As Integer
Get
' Gets the property value.
Return BPPValue
End Get
Set(ByVal Value As Integer)
' Sets the property value.
BPPValue = Value
End Set
End Property
Public Property Index() As Integer
Get
' Gets the property value.
Return IndexValue
End Get
Set(ByVal Value As Integer)
' Sets the property value.
IndexValue = Value
End Set
End Property
Public Property Name() As String
Get
' Gets the property value.
Return NameValue
End Get
Set(ByVal Value As String)
' Sets the property value.
NameValue = Value
End Set
End Property
Public Property Width() As String
Get
' Gets the property value.
Return WidthValue
End Get
Set(ByVal Value As String)
' Sets the property value.
WidthValue = Value
End Set
End Property
Public Property Height() As String
Get
' Gets the property value.
Return HeightValue
End Get
Set(ByVal Value As String)
' Sets the property value.
HeightValue = Value
End Set
End Property
Public Property HeightNtb() As String
Get
' Gets the property value.
Return HeightNtbValue
End Get
Set(ByVal Value As String)
' Sets the property value.
HeightNtbValue = Value
End Set
End Property
Public Property Scale() As Double
Get
' Gets the property value.
Return ScaleValue
End Get
Set(ByVal Value As Double)
' Sets the property value.
ScaleValue = Value
End Set
End Property
Public Property XStart() As String
Get
' Gets the property value.
Return XStartValue
End Get
Set(ByVal Value As String)
' Sets the property value.
XStartValue = Value
End Set
End Property
Public Property YStart() As String
Get
' Gets the property value.
Return YStartValue
End Get
Set(ByVal Value As String)
' Sets the property value.
YStartValue = Value
End Set
End Property
End Class
This is the Form1.vb code
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Threading
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
On Error Resume Next
CB1.Items.Clear()
Dim x As Integer
Dim MonH As Integer
Dim MonHtb As Integer
Dim MonW As Integer
For x = 0 To (UBound(Screen.AllScreens))
mon(x) = New ScreenSpecs()
mon(x).Index = x
mon(x).Name = Screen.AllScreens(x).DeviceName.ToString
mon(x).BPP = Screen.AllScreens(x).BitsPerPixel
MonH = Screen.AllScreens(x).Bounds.Size.Height.ToString
MonHtb = Screen.AllScreens(x).WorkingArea.Size.Height.ToString
MonW = Screen.AllScreens(x).Bounds.Size.Width.ToString
mon(x).Scale = GetScalleFactor(x)
mon(x).Height = (MonH * mon(x).Scale)
mon(x).HeightNtb = (MonHtb * mon(x).Scale)
mon(x).Width = (MonW * mon(x).Scale)
mon(x).XStart = Screen.AllScreens(x).Bounds.Location.X.ToString
mon(x).YStart = Screen.AllScreens(x).Bounds.Location.Y.ToString
CB1.Items.Add((x + 1))
Next
End Sub
Private Sub PB1_Click(sender As Object, e As EventArgs) Handles PB1.Click
PB1.Image = GrabScreen((Int(CB1.Text) - 1))
End Sub
Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
If CheckBox2.Checked = False Then
CheckBox2.Text = "No Taskbar"
CheckBox2.BackColor = Color.Pink
Else
CheckBox2.Text = "Show Taskbar"
CheckBox2.BackColor = Color.LightGreen
End If
End Sub
Private Sub CB1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CB1.SelectedIndexChanged
Dim MonSpec As String = ""
Dim x As Integer = sender.SelectedIndex
Me.Text = "Monitor Number " & mon(x).Index & " - BitsPerPixel = " & mon(x).BPP & " - Scaling Factor = " & mon(x).Scale & " - Width = " & mon(x).Width & " - Height = " & mon(x).Height & " - X-Start = " & mon(x).XStart & " - Y-Start = " & mon(x).YStart
End Sub
End Class
Made change to the picturebox click which will hide the screenshot program.
Private Sub PB1_Click(sender As Object, e As EventArgs) Handles PB1.Click
Me.SendToBack()
Application.DoEvents()
PB1.Image = GrabScreen((Int(CB1.Text) - 1))
Application.DoEvents()
Me.BringToFront()
End Sub
© 2022 - 2024 — McMap. All rights reserved.