none
Screen capture and display zooming RRS feed

  • Question

  • For some number of years I have been using the code listed below to capture my app's form.  What I am now seeing is that if users is scaling the display to anything over 100% then part of the form is missing when captured.  Anyone know of a way to account for the scaling factor so the whole form gets captured?

    Private Sub CaptureScreen() Dim myGraphics As Graphics = Me.CreateGraphics() Dim s As Size = Me.Size My.Application.DoEvents() ' ensure drop downs are hidden b4 capturing image

    memoryImage = New Bitmap(s.Width, s.Height, myGraphics)

    Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)

    memoryGraphics.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, s) myGraphics.Dispose() memoryGraphics.Dispose() End Sub


    TIA


    Terry

    Monday, October 29, 2018 10:08 PM

All replies

  •  You can try turning on your application's dpiaware setting in the app.manifest file.  I recently explained how you can try doing that at the link below.

     https://social.msdn.microsoft.com/Forums/en-US/842b75bc-c8e5-4b1d-9b15-5249dc508c6e/bad-resolution-with-textrenderer?forum=vbgeneral

     

     If you don't want to do it that way or if that does not work for some reason,  then you can use the GetDeviceCaps api function to get the scaling ratio of the screen which you use to multiply the X, Y, Width, and Height by.  I have shown 2 examples/answers in the two links below.

     Capture screen with high DPI

     Using CopyFromScreen returns different images when text size changes


    If you say it can`t be done then i`ll try it

    Monday, October 29, 2018 11:40 PM
  • Hi

    Another way. This is put together from various Internet sources found. This example: comment in/out the marked line to see the difference between DPIAware or not DPIAware. The saved image is displayed in PictureBox1 and also saved to the DeskTop.

    NOTE: you should see a marked difference of your initial Form.

    'BMP SCREENGRAB DPIAWARE
    
    ' Form1 with PictureBox1 (Docked - Full)
    
    Option Strict On
    Option Explicit On
    Imports System.Runtime.InteropServices
    Public Class Form1
      <DllImport("user32.dll", EntryPoint:="SetProcessDPIAware")> Private Shared Function SetToDPIAware() As <MarshalAs(UnmanagedType.Bool)> Boolean
      End Function
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Comment this line in/out to see difference in saved image
        Dim std As Boolean = SetToDPIAware()
    
        GrabScreen()
      End Sub
      Private Sub GrabScreen()
        Dim sz As Size = Screen.PrimaryScreen.Bounds.Size
        Using bmp As New Bitmap(sz.Width + 1, sz.Height + 1)
          Using g As Graphics = Graphics.FromImage(bmp)
            g.CopyFromScreen(Point.Empty, Point.Empty, sz, CopyPixelOperation.SourceCopy)
          End Using
          PictureBox1.ImageLocation = My.Computer.FileSystem.SpecialDirectories.Desktop & "\Grabbed.png"
          bmp.Save(PictureBox1.ImageLocation, Imaging.ImageFormat.Png)
          PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
          PictureBox1.Load()
        End Using
      End Sub
    End Class



    Regards Les, Livingston, Scotland


    • Edited by leshay Monday, October 29, 2018 11:59 PM
    Monday, October 29, 2018 11:48 PM
  • Hi,

    DPI is how scaling setting is implemented. Their relationship is:
    96 DPI = 100% scaling

    120 DPI = 125% scaling

    144 DPI = 150% scaling

    192 DPI = 200% scaling

    Read the DPI setting like so:

     Dim dpiX, dpiY As Single
        Dim graphics As Graphics = Me.CreateGraphics()
        dpiX = graphics.DpiX
        dpiY = graphics.DpiY

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, October 30, 2018 2:46 AM
  • I have tried this and I get no difference between "SetToDPIAware" and not doing it.  Also I have tried checking the dpix values based on the other answer I got and it is always 96 no matter what the scaling is.  And it makes no difference if I use the user32.dll method to do it or try and do it through the app.manifest file as someone suggested. 

    I have not tried the suggestion about GetDeviceCaps but have come up with something that seems to work - although I am not sure I like it:

    SendKeys.Send("%{PRTSC}")


    Terry

    Friday, November 9, 2018 8:29 PM
  • I have tried this and I get no difference between "SetToDPIAware" and not doing it.  Also I have tried checking the dpix values based on the other answer I got and it is always 96 no matter what the scaling is.  And it makes no difference if I use the user32.dll method to do it or try and do it through the app.manifest file as someone suggested. 

    I have not tried the suggestion about GetDeviceCaps but have come up with something that seems to work - although I am not sure I like it:

    SendKeys.Send("%{PRTSC}")


    Terry

    Hi

    Here is an odd-ball idea, but is something I use all the time. This may not be of use for your particular issue, but, it is easy to try out and see if it helps.

    On my system, I have a high definition screen and for any project, if I use the designer with the Form resized above the default, when I add controls etc and run the application, the controls become out of place, or indeed, off the Form altogether. It has definately something to do with DPIaware, but my simple solution doesn't need that.

    All I need to do, is when finished in the Designer, I resize the Form to a 'small' size (in the Designer) - roughly close to default (if permitted ny minimum size property). When doing this, controls can become jumbled up together, but, in the Form load event, resize to any size sorts that out (and doesn't have the misplaced controls as described above.)


    Regards Les, Livingston, Scotland

    Friday, November 9, 2018 10:31 PM

  • I have tried this and I get no difference between "SetToDPIAware" and not doing it.  Also I have tried checking the dpix values based on the other answer I got and it is always 96 no matter what the scaling is.  And it makes no difference if I use the user32.dll method to do it or try and do it through the app.manifest file as someone suggested. 

    I have not tried the suggestion about GetDeviceCaps but have come up with something that seems to work - although I am not sure I like it:

    SendKeys.Send("%{PRTSC}")


    Terry

    This shows how to use getdevcaps which is the best way to get the screen size for win 8,10 and etc. It is based on Razerz examples in the links he gives above. Give it a try and let us know what screen res works or not.

    The example shows the screen size in the form title and the screen capture in the form.

    Imports System.Runtime.InteropServices
    Public Class Form4
        'dpi aware screen capture
        Private Const DESKTOPVERTRES As Integer = &H75
        Private Const DESKTOPHORZRES As Integer = &H76
    
        <DllImport("gdi32.dll")> Private Shared Function GetDeviceCaps(ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
        End Function
    
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.BackgroundImageLayout = ImageLayout.Zoom
    
            Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
                Dim hdc As IntPtr = g.GetHdc
                Dim sz As New Size(GetDeviceCaps(hdc, DESKTOPHORZRES), GetDeviceCaps(hdc, DESKTOPVERTRES))
    
                Me.Text = sz.Width.ToString & " x " & sz.Height.ToString
    
                Using bmp As New Bitmap(sz.Width, sz.Height),
                    g2 As Graphics = Graphics.FromImage(bmp)
                    g2.CopyFromScreen(Point.Empty, Point.Empty, sz, CopyPixelOperation.SourceCopy)
    
                    Me.BackgroundImage = CType(bmp.Clone, Image)
                    'bmp.Save("C:\test\screen1.png", Imaging.ImageFormat.Png)
                End Using
    
                g.ReleaseHdc(hdc)
            End Using
        End Sub
    End Class

    Saturday, November 10, 2018 12:04 AM