第一篇文章:
《Dephi5中资源文件的创建和使用》
几乎每个Windows应用程序都使用图标、图片、光标等资源。资源是程序的一部分,但是它是不可执行代码。下面我们就详细介绍资源文件在Delphi5中建立和使用方法。1.把资源放到Exe文件的优点 
由于定位资源比在磁盘中定位文件花费时间少,所以应用程序执行会更快。多种资源可以放在一个文件中,减少了图标、图片、光标等文件数量。保存资源文件时不要和工程名相同,因为Delphi创建工程时会自动创建一个和工程名相同的资源文件。并且最好将资源文件保存到和工程文件同一个文件夹中。2.创建资源文件 
首先创建一个.Rc的纯文本文件。格式如下: 
资源标识符 + 关键字 + 资源文件名 
① 资源标识符:程序中调用资源时的特殊标号; 
② 关键字:标识资源文件类型;
Wave: 资源文件是声音文件;
RCDATA: JPEG文件;
AVI: AVI动画;
ICON: 图标文件; 
BITMAP: 位图文件; 
CURSOR: 光标文件; 
资源文件名:资源文件名; 
③ 资源文件名:编译的资源文件,比如动画、位图、光标等; 
④ 如:MyWav WAVE "FileName.Wav" 
使用Borland资源编译器(BRCC32.EXE)转化.Rc文件成.Res文件。在DOS命令行下输入下列命令: 
Brcc32 FileName.Rc // Brcc32.Exe在Delphi5\Bin文件下。3.在工程中引用资源文件 
为了存取我们的资源文件,必须告诉Delphi链接我们的资源文件到应用程序中。因此我们可以在源代码中加入一条编译指令完成上述功能。这条指令必须紧跟在窗口指令后,如下形式: 
{$R *.DFM} //Delphi自带编译指令 
{$R FileName.Res} //新加入的编译资源文件的指令。 
不要删除{$R *.DFM}指令,因为这行代码告诉Delphi链接下面的资源到窗口的资源中。4.调用资源文件 
(1)存取资源文件中的位图(Bitmap) 
程序中如果想存取资源,你必须调用一些Windows API函数。保存在资源文件中的位图、光标和图标可以通过调用LoadBitmap、LoadCursor和LoadIcon函数存取。 
本例举例说明如何存取资源文件中位图并显示在Timage控件中。 
procedure TfrMain.btnCanvasPic(Sender: TObject); 
Image1.Picture.Bitmap.Handle :=LoadBitmap(hInstance 
'资源标识符');
end; 
注:如果位图没有装载成功,程序仍旧执行,但是Image将不再显示图片。你可以根据LoadBitmap函数的返回值判断是否装载成功,如果装载成功返回值是非0,如果装载失败返回值是0。另外一个存取显示位图的方法如下 
procedure TfrMain.btnLoadPicClick(Sender: TObject); 
begin 
Image1.Picture.Bitmap.LoadFromResourceName(hInstance
'资源标识符'); 
end; 
(2)存取资源文件中的光标 
Screen.Cursors[]是一个光标数组,使用光标文件我们可以将定制的光标加入到这个属性中。因为默认的光标在数组中索引值是0,所以除非想取代默认光标,最好将定制的光标索引值设为1。 
procedure TfrMain.btnUseCursorClick(Sender: TObject);
begin
Screen.Cursors[1] :=LoadCursor(hInstance
'资源标识符');
Image1.Cursor :=1;
end;
(3)存取资源文件中的图标
将图标放在资源文件中,可以实现动态改变应用程序图标。
procedure TfrMain.LoadIconClick(Sender: TObject);
begin
Application.Icon.Handle := LoadIcon(hInstance
'资源标识符');
End;
(4)存取资源文件中的AVI
procedure TfrMain.LoadIconClick(Sender: TObject);
begin
Animate1.ResName :='MyAvi' ; //资源标识
Animate1.Active :=True ;
End ;
(5)存取资源文件中的JPEG
把jpeg单元加入到Interface的uses单元中。
procedure TForm1.LoadJPGClick(Sender: TObject);
var
Fjpg : TJpegImage ;
FStream :TResourceStream ;
begin
Fjpg :=TJpegImage.Create ;
FStream := TResourceStream.Create (Hinstance
'资源标识符'
RT_RCDATA) ;
FJpg.LoadFromStream (FStream) ;
Image1.Picture.Bitmap.Assign (FJpg);
end;
(6)存取资源文件中的Wave
把MMSystem加入到Interface的uses单元中
procedure TForm1.LoadWaveClick(Sender: TObject);
begin
PlaySound('MyWav'
HInstance
Snd_ASync or Snd_Memory or snd_Resource) ;
end;
5.结束语
位图、光标和图标、AVI动画、JPEG和Wave文件等可以放到资源文件中,上面我们介绍了如何将资源加入到资源文件中,并介绍了在Delphi中动态存取资源文件的方法。Delphi编译工程会自动创建一个和工程名相同的资源文件(如果没有其他的资源,主窗口的图标会放在这个资源文件中)。但是建议最好不要改变这个资源文件。

