微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

VB中的窗口位图

1. 影响VB窗口中位图的属性

1) BackColor属性:该属性确定窗口背景颜色。

2) Picture属性:该属性用于作为窗口背景的图片,在窗口内部,该属性封装了一个BITMAPGDI对象。

3) hDCImageAutoReDraw属性

a) 如果设置为AutoReDraw(True) 则:

Ø hDC1个内存DCImage属性值是选入hDC的位图句柄,此时GetCurrentObject(hDC,OBJ_BITMAP)=Image(朋友们自行验证)。

Ø 在窗口输出操作代码PrintCircle输出到内存DC中,然后再从内存DC拷贝到目标窗口。

Ø VB没有提供目标窗口的DC,如果需要目标窗口的DC,需要使用GetDC获取,使用ReleaseDC释放。

Ø 如果使用API输出hDC输出后,必须使用Refresh输出反映到目标窗口,如果使用VB自带的绘图及文字输出方法,则不需要使用Refresh

Ø 不会产生Paint事件,对应于WindowsPaint消息,只是简单的将Image内容拷贝到目标窗口。取代之,是在运行开始,会产生Show事件,可以在Show事件。

Ø 如果使用APIGetDIBits方法,将获取窗口的前景及背景内容

Ø 事实上,AutoReDraw(True)时,窗口绘画就是一种双缓冲机制,但此机制有缺陷,其可绘图空间VB被限制和窗口尺寸一致,无法大于窗口尺寸。

b) 如果设置为非AutoReDraw (False) 则:

Ø hDC一个和窗口关联的设备DC

Ø Image属性仍然和一个位图对象关联,只是这个位图的内容BackColor属性Picture属性决定,每次BackColor或者Picrure改变,则会重新生成Image对应的位图对象。BackColor属性Picture不能完全填充窗口时候填充Picture之外的部分。

Ø Image对象将作为目标窗口的背景。CLS操作,就是讲Image对象内容拷贝到目标窗口。

Ø 对应于WindowsPaint消息,将产生VBPaint事件,VB程序一般在该事件中,提供绘画窗口的代码,实现输出

Ø 如果使用APIGetDIBits方法,只能获取窗口的背景内容BackColorPicture属性相关)。AutoReDraw (False)时,如何获取前景的内容,后续介绍中将给出代码。)

Ø

无论AutoReDraw为何,当窗口尺寸改变时,将重建Image,以使得Imge的大小和窗口一致

c) AutoReDrawTrue变为False,则True状态下的绘画输出,在变为AutoReDraw(False)后,绘图输出将成为背景的一部分,此Cls,将不能清除True时的绘画输出;要清除True时的绘图输出,则只再设置AutoReDraw(True)

d) AutoReDrawFalse变为True VB会使用BackColorPicture属性值重新加载背景,前景将被取消

2. 获取完整的窗口位图数据:

AutoReDraw(True)时,Image实际上是一个和窗口内容一致的位图句柄,可以直接将Image属性直接赋值给另一个控件或窗口的Picture属性,或者以Image属性作为句柄,使用API调用获取窗口内容数据;此时,一般都能得到窗口背景及前景的位图内容

Picture2.Picrure=Picture1.Image ‘Picture1显示内容拷贝到Picture2Picrure属性

或者:

With Picture1

nLines=GetDiBits(.Hdc,.Image,mImgLine,ImgData(0),bmpInfoHeader,BI_RGB)

nLines=GetDiBits(.Hdc,Picture2.Image,BI_RGB)

end with

但是,使用Image属性获取位图,是无法获取下面几种情况的位图的:

1) 在非AutoReDraw(False)时,使用Image属性只能得到背景的图像,使用VB绘图方法及在hDC(窗口或者控件的hDC属性)上使用API绘图输出,这些输出都不能通过Image属性获得。

2) AutoReDraw(True)时,如果绘图操作是使用API输出到窗口的DC(不是控件的hDC,是使用hDCx=GetDC()得到的窗口DC)中,则该部分的位图内容是无法通过Image属性获取。同时,读取Image属性值的时候,VB会重新使用Image内容更新窗口显示,从而使得窗口丢失使用上述方法的前景的输出

3) 如果窗口或者控件上,有别的控件,那么这些控件虽然显示在窗口上,但是是不能通过Image属性获得。

