DC 即Device Context,是GDI内部的一个资料结构,一个DC会和某个特定的显示设备(如打印机、屏幕等)产生关联。我们如果能取得该DC的handle 那我们便可以在这显示设备上写字、画图。
在Form 或Picturebox中都有一个hdc的属性,指的便是这东西,但是,怎麽又会有一个Memory DC呢?这是一个存在记忆体内的 dc ,它除了不像form picturebox能将图形、文字显示出来之外,其他的几乎都相同,它也可以用在所有的 GDI API 呼叫之上,其实我们在VB中早就有使用上这 Memory DC 了,只是没有自觉。当我们设 form picturebox的AutoRedraw = True时, hdc所指的便是Momoory DC,这时我们在其上作绘图动作,都没有显示在form上,这便是先前说的,它只是在记忆体中,不会真的画出图。而我们下refresh指令时,便是将这MemoryDC上的图,copy到 form/PictureBox上。
另外我们也可以使用
CreateCompatibleDC() API 它传入一个 hDc ,代表产生的 Memory DC和 hdc相容,若传0则是与屏幕相容的 Memory DChMemDC = CreateCompatibleDC(0)
这时候,该hMemDC所指的绘图区有多大呢?其实只有一个单色Pixel,直到我们使用SelectObject( hMemDC, hBitmap)
那hMemDC显示区就会有和hBitmap一样的宽度、高度、颜色选择等。 而且我们在hMemDC上的任何绘图,也都会反映在 hBitMap上,也就是说,原本hBitMap所指的图,於SelectObject(hMemDC, hBitMap)後,我们使用gdi函式在hMemDC上画一条线,那麽该hBitmap所指的图也会有一条线了。
接下来令人心烦的是hBitmap如何取得,在vb可以使用以下的两个方式:
1.使用Form/PictureBox上Image属性(它是个物件),不管我们放入Form/PictureBox中Picture属性的图是否是Bitmap图,Image所指的,是一份存在记忆体中的Bitmap图,(这是我的想法,因我查了一下,Image.Type 永远说是BitMap图,而不管Picture属性的图是那一种类型),而Image.Handle所指,便是这bitmap图的hBitmap。但是,不要高兴太早,这hBitmap的范围可比你想像中的大,如果有一个PictureBox大小100*100而设定一个50*50 的图於其上, 那PictureBox.Image的大小是100*100,因为它所指的是整个PictureBox的图,而刚好PictureBox上有图形显示於其上。而如何才能取得50*50的hBitMap呢,我会用"偷吃部",指定 PictureBox比50*50小(如:1*1)而且设定AutoSize = True,BorderStyle = 0 当我们用LoadPicture把图形放进来时,
PictureBox会放大成与该图的大小相同,那麽,PictureBox.Image的大小也会随之放大
2.使用StdPicture物,而後用LoadPicture将图放进来,但是这一定只能使用BitMap图,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)要不然StdPicture.Handle不会是hBitmap,而是其他Handle( 如:hIcon)如果使用api,可以使用hBitMap = CreateCompatibleBitmap(hDc, Height, Width)那会产生一个高Height * 宽 Width大小(Pixels)的BitMap图,而且该BitMap图和Hdc所指的物件有相同的颜色数,且Bits Per Pixels也相同。然而该BitMap图里什麽也没有,一般我们接着使用SelectObject(hdc, hBitMap) 而利用hDc来绘图,这一切的绘图就会反映在hBitMap上,而我们一般会以MemoryDC来当作hdc的传入值,等绘图动作完了,我们便可以把这Memory DC删除(DeleteDC()),而只单纯的留下hBitmap。如:
hMemDc = CreateCompatibleDc(0)
hBitMap = CreateCompatibleBitMap(Screen.ActiveForm.hDc, 100,100)
Call SelectObject(hMemDc, hBitMap)
'执行一些绘图指令,如:Textout() StretchBltStretchBlt() BitBlt()DeleteDC hMemDc
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)
当然,如果我们不知道图形的大小时,CreateCompatibleBitMap就不是那麽方便了,要知道图形的大小我们也可以由PictureBox.Picture中Width/Height这两个属性来做,但是还得经过一下转换,因为这两个值的单位是HiMetric,要使用ScaleX() ScaleY()来转成Pixels即ScaleX(picture1.Picture.Width, vbHiMetric, vbPixels)才是我们想要的宽度,ScaleY(picture1.Picture.Height, vbHiMetric, vbPixels)才是我们想要的高度。另外也可以使用以下的方式来取得hBitmap'假设有一个PictureBox而我们事先已Load一个图进来了。
Dim bm As Bitmap, hBmp as Long
GetObject Picture1.Picture, Len(bm), bm '取得PictureBox内图形的的BitMap结构hBmp = CreateBitmapIndirect(bm) '产生一个Bitmap图,该图的大小颜色数由bm所控制hmemDC = CreateCompatibleDC(Picture1.hDC)SelectObject hmemDC, hBmp 'hmemDC的大小和hBmp相同了
picture1.AutoRedraw = True'将Picture1的图画在hmemDc上,如此,hBmp便是我们所要的。
BitBlt hmemDC, 0, 0, bm.bmWidth, bm.bmHeight, picture1.hDC, 0, 0, vbSrcCopy