分享
 
 
 

AutoRedraw属性与窗体设备场景的深入探讨

王朝vb·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

大家知道AutoRedraw是设置窗体是否重画的。那为什么为false窗体上的图形就不会被重画,而为true则窗体在被覆盖后再显示,窗体上的图形仍旧在?

这个问题其实与窗体的设备场景有直接的关系。即使没接触过Windows GDI开发的朋友也一定听说过设备场景(Device Context),设备场景是用来控制窗体图形显示方式的对象。比如,我们可以通过设置设备场景的画笔对象来控制在窗体上的线条的颜色、粗细,设置区域对象来控制窗体的外形,比如说将窗体变成五角形,星形,甚至任何乱七八糟的形状,可以设置剪切区并加一点代码就可以将窗体变成透明的,或者通过CBitmap对象来截获窗体的图象——而我们今天讨论的是如何在AutoRedraw属性的两种设置下返回我们所需的设备场景句柄。

窗体有这么几个属性需要复习一下:hDC——窗体的设备场景;窗体image对象的Handle属性——窗体前景画面图像的句柄;窗体picture对象的Handle属性——窗体背景图像的句柄。当我们将窗体的AutoRedraw属性设置为true时,窗体的设备场景其实存在两个。这可以以以下代码证实:

Private Sub Form_Click()

Dim lDC As Long

lDC = GetDC(Me.hwnd) ‘GetDC是一个API函数,它返回某窗体的设备场景。请用API Text Viewer加入该函数的声明

Print Me.hDC

Print lDC

End Sub

(注意当窗体的AutoRedraw属性为true时窗体的Paint事件不会被激发。)

在窗体上输出的数字中我们清析地看到,这两个句柄是不同的。其中,窗体的hDC属性是窗体的一个内存设备场景句柄。对于窗体的任何绘图(例如画一条线,一个圆圈等)工作都会写入该内存设备场景。每当该窗体接收到一个Paint事件时,它就用该内存设备场景刷新窗体。所以当我们重新显示窗体的时候,它始终能重画窗体上所有的图形。而我们用GetDC函数返回的设备场景句柄则是真正意义上的窗体句柄,当前窗体显示什么图形,那么该设备场景的CBitmap对象保存的就是该图形。比如说,我们画了一个圆圈,又用别的窗体将它掩盖了一半,我们又用GetDC返回的句柄截获窗体的图片,那么该图片中只有一半的圆圈。

当AutoRedraw属性为false的时候,窗体的内存设备场景就不存在了。由于没有了保存窗体图像信息的内存设备场景,所以窗体就无法确定重显时如何重画窗体,因而就不会去重画被覆盖掉又重显的内容。用GetDC函数和窗体的hDC属性返回的句柄是相同的,它们都是窗体真正意义上的设备场景句柄。

以下语句可以截取窗体的图像,大家可以在AutoRedraw属性为不同的时候截获这几种可能的窗体图片以比较一下。(请先在窗体上画一个PictureBox,取名为picSave,并将其Visible属性设为false,AutoRedraw属性设为true。再将窗体及图像框的ScaleMode设为3。运行该程序前请先检查PictureBox的hDC是否存在,小弟在几台机子上发现即使设置了HasDC属性仍无法获得该hDC的情况。)

如小弟有错误之处欢迎来信探讨:sproll@163.com

Option Explicit

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function CreateCompatibleDC 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 Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, _

ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _

ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Private Const SRCCOPY = &HCC0020

Private Sub Form_Click()

Dim lReturn As Long

Dim lDC As Long

Dim lBitmap As Long

Dim lOldBitmap As Long

lDC = CreateCompatibleDC(frmAutoRedraw.PicSave.hdc) '创建与PictureBox的设备场景兼容的一内存设备场景

lBitmap = CreateCompatibleBitmap(frmAutoRedraw.hdc, frmAutoRedraw.ScaleWidth, frmAutoRedraw.ScaleHeight) '创建与窗体设备场景的CBitmap对象兼容的CBitmap对象

lOldBitmap = SelectObject(lDC, lBitmap) '将创建的新Cbitmap对象选入内存设备场景,并保存原CBitmap对象。

lReturn = BitBlt(lDC, 0, 0, frmAutoRedraw.ScaleWidth, frmAutoRedraw.ScaleHeight, frmAutoRedraw.hdc, 0, 0, SRCCOPY) '将窗体上显示的图样拷贝到内存设备场景

lReturn = BitBlt(frmAutoRedraw.PicSave.hdc, 0, 0, frmAutoRedraw.ScaleWidth, frmAutoRedraw.ScaleHeight, lDC, 0, 0, SRCCOPY) '将内存设备场景的图样拷贝到PictureBox的设备场景中

SavePicture frmAutoRedraw.PicSave.Image, "c:\My documents\form.bmp" '保存PictureBox的图样

lBitmap = SelectObject(lDC, lOldBitmap) '将内存设备场景的原CBitmap对象选回内存设备场景

lReturn = DeleteObject(lBitmap) '删除创建的CBitmap对象

lReturn = DeleteDC(lDC) '删除内存设备场景

End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

If Button = vbRightButton Then

frmAutoRedraw.Line (0, 0)-(150, 150)

End If

End Sub

Private Sub Form_Resize()

PicSave.Width = Me.ScaleWidth

PicSave.Height = Me.ScaleHeight

End Sub

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有