Using Excel VBA Macro To Capture + Save Screenshot of Specific Area In Same File

前端 未结 3 1713
北荒
北荒 2020-12-08 12:46

I\'m trying to create a macro which uses an ActiveX control button (click) to take a screenshot of my desktop screen and save it within the same excel sheet as the button. H

3条回答
  •  伪装坚强ぢ
    2020-12-08 13:13

    You can try this code in a standard Module in Excel 32 Bit.

    • Screenshots can be captured immediately by calling Sub prcSave_Picture_Screen and it will capture your whole screen and save to the same path as your workbook (You can change the path and file name if you want)
    • Screenshots of an active window can also be captured after calling Sub prcSave_Picture_Active_Window 3 seconds (which is adjustable)

    Source: ms-office-forum.de

    Option Explicit
    
    Private Declare Sub Sleep Lib "kernel32.dll" ( _
        ByVal dwMilliseconds As Long)
    Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" ( _
        ByRef PicDesc As PicBmp, _
        ByRef RefIID As GUID, _
        ByVal fPictureOwnsHandle As Long, _
        ByRef IPic As IPicture) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
        ByVal hdc As Long) As Long
    Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
        ByVal hdc As Long, _
        ByVal nWidth As Long, _
        ByVal nHeight As Long) As Long
    Private Declare Function SelectObject Lib "gdi32.dll" ( _
        ByVal hdc As Long, _
        ByVal hObject As Long) As Long
    Private Declare Function GetDeviceCaps Lib "gdi32.dll" ( _
        ByVal hdc As Long, _
        ByVal iCapabilitiy As Long) As Long
    Private Declare Function GetSystemPaletteEntries Lib "gdi32.dll" ( _
        ByVal hdc As Long, _
        ByVal wStartIndex As Long, _
        ByVal wNumEntries As Long, _
        ByRef lpPaletteEntries As PALETTEENTRY) As Long
    Private Declare Function CreatePalette Lib "gdi32.dll" ( _
        ByRef lpLogPalette As LOGPALETTE) As Long
    Private Declare Function SelectPalette Lib "gdi32.dll" ( _
        ByVal hdc As Long, _
        ByVal hPalette As Long, _
        ByVal bForceBackground As Long) As Long
    Private Declare Function RealizePalette Lib "gdi32.dll" ( _
        ByVal hdc As Long) As Long
    Private Declare Function BitBlt Lib "gdi32.dll" ( _
        ByVal hDestDC As Long, _
        ByVal x As Long, _
        ByVal y As Long, _
        ByVal nWidth As Long, _
        ByVal nHeight As Long, _
        ByVal hSrcDC As Long, _
        ByVal xSrc As Long, _
        ByVal ySrc As Long, _
        ByVal dwRop As Long) As Long
    Private Declare Function DeleteDC Lib "gdi32.dll" ( _
        ByVal hdc As Long) As Long
    Private Declare Function GetDC Lib "user32.dll" ( _
        ByVal hWnd As Long) As Long
    Private Declare Function GetWindowRect Lib "user32.dll" ( _
        ByVal hWnd As Long, _
        ByRef lpRect As RECT) As Long
    Private Declare Function GetSystemMetrics Lib "user32.dll" ( _
        ByVal nIndex As Long) As Long
    Private Declare Function GetForegroundWindow Lib "user32.dll" () As Long
    
    Private Const SM_CXSCREEN = 0&
    Private Const SM_CYSCREEN = 1&
    Private Const RC_PALETTE As Long = &H100
    Private Const SIZEPALETTE As Long = 104
    Private Const RASTERCAPS As Long = 38
    
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    
    Private Type PALETTEENTRY
        peRed As Byte
        peGreen As Byte
        peBlue As Byte
        peFlags As Byte
    End Type
    
    Private Type LOGPALETTE
        palVersion As Integer
        palNumEntries As Integer
        palPalEntry(255) As PALETTEENTRY
    End Type
    
    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(7) As Byte
    End Type
    
    Private Type PicBmp
        Size As Long
        Type As Long
        hBmp As Long
        hPal As Long
        Reserved As Long
    End Type
    
    Public Sub prcSave_Picture_Screen() 'ganzer bildschirm
        stdole.SavePicture hDCToPicture(GetDC(0&), 0&, 0&, _
            GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)), _
            ThisWorkbook.Path & "\Screenshot.bmp" 'anpassen !!!
    End Sub
    
    Public Sub prcSave_Picture_Active_Window() 'aktives Fenster
        Dim hWnd As Long
        Dim udtRect As RECT
        Sleep 3000 '3 sekunden pause um ein anderes Fenster zu aktivieren
        hWnd = GetForegroundWindow
        GetWindowRect hWnd, udtRect
        stdole.SavePicture hDCToPicture(GetDC(0&), udtRect.Left, udtRect.Top, _
            udtRect.Right - udtRect.Left, udtRect.Bottom - udtRect.Top), _
            ThisWorkbook.Path & "\Screenshot.bmp" 'anpassen !!!
    End Sub
    
    Private Function CreateBitmapPicture(ByVal hBmp As Long, ByVal hPal As Long) As Object
        Dim Pic As PicBmp, IPic As IPicture, IID_IDispatch As GUID
        With IID_IDispatch
            .Data1 = &H20400
            .Data4(0) = &HC0
            .Data4(7) = &H46
        End With
        With Pic
            .Size = Len(Pic)
            .Type = 1
            .hBmp = hBmp
            .hPal = hPal
        End With
        Call OleCreatePictureIndirect(Pic, IID_IDispatch, 1, IPic)
        Set CreateBitmapPicture = IPic
    End Function
    
    Private Function hDCToPicture(ByVal hDCSrc As Long, ByVal LeftSrc As Long, _
        ByVal TopSrc As Long, ByVal WidthSrc As Long, ByVal HeightSrc As Long) As Object
        Dim hDCMemory As Long, hBmp As Long, hBmpPrev As Long
        Dim hPal As Long, hPalPrev As Long, RasterCapsScrn As Long, HasPaletteScrn As Long
        Dim PaletteSizeScrn As Long, LogPal As LOGPALETTE
        hDCMemory = CreateCompatibleDC(hDCSrc)
        hBmp = CreateCompatibleBitmap(hDCSrc, WidthSrc, HeightSrc)
        hBmpPrev = SelectObject(hDCMemory, hBmp)
        RasterCapsScrn = GetDeviceCaps(hDCSrc, RASTERCAPS)
        HasPaletteScrn = RasterCapsScrn And RC_PALETTE
        PaletteSizeScrn = GetDeviceCaps(hDCSrc, SIZEPALETTE)
        If HasPaletteScrn And (PaletteSizeScrn = 256) Then
            LogPal.palVersion = &H300
            LogPal.palNumEntries = 256
            Call GetSystemPaletteEntries(hDCSrc, 0, 256, LogPal.palPalEntry(0))
            hPal = CreatePalette(LogPal)
            hPalPrev = SelectPalette(hDCMemory, hPal, 0)
            Call RealizePalette(hDCMemory)
        End If
        Call BitBlt(hDCMemory, 0, 0, WidthSrc, HeightSrc, hDCSrc, LeftSrc, TopSrc, 13369376)
        hBmp = SelectObject(hDCMemory, hBmpPrev)
        If HasPaletteScrn And (PaletteSizeScrn = 256) Then
            hPal = SelectPalette(hDCMemory, hPalPrev, 0)
        End If
        Call DeleteDC(hDCMemory)
        Set hDCToPicture = CreateBitmapPicture(hBmp, hPal)
    End Function
    

提交回复
热议问题