gpt4 book ai didi

.net - 使 .NET 截图工具与多个监视器兼容

转载 作者:行者123 更新时间:2023-12-01 22:56:55 25 4
gpt4 key购买 nike

此帖子中提供了另一种截图工具解决方案:.NET Equivalent of Snipping Tool

现在有必要使其适用于选定的屏幕(在多显示器系统上)。

代码已相应修改:

Public Class SnippingTool


Private Shared _Screen As Screen

Private Shared BitmapSize As Size

Private Shared Graph As Graphics


Public Shared Function Snip(ByVal screen As Screen) As Image

_Screen = screen

Dim bmp As New Bitmap(screen.Bounds.Width, screen.Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)

Dim gr As Graphics = Graphics.FromImage(bmp)

Graph = gr


gr.SmoothingMode = Drawing2D.SmoothingMode.None '###

BitmapSize = bmp.Size


Using snipper = New SnippingTool(bmp)

snipper.Location = New Point(screen.Bounds.Left, screen.Bounds.Top)

If snipper.ShowDialog() = DialogResult.OK Then
Return snipper.Image
End If

End Using

Return Nothing


End Function



Public Sub New(ByVal screenShot As Image)
InitializeComponent()
Me.BackgroundImage = screenShot
Me.ShowInTaskbar = False
Me.FormBorderStyle = FormBorderStyle.None


'Me.WindowState = FormWindowState.Maximized

Me.DoubleBuffered = True
End Sub
Public Property Image() As Image
Get
Return m_Image
End Get
Set(ByVal value As Image)
m_Image = Value
End Set
End Property
Private m_Image As Image


Private rcSelect As New Rectangle()
Private pntStart As Point

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
' Start the snip on mouse down
If e.Button <> MouseButtons.Left Then
Return
End If
pntStart = e.Location
rcSelect = New Rectangle(e.Location, New Size(0, 0))
Me.Invalidate()
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
' Modify the selection on mouse move
If e.Button <> MouseButtons.Left Then
Return
End If
Dim x1 As Integer = Math.Min(e.X, pntStart.X)
Dim y1 As Integer = Math.Min(e.Y, pntStart.Y)
Dim x2 As Integer = Math.Max(e.X, pntStart.X)
Dim y2 As Integer = Math.Max(e.Y, pntStart.Y)
rcSelect = New Rectangle(x1, y1, x2 - x1, y2 - y1)
Me.Invalidate()
End Sub


Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
' Complete the snip on mouse-up
If rcSelect.Width <= 0 OrElse rcSelect.Height <= 0 Then
Return
End If
Image = New Bitmap(rcSelect.Width, rcSelect.Height)
Using gr As Graphics = Graphics.FromImage(Image)
gr.DrawImage(Me.BackgroundImage, New Rectangle(0, 0, Image.Width, Image.Height), rcSelect, GraphicsUnit.Pixel)
End Using
DialogResult = DialogResult.OK
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
' Draw the current selection
Using br As Brush = New SolidBrush(Color.FromArgb(120, Color.White))
Dim x1 As Integer = rcSelect.X
Dim x2 As Integer = rcSelect.X + rcSelect.Width
Dim y1 As Integer = rcSelect.Y
Dim y2 As Integer = rcSelect.Y + rcSelect.Height
e.Graphics.FillRectangle(br, New Rectangle(0, 0, x1, Me.Height))
e.Graphics.FillRectangle(br, New Rectangle(x2, 0, Me.Width - x2, Me.Height))
e.Graphics.FillRectangle(br, New Rectangle(x1, 0, x2 - x1, y1))
e.Graphics.FillRectangle(br, New Rectangle(x1, y2, x2 - x1, Me.Height - y2))
End Using
Using pen As New Pen(Color.Red, 3)
e.Graphics.DrawRectangle(pen, rcSelect)
End Using
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
' Allow canceling the snip with the Escape key
If keyData = Keys.Escape Then
Me.DialogResult = DialogResult.Cancel
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
Me.Size = New Size(_Screen.Bounds.Width, _Screen.Bounds.Height)
Dim area = _Screen.WorkingArea
Graph.CopyFromScreen(area.X, area.Y, area.Y, area.Y, BitmapSize)
End Sub

End Class

但它拒绝按预期工作。截图不会出现在所选屏幕上,而是出现在第一个屏幕上,无论“截图”功能中的“屏幕”参数如何。如何让它正常工作?

更新:最新的 snipper 版本出现在正确的屏幕上,但为空白。

UPDATE X2:上面的代码已经更新以反射(reflect)最新版本,现在可以正常工作。

最佳答案

LoveDotNet,我相信你的源代码有一个小问题,如下一行:

Graph.CopyFromScreen(area.X, area.Y, area.Y, area.Y, BitmapSize)

应该是:

Graph.CopyFromScreen(area.X, area.Y, 0, 0, BitmapSize)

另外,给任何想要使用此代码的人一个快速提示,您可以像下面这样调用它:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim img As Image = SnippingTool.Snip(Screen.AllScreens(0)) 'Set to (1) for secondary monitor'
End Sub

此外,当您创建 SnippingTool 表单时,请务必将 StartPosition 属性更改为 Manual

大编辑:

我做了一些工作来一次支持多个显示器,这不需要开发人员选择要使用的显示器(这克隆了“截图工具”更接近一点)。

基本上,我遍历所有屏幕以找到最小的 XY 坐标,以及最大的 Right底部,这让我们可以评估“虚拟监视器”的完整大小:

