[VB.NET] 윈도우 프로그램과 폼안의 객체만 따로 캡쳐하기 > vb.net

본문 바로가기

vb.net

[기타] [VB.NET] 윈도우 프로그램과 폼안의 객체만 따로 캡쳐하기

회원사진
하나를하더라도최선을
2022-09-06 13:54 4,283 0

본문



훔쳐온곳: h t t p s : / / m . b l o g . n a v e r . c o m / r o l e _ _ _ p l a y / 2 2 0 5 6 7 7 8 9 9 6 8


Imports System.Runtime.InteropServices
Public Class Form1
    'SendMessage 의 캡쳐 메세지
    Private Const WM_PAINT = &HF
    '''
    ''' GDI32 API 함수를 가지고있는 클래스입니다.
    '''
    Private Class GDI32
        Public Const SRCCOPY As Integer = &HCC0020
        ' BitBlt dwRop parameter
        <DllImport("gdi32.dll")> _
        Public Shared Function BitBlt(hObject As IntPtr, nXDest As Integer, nYDest As Integer, nWidth As Integer, nHeight As Integer, hObjectSource As IntPtr, _
        nXSrc As Integer, nYSrc As Integer, dwRop As Integer) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleBitmap(hDC As IntPtr, nWidth As Integer, nHeight As Integer) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleDC(hDC As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteDC(hDC As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteObject(hObject As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function SelectObject(hDC As IntPtr, hObject As IntPtr) As IntPtr
        End Function
    End Class
    '''
    ''' User32 API 함수를 가지고있는 클래스입니다.
    '''
    Private Class User32
        <StructLayout(LayoutKind.Sequential)> _
        Public Structure RECT
            Public left As Integer
            Public top As Integer
            Public right As Integer
            Public bottom As Integer
        End Structure
        <DllImport("user32.dll", EntryPoint:="SendMessageA")> _
        Public Shared Function SendMessage(hWnd As IntPtr, wMsg As Integer, wParam As IntPtr, lParam As IntPtr) As UInteger
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function GetDesktopWindow() As IntPtr
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As IntPtr
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef rect As RECT) As IntPtr
        End Function
    End Class
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim bmp As Image = Nothing
        '프로세스가 체크되어있을경우
        If cbProcess.Checked = True Then
            'pname 변수에 프로세스를 담고
            Dim pname As IntPtr = GetProcess(txtName.Text)
            '캡쳐하여 변수에 저장합니다.
            bmp = CaptureWindow(pname)
            '폼 객체가 체크되어있을경우
        ElseIf cbFormObject.Checked = True Then
            'cname 변수에 컨트롤을 담고
            Dim cname As Control = StringToControl(txtName.Text)
            '캡쳐하여 변수에 저장합니다.
            bmp = getSnapShot(cname)
        End If
        '이미지를 띄웁니다.
        PictureBox1.Image = bmp
    End Sub
    ''' <summary>
    ''' 폼에 있는 객체를 캡쳐합니다.
    ''' </summary>
    ''' <param name="control"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function getSnapShot(control As System.Windows.Forms.Control) As Bitmap
        Try
            Dim image As Image = New Bitmap(control.Width, control.Height)
            ' 어느 컨트롤로 부터 그래픽 객체를 얻습니다.
            Dim g As Graphics = Graphics.FromImage(image)
            Dim hDCT As IntPtr = g.GetHdc()
            User32.SendMessage(control.Handle, WM_PAINT, hDCT, IntPtr.Zero)
            g.ReleaseHdc(hDCT)
            g.Dispose()
            Return New Bitmap(image)
        Catch ex As Exception
        End Try
        Return Nothing
    End Function
    ''' <summary>
    ''' 윈도우에 있는 프로그램을 캡쳐합니다.
    ''' </summary>
    ''' <param name="handle"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CaptureWindow(handle As IntPtr) As Image
        ' 대상 윈도우의 hDC를 얻습니다.
        Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
        ' 사이즈를 얻습니다.
        Dim windowRect As New User32.RECT()
        User32.GetWindowRect(handle, windowRect)
        Dim width As Integer = windowRect.right - windowRect.left
        Dim height As Integer = windowRect.bottom - windowRect.top
        ' 복사할 수 있는 드라이브 장치를 만듭니다.
        Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
        ' 복사할 수 있는 비트맵 변수를 만듭니다.
        ' GetDeviceCaps 를 사용하여 너비/높이를 얻습니다.
        Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
        ' 비트맵 객체를 선택합니다.
        Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
        ' bitblt 처리
        GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, _
            0, 0, GDI32.SRCCOPY)
        ' 선택한것을 복원합니다.
        GDI32.SelectObject(hdcDest, hOld)
        ' 마무리
        GDI32.DeleteDC(hdcDest)
        User32.ReleaseDC(handle, hdcSrc)
        ' 이것으로 .NET 이미지 객체를 얻습니다.
        Dim img As Image = Image.FromHbitmap(hBitmap)
        ' 비트맵 객체를 지워줘서 공간을 확보해줍니다.
        GDI32.DeleteObject(hBitmap)
        Return img
    End Function
    ''' <summary>
    ''' 해당 프로세스를 찾아 반환합니다.
    ''' </summary>
    ''' <param name="name"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetProcess(name As String) As IntPtr
        Dim targetwindow As IntPtr ' targetwindow의 변수를 만들어준다.
        Dim a() As System.Diagnostics.Process = System.Diagnostics.Process.GetProcesses ' a는 프로세스를 가져오는 변수로 만들어준다.
        For Each p In a 'a에 p가 있을떄까지 포문을 돌립니다.
            If p.ProcessName = txtName.Text Then ' p의 프로세스 이름을 정해줍니다.
                targetwindow = p.MainWindowHandle 'targetwindow 변수는 프로세스의 메인윈도우핸들 값이 되고.
                Return targetwindow
                Exit For '찾았으니 포문을 탈출합니다.
            End If
        Next
        Return Nothing
    End Function
    ''' <summary>
    ''' 문자열형식을 Control형식으로 바꾸어 반환합니다.
    ''' </summary>
    ''' <param name="name"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function StringToControl(name As String) As Control
        Try
            '컨트롤을 찾아 저장시킬 변수를 만듭니다.
            Dim ControlName As Control = Nothing
            '컨트롤을 찾기위해 반복적으로 검색합니다.
            Dim SearchedControls = Me.Controls.Find(key:=name, searchAllChildren:=True)
            '한개의 컨트롤을 발견했을 경우
            If SearchedControls.Count = 1 Then
                '변수에 담습니다.
                ControlName = SearchedControls(0)
                Return ControlName
            End If
        Catch ex As Exception
        End Try
        Return Nothing
    End Function
    Private Sub cbProcess_CheckedChanged(sender As Object, e As EventArgs) Handles cbProcess.CheckedChanged
        If cbProcess.Checked = True Then
            cbFormObject.Checked = False
        End If
    End Sub
    Private Sub cbFormObject_CheckedChanged(sender As Object, e As EventArgs) Handles cbFormObject.CheckedChanged
        If cbFormObject.Checked = True Then
            cbProcess.Checked = False
        End If
    End Sub
End Class

댓글목록0

등록된 댓글이 없습니다.
게시판 전체검색