我是靠谱客的博主 精明乌龟,这篇文章主要介绍利用系统位图函数CreateCompatibleBitmap处理截屏图像,现在分享给大家,希望可以做个参考。

Option Explicit
'--------------------------------------------------------------------------
'   您可以在这里添加自己的插件函数,插件的制作和使用方法如下:
'   利用CreateCompatibleBitmap函数,后台截屏,截窗口处理图像,
'   以下是原理与实现过程。
'   2022-1-29备注/杭州/徐宵龙
'--------------------------------------------------------------------------
Private Const DIB_RGB_COLORS        As Long = &H0&
Private Const BI_RGB                As Long = &H0&
Private Const OBJ_BITMAP            As Long = &H7&
Private Type RECT
    Left            As Long
    Top             As Long
    Right           As Long
    Bottom          As Long
End Type

'位图信息头。位图信息头包含了单个像素所用字节数以及描述颜色的格式,
'此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。以下是位图信息头结构的定义
Private Type BITMAPINFOHEADER
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type
'这个结构的长度是固定的,为40个字节(LONG为32位整数),各个域的说明如下:
'biSize'指定这个结构的长度,为40。
'biWidth'指定图象的宽度,单位是象素。
'biHeight'指定图象的高度,单位是象素。
'biPlanes'必须是1,不用考虑。
'biBitCount'指定表示颜色时要用到的位数,常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)(新的.bmp格式支持32位色,这里就不做讨论了)。
'biCompression'指定位图是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)。
'要说明的是,Windows位图可以采用RLE4,和RLE8的压缩格式,但用的不多。我们今后所讨论的只有第一种不压缩的情况,即biCompression为BI_RGB的情况。
'biSizeImage'指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:
'biSizeImage = biWidth ' × biHeight
'要注意的是: 上述公式中的biWidth '必须是4的整倍数(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数。
'举个例子,如果biWidth=240,则biWidth’=240;如果biWidth=241,biWidth’=244)。
'如果biCompression为BI_RGB,则该项可能为零
'biXPelsPerMeter'指定目标设备的水平分辨率,单位是每米的象素个数,关于分辨率的概念。
'biYPelsPerMeter'指定目标设备的垂直分辨率,单位同上。
'biClrUsed'指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2biBitCount。
'biClrImportant'指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

Private Type RGBQUAD
    rgbBlue         As Byte
    rgbGreen        As Byte
    rgbRed          As Byte
    rgbReserved     As Byte
End Type
'rgbBlue
'The intensity of blue in the color.蓝色的颜色强度。
'rgbGreen rgbGreen
'The intensity of green in the color.绿色在色彩的强度。
'rgbRed rgbRed
'The intensity of red in the color.红颜色的强度。
'rgbReserved rgbReserved
'This member is reserved and must be zero.这名成员是保留的,必须为零。

'可见位图信息也是由两部分组成的:位图信息头 + 颜色表
Private Type BITMAPINFO
    bmiHeader       As BITMAPINFOHEADER
    bmiColors       As RGBQUAD
End Type
'Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, _
'    ByVal nNumScans As Long, ByVal lpBits As Long, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
'Private Declare Function GetCurrentObject Lib "gdi32" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetDC Lib "user32" (ByVal Hwnd As Long) As Long
'Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

Private Declare Function GetCurrentObject Lib "gdi32.dll" _
        (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Private Declare Function GetDIBits Lib "gdi32" _
        (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function GetWindowRect Lib "user32.dll" _
        (ByVal Hwnd As Long, ByRef lpRect As RECT) As Long
Private Declare Function DeleteObject Lib "gdi32" _
        (ByVal hObject As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PrintWindow Lib "user32" _
        (ByVal Hwnd As Long, ByVal hdcBlt As Long, ByVal nFlags As Long) As Long
Private Declare Function SelectObject Lib "gdi32" _
        (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function SetDIBitsToDevice Lib "gdi32" _
        (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long

Private Declare Function IsWindow Lib "user32" (ByVal Hwnd As Long) As Long     '判断一个窗口句柄是否有效,Long,非零表示成功,零表示失败
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
        (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long

Private bi24BitInfo As BITMAPINFO
Private bi32BitInfo As BITMAPINFO
Private aBytes()    As Byte

‘以下开始为子函数,实现过程:

Public Function SgetC(ByVal Hwnd As Variant, px As Variant, py As Variant) As String
    '获取单点颜色,1窗口句柄,2指定点X坐标,指定点Y坐标
    Dim hWndTarget  As Long
    Dim rc          As RECT
    Dim iBitmap     As Long
    Dim mDC As Long, nDC As Long
    Dim W As Long, H As Long, NewB As Long
    Dim mBmp As Long
    Dim oldBmp As Long
    Dim Getcs As String
    Dim X0 As Long, Y0 As Long
    hWndTarget = Hwnd
    GetWindowRect hWndTarget, rc        '得到句柄窗口的矩形位置,大小
    '像素点必须是4的倍数,不是的话需要补正为4的倍数,系统是4个像素寻址的。
    W = rc.Right - rc.Left
    W = Int((W + 3) / 4) * 4
    H = rc.Bottom - rc.Top
    If hWndTarget = 0 Or py < 0 Or px < 0 Or px > W Or py > H Then
        SgetC = "ERROR"
        Exit Function
    End If
'''    With bi24BitInfo.bmiHeader          '初始化24位BMP信息头
'''        .biBitCount = 24
'''        .biCompression = BI_RGB
'''        .biPlanes = 1
'''        .biSize = Len(bi24BitInfo.bmiHeader)
'''        .biWidth = W
'''        .biHeight = rc.Bottom - rc.Top
'''    End With
    With bi32BitInfo.bmiHeader          '初始化32位BMP信息头
        .biBitCount = 32
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = Len(bi32BitInfo.bmiHeader)
        .biWidth = W
        .biHeight = H
    End With
    nDC = GetDC(hWndTarget)             '得到指定窗口句柄DC
    mDC = CreateCompatibleDC(nDC)         '创建内存DC
    mBmp = CreateCompatibleBitmap(nDC, W, H)
    'CreateCompatibleBitmap  创建一幅与批定窗口设备有关位图,它与指定的设备场景兼容
    '内存设备场景即与彩色位图兼容,也与单色位图兼容。这个函数的作用是创建一幅与当前选入hdc中的场景兼容。
    '对一个内存场景来说,默认的位图是单色的。倘若内存设备场景有一个DIBSection选入其中,
    '这个函数就会返回DIBSection的一个句柄。如hdc是一幅设备位图,那么结果生成的位图就肯定兼容于设备
    '(也就是说,彩色设备生成的肯定是彩色位图)如果nWidth和nHeight为零,返回的位图就是一个1×1的单色位图
    '一旦位图不再需要,一定用DeleteObject函数释放它占用的内存及资源
    oldBmp = SelectObject(mDC, mBmp)    '把窗口位图选入内存DC
    '每个设备场景都可能有选入其中的图形对象。其中包括位图、刷子、字体、画笔以及区域等等。一次选入设备场景的只能有一个对象。
    '选定的对象会在设备场景的绘图操作中使用。例如,当前选定的画笔决定了在设备场景中描绘的线段颜色及样式
    PrintWindow hWndTarget, mDC, 0      '把窗口截取保存到内存DC中,
'''    ReDim aBytes(0 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight * 3 - 1) As Byte
    ReDim aBytes(0 To bi32BitInfo.bmiHeader.biWidth * bi32BitInfo.bmiHeader.biHeight * 4 - 1) As Byte
    iBitmap = GetCurrentObject(mDC, OBJ_BITMAP)   '用于获得指定类型的当前选定对象
'''     GetDIBits mDC, iBitmap, 0, bi24BitInfo.bmiHeader.biHeight, aBytes(0), bi24BitInfo, DIB_RGB_COLORS
     GetDIBits mDC, iBitmap, 0, H, aBytes(0), bi32BitInfo, DIB_RGB_COLORS
    X0 = px: Y0 = py        '把传进来需要取点的像素坐标付给x0,y0
'''    NewB = ((H - y0 - 1) * W + x0 + 1) * 3 - 1
    NewB = ((H - Y0 - 1) * W + X0) * 4
On Error Resume Next
    Getcs = ChangeH(aBytes(NewB)) & ChangeH(aBytes(NewB + 1)) & ChangeH(aBytes(NewB + 2)) ' & "|" & ChangeH(aBytes(NewB + 3)) 'BGR顺序
    DeleteObject iBitmap
    DeleteObject mBmp
    DeleteObject oldBmp
    DeleteDC mDC
    DeleteDC nDC
    Erase aBytes
'Debug.Print "W=" & W & "  H=" & H
    SgetC = Replace(Getcs, " ", "")     '去除字符串中的空格
End Function

Public Function MutiGetC(ByVal Hwnd As Variant, px As Variant, py As Variant, MutiStr As Variant) As String
'得到多点色彩,1窗口句柄,2基点X坐标,3基点Y坐标,4相对于基点的坐标集合“1,2|3,2”或者"10-15"取150个点
    Dim hWndTarget  As Long
    Dim rc          As RECT
    Dim iBitmap     As Long
    Dim mDC As Long, nDC As Long
    Dim mBmp As Long
    Dim oldBmp As Long
    Dim W As Long, H As Long, NewB As Long, i As Long, j As Long, iall As Long
    Dim Getcs As String
    Dim X0 As Long, Y0 As Long, Xd As Long, Yd As Long, Posi As Long
    Dim ZBtext() As String
    hWndTarget = Hwnd
    GetWindowRect hWndTarget, rc        '得到句柄窗口的矩形位置,大小
'    If (rc.Right - rc.Left) Mod 4 > 0 Then
'        W = rc.Right - rc.Left - ((rc.Right - rc.Left) Mod 4) + 4
'    Else
'        W = rc.Right - rc.Left
'    End If
    W = rc.Right - rc.Left
    W = Int((W + 3) / 4) * 4
    H = rc.Bottom - rc.Top
    If hWndTarget = 0 Or py < 0 Or px < 0 Or px > W Or py > H Then
        MutiGetC = "ERROR"
        Exit Function
    End If
    
    If InStr(MutiStr, ",") > 0 Then             '增加取小块图全部颜色功能,检测是多点坐标,还是色块
        ZBtext = Split(MutiStr, "|")
        iall = UBound(ZBtext)                   '确定上标
    Else
        Posi = InStr(MutiStr, "-")              '确定字符串中“-”在字符串中的位置
        Xd = CLng(Left(MutiStr, Posi - 1))
        Yd = CLng(Right(MutiStr, Len(MutiStr) - Posi))
        iall = Xd * Yd - 1                      '要计算的总像素量,从0开始计数,确定上标
        ReDim ZBtext(0 To iall)
        NewB = 0
        For j = 0 To Yd - 1
            For i = 0 To Xd - 1
              ZBtext(NewB) = CStr(i) & "," & CStr(j)    '把色块坐标转换成相对给定基点的坐标集给字符数组ZBtext()
              NewB = NewB + 1
            Next
        Next
    End If
    
'''    With bi24BitInfo.bmiHeader          '初始化24位BMP信息头
'''        .biBitCount = 24
'''        .biCompression = BI_RGB
'''        .biPlanes = 1
'''        .biSize = Len(bi24BitInfo.bmiHeader)
'''        .biWidth = W
'''        .biHeight = rc.Bottom - rc.Top
'''    End With
    With bi32BitInfo.bmiHeader          '初始化24位BMP信息头
        .biBitCount = 32
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = Len(bi32BitInfo.bmiHeader)
        .biWidth = W
        .biHeight = H
    End With
    nDC = GetDC(hWndTarget)             '得到句柄DC
    mDC = CreateCompatibleDC(nDC)         '创建内存DC
    mBmp = CreateCompatibleBitmap(nDC, W, rc.Bottom - rc.Top)
    oldBmp = SelectObject(mDC, mBmp)
    PrintWindow hWndTarget, mDC, 0      '在内存DC中保存图片
'''    ReDim aBytes(0 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight * 3 - 1) As Byte
    ReDim aBytes(0 To W * H * 4 - 1) As Byte
    iBitmap = GetCurrentObject(mDC, OBJ_BITMAP)   '用于获得指定类型的当前选定对象
'''     GetDIBits mDC, iBitmap, 0, bi24BitInfo.bmiHeader.biHeight, aBytes(0), bi24BitInfo, DIB_RGB_COLORS
     GetDIBits mDC, iBitmap, 0, H, aBytes(0), bi32BitInfo, DIB_RGB_COLORS
    X0 = px: Y0 = py: Getcs = ""
On Error Resume Next
    For i = 0 To iall
        Posi = InStr(ZBtext(i), ",")
        Xd = CLng(Left(ZBtext(i), Posi - 1)): Yd = CLng(Right(ZBtext(i), Len(ZBtext(i)) - Posi))        '取得各像素点的X,Y步长
        X0 = px + Xd: Y0 = py + Yd
        NewB = ((H - Y0 - 1) * W + X0) * 4
        Getcs = Getcs & "|" & ChangeH(aBytes(NewB)) & ChangeH(aBytes(NewB + 1)) & ChangeH(aBytes(NewB + 2)) ' & "," & ChangeH(aBytes(NewB + 3))
    Next
    DeleteObject iBitmap
    DeleteObject mBmp
    DeleteObject oldBmp
    DeleteDC mDC
    DeleteDC nDC
    Erase aBytes
    Erase ZBtext
    MutiGetC = Right(Getcs, Len(Getcs) - 1)
End Function

最后

以上就是精明乌龟最近收集整理的关于利用系统位图函数CreateCompatibleBitmap处理截屏图像的全部内容,更多相关利用系统位图函数CreateCompatibleBitmap处理截屏图像内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部