Delphi GDI对象之脱屏位图(Offscreen Bitmaps),也叫内存位图

http://www.cnblogs.com/pchmonster/archive/2012/07/09/2583613.html

脱屏位图(Offscreen Bitmaps)

脱屏位图,也叫内存位图,普遍用于Windows程序设计中。它在内存中制作图像,然后利用Draw方法在屏幕上显示出来。当用户想更快的在屏幕上绘制图像时,脱屏位图有助于避免闪烁。脱屏位图也适合于复杂制图程序。用户可以将图像预存起来,需要时显示出来。脱屏位图用于动画,最流行的动画制作方法是Microsoft的DirectX SDK。

脱屏位图的原则是三个简单的步骤:

  1. 建立内存位图(Create a memory bitmap)
  2. 绘制内存位图(Draw on the memory bitmap)
  3. 拷贝内存位图于屏幕(Copy the memory bitmap to the screen)

创建内存位图(Creating a Memory Bitmap)

创建内存位图很容易。事实上,前面的讲解中已经创建过好几次了。每次创建TBitmap对象时就是在创建内存位图,其中一些是将文件载入内存位图中,还有一些是创建内存位图,设置其大小,然后绘制内存位图,例如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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)

将内存位图保存起来极其容易。它所需要的做的就是一下代码:


1

Bitmap.SaveToFile(‘test.bmp‘); { 保存内存位图}

是的,这样就可以。事实上可以很容易地创建自己的屏幕捕捉程序。所要做的只是将桌面的适当部分拷贝到内存位图中,并存储到文件中。如下代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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)

下面的清单中的程序,它说明内存位图的应用。当点击两个按钮中的某一个时,文本沿着屏幕水平滚动。

第一个按钮的实现,不使用内存位图(直接写于窗体画面上)。

第二个按钮使用内存位图来实现文本屏幕水平滚动。

第三个按钮停止滚动。

部分代码如下(详细代码请下载本讲示例代码):


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

{ 直接画到画布上}

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

时间: 2024-10-22 13:47:41

Delphi GDI对象之脱屏位图(Offscreen Bitmaps),也叫内存位图的相关文章

Delphi GDI对象之绘制位图

http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579334.html 绘制位图(Drawing Bitmaps) 绘制位图听起来似乎很难,然而如几次所见到的那样,绘制位图非常容易.TCanvas类具有几种方法绘制位图,最常用的方法是Draw方法,这种方法只是在画布上指定位置绘制位图.用户已经见过几个这样的例子.下面是简短的例子. 1 2 3 4 5 6 7 8 9 procedure TForm1.btn1Click(Sender:

Delphi GDI对象之剪切区域

原文链接: http://www.cnblogs.com/pchmonster/archive/2012/07/05/2577627.html 剪切区域(Clipping Regions) Regions是屏幕的一部分,它可用于控制绘图的那部分画布.TCanvas类具有ClipRect属性,但这个属性只是只读的,要改变裁减区,必须使用Windows API,仍以前面的例子为例,并加以修改来说明裁剪区是如何工作的,下面是代码: 1 2 3 4 5 6 7 8 9 10 11 12 var   Bi

(转载)VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)

上一节中鸡啄米讲了CDC类及其屏幕绘图函数,本节的主要内容是GDI对象之画笔CPen. GDI对象 在MFC中,CGdiObject类是GDI对象的基类,通过查阅MSDN我们可以看到,CGdiObject类有六个直接的派生类,GDI对象主要也是这六个,分别是:CBitmap.CBrush.CFont.CPalette.CPen和CRgn. 在这六个GDI对象中,最常用的莫过于画笔和画刷了,即CPen类和CBrush类.本文就主要讲解画笔的使用. 画笔的应用实例 鸡啄米在这里直接通过一个波形图的实

Delphi GDI+ Library

GDI+ LibraryThis library enables GDI+ functionality for Delphi 2009 and later. It differs from other Delphi GDI+ libraries in the following ways: It is modeled more after the .NET System.Drawing namespace instead of the C++ GDI+ classes. As a result,

(转载)VS2010/MFC编程入门之五十一(图形图像:GDI对象之画刷CBrush)

上一节中鸡啄米主要讲的是画笔CPen的用法,前面也说了,GDI对象中最常用的就是画笔和画刷,本节就讲讲画刷CBrush. 鸡啄米依然是通过实例的方式来说明画刷的用法.此实例要实现的功能是,对话框上有一个按钮控件和一个图片控件,点击按钮弹出颜色对话框,然后在颜色对话框中选择颜色并点击"确定"后,图片控件中将显示选择的颜色. 其实此实例的功能,还可以通过重载对话框WM_CTLCOLOR消息的响应函数等方法来实现,但为讲解画刷的CBrush的使用,鸡啄米采用了下面代码中的方法. 以下是此实例

多线程的基本概念和Delphi线程对象Tthread介绍

多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行时间和资源,或者说,把CPU 时间划成片,每个片分给不同的线程,这样,每个线程轮流的“挂起”和“唤醒”,由于时间片很小,给人的感觉是同时运行的. 多线程带来如下好处: 1)避免瓶颈: 2)并行操作: 3)提高效率:多线程的两个概念: 1) 进程:也称任务,程序载入内存,并分配资源,称为“一个进程”. 注意

每添加一张图片后,GDI对象 + 3 原因: ImageList_AddIcon(hIcon) 后没调用 DestroyIcon(hIcon)

今天无意间在[任务管理器]中发现,每添加1张图片后,应用程序的 GDI对象 + 3,添加图片后,再把所有图片删除, GDI对象数量没减少! 排查原因,发现: GDI对象 + 3 的代码是: int offset = LookupIconIdFromDirectoryEx(pIcoData, TRUE, width_thumbnail, height_thumbnail, LR_DEFAULTCOLOR); if(offset != 0) //成功 { HICON ico = CreateIcon

VS2010/MFC编程入门之五十一(图形图像:GDI对象之画刷CBrush)

上一节中鸡啄米主要讲的是画笔CPen的用法,前面也说了,GDI对象中最常用的就是画笔和画刷,本节就讲讲画刷CBrush. 鸡啄米依然是通过实例的方式来说明画刷的用法.此实例要实现的功能是,对话框上有一个按钮控件和一个图片控件,点击按钮弹出颜色对话框,然后在颜色对话框中选择颜色并点击"确定"后,图片控件中将显示选择的颜色. 其实此实例的功能,还可以通过重载对话框WM_CTLCOLOR消息的响应函数等方法来实现,但为讲解画刷的CBrush的使用,鸡啄米采用了下面代码中的方法. 以下是此实例

VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)

上一节中鸡啄米讲了CDC类及其屏幕绘图函数,本节的主要内容是GDI对象之画笔CPen. GDI对象 在MFC中,CGdiObject类是GDI对象的基类,通过查阅MSDN我们可以看到,CGdiObject类有六个直接的派生类,GDI对象主要也是这六个,分别是:CBitmap.CBrush.CFont.CPalette.CPen和CRgn. 在这六个GDI对象中,最常用的莫过于画笔和画刷了,即CPen类和CBrush类.本文就主要讲解画笔的使用. 画笔的应用实例 鸡啄米在这里直接通过一个波形图的实