WIN32API讲座5

设备场景是Windows图形系统中的重要概念,所有绘图操作都通过设备场景进行。它是一种内部数据结构,包含了背景色、绘图模式等多个属性。在VB中,设备场景可以通过hDC属性或GetDC函数获取,使用完毕应释放。设备场景有逻辑坐标和物理坐标之分,可以通过API函数进行坐标转换。此外,设备场景还涉及剪裁区域,用于控制显示的图形范围。在AutoRedraw属性为True时,VB中存在两个设备场景,需要理解它们的区别以正确绘图。
摘要由CSDN通过智能技术生成

第五课∶设备场景

一、什么是设备场景

    关于设备场景,叫法颇多,有些书上说为设备环境、显示场景,更常见的叫做设备描述表或设备描述体。当然你爱怎么叫随你的便,我还是喜欢说为设备场景。
    那么究竟什么是设备场景呢? 设备场景是一种Windows对象,而Windows则是一种图形环境,其图形系统令人难以自信地灵活和强大。而实质上,Widnows下的所有绘图都是通过设备场景进行的,而不是直接对窗口和设备本身进行。为了说明设备场景,很多书都拿一些现实生活中的现象来进行对照说明。其中,最常见的是把它比喻为一位画家在作画。我想大家都看过画家是如何画画的,最起码是在电影里或者是在道旁的广告牌上作画的画家。我们可以想象一下∶有个风景秀丽的白云山(是我瞎起的名)上,有位画家一只手拿着调色板,另一只手则拿着画笔,面对一个画板正在写风景画。有些书认为画家的调色板相当于设备场景,有些书则认为画板相当于设备场景,说法不一。鉴于这种情况,我认为还是直接去说明设备场景比较好。

    作为Windows的对象,设备场景实际上是一种Windows内部的数据结构。就象POINTAPI数据结构具有x和y两个属性一样,设备场景同样具有着它自身的属性,只是属性比较多而已,如下表∶


                                设备场景属性

属    性                                             默  认  值
背景色(Background color)              白色(White)
背景模式(Background mode)          不透明(Opaque)
位图(Bitmap)                                 无(None)
刷子(Brush)                                   白色刷子(White brush)
刷子起点(Brush origin)                   0,0
剪切区(Clipping region)                  整个窗口或设备表面(Entire window or device surface)
调色板(Color palette)                     默认调色板(Default palette)
画笔位置(Pen position)                   0,0
绘图模式(Drawing mode)                R2_COPYPEN
字体(Font)                                      系统字体
字间距(Intercharater spacing)       0
影射模式(Mapping mode)               MM_TEXT
画笔(Pen)                                      黑色(Black)
多边形填充模式(Mapping Mode)      ALTERNATE
伸缩模式(Stretching mode)            BLACKONWHITE
文本色(Text color)                          黑色(Black)
视口起点(Viewport origin)             0,0
视口范围(Viewport extents)          1,1
窗口起点(Window origin)              0,0
窗口范围(Window extents)           1,1


    请你多看看这张表,对设备场景都有哪些属性,脑子里应当有个印象。事实上,设备场景的很多属性对应于VB中的Form、PictureBox、Text等窗体或控件的属性。比如,字体、背景色、绘图模式等等。可想而知,很多学VB的朋友尽管并不知道什么叫设备场景,但实质上都不知不觉地使用了设备场景。可以说,设备场景是Windows编程中最重要的概念之一。
     对于设备场景,有些朋友可能一时不大好理解,这很自然,不用担心谁都是一样。不知对你能否作为一个帮助,我是把设备场景想象成一种配套的(包括画板、调色板、画笔、刷子等)的绘画工具。其中画板是最重要的,其他的东西都是为这个画板服务的。如过你创建了一个设备场景,就等于是你从百货商店买来了这一套绘画工具,从而具备了绘画的条件。但,你的房间总不是那么宽敞的。为了继续绘出别的画、继续购买新的绘画工具,无用的工具应当及时清理掉。因为设备场景本身是占用内存的。不要担心这会降低运行速度,对计算机来说创建一个设备场景,再删掉一个设备场景,那都是瞬息之间的事情,根本谈不上什么浪费时间,绝对不像跑一趟百货商店那么麻烦、费时。对于绘图,你应当认识的一点是,绘图并不是简单地指绘画,输出文本也是一种绘图过程。尽管如此,API函数中图形函数与文本函数大体都是各自各的。绘画和写文本都是在同样的设备场景中进行,这一点很重要。

      我想,你大概还是没有理解好,不过没有关系,继续往下看好了。本节中请记住一点∶
     Widnows下的所有绘图都是通过设备场景进行的。

