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 DC hMemDC = 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圖,
要不然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
當然,如果我們不知道圖形的大小時,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