Link to home
Start Free TrialLog in
Avatar of rdavis101
rdavis101

asked on

GDI+ copy and paste a section of a picture

Say I have two picture boxes on a form. One holds an image and the other is empty. I want to copy a section from the left side of PictureBox1 and display it in PictureBox2 using the GDI classes. Say I want the section to be 10 pixels wide.

Roger
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Here is some lightning fast, generic screen capture code.  You press F9 to start dragging a rectangular region on the screen and then press F9 again to copy the selected area to the Panel on the Form.  The code calls the GetScreen() function using the screen coordinates of the selected region.  You can call the function directly with your required coordinates though.  You would just need to convert your PictureBox coordinates to screen coordinates using the PointToScreen() function.

Regards,

Idle_Mind

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Panel1 As System.Windows.Forms.Panel
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Timer1 As System.Windows.Forms.Timer
    Friend WithEvents NotifyIcon1 As System.Windows.Forms.NotifyIcon
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Me.Panel1 = New System.Windows.Forms.Panel
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.Label1 = New System.Windows.Forms.Label
        Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
        Me.NotifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
        Me.Panel1.SuspendLayout()
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.Panel1.AutoScroll = True
        Me.Panel1.BackColor = System.Drawing.Color.LightPink
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Controls.Add(Me.PictureBox1)
        Me.Panel1.Location = New System.Drawing.Point(8, 40)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(292, 276)
        Me.Panel1.TabIndex = 1
        '
        'PictureBox1
        '
        Me.PictureBox1.Location = New System.Drawing.Point(0, 0)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(184, 128)
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(8, 8)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(296, 24)
        Me.Label1.TabIndex = 2
        Me.Label1.Text = "Label1"
        Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
        '
        'Timer1
        '
        Me.Timer1.Interval = 25
        '
        'NotifyIcon1
        '
        Me.NotifyIcon1.Text = "RubberBand Screen Capture Demo"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(312, 326)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.Panel1)
        Me.Name = "Form1"
        Me.Text = "RubberBand Screen Capture Demo"
        Me.Panel1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Enum HotKeyModifiers
        None = &H0
        Alt = &H1
        Control = &H2
        Shift = &H4
        Windows = &H8
    End Enum

    Private Const SRCCOPY = &HCC0020

    Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, ByVal lpInitData As String) As Integer
    Private Declare Function CreateCompatibleDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function CreateCompatibleBitmap Lib "GDI32" (ByVal hDC As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
    Private Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
    Private Declare Function BitBlt Lib "GDI32" (ByVal hDestDC As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As Integer, ByVal SrcX As Integer, ByVal SrcY As Integer, ByVal Rop As Integer) As Integer
    Private Declare Function DeleteObject Lib "GDI32" (ByVal hObj As Integer) As Integer
    Private Declare Function DeleteDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Boolean
    Private Declare Function UnregisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean

    Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hWnd As IntPtr, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As IntPtr
    Private Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Integer

    Private startX As Integer
    Private startY As Integer
    Private lastX As Integer
    Private lastY As Integer
    Private curX As Integer
    Private curY As Integer
    Private boxDrawn As Boolean = False
    Private hotKeySet As Boolean = False
    Private capturing As Boolean = False

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        RegisterHotKey(HotKeyModifiers.None, Keys.F9)
        If Not hotKeySet Then
            Label1.Text = "Unable to Set Hotkey F9"
            MsgBox("Unable to Set Hotkey F9")
        Else
            Label1.Text = "Press F9 to Start/Stop area selection"
        End If
    End Sub

    Private Function GetScreen(ByVal X As Integer, ByVal Y As Integer, ByVal Width As Integer, ByVal Height As Integer) As Bitmap
        Dim hDeskDC As Integer
        Dim hTempDC As Integer
        Dim hBitmap As Integer
        Dim hTempBmp As Integer
        Dim desktopArea As Bitmap

        hDeskDC = CreateDC("DISPLAY", "", "", "")
        If hDeskDC Then
            hTempDC = CreateCompatibleDC(hDeskDC)
            If hTempDC Then
                hBitmap = CreateCompatibleBitmap(hDeskDC, Width, Height)
                If hBitmap Then
                    hTempBmp = SelectObject(hTempDC, hBitmap)
                    BitBlt(hTempDC, 0, 0, Width, Height, hDeskDC, X, Y, SRCCOPY)
                    desktopArea = Bitmap.FromHbitmap(New IntPtr(hBitmap))
                    DeleteObject(SelectObject(hTempDC, hTempBmp))
                End If
                DeleteDC(hTempDC)
            End If
            DeleteDC(hDeskDC)
        End If
        Return desktopArea
    End Function

    Public Sub RegisterHotKey(ByVal mods As Integer, ByVal key As Integer)
        If hotKeySet Then
            UnregisterHotKey()
        End If
        hotKeySet = RegisterHotKey(Me.Handle, 0, mods, key)
    End Sub

    Public Sub UnRegisterHotkey()
        If hotKeySet Then
            hotKeySet = Not UnregisterHotKey(Me.Handle, 0)
        End If
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_HOTKEY As Integer = &H312

        Select Case m.Msg
            Case WM_HOTKEY
                hotKeyPressed()

        End Select
        MyBase.WndProc(m)
    End Sub

    Private Sub hotKeyPressed()
        If Not capturing Then
            capturing = True
            boxDrawn = False
            startX = Cursor.Position.X
            startY = Cursor.Position.Y
            lastX = startX
            lastY = startY
            Timer1.Enabled = True
        Else
            capturing = False
            Timer1.Enabled = False
            If boxDrawn Then
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
                PictureBox1.Image = GetScreen(Math.Min(startX, curX), Math.Min(startY, curY), Math.Abs(curX - startX), Math.Abs(curY - startY))
                PictureBox1.Width = PictureBox1.Image.Width
                PictureBox1.Height = PictureBox1.Image.Height
            End If
        End If
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If capturing Then
            curX = Cursor.Position.X
            curY = Cursor.Position.Y
            If curX <> lastX Or curY <> lastY Then
                If Not boxDrawn Then
                    boxDrawn = True
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, curX - startX, curY - startY), Color.Black, FrameStyle.Dashed)
                Else
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, curX - startX, curY - startY), Color.Black, FrameStyle.Dashed)
                End If
                lastX = curX
                lastY = curY
            End If
        End If
    End Sub

    Private Sub Form1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged
        If Me.WindowState = FormWindowState.Minimized Then
            If Not (NotifyIcon1.Icon Is Nothing) Then
                Me.Hide()
                NotifyIcon1.Visible = True
            End If
        End If
    End Sub

    Private Sub NotifyIcon1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.DoubleClick
        NotifyIcon1.Visible = False
        Me.Show()
        Me.WindowState = FormWindowState.Normal
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        UnregisterHotKey()
    End Sub

End Class
Avatar of rdavis101
rdavis101

ASKER

Thanks, your code looks real good, but I'm just looking to learn how to copy a section of one picture to another picture, using the .Net GDI

Roger.
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Awesome, dude. Works a treat!

Roger