因此,要想获得窗口的所有位图,只有使用hWnd属性而获得真正的窗口DC(称之为hDCx),然后通过hDCx的位图句柄hBmp,再通过hBmp获取位图数据;但是问题没有这么简单,因为Windows不允许直接读取窗口DC的位图数据,因此,还得将窗口位图拷贝到内存位图中后,才能读取位图数据。以下是完整的使用DIB读取窗口位图的函数

Private Function GetwindowBmp(hWnd As Long,BmpInfo As BitmapInfo,nBits As Long,Optional mOffset As Long = 0) As Byte()

Dim hDCx As Long

Dim hBmp As Long

Dim r As Long

Dim hMemDC As Long

Dim nWidth As Long,nHeight As Long

Dim Rect As Rect

Dim ImgData() As Byte

Dim mLine As Long

Dim mLineBytes As Long

Call GetwindowRect(hWnd,Rect)

nWidth = Rect.Right - Rect.Left

nHeight = Rect.Bottom - Rect.Top

hDCx = GetDC(hWnd)

hMemDC = CreateCompatibleDC(hDCx)

hBmp = CreateCompatibleBitmap(hDCx,nWidth,nHeight)

r = SelectObject(hMemDC,hBmp)

r = BitBlt(hMemDC,nHeight,hDCx,vbSrccopy)

With BmpInfo.bmiHeader

.biSize = Len(BmpInfo.bmiHeader)

.biWidth = nWidth

.biHeight = nHeight

.biPlanes = 1

.biBitCount = nBits

.biCompression = BI_RGB

End With

mLineBytes = (((nWidth * nBits) + &H1F) And &HFFFFFFE0) \ &H8

ReDim ImgData(mLineBytes * nHeight - 1 + mOffset)

mLine = GetDIBits(hDCx,hBmp,ImgData(mOffset),BmpInfo,BI_RGB)

GetwindowBmp = ImgData

DeleteDC hMemDC

ReleaseDC hWnd,hDCx

DeleteObject hBmp

End Function

函数返回窗口hWnd显示的所有位图数据的数组,位图数据在该数组的mOffset位置开始放置,mOffset前的字节为保留字节(后面将介绍这些保留字节的用途),参数BmpInfo一个BitmapInfo的数据结构,调用时候只要定义,不需给结构成员赋值,函数会按照窗口的位图数据自动填充,函数调用者,一般需要使用该结构返回的数据。

3. 获取位图数据进行处理:

以下代码用于获取Pic1的位图数据到一个数组中,然后将其转换为灰度图像的数据,再将灰度 图像拷贝到Pic2中进行显示显示时,我们使用Pic2Image属性,使用该属性能将拷贝入的位图保持住。

Private Sub Command3_Click()

Dim ImgData() As Byte

Dim mLineBytes As Long

Dim BitmapInfo As BitmapInfo

Dim mLineBytesA As Long

Dim mIdx As Long

Dim x As Long,y As Long,C As Long

Dim mLineFromIdx As Long

Dim mBytesPerPix As Long

ImgData = GetwindowBmp(Pic1.hWnd,BitmapInfo,32&) '获取Pic1窗口上显示的位图数据

With BitmapInfo.bmiHeader

'计算每行字节数

mLineBytes = .biWidth * .biBitCount / 8

If mLineBytes Mod 4 <> 0 Then

mLineBytesA = ((mLineBytes + 3) \ 4) * 4

Else

mLineBytesA = mLineBytes

End If

mBytesPerPix = .biBitCount / 8 '每像素字节数

For y = 0 To .biHeight - 1

mIdx = mLineFromIdx

For x = 0 To mLineBytes - 1 Step mBytesPerPix

C = ImgData(mIdx)

C = (C + ImgData(mIdx + 1) + ImgData(mIdx + 2)) / 3

ImgData(mIdx) = C

ImgData(mIdx + 1) = C

ImgData(mIdx + 2) = C

mIdx = mIdx + mBytesPerPix

Next

mLineFromIdx = mLineFromIdx + mLineBytesA

Next

End With

SetDIBits 0,Pic2.Image,BitmapInfo.bmiHeader.biHeight,BI_RGB

如果Pic2.Image改为Pic1.Image则,将Pic1彩色改变为黑白

Pic2.Refresh

End Sub

原文地址:https://www.jb51.cc/vb/260152.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