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处理截屏图像内容请搜索靠谱客的其他文章。
发表评论 取消回复