Solved

GDI+ copy and paste a section of a picture

Posted on 2004-09-18
4
299 Views
Last Modified: 2008-03-06
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
0
Comment
Question by:rdavis101
  • 2
  • 2
4 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
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
0
 

Author Comment

by:rdavis101
Comment Utility
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.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 50 total points
Comment Utility
I think the DrawImage function is what you are after.  Here is an example:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' Get a graphics context from PictureBox2 so we can draw on it
        Dim g As Graphics = PictureBox2.CreateGraphics

        ' Destination Paralleogram
        Dim upperLeftCorner As New Point(0, 0)
        Dim upperRightCorner As New Point(10, 0)
        Dim lowerLeftCorner As New Point(0, 20)
        Dim destinationParallelogram As Point() = {upperLeftCorner, upperRightCorner, lowerLeftCorner}

        ' Portion of Source Image to Copy
        ' 10x20 section at (50,50)
        Dim sourceRectangle As New Rectangle(50, 50, 10, 20)

        ' Draw the portion from PictureBox1 to PictureBox2
        g.DrawImage(PictureBox1.Image, destinationParallelogram, sourceRectangle, GraphicsUnit.Pixel)

        ' Dispose of the graphics object because we created it
        g.Dispose()
    End Sub
0
 

Author Comment

by:rdavis101
Comment Utility
Awesome, dude. Works a treat!

Roger
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now