@bobnoordam

Reading screen pixels from the main screen, and specific other application windows

Reading from the full screen

This code sample reads the pixel of the screen that the mouse points to, and changes the form’s background color to match that pixel’s color. Note that this code attaches to the main screen, and not to the window of a specific application. If you want to attach to a specific application’s window and read inside that, the sample lower on the page applies.

Public Class Form1
  
    Public Declare Function GetPixel Lib "gdi32.dll" (ByVal hdc As IntPtr, _
                                                      ByVal nXPos As Int32, _
                                                      ByVal nYPos As Int32 _
                                                     ) As Int32
  
    Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr
  
    Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As IntPtr, _
                                                         ByVal hdc As IntPtr _
                                                        ) As Int32
  
    Private mainhdc = New IntPtr()
  
    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
  
        mainhdc = GetDC(IntPtr.Zero)
  
        While True ' --- endless loop
            BackColor = ColorTranslator.FromWin32(GetPixel(mainhdc, Cursor.Position.X, Cursor.Position.Y))
            Application.DoEvents()
        End While
  
    End Sub
End Class

Reading from a specific applications window

For the second sample, start notepad and type some text on the top line. The programm will retrieve a handle to the notepad window, and copy the upper left part of that window to the form.

Public Class Form1
  
    Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr
  
    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
  
        ' --- GetProcessByName attaches to the friendly name of a process, so without path and the .exe
        Dim oProc As Process() = Process.GetProcessesByName("notepad")
        If oProc.Length = 0 Then
            MsgBox("Unable to find the notepad.exe process")
            End
        End If
  
        ' --- Get a handle to
        Dim ptrWindowhandle As IntPtr = oProc(0).MainWindowHandle
        Dim ptrNotepadhdc As IntPtr = GetDC(ptrWindowhandle)
  
        ' --- Create a graphics object on the current form1
        Dim oGraphics As Graphics = Me.CreateGraphics
  
        ' --- Loop some notepad pixels and draw them on the form
        '     If you typed something in the notepad window it will appear on the Form
        '     If you left notepad blank just a white block will appear
        For x = 1 To 50
            For y = 1 To 50
                ' --- Get the pixel from the notepad window handle
                Dim oPixelcolor As Color = ColorTranslator.FromWin32(GetPixel(ptrNotepadhdc, x, y))
                ' --- we cant set a pixel directly on a gdi+ surface, so we need to resort
                '     to creating a single pixel bitmap in the correct color, and placing that
                Dim bm As Bitmap = New Bitmap(1, 1)
                bm.SetPixel(0, 0, oPixelcolor)
                oGraphics.DrawImageUnscaled(bm, x, y)
            Next
        Next
  
    End Sub
End Class

as minitech pointed out here there is a shorter and more “.net way” method to read pixels from the screen if you are not interested in attaching to a specific process.

Private Function GetScreenColor(ByVal location As Point)
     Dim bmp As New Bitmap(1, 1)
     Using g As Graphics = Graphics.FromImage(bmp)
          g.CopyFromScreen(location, Point.Empty, New Size(1, 1))
     End Using
     Return bmp.GetPixel(0, 0)
End Function