加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

VB中的窗口位图

发布时间:2020-12-16 22:33:20 所属栏目:大数据 来源:网络整理
导读:1. 影响 VB 窗口中位图的属性 1) BackColor 属性:该属性确定窗口背景颜色。 2) Picture 属性:该属性用于作为窗口背景的图片,在窗口内部,该属性封装了一个 BITMAP 的 GDI 对象。 3) hDC 、 Image 及 AutoReDraw 属性: a) 如果设置为 AutoReDraw(True) 则

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读