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

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

  1. Delphi GDI对象之脱屏位图(Offscreen Bitmaps)

    脱屏位图(Offscreen Bitmaps) 脱屏位图,也叫内存位图,普遍用于Windows程序设计中.它在内存中制作图像,然后利用Draw方法在屏幕上显示出来.当用户想更快的在屏幕上绘制图像时,脱 ...

  2. Delphi GDI对象之绘制位图

    http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579334.html 绘制位图(Drawing Bitmaps) 绘制位图听起来似乎很难, ...

  3. Delphi GDI对象之绘制文本

    转载:http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579185.html 基本绘图操作(Basic Drawing Operations ...

  4. Delphi GDI对象之剪切区域

    原文链接: http://www.cnblogs.com/pchmonster/archive/2012/07/05/2577627.html 剪切区域(Clipping Regions) Regio ...

  5. 【笨嘴拙舌WINDOWS】GDI对象之位图

    GDI对象在windows中可以描述成为一次绘画操作时可使用的抽象工具.包括(画笔.画刷.字体.区域.调色板.位图等) GDI对象里的对象概念和在编程领域中面向对象编程的对象概念是不一样的! GDI对 ...

  6. Delphi GDI+ Library

    GDI+ LibraryThis library enables GDI+ functionality for Delphi 2009 and later. It differs from other ...

  7. GDI 对象的释放与内存泄漏的问题研究

    最近写了一个GDI 绘图的程序,过程中遇到一个奇怪的问题,就是 定时器定时一会GDI绘的图就消失了..后来经过分析,原来是 GDI对象数量过多 ,即GDI对象超过10000个 导致内存泄漏的问题.找到 ...

  8. 查GDI对象泄露的利器:GDIView

    查GDI对象泄露的利器:GDIView可以很详细的查到进程的GDI对象的总个数,详细的GDI对象的个数,以及其增减数量.其GDI对象类型也可以很详细的得知,以及其内存地址,句柄.实在是好使! 下载地址 ...

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

    今天无意间在[任务管理器]中发现,每添加1张图片后,应用程序的 GDI对象 + 3,添加图片后,再把所有图片删除, GDI对象数量没减少! 排查原因,发现: GDI对象 + 3 的代码是: int o ...

随机推荐

  1. svn提交报错,提示:locked,需要cleanup

    版权声明:本文为博主原创文章,未经博主允许不得转载. 原文地址: https://www.cnblogs.com/poterliu/p/9285137.html 在使用SVN提交代码或更新代码时经常会 ...

  2. Python学习笔记:configparser(INI格式配置文件解析)

    在平时的开发中感觉INI格式的配置文件使用还是挺需要的,有时会使用一个单独的py来存放一些常量或者配置项,大多时候这样倒是挺好用的,但是如果某些配置项需要在运行时由用户来修改指定,比如很多app在关闭 ...

  3. LeetCode(5)Longest Palindromic Substring

    题目 Given a string S, find the longest palindromic substring in S. You may assume that the maximum le ...

  4. FIFO buffer 和普通buffer区别

    1.FIFO可以说一块具体的硬件存储设备,也可以说程序在内存中开辟的一段内存区域.而buffer往往就是一段缓冲的数据区域 2.FIFO的数据是先进先出的,而buffer没有这个限制,可以全局访问 3 ...

  5. Shuffle UVA - 12174 尺取法

    题目:题目链接 思路:见紫书,对具体操作方式还不是很理解,代码是从一个题解里看的,以后多回顾下,需要理解 代码: #include <iostream> #include <cstr ...

  6. Mysql源码编译安装&主从复制

    一)camke源码编译安装mysql 1)创建软件安装目录software [root@master software]# ls cmake-2.8.8.tar.gz mysql-5.5.32.tar ...

  7. Linux学习-使用传统程序语言进行编译的简单范例

    单一程序:印出 HelloWorld 编辑程序代码,亦即原始码 [root@study ~]# vim hello.c <==用 C 语言写的程序扩展名建议用 .c #include <s ...

  8. Hadoop4.2HDFS测试报告之一

    1.1   测试方案 1.1.1 测试目标 为了验证本地文件系统和HDFS存储能力对比,将1G文件组存储进各个文件系统,记录存储任务消耗的时间. l   测试HDFS的高可用性和高稳定性 l   测试 ...

  9. HDU 3966 RE 树链剖分 线段树 Aragorn's Story

    题意: 给出一棵树,每个顶点上有一个权值. 操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数. 查询:某个点的当前权值 分析: 树链剖分完毕后,就是简单的线段树区间更新. 提交的时候注意要 ...

  10. 关于 NSData 的数据类型(2进制,16进制之间)及深入剖析

    1. NSData 与 NSString NSData-> NSString NSString *aString = [[NSString alloc initWithData:adataenc ...