Image size when capturing a screenshot of another application changes if application not at 0,0

前端 未结 1 408
被撕碎了的回忆
被撕碎了的回忆 2020-12-22 11:17

I have an app which properly captures the image of an application window if it is in the upper-left corner of the primary screen.
But if it is not, the image size is not

相关标签:
1条回答
  • 2020-12-22 11:47

    Your code can be simplified in some details.
    First of all, as already mentioned in the comments, your declaration of GetWindowRect() is not correct. You need to pass it a Window handle, usually in the form of an IntPtr structure, and a RECT structure.

    Refer to the PInvoke website when you need to include a Windows API function call in your code. The experience of many programmers has forged :) those lines of code.

    The Desktop size, here, is returned by SystemInformation.PrimaryMonitorSize.
    You could also use Screen.PrimaryScreen.Bounds or SystemInformation.VirtualScreen.
    Choose the one that best fits your plans.

    Imports System.Diagnostics
    Imports System.Drawing
    Imports System.Drawing.Drawing2D
    Imports System.Runtime.InteropServices
    
    <DllImport("user32.dll")>
    Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
    End Function
    
    <StructLayout(LayoutKind.Sequential)>
    Public Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure
    
    Private Sub BtnCapture_Click(sender As Object, e As EventArgs) Handles BtnCapture.Click
        Dim wRect As RECT = Nothing
        Dim WindowArea As Rectangle = Nothing
    
        Dim FindProcess As Process = Process.GetProcessesByName("calc").FirstOrDefault()
        If FindProcess IsNot Nothing AndAlso CInt(FindProcess.MainWindowHandle) > 0 Then
            If GetWindowRect(FindProcess.MainWindowHandle, wRect) Then
                WindowArea = Rectangle.FromLTRB(wRect.Left, wRect.Top, wRect.Right, wRect.Bottom)
            End If
        End If
        If WindowArea = Nothing Then WindowArea = New Rectangle(Point.Empty, SystemInformation.PrimaryMonitorSize)
        Using img As Image = New Bitmap(WindowArea.Width, WindowArea.Height, PixelFormat.Format32bppArgb)
            Using g As Graphics = Graphics.FromImage(img)
                g.SmoothingMode = SmoothingMode.HighQuality
                g.CopyFromScreen(WindowArea.Location, Point.Empty, WindowArea.Size, CopyPixelOperation.SourceCopy)
                img.Save("[The Image Path]", ImageFormat.Png)
                ScaleToClipboard(img, 65.0F) '65% of its original size or 
            End Using
        End Using
        '(...) Other processing
    End Sub
    

    Edit:
    A method to save the original image to disk, reduce the source Image size to a specific size or to a fraction of it, then set the modified Image to the ClipBoard, ready to be pasted in some recepient.

    ScaleToClipboard([Source Image], [Percent of Original] As Single)
    ScaleToClipboard([Source Image], [Specific Size] As Size)

    Example:
    ScaleToClipboard([Source Image], 72.0F)
    ScaleToClipboard([Source Image], New Size(200, 125))

    Private Sub ScaleToClipboard(SourceImage As Image, SizeScale As Single)
        Dim NewSize As SizeF = New SizeF((SourceImage.Width \ 100) * SizeScale, (SourceImage.Height \ 100) * SizeScale)
        ScaleToClipboard(SourceImage, Size.Round(NewSize))
    End Sub
    
    Private Sub ScaleToClipboard(SourceImage As Image, SizeScale As Size)
        Using img As Image = New Bitmap(SourceImage, Size.Round(SizeScale))
            Using g As Graphics = Graphics.FromImage(img)
                g.SmoothingMode = SmoothingMode.HighQuality
                g.InterpolationMode = InterpolationMode.HighQualityBicubic
                g.DrawImage(SourceImage, New Rectangle(Point.Empty, SizeScale))
                Clipboard.SetImage(TryCast(img.Clone(), Image))
            End Using
        End Using
    End Sub
    
    0 讨论(0)
提交回复
热议问题