解决方案 »

  1.   

    第二篇文章:
    《谈Delphi编程中资源文件的应用》
     [来源:陈经韬]
    (一)初级应用篇:
      资源文件一般为扩展名为res的文件.在VC中资源文件用得非常普遍,但Delphi在其联机帮助中对资源文件没作什么介绍,其实利用其自带的资源编译工具BRCC32.EXE(一般位于\Delphi\BIN目录下),我们完全可以做出跟VC一样效果的文件来。
      资源文件最大的好处是能将一些在必要时才调用的文件跟可执行文件一起编译,生成一个文件.这样做最大的好处就是使外部文件免遭破坏.例如在一条程序中你要临时调用一幅图片,一般作法是把图片放在某一路径下(通常是主程序所在路径),但如果用户路径误删你的图片文件,则可能使程序找不到相应文件而出错崩溃.另外,如果你想自己的程序界面美观,想用一些自定义光标,也要用到资源文件。
      资源文件的使用步骤为:
    1.编写rc脚本文本
    用记事本或其它文本编辑器编写一个扩展名为rc的文件。例如:mycur cursor move.cur //加入光标
    mypic Bitmap Water.BMP //加入位图
    mywav WAVE happy.wav //加入声音
    myAVI AVI EPOEN.AVI //加入视频
    myIco ICON CJT.ICO //加入图标  格式分别为在资源文件中的名称->类型->实际文件名称,例如上面第一行定义一个名为mycur的光标,实际名称为加入光标move.cur.
    2.将rc文件编译成res资源文件
      将脚本文件和实际文件拷到Brcc32.EXE所在目录,执行DOS命令。格式为:Brcc32 脚本文件(回车),例如有一名为myfirst.rc的脚本文件,则执行 Brcc32 myfirst.rc(回车)即可。如果你是懒人,也可新建一批处理文件,内容只有一行:Brcc32 mufist.rc.(因为Delphi安装后一般会在自动批处理文件中指明搜索路径的。)如果编译成功,则会生成一个结尾为res的文件,这个文件就是我们需要的资源文件。
    3.在Delphi单元中加入资源文件
      将生成的res资源文件拷贝到你所编程序的路径下,在单元文件{$R *DFM}后加上一句{$R mufirst.res},则将res文件加入去,编译后资 源文件即已包含在可执行文件中了。若你有多个资源文件,也按上法依次加入。
    4.在Delphi程序中调用资源文件
      资源文件在Delphi中的关键字为hinstance.下面给出具体用法.
    <1>光标的调用
      首先在程序中定义一个值大于0的常量,因为Delphi本身用0-负16来索引默认的光标,所以我们制定的光标应从表面上1开始索引。然后在窗口的Oncreat事件中添加以下代码:
    screen.cursor[35]:=Loadcursor (hinstance,'mycur');
      其中35为大于1的常量,mycur为光标在资源文件中的名字。如果希望在其他控件上使用定制光标,例如Panel控件,只需在程序的适当处加入以下代码:
    Panel1.cursor:=35;
    <2>位图的调用
      新建一项工程,添加一Timage控件,在需要显示的地方写以下代码:
    Var mymap:Hbitmap;
    begin 
    mymap:=LoadBitmap(hinstance,'mypic');
    Image1.picture.Bitmap.Handle:=mymap;
    end;
      其中"mypic"为位图资源文件中的名称。
    〈3〉AVI文件的调用
    新建一工程,添加一Animate控件,在需要的地方加入:
    animater1.resname:='myAVI';
    animater1.Active:=true;
    其中myAVI为视频文件在资源文件中的名称。
    〈4〉调用WAV文件
      在uses中加入mmsystm单元,以便在程序中播放WAV文件。播放时Playsound(pchar('mywav'),hinstance,sndsync or snd_resource);其中mywav为声音文件在资源中的名称。
    〈5〉加入光标
      加入光标比较容易,只要将res文件加入单元文件中即可。但需注意,名称最好取"W"."WW"等,使第一个字母尽量靠后,以免与主程序的图标顺序颠倒。这样一来,别人在使用你的程序时如果想选择其它图标就有很多选择了。
    补充:
    1.资源类型除上述类型外,还可以字体文件,字符串文件等。
    2.资源文件不但可以在标准图形界面下使用还可在控制台下使用。
    下面我们来试验一下:
      新建一工程,将唯一的一个Form删除,然后修改工程文件。增加一句{$Apptype console},在uses子句中加入mmsystem,并将其它引用单元删掉。将Begin和end之间语句删掉。至此,我们就可和Turbo PASCAL下编程序一样,且还可以调用windows的API和资源。将资源文件----{$R myfist.res}加入。在Begin和end之间写下:
    writeln('演示程序,按任意键开始!');
    readln;
    playsound(pchar('mywav'),hinstance,snd_sync or snd_resource);
    writeln('演示结束!');
      运行程序,将弹出一个标准DOS窗口,按任意键播放声音文件。是不是很COOL呢!我曾下载过一个播放器,在其安装目录下我发现有一"DOS程序",用鼠标双击它便弹出一个DOS窗口,显示DOS时代特有的画图,并有背景音乐!可能就是用这个方法做的。
    3.Delphi本身自带了一个叫Image Editor的工具,同样可以编辑资源文本,但和本文的方法比较,可得出下表:**************************************
    Image Editor Brcc32BMP 只支持16位色 任意色光标 黑白两色 任意色ICO 只支持16位色 任意色AVI 不支持 支持WAV 不支持 支持字体 
    字符串 不支持 支持
    其他 
    ****************************************  上面说的是直接在程序本身的调用。其实资源文件还有其它用法。比如说在你的程序携带其它文件,要用的时候释放出来。
    例如: myexe exefile 'ha1.exe'//脚本文件
    下面是自定义释放函数ExtractRes,本例中使用如下:
    ExtractRes('exefile','myexe','c:\new.exe');
    就把ha1.exe以new.exe为名字保存到C盘根目录下了. function TForm1.ExtractRes(ResType, ResName, ResNewName: string): boolean;
    var
    Res: TResourceStream;
    begin
    try
    Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
    try
    Res.SavetoFile(ResNewName);
    Result := true;
    finally
    Res.Free;
    end;
    except
    Result := false;
    end;
    end;
    ----------------------------------------------------------------------
      

  2.   

    (二)中级应用篇:
      上面我们已经知道如何把一副BMP图像从资源文件里面读出来,但是BMP文件太大了,JPG文件应用的相对较多.那么如何把JPG图像读出来呢?用资源文件加流方式即可。具体方法如下:
    (1)MyJpg JPEG My.JPG
    (2)Var
       Stream:TStream;
       MyJpg:TJpegImage;
      Begin
       Stream:=TResourceStream.Cceat(HINSTANCE,'MyJpg','JPEG');
       Try
         MyJpg:=TJpegImage.Create;
        Try
          MyJpg.LoadfromStream(Stream);
          Image1.Picture.Assignc(MyJpg);
        Finally
          MyJpg.Free;
        end;
       Finally
        Stream.Free;
       end;
      end;
      读取其它图片文件也是一样的.比如说gif动画文件,当然前提是你有一个gif.pas,这个单元很多站点都有的,可以自己去找找。实际应用中我还发现用上面的代码可以直接显示资源文件中的ICON和BMP.
      说到图形处理,实际上还可以用Delphi创建、调用纯图标资源的DLL.比如说你可以看看超级解霸目录下的Dll,很多就是纯图标资源而已。具体方法如下:
    (1):创建一个Hicon.RES文件,这里不再重复.
    (2):新建一文本文件Icon.dpr,内容如下:
    library Icon;
    {$R Icon.RES}
    begin
    end.
    用Delphi打开编译即可得到Icon.dll.
    (3):实际调用方法如下:
    ......
     Private
      Hinst:THANDLE;
    ......
     Var Hicon:THANDLE;
    begin
     Hinst:=Loadlibrary('Icon.dll');
     If Hinst=0 Then Exit;
     Hicon:=Loadicon(Hinst,Pchar(Edit1.Text));
    If Hicon<>0 Then Image1.Picture.Icon.Handle:=Hicon;
     FreeLibrary(Hinst);
    end;
      如果你的程序想在国际上供使用不同语言的人使用的话,用Dll来存放字符资源将是一个好方法.因为Dll不象ini文件那样可以被人随便修改,特别是有时侯如果想保存一些版权信息的话用Dll就再好不过了。比如说你准备开发一个"汉字简繁体翻译器"软件,准备提供Gb32,Big5码和英文三种语言菜单给用户,那么你可以试试用Dll来保存字符资源.
      我们需要建立三个Dll.第一步当然是写Rc文件,举Gb32码为例,内容如下:
    /*MySc.rc*/
    #define IDS_MainForm_Caption 1
    #define IDS_BtnOpen_Caption 2
    #define IDS_BtnSave_Caption 3
    #define IDS_BtnBig5_Caption 4
    #define IDS_BtnGb32_Caption 5
    #define IDS_BtnHelp_Caption 6
    #define IDS_Help_Shelp 7
    Stringtable
    {
    IDS_MainForm_Caption,"汉字简繁体翻译器"
    IDS_BtnOpen_Caption,"打开文件"
    IDS_BtnSave_Caption,"保存文件"
    IDS_BtnBig5_Caption,"转换成Big5"
    IDS_BtnGb32_Caption,"转换成Gb32"
    IDS_BtnHelp_Caption,"帮助"
    IDS_Help_Shelp,"输入文字或打开文件后按需要点击按钮即可转换!"
    }
      第二步是Brcc32编译为Res文件后用上面的方法得到Dll文件,另外两个Dll用同样的方法生成.下面来应用一下:
      新建一个工程,放上五个Button:BtnOpen,BtnSave,BtnBig5,BtnGb32和BtnHelp.还有一个TComboBox:CbSelect用来选择语言种类的.
    具体代码如下:
    unit Unit1;
    interface
    ......
    private
    SHelp: string;
    function SearchLanguagePack: TStrings;
    procedure SetActiveLanguage(LanguageName: string);
    { Private declarations }
    ......
    implementation
    procedure TForm1.CbSelectChange(Sender: TObject);
    begin
    SetActiveLanguage(CbSelect.Text);//调用相应Dll文件读取相应字符.
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    CbSelect.Items.AddStrings(SearchLanguagePack);//搜索当前目录下所有的Dll文件名称
    end;
    function TForm1.SearchLanguagePack: TStrings;
    var
    ResultStrings: TStrings;
    DosError: integer;
    SearchRec: TsearchRec;
    begin
    ResultStrings := TStringList.Create;
    DosError := FindFirst(ExtractFilePath(ParamStr(0)) + '*.dll', faAnyFile, SearchRec);
    while DosError = 0 do
    begin
    ResultStrings.Add(ChangeFileExt(SearchRec.Name, ''));
    DosError := FindNext(SearchRec);
    end;
    FindClose(SearchRec);
    Result := ResultStrings;
    end;procedure TForm1.SetActiveLanguage(LanguageName: string);
    var
    Hdll: Hmodule;
    MyChar: array[0..254] of char;
    DllFileName: string;
    begin
    DllFileName := ExtractFilePath(ParamStr(0)) + LanguageName + '.dll';
    if not FileExists(DllFileName) then Exit;
    Hdll := loadlibrary(Pchar(DllFileName));Loadstring(hdll, 1, MyChar, 254);
    Self.Caption := MyChar;
    //读取字符资源,1表示资源文件中定义的1
    Loadstring(hdll, 1, MyChar, 254);
    Self.Caption := MyChar;Loadstring(hdll, 2, MyChar, 254);
    BtnOpen.Caption := MyChar;Loadstring(hdll, 3, MyChar, 254);
    BtnSave.Caption := MyChar;Loadstring(hdll, 4, MyChar, 254);
    BtnBig5.Caption := MyChar;Loadstring(hdll, 5, MyChar, 254);
    BtnGb32.Caption := MyChar;Loadstring(hdll, 6, MyChar, 254);
    BtnHelp.Caption := MyChar;Loadstring(hdll, 7, MyChar, 254);
    SHelp := MyChar;Freelibrary(hdll);
    Application.Title := Self.Caption;
    //------------------------
    BtnOpen.Visible := True;
    BtnSave.Visible := True;
    BtnBig5.Visible := True;
    BtnGb32.Visible := True;
    BtnHelp.Visible := True;
    //------------------------
    end;
    procedure TForm1.BtnHelpClick(Sender: TObject);
    begin
    Application.MessageBox(Pchar(SHelp), 'Http://lovejingtao.126.com', MB_ICONINFORMATION);
    end;
    end.
      可能你会说,这种方法还不如我自己在程序中直接定义三种具体的值来的方便.甚至我自己自定义一个结构好了,用不着用DLL那么麻烦的。但是如果你的程序要用的字符很多呢?比如说Windows操作系统,本身就有简体中文,繁体中文,英文等等版本,用Dll的话只要直接替换DLL即可,而不用每发行一个版本就打开代码来修改一次。这样一来可以大大减少工作量和出错的机会.说到这里,再多说一句:Windows系统本身很多Dll带有了图片等资源,我们可以在程序中直接调用,这样一来我们的EXE也可以减少不少!当然最小的方法是实时生成技术.老外曾经写了一个67KB的程序就是利用了这个方法.感兴趣的朋友可以到http://go4.163.com/lovejingtao/ha1.exe下载.
    ----------------------------------------------------------------------
      

  3.   

    (三)高级应用篇:
       Delphi是个很有效率的开发工具,但是它有一个缺点就是生成的EXE文件太大.一个程序就算只有一个空窗口体积也有286KB.如果直接用API来写的话程序体积是小了,但是又太繁琐,无法立即看到界面效果,根本谈不上是可视化开发.其实并非"鱼与熊掌不可兼得",利用资源文件我们就可以轻松达到这个目的.
      在开始之前,我们需要一个可以编辑资源文件的工具.这类工具很多,比如说Resource WorkShop就是非常好的一个.如果一时找不到,利用VC的编辑器来也是可以的.下面我们就以VC的为例示范如何创建一个窗口资源文件.运行VC,打开菜单File-->New,将出现一个多项选择页.我们选择Files-->ResourceTemplate,在右边的File填上Demo,Location选择保存路径,然后点击按钮OK返回VC开发环境.
      选择菜单Insert-->Resource,将出现一个资源类型选择框.我们把鼠标移到Dialog上面.不用展开,点击右边的New即可,这时候返回VC开发环境并出现一个只有关闭按钮和两个Button的窗体.将鼠标选定窗体,击右键选择最后一项Properties,将出现一个设置窗口,将ID改为"MAINFORM"(注意:跟下面添加的其它控件的属性设置方法不同,主窗口的ID必须把双引号写上去,而且名称必须为大写.否则程序将找不到资源.程序会一运行就退出了.)Caption改为"安装程序",这时候可以立刻看到窗口的标题变成了"安装程序",把Styles的Minimize box选上,More Styles的Center勾上使程序运行时的位置居中.当然你也可以设置它的坐标.其它保留默认值即可.回到开发环境,在控件框里面分别选择一个Static Text,一个Edit Box,一个Button和一个Group Box添加到窗体上面.把它们按照自己的爱好排列整齐.然后逐个修改它们的属性.方法就是按照上面说的选定控件后击右键选择最后一项Properties,在出现的属性框里面修改.其中属性如下:Group Box的Caption属性清空,Static Text的Caption属性改为"请选择安装目录:",Edit Box的ID改为10001.第一个Button的ID为10002,Caption属性为"选择",第二个Button的ID为10003,Caption属性为"安装",第三个Button的ID为10004,Caption属性为"退出".为了使程序更加完美,我们为它再添加一个菜单IDR_MENU1.选择Insert-->Resource-->Menu,我们这里只简单添加一项"文件-->退出",其中"退出"的ID为10005.然后在主窗口的属性Menu设定为IDR_MENU1即可.
      为了使程序更加美观,我们再添加一个小图标,同时这也将是我们程序的图标.选择Insert-->Resource-->Icon-->Import,选择一个图标文件.并将它的ID设置为"MAINICON"(注意:必须把双引号写上而且字母为大写),为窗口添加一个Picture控件并设置它的属性Type:Icon,Image下拉选择刚才的图标MainIcon即可.
      如果你想为程序在鼠标添加一些信息也是可以的.选择Insert-->Resource-->Version即可.
      到这里我们已经完成了一个简单的"安装程序"的窗体设计.实际上我们现在就可以在Delphi中调用它了.我们先把"劳动成果"保存起来.选择File-->Save As,在文件类型里选择"32-bit Resource File(.res)"保存为"Demo.res",文件大小大约为2.65KB.
    新建一个扩展名为dpr的文本文件MyDemo.Dpr,键入如下代码:
    Uses Windows,Messages;
    {$R Demo.Res}
    function MainDialogProc(DlgWin:hWnd;DlgMessage:UINT;DlgWParam:WPARAM;DlgLParam:LPARAM):integer;stdcall;
    begin
    Result := 0;
    case DlgMessage of
    WM_Close:
    begin
    PostQuitMessage(0);
    Exit;
    end;
    end;
    end;
    begin
    DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
    end.
      用Delphi打开它编译一次即可产生一个大小为19KB的EXE.是不是很小!实际上,你甚至只用一行代码就把它Show出来,不过程序无法关闭而已.
    Uses Windows;
    {$R Demo.Res}
    function MainDialogProc: integer;
    begin
    Result := 0;
    end;
    begin
    DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
    end.
      上面的程序只不过是一个空窗口而已,现在我们来写代码响应按下相应按钮响应的事件.完整代码如下:
    program MyDemo;
    uses Windows, Messages, shlobj;
    const
    ID_Edit = 10001;
    ID_Selet = 10002;
    ID_Setup = 10003;
    ID_Quit = 10004;
    ID_Exit = 10005;
    {$R Demo.Res}
    var
    MainWin: HWND;function My_Gettext: string;
    var
    Textlength: Integer;
    Text: PChar;
    s: string;
    begin
    TextLength := GetWindowTextLength(GetDlgItem(MainWin, ID_Edit));
    GetMem(Text, TextLength + 1);
    GetWindowText(GetDlgItem(MainWin, ID_Edit), Text, TextLength + 1);
    s := text;
    FreeMem(Text, TextLength + 1);
    Result := s;
    end;function Getmyname: string;
    var
    i, j: integer;
    begin
    J := 3;
    for i := 1 to length(ParamStr(0)) do
    if ParamStr(0)[i] = '\' then J := I;
    Result := copy(ParamStr(0), J + 1, length(ParamStr(0)) - J);
    end;function SelectDirectory(handle: hwnd; const Caption: string; const Root:WideString;outDirectory:string): Boolean;
    var
    lpbi: _browseinfo;
    buf: array[0..MAX_PATH] of char;
    id: ishellfolder;
    eaten, att: cardinal;
    rt: pitemidlist;
    initdir: pwidechar;
    begin
    result := false;
    lpbi.hwndOwner := handle;
    lpbi.lpfn := nil;
    lpbi.lpszTitle := pchar(caption);
    lpbi.ulFlags := BIF_RETURNONLYFSDIRS + BIF_EDITBOX;
    SHGetDesktopFolder(id);
    initdir := pwchar(root);
    id.ParseDisplayName(0, nil, initdir, eaten, rt, att);
    lpbi.pidlRoot := rt;
    getmem(lpbi.pszDisplayName, MAX_PATH);
    try
    result := shgetpathfromidlist(shbrowseforfolder(lpbi), buf);
    except
    freemem(lpbi.pszDisplayName);
    end;
    if result then
    begin
    directory := buf;
    if length(directory) <> 3 then directory := directory + '\';
    end;
    end;function MainDialogProc(
    DlgWin: hWnd;
    DlgMessage: UINT;
    DlgWParam: WPARAM;
    DlgLParam: LPARAM
    )
    : integer; stdcall;
    var
    MyIcon: HICON;
    Sdir: string;
    begin
    Result := 0;
    case DlgMessage of
    WM_INITDIALOG:
    begin
    MyIcon := LoadIcon(hInstance, 'MainIcon');
    SetClassLONG(DlgWin, GCL_HICON, MyIcon);
    MainWin := DlgWin;
    end;
    WM_Close:
    begin
    PostQuitMessage(0);
    Exit;
    end;
    WM_COMMAND:
    case LOWORD(DlgWParam) ofID_Selet:
    begin
    if SelectDirectory(DlgWin, '请选择安装目录', '', Sdir)
    then SendMessage(GetDlgItem(DlgWin, ID_Edit), WM_SETTEXT, 0, lParam(pChar(Sdir)));
    end;
    ID_Setup:
    begin
    if My_Gettext = '' then
    begin
    MessageBox(DlgWin, '请先选择安装文件夹!', '信息', MB_ICONINFORMATION + MB_OK);
    Exit;
    end;
    CopyFile(pchar(ParamStr(0)), pchar(My_Gettext + Getmyname), false);
    MessageBox(DlgWin, '安装完毕!', '信息', MB_ICONINFORMATION + MB_OK);
    PostQuitMessage(0);
    Exit;
    end;
    ID_Quit:
    begin
    PostQuitMessage(0);
    EXIT;
    end;
    ID_Exit:
    begin
    if MessageBox(DlgWin, '你点击了菜单“退出”,你确定退出程序吗?', '信息', MB_ICONQUESTION + MB_OKCANCEL) = IDOK then
    PostQuitMessage(0);
    Exit;
    end;
    end;
    end;
    end;
    begin
    DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
    end.
      其中SelectDirectory函数的作用是返回一个选择的文件路径.然后把自己拷贝到选择的目录下,当然很多处理没有写,读者可以自行添加.文件编译后大小为22KB,如果直接用Delphi的VCL来写的话,将为338KB!完整代码可以在我的主页上下载:http://go4.163.com/lovejingtao/setup2.zip.代码中的消息处理相信大家看的懂.如果不用资源文件而直接用API来写将对它更加理解深刻,.限于篇幅这里不做详细介绍,感兴趣的读者可以自行下载代码来看:http://go4.163.com/lovejingtao/setup1.zip.
      全部代码在Delphi+Pwin2000下通过.
      

  4.   

    资 源 是 存 放 在 扩 展 名.RES 的 文 件 里 的 二 进 制 数 据 结 构, 在DELPHI 中 资 源 文 件 可 以 使 用 图 象 编 辑 器 来 制 作(IMAGE EDITOR), 或 者 使 用 其 他 的 工 具。 如:BORLAND 公 司 提 供 的RAD PACK FOR DELPHI 中 的RESOURCE WORKSHOP 来 创 建。 资 源 文 件 中 通 常 存 放 的 是 应 用 程 序 可 以 随 时 存 取 的 一 些 对 象, 包 括:ICON、CURSOR、BITMAP、FONT 等 近 十 种。 大 部 分 的 资 源 在 通 常 的 情 况 下 可 以 保 留 在 磁 盘 当 中, 直 到 程 序 需 要 使 用 它 们 时 才 将 其 调 入, 可 以 大 大 的 节 省 内 存 资 源, 同 样, 资 源 文 件 也 是 可 以 共 享 的, 即: 多 个 程 序 可 以 共 享 一 个 资 源 文 件, 进 而 减 少 了 在 应 用 程 序 之 间 代 码 重 复 的 现 象, 使 程 序 的 代 码 得 到 很 大 的 优 化, 因 此 在 应 用 程 序 中 使 用 资 源 文 件 有 独 立 制 作、 方 便、 随 时 修 改 而 不 需 要 对 应 用 程 序 代 码 做 任 何 修 改 的 好 处。 一 般 来 说, 一 个 应 用 程 序 的 所 有 资 源 都 存 放 在 一 个RES 文 件 里, 然 后 在DELPHI 进 行 编 译 的 阶 段 将 资 源 文 件 的 内 容 与 最 终 的EXE 文 件 合 并 在 一 起, 因 此 编 译 后 的RES 文 件 并 没 有 什 么 作 用, 仅 仅 提 供 用 来 查 阅 使 用, 在 分 发 应 用 时 不 必 把RES 文 件 分 发 给 最 终 用 户。 当 然, 不 同 的 资 源 可 以 分 别 放 在 不 同 的 资 源 文 件 当 中, 而 且 资 源 文 件 越 小 调 入 内 存 的 速 度 越 快。 在 这 里 还 要 说 明 的 一 点 是: 在 修 改 了 原 来 的 资 源 文 件 之 后, 在 原 来 编 译 的EXE 文 件 中 加 入 的 资 源 不 会 随 之 而 更 新, 只 有 在 重 新 进 行 编 译 以 后, 才 能 将 新 的 资 源 加 入 到 新 的EXE 文 件 当 中 去。 下 面 我 们 通 过 两 个 例 子 来 说 明 在DELPHI 中 如 何 使 用 资 源 文 件( 在 这 里 我 们 不 讲 述 资 源 文 件 的 制 作 方 法)。 一、 如 何 在DELPHI 中 使 用 定 制 的 光 标。 
    在 使 用DELPHI 进 行 编 程 时, 有 一 个 很 重 要 的 对 象 ─ ─TSCREEN, 它 是 用 来 管 理 和 操 纵 运 行 时 期 屏 幕 的 不 可 视 构 件。 它 的CURSOR 属 性 是 用 来 指 定 各 个 不 同 的 构 件 光 标 形 状, 声 名 为: PROPERTY CURSORS[INDEX:INTEGER]:HCURSOR; 
    这 个 只 读 的 特 性 返 回 应 用 程 序 支 持 的 光 标 组 成 的 一 个HCURSOR 类 型 的 数 组, 它 存 储 了 屏 幕 上 所 有 的 鼠 标 光 标 的 身 份 代 码(HCURSOR 就 是 光 标 的HANDLE 句 柄), 数 组 下 标 从0 开 始, 在DELPHI 预 定 义 了 一 些 代 表 不 同 光 标 的 常 量, 它 的 值 是 从0 到-17, 您 可 以 直 接 指 定 程 序 使 用 的 光 标。 如: FORM1.CURSOR:=-3 表 示FORM1 采 用 的 光 标 是CRCROSS( 十 字)。 大 家 可 能 都 会 发 现 构 件 的CURSOR 的 属 性 最 多 提 供 十 八 种 常 用 的CURSOR 值, 这 在 很 多 的 情 况 下 是 不 够 的, 如: 当 光 标 进 入 一 个PANEL 面 板 时 光 标 的 形 状 为 一 只 手, 那 么PANEL 的CURSOR 就 不 能 满 足 这 种 要 求, 这 时 就 需 要 我 们 自 定 义 一 个 手 的 光 标 并 将 其 赋 给PANEL 的CURSOR 属 性。 如 何 实 现 则 可 以 按 以 下 步 骤 进 行: 使 用 资 源 文 件 编 辑 器(IMAGE EDITOR 或 者RESOURCE WORKSHOP) 编 写 资 源 文 件。 定 义 一 个 光 标 常 量, 注 意 这 个 常 量 不 能 与DELPHI 中 提 供 的 光 标 常 量 相 冲 突。 
    在FORMCREATE 事 件 中 使 用WINDOWS API 当 中 的LOADCURSOR 函 数 来 载 入 自 定 义 的CURSOR。 
    在 程 序 中 将 自 定 义 的CURSOR 分 配 给PANEL 的CURSOR 属 性。 
    下 面 说 明 如 何 将 自 定 义 的 一 只 手 的 鼠 标 光 标 赋 给PANEL1 的CURSOR 属 性。 首 先 使 用IMAGE EDITOR 建 立 一 个HAND.RES 的 文 件。 之 后 按 如 下 书 写 程 序 代 码: implementation {$R *.DFM} const Crhand=2; procedure TForm1.FormCreate(Sender: TObject); begin screen.cursors[crhand]:=loadcursor(Hinstance,'hand'); panel1.cursor:=crhand; end; 
    除 了 编 写 上 面 的 代 码 以 外, 我 们 还 需 要 做 的 一 项 工 作 是 将 资 源 文 件 加 入 到 项 目 文 件 当 中 去, 编 译 指 令 中 的{$R filename} 伪 指 令 让 我 们 来 增 加 资 源 文 件, 让 我 们 来 看 一 看 项 目 文 件 的 代 码。 program PCUR; uses Forms, HAND in 'HAND.pas' {Form1}; 
    {$R *.RES}// 这 里 的* 意 义 为 在 程 序 编 译 以 后 会 产 生 一 个 与 项 目 文 件 同 名 的 资 源 文 件, 在 这 里 为PCUR.RES 文 件, 这 部 分 是 自 动 产 生 的。 {$R hand.res}// 这 部 分 是 我 们 自 己 加 入 的 自 定 义 资 源 文 件, 这 两 个 资 源 文 件(HAND.RES 和//PCUR.RES 中 的 资 源 都 会 附 加 在 可 执 行 文 件PCUR.EXE 的 后 面。 begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. 
    二、 资 源 文 件 在 编 写 动 画 程 序 中 的 应 用 
    上 面 的 例 子 使 用 的 是 在 资 源 文 件 中 存 储 的CURSOR 资 源 , 在 下 面 的 例 子 中 我 们 将 使 用 的 是 在 资 源 文 件 中 提 供 的ICON 资 源 来 编 写 一 个 小 小 的 动 画 程 序。 在 这 里 动 画 的 产 生 是 利 用 定 时 器 在 一 定 的 时 间 间 隔 内 产 生TIMER 事 件 将 存 储 在 资 源 文 件 中 的ICON 依 次 的 绘 制 在FORM 的 同 一 处 而 产 生 的。 这 时 要 用 到 画 布CANVAS 的DRAW 方 法, 其 声 明 如 下: procedure Draw(X, Y: Integer; Graphic: TGraphic); 在 这 个 方 法 当 中 的 参 数GRAPHIC 可 以 为:BITMAPS、ICONS、METAFILES。 具 体 的 实 现 方 法 为: 建 立DEMO.RES 文 件, 其 中 含 有 名 为ICON1 —ICON6 的ICON。 并 将DEMO.RES 加 到 项 目 原 代 码 中 去( 如: 上 面 例 子 的 方 法)。 动 画 程 序 的 具 体 代 码 如 下: 
      

  5.   

    unit donghua; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TForm1 = class(TForm) Image1: TImage; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation var wicon:array[0..5]of Ticon; // 建 立TICON 类 型 的 数 组 存 储ICON 文 件 idx:integer; {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); var iconname:string; piconame:pchar; begin piconame:=stralloc(7); // 建 立PCHAR 类 型 的 字 符 串 for idx:=0 to 5 do begin wicon[idx]:=ticon.create;// 建 立TICON 型 对 象 iconname:='icon'+inttostr(idx); strpcopy(piconame,iconname); // 将STRING 类 型 转 换 成PCHAR 类 型 wicon[idx].handle:=loadicon(hinstance,piconame); // 调 用WINDOWS API 中 的LOADICON 函 数 // 载 入 资 源 中 的ICON end; strdispose(piconame);//PCHAR 类 型 的 删 除 form1.canvas.draw(3,3,wicon[1]); // 调 用DRAW 的 方 法 在FORM 上 画 出ICON1 idx:=1; form1.setbounds(0,0,100,100); // 固 定FORM 的 大 小 和 位 置 end; procedure TForm1.Timer1Timer(Sender: TObject); // 形 成 动 画 的 定 时 器 事 件 begin idx:=idx+1; if idx=6then idx:=1; form1.canvas.draw(3,3,wicon[0]); form1.canvas.draw(3,3,wicon[idx]); end; end. 
    以 上 可 以 作 为 一 个 通 用 的 动 画 程 序, 我 们 只 需 要 修 改 不 同 的ICON 以 及 增 加IDX 的 大 小 就 可 以 编 出 不 同 的 动 画 应 用( 同 样 在 资 源 中 可 以 有 其 他 形 式 的 图 形 如:BITMAPS 这 时 需 要 动 态 创 建 的 是TBITMAPS 对 象 而 不 是TICON 对 象)。 在 两 个 例 子 中 我 们 都 用 到 了WINDOWS API 函 数, 这 些 函 数 在WINDOWS 单 元 中 均 有 说 明 在 这 里 不 加 赘 述。 以 上 的 两 个 例 子 只 是 资 源 文 件 的 一 点 点 应 用, 要 真 正 的 掌 握 资 源 文 件 在 程 序 设 计 中 的 强 大 作 用, 还 要 靠 自 己 在 实 践 中 不 断 的 总 结。 
      

  6.   

    嗬嗬,眼镜蛇兄找的好东西啊。其实懂win32 sdk的,应该对这个很了解了。
      

  7.   

    不过为什么要用这个呢??????我反问眼镜蛇老兄一句,如果这样delphi与VC有什么区别呢?也用resource shop编好资源,编辑管理打成包。然后用sdk调用…… 这不是舍近求远?我随便说说而已,其实不失为一种好办法。
      

  8.   

    欢迎大家就:reallike(认真学习Cpp用Cpp考虑delphi)  老兄提出的问题展开讨论,我目前正在研究,活活,:)
      

  9.   

    如果这些文件比较大,就尝试上面说的,做成dll文件,然后loadlibrary调用。除了这个,就是文件流的方式,delphi的这个文件流方法非常好。可以从pe文件格式中提取。可以管理几乎任何文件。比如较大的字体文件,但是又不想给别人用。再就是纯SDK的方式,但,这个嘿嘿,我不赞同使用啊。
      

  10.   

    资源文件(.RES)的应用
    来源:cww资源档有什麽用处呢?最重要的有两个地方
    1.国际发行:我们将Application中所有的文字从Resource用读取,那麽,只要更动
                Resource档的内容,就可以用不同语言的方式来显示。
    2.管理资源:例如说,我们的AP中用了数百张的图片或声音,不用Resource档的话,
                在发行出去的AP中,就必需有数百个图形、声音档,那似乎不太好,使
                用Resource档,便可以将这些图形、声音放进一个.Res档。使用RC.exe来Compiler我们所定义的Resource档, RC.EXE在vb5.0光碟中的\TOOLS\RESOURCE Resources 可分成两大部份:- String resources (text strings such as "Hello World").
    - Binary resources (icons, bitmaps, cursors, sounds, video等)
    String Resources语法:STRINGTABLE [load-option] [mem-option]
    BEGIN
    stringID string
    .
         .
         .
    END叁数说明 :
    - load-option 可以是以下两种 
    Option        Description 
    ------        ----------- 
    PRELOAD       Resource is loaded immediately. LOADONCALL   (Default) Resource is loaded when called. - mem-option 可以是以下三种
    Option       Description 
    ------       ----------- 
    FIXED        Resource remains at a fixed memory location. 
    MOVEABLE     Resource can be moved if necessary in order to compact memory. 
    DISCARDABLE  Resource can be discarded if no longer needed. - stringID  自行定义的integer,用来定义字串 resource.
    - string    我们定义的字串,字串前後要用双引号(")将之包围起来,字串长度不可
                超过255 bytes,而且字串要在同一行 BINARY RESOURCES
    语法:nameID keyword [load-option] [mem-option] filename叁数:- nameID 定义一个於以下keyword类别中,一个唯一的名称或数字,即,有三个BITMAP
             类别的Resource,其nameID可以分别为1,2,3不重覆,而另有三个ICON的资源
             ,其nameID亦可分别为1,2,3,不会和BITMAP的1,2,3相冲突。注:ICON类别
             的nameID不可以为0,0保留给 Visual Basic icon。nameID亦可以为字串- keyword 定义资源类别 Option Description ------ ----------- BITMAP Defines a bitmap (.BMP) CURSOR Defines a cursor (.CUR) ICON Defines an icon (.ICO) SOUND Defines a wave file (.WAV) VIDEO Defines a video file (.AVI) 
    - load-option
    Option     Description 
    ------     ----------- PRELOAD    Resource is loaded immediately. LOADONCALL (Default) Resource is loaded when called. 
    - mem-option
    Option       Description  
    ------       -----------  
    FIXED        Resource remains at a fixed memory location.  
    MOVEABLE     Resource can be moved if necessary in order to compact memory.  
    DISCARDABLE  Resource can be discarded if no longer needed.  default for binary resources is MOVEABLE. - filename 资源所在的档名 
     
    Compiler的语法:rc /r [options] SourceFile(.RC) - /r 只Compiler .RC file , not linked to any executable.可用rc /? 来查语法EXAMPLERC /r /fo TEST32.RES TEST.RC 上面的表格中是读取Test.RC的定义,而产生TEST32.RES,这个档便是我们程式设计中所需的资源档,而在vb5.0中如何来使用呢,在 "专案功能表 的 新增档案"中来选取该Resource file(.RES) ,之後在专案总管中,会出现 
    - ---Project1
       +-- 表单
       --- 相关文件
         |  
         ------TEST32.RES 那便可以使用 LoadResString LoadResPicture LoadResData来抓取相关的资料了 以下是Test.RC的内容,而BitMap, Icon写的档名,请自行更改成您对映的档案 #define IDS_HELLO    1
    #define IDS_GOODBYE  2STRINGTABLE
    BEGIN
        IDS_HELLO,   "Hello"
        IDS_GOODBYE, "Goodbye"
        3,           "This is a Test"
    END
    STRINGTABLE
    BEGIN
        101,        "您好"
        102,        "再见了"
        103,        "这是一个测试"
    END/////////////////////////////////////////////////
    // Bitmap 
    ////////////////////////////////////////////////
    1          BITMAP "CLI.BMP"
    101        BITMAP "CLI2.BMP"
    BITMAP3    BITMAP "多多.BMP"////////////////////////////////////////////////
    // ICON
    ///////////////////////////////////////////////
    1          ICON   CLIENT.ICO
     
    以下是在form中,需3个Command Button 3个Label 1个PictureBox 另需在 专案功能表 中选 新增档案 并进而选取Test32.Res 
    Option ExplicitPrivate Sub Command1_Click()
    Call ShowRtn(0)
    End SubPrivate Sub ShowRtn(ByVal i As Long)
    Label1.Caption = LoadResString(i + 1)
    Label2.Caption = LoadResString(i + 2)
    Label3.Caption = LoadResString(i + 3)
    Set Picture1 = LoadResPicture(i + 1, vbResBitmap)
    End SubPrivate Sub Command2_Click()
    Call ShowRtn(100)
    End SubPrivate Sub Command3_Click()
    Set Picture1 = LoadResPicture("BITMAP3", vbResBitmap)
    End Sub 
      

  11.   

    那我们请
    reallike(认真学习Cpp用Cpp考虑delphi) 给介绍一下你在这方面的经验和方法,要知道在CSDN上很多同僚们都会遇到这种问题,但一般都不会去想,不会去捉摸该采用什么方法来读取,
    reallike(认真学习Cpp用Cpp考虑delphi) :你所说的纯SDK方式是怎么实现的??你为什么不提倡???
    我知道我在以往的工程中都是IMAGE1.Picture.LoadFromFile()之类的,你采用的何种方式??
      

  12.   

    纯sdk就是你刚才所贴的这个,直接利用.res文件,因为这个不管用什么语言,win32汇编,C/C++都一样。都是这么把资源打进包。而delphi的优势就是这些都不用关心,因为它有它自己的资源文件。而不是利用windows sdk提供的这种。所以我上面说舍近求远。研究研究倒是没什么,如果应用,那就和使用VC写程序没有什么区别了。
      

  13.   

    procedure LoadJPEGFromRes(TheJPEG : string; ThePicture : TPicture);
    var
      Stream:TStream;
      MyJpg:TJpegImage;
    begin
      Stream:=TResourceStream.Create(HINSTANCE,TheJPEG,'JPEG');
      Try
        MyJpg:=TJpegImage.Create;
        Try
          MyJpg.LoadfromStream(Stream);
          ThePicture.Assign(MyJpg);
        Finally
          MyJpg.Free;
        end;
      Finally
        Stream.Free;
      end;
    end;调用
    LoadJPEGFromRes('SAVE1', BTNSave.Picture);
    LoadJPEGFromRes('COPY1', BTNCopy.Picture);
    LoadJPEGFromRes('CLEAR1', BTNClear.Picture);现在忙,先写写自己的应用。有时间在和大家讨论
      

  14.   

    舍近求远:指的是舍了哪个??指舍掉vc用delphi???
      

  15.   

    哦,就资源文件来说设掉dfm而使用了res,这个事情。
      

  16.   

    reallike(认真学习Cpp用Cpp考虑delphi) 
    一路走好!!!!!!
      

  17.   

    叫我like就行了。不用把后面的东西都弄上。like是我的真实姓名。
      

  18.   

    还讲D5呀,讲D7吧,D8都快出场了
      

  19.   

    就是通过流建立文件,呵呵。
    陈经韬的恶作剧之王就用了这个方法生成了format.exe,哈哈,够狠吧。
      

  20.   

    用例子最好证明一些事情了。ftp://61.129.70.192/datanew/2003101818593820468.zip这里面使用res文件。是纯sdk编程。可以说有些帮助。
      

  21.   

    like:你说的那个站点打不开,
      

  22.   

    眼镜蛇兄,你去www.playicq.com一下子就看到了。http://www.playicq.com/dispdocnew.php?id=9733&PHPSESSID=a72d570935a10db5212b034f1288d9e3这个呢?能不能用?
      

  23.   

    [Delphi & Kylix] delphi_clock名字就叫:delphi_clock