脫屏位圖(Offscreen Bitmaps)
脫屏位圖,也叫內存位圖,普遍用於Windows程序設計中。它在內存中制作圖像,然后利用Draw方法在屏幕上顯示出來。當用戶想更快的在屏幕上繪制圖像時,脫屏位圖有助於避免閃爍。脫屏位圖也適合於復雜制圖程序。用戶可以將圖像預存起來,需要時顯示出來。脫屏位圖用於動畫,最流行的動畫制作方法是Microsoft的DirectX SDK。
脫屏位圖的原則是三個簡單的步驟:
- 建立內存位圖(Create a memory bitmap)
- 繪制內存位圖(Draw on the memory bitmap)
- 拷貝內存位圖於屏幕(Copy the memory bitmap to the screen)
創建內存位圖(Creating a Memory Bitmap)
創建內存位圖很容易。事實上,前面的講解中已經創建過好幾次了。每次創建TBitmap對象時就是在創建內存位圖,其中一些是將文件載入內存位圖中,還有一些是創建內存位圖,設置其大小,然后繪制內存位圖,例如:
procedure TForm1.btn1Click(Sender: TObject); var Bitmap: TBitmap; I, X, Y, W, H: Integer; Red, Green, Blue: Integer; begin Bitmap := TBitmap.Create; Bitmap.Width := 500; Bitmap.Height := 500; for I := 0 to 19 do begin X := Random(400); Y := Random(400); W := Random(100) + 50; H := Random(100) + 50; Red := Random(255); Green := Random(255); Blue := Random(255); Bitmap.Canvas.Brush.Color := RGB(Red, Green, Blue); Bitmap.Canvas.Rectangle(X, Y, W, H); end; Canvas.Draw(0, 0, Bitmap); Bitmap.Free; end;
每次點擊按鈕,隨意一串矩形框畫於屏幕上。這段代碼簡單地繪制內存位圖,然后將位圖拷貝到窗體畫面上。
如果使用桌面256色設置,最終運行的結果的顏色將不確定。
Note
當創建內存位圖時,位圖將具有與當前顯示設置相同的顏色深度。換句話說,若有256種顏色的顯示設置,內存位圖也是256色的位圖,如果顯示設置為24位或32位,則內存位圖將包含32K、64K或16M種顏色。
保存內存位圖(Saving a Memory Bitmap)
將內存位圖保存起來極其容易。它所需要的做的就是一下代碼:
Bitmap.SaveToFile('test.bmp'); { 保存內存位圖}
是的,這樣就可以。事實上可以很容易地創建自己的屏幕捕捉程序。所要做的只是將桌面的適當部分拷貝到內存位圖中,並存儲到文件中。如下代碼:
procedure TForm1.btn2Click(Sender: TObject); var DtCanvas: TCanvas; Bitmap: TBitmap; NumColor: Integer; LogPal: PLogPalette; Src, Dst: TRect; begin { Create a TCanvas object for the desktop DC.} DtCanvas := TCanvas.Create; DtCanvas.Handle := GetDC(0); { Create a new TBitmap object and set its} { size to the size of the form.} Bitmap := TBitmap.Create; Bitmap.Width := Width; Bitmap.Height := Height; { Create a palette from the form's Canvas} { and assign that palette to the Bitmap's} { Palette property.} NumColor := GetDeviceCaps(Canvas.Handle, SIZEPALETTE); { 返回調色板的顏色數} GetMem(LogPal, SizeOf(TLogPalette) + (NUMCOLORS - 1) * SizeOf(TPaletteEntry)); LogPal.palVersion := $300; LogPal.palNumEntries := NumColor; GetSystemPaletteEntries(Canvas.Handle, 0, NumColor, LogPal.palPalEntry); Bitmap.Palette := CreatePalette(LogPal^); FreeMem(LogPal); { Copy a section of the screen from the desktop canvas to the Bitmap } Src := BoundsRect; Dst := Rect(0, 0, Width, Height); Bitmap.Canvas.CopyRect(Dst, DtCanvas, Src); { Save it to disk} Bitmap.SaveToFile('form.bmp'); { Clean up and go home} Bitmap.Free; DtCanvas.Free; end;
運行后,將截取本程序界面並保存到form.bmp文件中,顯示圖片如下:
內存位圖程序實例(Sample Memory Bitmap Program)
下面的清單中的程序,它說明內存位圖的應用。當點擊兩個按鈕中的某一個時,文本沿着屏幕水平滾動。
第一個按鈕的實現,不使用內存位圖(直接寫於窗體畫面上)。
第二個按鈕使用內存位圖來實現文本屏幕水平滾動。
第三個按鈕停止滾動。
部分代碼如下(詳細代碼請下載本講示例代碼):
{ 直接畫到畫布上} procedure TForm1.btn3Click(Sender: TObject); var I: Integer; begin Canvas.Font.Name := 'Arial Bold'; Canvas.Font.Size := 20; Canvas.Brush.Color := clSilver; Done := False; while not Done do begin for I := -canvas.TextWidth(DisplayText) to pred(Width) do begin Sleep(1); Application.ProcessMessages; if Done then Break; Canvas.Font.Color := clGray; Canvas.Brush.Style := bsClear; Canvas.TextOut(i + 2, 12, DisplayText); Canvas.Font.Color := clBlack; Canvas.Brush.Style := bsClear; Canvas.TextOut(i, 10, DisplayText); Canvas.Font.Color := clSilver; Canvas.TextOut(i + 2, 12, DisplayText); Canvas.TextOut(i, 10, DisplayText); end; end; end; { 通過脫屏位圖} procedure TForm1.btn5Click(Sender: TObject); begin Done := True; end; procedure TForm1.btn4Click(Sender: TObject); var Bitmap: TBitmap; I: Integer; begin Bitmap := TBitmap.Create; Bitmap.Width := Width; Bitmap.Height := 40; Bitmap.Canvas.Font.Name := 'Arial Bold'; Bitmap.Canvas.Font.Size := 20; Bitmap.Canvas.Brush.Color := clSilver; Bitmap.Canvas.FillRect(Rect(0, 0, Width, 40)); Done := False; while not Done do begin for I := -Bitmap.Canvas.TextWidth(DisplayText) to Pred(Width) do begin Application.ProcessMessages; if (Done) then Break; Sleep(1); Bitmap.Canvas.Font.Color := clGray; Bitmap.Canvas.Brush.Style := bsClear; Bitmap.Canvas.TextOut(2, 12, DisplayText); Bitmap.Canvas.Font.Color := clBlack; Bitmap.Canvas.Brush.Style := bsClear; Bitmap.Canvas.TextOut(0, 10, DisplayText); Canvas.Draw(i, 0, Bitmap); end; end; Bitmap.Free; end;
兩種不同的畫圖方式,顯示的效果也不同,其中通過脫屏位圖繪制的滾動字幕是最平滑的。如下圖:
以上代碼均在Delphi7中測試通過,示例代碼下載:GDI之脫屏位圖.rar