二、如何从VB里使用设备场景

    如何从VB里使用设备场景呢?VB的设计者们已经为我们想到了这一点,就象为了直接操纵窗体而提供了窗体句柄hWnd一样,为设备场景提供了hDC的句柄属性。很多API函数都是以hDC作为它的一个参数。如果控件没有提供hDC属性,你也可以用GetDC或
GetDCEx函数去获得,不用时就用ReleaseDC函数把它释放掉即可。不过这得需要控件具有hWnd属性。如果连hWnd属性也没有,那就没办法了,大概那根本不是绘图的地方。
    按自己的需要也可以创建一个或多个设备场景,需要多少就创建多少。这可能是
CreateCompatibleDC和CreateDC函数的最拿手的好戏。设备场景可以同某一窗口关联,也可以以孤立的方式存在。所谓关联就是说,你在这个设备场景中绘图,内容将立即输出到关联的窗口,所谓孤立就是指尽管你在这个设备场景中绘出了图形,但它只存在于这个设备场景,而不显示在哪里。我们可以通过多个设备场景来对一个最终图形进行光栅运算,从而进行加工,最后把图象传送给已与窗体关联的设备场景,让它显示出来。被创建的设备场景,如果不再使用,应当删去。(这段描述,请参考附带的演示程序WindowDC.vbp。)

以下表格总结了用于获取和释放设备场景的API函数。

函  数                                                    说   明
CreateCompatibleDC      创建一个与源DC兼容的内存设备场景。内存设备场景可看作一种对内存中设备的模拟。通过在设备中选进一幅位图,可创建与设备兼容的内存影响。
CreateDC                        为指定的设备创建一个设备场景,它通常用于为打印机创建一个DC。
CreateIC                         为指定的设备创建一个信息场景(IC)。IC类似于设备场景,只是所需系统开销更少,它可用来获取关于设备的信息,但不能作绘图操作。
DeleteDC                        删除一个已经建立的设备场景。可用它释放CreateDC,CreateIC和CreateCompatibleDC     函数建立的设备场景。
GetDC,GetDCEx              为指定窗口获取一个设备场景。若窗口类使用专用DC,用该函数取回设备场景,否则它从Windows缓存中获取一个DC,用GetDCEx才能在窗口使用专用DC时获得一个缓存场景。
GetWindowDC                该函数与GetDC类似,只是取回的设备场景是针对窗口整个,而不是客户区。
ReleaseDC                      释放用GetDC,GetDCEx和GetWindowDC获得的设备场景。若DC是一个专用设备场景,该函数无效。
WindowFromDC              判断与指定设备场景关联在一起的窗口句柄。
 
     以下的演示程序是一个非常敾奶茢的程序。这个程序的目的是这样的∶我们要在Text控件中画一个圆。当然我估计没有人会选择Text控件来绘图。我总是喜欢用API做出一些歪门邪道的事情。以下是程序的源代码,你也可以直接启动教程附送的Program1.vbp演示程序。使用方法是,当我们点击Text控件时那里将出现了一个空心圆。

Option Explicit

Private Declare Function GetDC& Lib "user32" (ByVal hwnd As Long)
Private Declare Function Ellipse& Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long)
Private Declare Function ReleaseDC& Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long)

Private Sub Form_Load()
   Text1.Text = ""
End Sub

Private Sub Text1_Click()
   Dim TextDC As Long
  
   TextDC = GetDC(Text1.hwnd)       '获取设备场景句柄

   Ellipse TextDC, 0, 0, 100, 100        '画空心圆
   ReleaseDC Text1.hwnd, TextDC     '释放设备场景

End Sub
     程序的工作原理是这样的。首先在Form_Load()事件中,我们用Text1.Text = ""代码来清除Text控件内的所有文本。接着,当我们点击Text控件时,程序在那里画一个圆,用的是API函数Ellipse(这个函数是下一课堂的内容)。Ellipse函数的功能很简单,在左上角为(x1,x2),右下角为(x2,y2)的矩形中画一个内切的椭圆。而Ellipse函数需要一个DC(设备场景句柄),但Text控件却没有提供hDC属性,没有办法只好用GetDC函数来获取∶TextDC = GetDC(Text1.hwnd)。然后做绘图操作,最后用ReleaseDC函数来把设备场景释放掉(关联设备场景,不能删除)。

如果我们把上述代码中的
   TextDC = GetDC(Text1.hwnd)
   Ellipse TextDC, 0, 0, 100, 100
改成
   TextDC = GetDC(0)

       Ellipse TextDC, 0, 0, 500, 500
    会怎么样呢?不妨你试试看。学会了什么?还是直接告诉你吧∶整个屏幕的设备场景句柄总是等于0。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值