Delphi GDI对象之脱屏位图(Offscreen Bitmaps)
脱屏位图(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对象时就是在创建内存位图,其中一些是将文件载入内存位图中,还有一些是创建内存位图,设置其大小,然后绘制内存位图,例如:
|
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)的更多相关文章
- Delphi GDI对象之脱屏位图(Offscreen Bitmaps),也叫内存位图
http://www.cnblogs.com/pchmonster/archive/2012/07/09/2583613.html 脱屏位图(Offscreen Bitmaps) 脱屏位图,也叫内存位 ...
- Delphi GDI对象之绘制位图
http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579334.html 绘制位图(Drawing Bitmaps) 绘制位图听起来似乎很难, ...
- Delphi GDI对象之绘制文本
转载:http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579185.html 基本绘图操作(Basic Drawing Operations ...
- Delphi GDI对象之剪切区域
原文链接: http://www.cnblogs.com/pchmonster/archive/2012/07/05/2577627.html 剪切区域(Clipping Regions) Regio ...
- 【笨嘴拙舌WINDOWS】GDI对象之位图
GDI对象在windows中可以描述成为一次绘画操作时可使用的抽象工具.包括(画笔.画刷.字体.区域.调色板.位图等) GDI对象里的对象概念和在编程领域中面向对象编程的对象概念是不一样的! GDI对 ...
- Delphi GDI+ Library
GDI+ LibraryThis library enables GDI+ functionality for Delphi 2009 and later. It differs from other ...
- GDI 对象的释放与内存泄漏的问题研究
最近写了一个GDI 绘图的程序,过程中遇到一个奇怪的问题,就是 定时器定时一会GDI绘的图就消失了..后来经过分析,原来是 GDI对象数量过多 ,即GDI对象超过10000个 导致内存泄漏的问题.找到 ...
- 查GDI对象泄露的利器:GDIView
查GDI对象泄露的利器:GDIView可以很详细的查到进程的GDI对象的总个数,详细的GDI对象的个数,以及其增减数量.其GDI对象类型也可以很详细的得知,以及其内存地址,句柄.实在是好使! 下载地址 ...
- 每添加一张图片后,GDI对象 + 3 原因: ImageList_AddIcon(hIcon) 后没调用 DestroyIcon(hIcon)
今天无意间在[任务管理器]中发现,每添加1张图片后,应用程序的 GDI对象 + 3,添加图片后,再把所有图片删除, GDI对象数量没减少! 排查原因,发现: GDI对象 + 3 的代码是: int o ...
随机推荐
- new和delete,p150
创建对象,不带()的称为不提供显式初始化,()为空的称为值初始化. 内置类型和没定义默认ctor的类型,不带()未初始化,带()初始化为0.但有默认构造函数的,带不带()都是利用默认构造函数初始化. ...
- kubeadm部署多master节点高可用k8s1.16.2
一.架构信息 系统版本:CentOS 7.6 内核:3.10.0‐1062.4.1.el7.x86_64 Kubernetes: v1.16.2 Dockerce: 19.03 推荐硬件配置:2核4 ...
- 简单的使用Qt的QCustomplot画图
一.新建一个widget工程 二.将Qcustomplot文件复制到项目下 三.右键qt项目增加已存在的文件 四.在.pro中添加 QT += widgets printsupport 五.在.h中添 ...
- 密码学之RSA基础
预备数论知识 互质关系 如果两个正整数,除了1以外,没有其他公因子,那么就称这两个数是互质关系 比如:4和7,13和61 欧拉函数 思考:任意给定整数n,在小于等于n的正整数中,有多少个数与n构成互质 ...
- 网关协议:CGI和WSGI
通常服务器程序分为web服务器和应用程序服务器.web服务器是用于处理HTML文件,让客户可以通过浏览器进行访问,主流的web服务器有Apache.IIS.Nginx.lighthttpd等.应用服务 ...
- [NOIP模拟13]题解
A.矩阵游戏 其实挺水的? 考场上根本没有管出题人的疯狂暗示(诶这出题人有毛病吧这么简单的东西写一大堆柿子),而且推公式能力近乎没有,所以死掉了. 很显然乘法有交换率结合率所以操作顺序对最终结果没什么 ...
- CSS:CSS 语法
ylbtech-CSS:CSS 语法 1.返回顶部 1. CSS 语法 实例 查看 实例 1 查看 实例 2 CSS 实例 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明: 选择器通常是 ...
- Centos7.4安装elasticsearch6.3+kibana6.3集群
Centos7.4安装elasticsearch+kibana集群 Centos7.4安装elasticsearch+kibana集群 主机环境 软件环境 主机规划 主机安装前准备 安装jdk1.8 ...
- *&m与m的区别
int *a;int * &p=a; 把 int * 看成一个类型,a就是一个整型指针,p 是a的别名 #include<iostream> using namespace std ...
- git: 使用submodule进行托管
问题描述: 当一个prj.git项目里引用了另外一个moduleA.git项目作为其一个子模块,由于该模块未完善后续可能将继续升级,也就是需要两套git分别管理prj.git与moduleA.git, ...