VB中的窗口位图
来源:互联网 发布:房产销售提成软件 编辑:程序博客网 时间:2024/06/06 16:38
1. 影响VB窗口中位图的属性
1) BackColor属性:该属性确定窗口背景颜色。
2) Picture属性:该属性用于作为窗口背景的图片,在窗口内部,该属性封装了一个BITMAP的GDI对象。
3) hDC、Image及AutoReDraw属性:
a) 如果设置为AutoReDraw(True) 则:
Ø hDC为1个内存DC,Image属性值是选入hDC的位图句柄,此时GetCurrentObject(hDC,OBJ_BITMAP)=Image(朋友们自行验证)。
Ø 在窗口输出操作代码入Print、Circle等输出到内存DC中,然后再从内存DC拷贝到目标窗口。
Ø VB没有提供目标窗口的DC,如果需要目标窗口的DC,需要使用GetDC获取,使用ReleaseDC释放。
Ø 如果使用API输出到hDC,输出后,必须使用Refresh将输出反映到目标窗口,如果使用VB自带的绘图及文字输出方法,则不需要使用Refresh。
Ø 不会产生Paint事件,对应于Windows的Paint消息,只是简单的将Image的内容拷贝到目标窗口。取代之,是在运行开始,会产生Show事件,可以在Show事件。
Ø 如果使用API的GetDIBits方法,将获取窗口的前景及背景内容。
Ø 事实上,AutoReDraw(True)时,窗口绘画就是一种双缓冲机制,但此机制有缺陷,其可绘图空间VB被限制和窗口尺寸一致,无法大于窗口尺寸。
b) 如果设置为非AutoReDraw (False) 则:
Ø hDC是一个和窗口关联的设备DC
Ø Image属性仍然和一个位图对象关联,只是这个位图的内容由BackColor属性及Picture属性决定,每次BackColor或者Picrure改变,则会重新生成Image对应的位图对象。BackColor属性在Picture不能完全填充窗口时候填充Picture之外的部分。
Ø Image对象将作为目标窗口的背景。CLS操作,就是讲Image对象内容拷贝到目标窗口。
Ø 对应于Windows的Paint消息,将产生VB的Paint事件,VB程序一般在该事件中,提供绘画窗口的代码,实现输出。
Ø 如果使用API的GetDIBits方法,只能获取窗口的背景内容(BackColor及Picture属性相关)。(AutoReDraw (False)时,如何获取前景的内容,后续介绍中将给出代码。)
Ø
无论AutoReDraw为何,当窗口尺寸改变时,将重建Image,以使得Imge的大小和窗口一致
c) AutoReDraw由True变为False,则True状态下的绘画输出,在变为AutoReDraw(False)后,绘图输出将成为背景的一部分,此Cls,将不能清除True时的绘画输出;要清除True时的绘图输出,则只再设置AutoReDraw(True)
d) AutoReDraw由False变为True: VB会使用BackColor及Picture属性值重新加载背景,前景将被取消
2. 获取完整的窗口位图数据:
在AutoReDraw(True)时,Image实际上是一个和窗口内容一致的位图句柄,可以直接将Image属性直接赋值给另一个控件或窗口的Picture属性,或者以Image属性作为句柄,使用API调用获取窗口内容数据;此时,一般都能得到窗口背景及前景的位图内容。
Picture2.Picrure=Picture1.Image ‘Picture1上显示的内容拷贝到Picture2的Picrure属性中
或者:
With Picture1
nLines=GetDiBits(.Hdc,.Image,0, mImgLine,ImgData(0),bmpInfoHeader,BI_RGB)
nLines=GetDiBits(.Hdc,Picture2.Image,0, mImgLine,ImgData(0),bmpInfoHeader,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, 0, 0, nWidth, nHeight, hDCx, 0, 0, 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, 0, nHeight, ImgData(mOffset), BmpInfo, BI_RGB)
GetWindowBmp = ImgData
DeleteDC hMemDC
ReleaseDC hWnd, hDCx
DeleteObject hBmp
End Function
该函数返回窗口hWnd上显示的所有位图数据的数组,位图数据在该数组的mOffset位置开始放置,mOffset前的字节为保留字节(后面将介绍这些保留字节的用途),参数BmpInfo是一个BitmapInfo的数据结构,调用时候只要定义,不需给结构成员赋值,函数会按照窗口的位图数据自动填充,函数的调用者,一般需要使用该结构返回的数据。
3. 对获取位图数据进行处理:
以下代码用于获取Pic1的位图数据到一个数组中,然后将其转换为灰度图像的数据,再将灰度 图像拷贝到Pic2中进行显示,显示时,我们使用Pic2的Image属性,使用该属性能将拷贝入的位图保持住。
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, 0, BitmapInfo.bmiHeader.biHeight, ImgData(0), BitmapInfo, BI_RGB
‘如果Pic2.Image改为Pic1.Image则,将Pic1的彩色改变为黑白
Pic2.Refresh
End Sub
- VB中的窗口位图
- 将bmp位图贴到excel中的一段VB代码
- 关于vb.net读取access数据库中的位图图片问题
- 关于去掉vb中的nag窗口
- VB 位图类
- 挖位图,做窗口.
- 托拽Explore中的文件到VB.net的窗口
- MFC---在窗口贴位图
- 双击子窗口中的行,自增到父窗口中新增一个行(vb.net)
- 制作VB属性窗口
- VB让窗口置顶
- VB一次关闭窗口
- VB 关闭其它窗口
- VB 无标题窗口置顶
- vb窗口置顶函数
- vb查看窗口句柄
- VB.NET窗口最小化
- MicrosoftSQLServer2000中的位图
- gps
- 搜索引擎索引之如何更新索引
- Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"
- 批处理创建数据库
- 第五周实验报告2
- VB中的窗口位图
- 《Java Concurrency in Practice》ch11 Performance and Scalability
- 分布式数据库
- 一维对流扩散问题TDMA算法
- 图的相关算法
- sizeof ()和strlen()的区别
- Say Hello!
- ROR (一)
- 使用jQuery插件实现简单购物