我已经用我的配置测试了它:

主要 1280x800

二级 1280x1024 w/-224 X 偏移

enter image description here

代码:

'SnippingTool Code: Place this in a new form (set the StartUp Property to Manual)'
Public Class SnippingTool


Private Shared _Screen As Screen

Private Shared BitmapSize As Size

Private Shared Graph As Graphics

Private Structure MultiScreenSize
Dim minX As Integer
Dim minY As Integer
Dim maxRight As Integer
Dim maxBottom As Integer
End Structure


Private Shared Function FindMultiScreenSize() As MultiScreenSize

Dim minX As Integer = Screen.AllScreens(0).Bounds.X
Dim minY As Integer = Screen.AllScreens(0).Bounds.Y

Dim maxRight As Integer = Screen.AllScreens(0).Bounds.Right
Dim maxBottom As Integer = Screen.AllScreens(0).Bounds.Bottom

For Each aScreen As Screen In Screen.AllScreens
If aScreen.Bounds.X < minX Then
minX = aScreen.Bounds.X
End If

If aScreen.Bounds.Y < minY Then
minY = aScreen.Bounds.Y
End If

If aScreen.Bounds.Right > maxRight Then
maxRight = aScreen.Bounds.Right
End If

If aScreen.Bounds.Bottom > maxBottom Then
maxBottom = aScreen.Bounds.Bottom
End If
Next
Dim m_MultiScreenSize As MultiScreenSize
With m_MultiScreenSize
.minX = minX
.minY = minY
.maxBottom = maxBottom
.maxRight = maxRight
End With
Return m_MultiScreenSize
End Function
Public Shared Function Snip() As Image
Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()

Dim bmp As New Bitmap(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX, _
m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY, _
System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
Dim gr As Graphics = Graphics.FromImage(bmp)

Graph = gr


gr.SmoothingMode = Drawing2D.SmoothingMode.None
BitmapSize = bmp.Size


Using snipper = New SnippingTool(bmp)

snipper.Location = New Point(m_MultiScreenSize.minX, m_MultiScreenSize.minY)

If snipper.ShowDialog() = DialogResult.OK Then
Return snipper.Image
End If

End Using

Return Nothing


End Function



Public Sub New(ByVal screenShot As Image)
InitializeComponent()
Me.BackgroundImage = screenShot
Me.ShowInTaskbar = False
Me.FormBorderStyle = FormBorderStyle.None

Me.DoubleBuffered = True
End Sub
Public Property Image() As Image
Get
Return m_Image
End Get
Set(ByVal value As Image)
m_Image = Value
End Set
End Property
Private m_Image As Image


Private rcSelect As New Rectangle()
Private pntStart As Point

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
' Start the snip on mouse down'
If e.Button <> MouseButtons.Left Then
Return
End If
pntStart = e.Location
rcSelect = New Rectangle(e.Location, New Size(0, 0))
Me.Invalidate()
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
' Modify the selection on mouse move'
If e.Button <> MouseButtons.Left Then
Return
End If
Dim x1 As Integer = Math.Min(e.X, pntStart.X)
Dim y1 As Integer = Math.Min(e.Y, pntStart.Y)
Dim x2 As Integer = Math.Max(e.X, pntStart.X)
Dim y2 As Integer = Math.Max(e.Y, pntStart.Y)
rcSelect = New Rectangle(x1, y1, x2 - x1, y2 - y1)
Me.Invalidate()
End Sub


Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
' Complete the snip on mouse-up'
If rcSelect.Width <= 0 OrElse rcSelect.Height <= 0 Then
Return
End If
Image = New Bitmap(rcSelect.Width, rcSelect.Height)
Using gr As Graphics = Graphics.FromImage(Image)
gr.DrawImage(Me.BackgroundImage, New Rectangle(0, 0, Image.Width, Image.Height), _
rcSelect, GraphicsUnit.Pixel)
End Using
DialogResult = DialogResult.OK
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
' Draw the current selection'
Using br As Brush = New SolidBrush(Color.FromArgb(120, Color.White))
Dim x1 As Integer = rcSelect.X
Dim x2 As Integer = rcSelect.X + rcSelect.Width
Dim y1 As Integer = rcSelect.Y
Dim y2 As Integer = rcSelect.Y + rcSelect.Height
e.Graphics.FillRectangle(br, New Rectangle(0, 0, x1, Me.Height))
e.Graphics.FillRectangle(br, New Rectangle(x2, 0, Me.Width - x2, Me.Height))
e.Graphics.FillRectangle(br, New Rectangle(x1, 0, x2 - x1, y1))
e.Graphics.FillRectangle(br, New Rectangle(x1, y2, x2 - x1, Me.Height - y2))
End Using
Using pen As New Pen(Color.Red, 3)
e.Graphics.DrawRectangle(pen, rcSelect)
End Using
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
' Allow canceling the snip with the Escape key'
If keyData = Keys.Escape Then
Me.DialogResult = DialogResult.Cancel
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()
Me.Size = New Size(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX, _
m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY)

Graph.CopyFromScreen(m_MultiScreenSize.minX, m_MultiScreenSize.minY, 0, 0, BitmapSize)
End Sub
End Class

你可以这样调用它:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim img As Image = SnippingTool.Snip()
img.Save("C:\ScreenShot.png")
End Sub

关于.net - 使 .NET 截图工具与多个监视器兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4005910/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com