📄 9915.txt
字号:
begin
with TToolButton.Create(ToolBar) do
begin
Parent := ToolBar;
Caption := ButtonCaptions[I];
onclick:=superbuttonclick;{为toolbutton增加鼠标click事件}
if (ButtonCaptions[I]=‘|’) then{判断是不是分隔符}
begin
Style := tbsSeparator;
m:=m+1;
end
else
begin
Style := tbsButton;
imageindex:=i-m;
end;
end;
end;
end;
{这里是响应鼠标事件,实现应用程序的打开}
procedure TForm1.superbuttonclick(sender:Tobject);
begin
winexec(pchar((sender as TToolbutton).caption),SW_ShowNormal);
{打开一个Windows的应用程序}
end;
procedure TForm1.FormCreate(Sender: TObject);
const
ExeList:array[0..2] of String=(
‘winfile.exe’,
‘|’,
‘notepad.exe’);{可以在这里加上其它应用程序的全称,也可以不要分隔符}
var
imagelist:Timagelist;
i:integer;
begin
imagelist:=Timagelist.Create(self);
try{加入安全代码,也可不加}
for i:=0 to high(exelist) do
if exelist[i] <> ‘|’ then
begin
ImageList_AddIcon(ImageList.Handle,ExtractIcon(Handle,PChar(ExeList[i]),0));
{为imagelist添加图标}
end;
createsuperbar(self,imagelist);
createbutton(toolbar,exelist);
finally
end;
end;
end.
以上程序已在Pentium-MMX166 32M Windows 98 DELPHI 4.0 通过,小弟反复
测试没有问题,才斗胆拿出来与大家分享,如有问题望广大Delphi迷能给小弟多提
意见,在下将翘首期待你的来信。本人的E-mail:xuxiaoming@163.net.谢谢!
***********************************************************
用DirectDraw编写动画程序
(成都 张巍)
一.理论篇
说起DirectDraw也许大多数人还不知其为何物,但一提到DirectX恐怕每一个
Computer Fan 和Game Fan都再耳熟不过了。(什么!你没听说过DirectX!?Oh,My god!
来人哪,拉下去重责五十大板!)DirectX又叫Game SDK,它最大的特点是直接对硬
件的抽象层(HAL)进行操作,利用这个特点可以制作出高性能的Windows游戏。具
体信息请见http://www. microsoft.com/directx/default.asp。
DirectDraw就是DirectX5的6个组件之一。DirectX5的其它5个组件分别是:
Direct3D:提供了3D硬件接口。
DirectSound:立体声和3D声音效果,同时管理声卡的内存。
DirectPlay:支持开发多人网络游戏,并能处理游戏中网络之间的通信问题。
DirectInput:为大量的设备提供输入支持。
DirectSetup:自动安装DirectX驱动程序。
而DirectDraw则是DirectX的基石,DirectX的其它组件都是建立在它的基础
之上的。DirectDraw使用页面切换的方法实现动画,它不仅可以访问系统内存,
还可以访问显示内存,这是以往的Windows程序员所不能的。另外,我们利用
DirectDraw还可以生成、移动、剪切、转换、合成图像数据,从而编写出各种
“炫丽多彩”图形的应用程序。
介绍了这么一大堆DirectX的理论,你的头是不是已经有些大了呢?心中一
定在嘀咕:“哼,原来是个江湖骗子,光说不练。”各位看官不要着急,不把这
些基础理论搞懂就去看下面的程序,你肯定是“洋鬼子看戏——目瞪口呆”。
首先,让我们先了解一下DirectDraw的三个重要概念。
1.表面
在用DirectDraw编写程序时,我们先要创建若干个图形数据缓冲区,并把这些
图形数据装入其中,再进行转换、拉伸、挎贝等操作,并且还可以显示这些缓冲
区中的图形数据,这些缓冲区就称为表面。
表面可以分为几类。
主表面(primary surface)是用户在屏幕上可以看到的,它是显示内存的一部
分。所有DirectDraw程序都有主表面,而且只有一个。它在DirectDraw表面对象
之前就已经存在了,因此不能改变它的尺寸、格式和位置。主表面有一个很重要
的特性——翻转。页面翻转用于程序中,可以产生相当平滑、不闪烁的动画。一
个可以翻转的主表面实际上是两个表面,一个是可见的,一个是不可见的。不可
见的表面称为后备缓冲区。当发生表面翻转时,后备缓冲区就成为可见的,而以
前的可见表面则成为后备缓冲区。
还有一种表面叫离屏表面(off_screen surface),它是不能直接见到的。离
屏表面作为存储缓冲区,有助于表面之间的互相切换,它的大小是可以改变的。
主表面和离屏表面都分为有调色板的和无调色板的这两类。像素深度为8位
(256色)的表面称为有调色板的表面;而像素深度为16位(64K色)、24位(16M色)的
像素表面称为无调色板的表面,它们存储实际的色彩值(RGB值)。在本文下面的程
序中,我们使用24位表面即无调色板的表面。
2. Bltting
Bltting是用于复制图形的语言,可以将图像从一处拷贝到另一处。例如大家
所熟悉的CDC类(设备描述表类)的BitBlt()就是具有这样功能的函数。在DirectDraw
中,典型的blt操作是将离屏表面的内容拷贝到一个后备缓冲区,而一般的blt操
作调用一个源表面和一个目标表面,把源表面的内容拷贝到目标表面中,不仅可
以整体拷贝源表面,而且还可以拷贝源表面内的任何矩形区域到目标表面的任何
位置。blt还支持透明拷贝,就是指表面中的某一像素在blt过程中可以不予以拷
贝,而这个像素值是由色彩键码(DDCOLOR KEY )决定的。
DirectDraw中有三个支持blt的函数,它们是Blt()、BltBatch()、BltFast()。
Blt( )用得最多,BltFast()的速度比Blt()要快,但功能却很有限,例如不支持
拉伸、剪切等操作。
还有一个函数BltSurface(),它是DirectWin类的一个成员函数,Blt()、
BltFast()更具有适应性,并且使用起来更加简单。例如,当我们把源表面拷贝到
目标表面外时需要裁剪,而BltFast()不支持裁剪。这时我们使用BltSurface()函
数,它在内部使用Blt()和 BltSurface()函数,并根据情况自动执行裁剪。
3.色彩键码
DirectDraw 可以把某种颜色或某个范围的颜色指定为一个颜色值,这个颜色
值是由DDCOLORKEY结构即色彩键码说明的,DDCORLORKEY结构说明如下:
typedef struct _DDCOLORKEY{
DWORD dwColorSpaceLowValue; //颜色范围的低端
DWORD dwColorSpaceHighValue; //颜色范围的高端
} DDCOLORKEY;
当我们对表面进行拷贝操作时,表面中哪些像素不被拷贝是由色彩键码决定的。
例如当DDCOLORKEY结构的两个分量都为零时,表面内所有置为零的像素都不能被
拷贝。又例如,当表面是24位RGB模式时,若想指定RGB=(120,120,120)像素不
被拷贝,则应该:
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue=RGB(120,120,120);
ddck.dwColorSpaceHighValue=RGB(120,120,120);
surf→SetColorKey(DDCKEY_SRCBLT,&ddck);
其中SetColorKey()函数是把色彩键码赋给表面surf。这样,在对表面surf的
blt操作期间RGB值为(120,120,120)的像素不能被拷贝。
二.实践篇
古语云:“君欲善其事,必先利其器”,在编写DirectDraw应用程序之前,
我们先要准备好以下工具:
Windows95、Windows98或WindowsNT4.0
DirectX 驱动程序(最好是DirectX3.0以上版本)
DirectX SDK
Visual C++ 5.0
Direct SDK包括开发基于DirectX应用程序所需的全部文件,全部安装需要80
几兆的硬盘空间。其实你只需安装必需的头文文件(.h文件)和库文件(.lib文件)
就行了。
安装完DirectX SDK,需要通知Visual C++ DirectX SDK的路径。具体做法是:
在VC的编译环境中,依次把Tools-Options-Directories中的Show Directories for
一栏中的include files和library files中分别填入SDK的inc和lib目录。
再准备两幅bmp格式的位图,要求24位(16M色),其中background.bmp作背景,
另一幅bird.bmp作为子画面,如图3。bird.bmp是由4幅小画面组成的,从左到右,
从上到下,分别为动画的1至4帧。这样做的目的是避免过多位图文件带来的不必要
的麻烦。还要注意一点的是子画面的背景要为黑色(RGB=(0,0,0)),因为在下面的
程序中,色彩键码把黑色设为透明色。
好,一切准备就绪,让我们开始吧!
进入VC5的编程环境,File-New-Project,选择DirectDraw AppWizard,输入
项目名Fly,按下Ok,以后每一步都按其缺省值即可,这样AppWizard就会自动创建
一个项目Fly,属性如下:
APPLICATION STYLE
Full-Screen
SETTINGS
640x480
16-bit
CLASS NAMES
FlyApp
FlyWin
CONTENT
Bitmap
这时,按“Ctrl+F5”编译运行,你就会看到一个“三角形”在屏幕上撞来撞去。
在FlyWin.h中添加代码,如下所示:
#ifndef FLYWIN_H
#define FLYWIN_H
#include “DirectDrawWin.h”
class FlyWin : public DirectDrawWin
{
public:
FlyWin();
protected:
//{{AFX_MSG(FlyWin)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int SelectDriver();
int SelectInitialDisplayMode();
BOOL CreateCustomSurfaces();
void DrawScene();
void RestoreSurfaces();
private:
void CopySurface(LPDIRECTDRAWSURFACE ts,
LPDIRECTDRAWSURFACE ss,
int x,int y);
void SplitSurface(LPDIRECTDRAWSURFACE ts,
LPDIRECTDRAWSURFACE ss,
CRect& srcc,
int x,int y);
private:
LPDIRECTDRAWSURFACE bksurf, //定义指向背景画面表面的指针
flysurf, //指向总子画面表面的指针
storesurf,//指向存储背景区域表面的指针
flysurf1, //指向第一帧子画面表面的指针
flysurf2, //指向第二帧子画面表面的指针
flysurf3, //指向第三帧子画面表面的指针
flysurf4, //指向第四帧子画面表面的指针
cursurf; //指向当前移动的子画面表面的指针
//背景画面指background.bmp;总子画面指bird.bmp
int x,y,nPreX,nPreY;//定义子画面移动的坐标
int nIncX,nIncY;// 定义子画面移动的像素数
int nCount; //定义计数器
DWORD fw,fh; //定义总子画面的宽和高
};
#endif
其中,CopySurface()函数起保存被子画面覆盖掉的背景区域的作用。参数ts
是指向目标表面的指针,ss是指向源表面的指针,x、y是源表面上需要拷贝的矩
形区域左上角的坐标。
SplitSurface()函数用于分离一个大的总子画面表面为4帧小子画面表面。参
数ts是指向目标表面的指针,ss是指向源表面的指针,srcc是源表面上需要选取
的矩形区域,x、y要拷贝到目标表面上的左上角坐标。
其实当我们看了下面FlyWin.cpp中这两个函数的原型后,细心的朋友也许会
发现,两个函数完全可以写成一个函数。而本文特意写成两个函数,为的是程序
的清楚易读,不易引起混淆。
下一步在FlyWin.cpp中添加代码,如下所示:
#include “Headers.h”
#include “resource.h”
#include “DriverDialog.h”
#include “FlyWin.h”
#pragma comment (lib,“ddraw.lib”)
#pragma comment (lib,“dxguid.lib”)
const DWORD desiredwidth=640;
const DWORD desiredheight=480;
const DWORD desireddepth=16;
const int nMoveSpeed=100; //设置动画速度为100毫秒/帧
const int nMoveIncX=8; //设置子画面沿X轴移动8个像素
const int nMoveIncY=8; //设置子画面沿y轴移动8个像素
BEGIN_MESSAGE_MAP(FlyWin, DirectDrawWin)
//{{AFX_MSG_MAP(FlyWin)
ON_WM_KEYDOWN()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -