如何编程实现替换EXE文件的图标,并使替换后的图标色彩不明显失真!! ( 积分: 100 )

  • 主题发起人 主题发起人 simon.yeah
  • 开始时间 开始时间
S

simon.yeah

Unregistered / Unconfirmed
GUEST, unregistred user!
我看了jingtao文章之后,实验了发现虽然替换了图标但是色彩会明显失真!急需解决,给100分!!各位兄弟帮忙!!
jingtao (2002-11-08 23:24:00)
My_CutMpegFile(Label_Filename.Caption,Edit_Save1.Text,iStart,iEnd);
Application.MessageBox('切割完毕!',Pchar(Application.Title),
MB_ICONINFORMATION+MB_OK);
end;

end.

可能大家还记得我曾经写过一篇<<用Delphi在局域网中实现网上影院>>,就是在局部网
内一台电脑播放视频文件整个局部网的电脑都可以收到.那个采用的是隐形动态共享的办法
.但是那个方法有个致命的弱点,就是当播放的是光盘文件而不是磁盘文件的时候,当几个人
同时访问光驱就不行了.所以那个是取巧的方法.真正的方法是采用流.或者在数据头伪造M
ediaplay Server服务器.这样一来无论是磁盘文件还是光盘文件,实际上都是服务器一台电
脑读数据而已,就不会发生上面的情况了.具体程序可以在我的主页http://www.138soft.com
下载.但是如果对这些不熟练怎么办?哈哈,你还是可以采用取巧的方法:服务端开两个线程,
一个发送文件头,另外一个发送数据.客户端也开两个线程,一个接收数据保存为文件,另外
一个播放.比如说每个文件为4MB,接收完第一个后开始播放同时继续接收第二个.播放完第
一个就删除并播放第二个文件.实际上,早期的DVB就是这样做的.

三:图标文件ICO格式程序编程
Windows下的可执行文件大多都有一个图标的.如果这个程序是你自己编写的,那么你可
以轻松的在编译为EXE之前把图标更换掉.但是如果这个EXE不是你的呢?怎么办?当然是用工
具了.ResHacker(资源黑客)就是一个很好的工具.但是如果想自己编写程序来实现呢?
图标在可执行文件里面实际上是一项资源.Windows提供了一个API函数来取出EXE里面
的图标.函数原型为:HICON ExtractIcon(HINSTANCE hInst,LPCTSTR lpszExeFileName,
UINT nIconIndex);其中第一个参数为实例句柄,第二个参数为需要操作的EXE,DLL,BMP或
ICON等包含有图标资源的文件名,第三个参数为需要取出的图标在该EXE里面的索引(因为
一个EXE文件里面可能含有多个图标).如果这个参数为0,那么将返回第一个图标,如果这个
参数为-1,将返回该文件可能含有的所有图标数.如果该文件含有该索引图标,函数将返回该
图标的句柄,否则返回值NULL.
那么,到底我们应该怎么样才能更换一个EXE的图标呢?如果你熟悉PE文件结构的话就
很简单了.不过PE文件格式是比较复杂的,讲述它的话要费很大篇幅.实际上,你可以这样
简单的看一个EXE文件的组成:EXE文件=文件头之类+图标资源+文件尾.也就是说,你不用
管它的文件头和文件尾之类,只要找到图标在该EXE里面的位置,然后用你的图标覆盖它即可.
不过需要注意的是,图标是有多种格式的,比如说16X16的16色,32X32的16色,16X16的32
色等等.用这种方法更换图标的话必须注意格式要一致.另外,ExtractIcon函数返回的将是3
2X32的16色图标.这是个很有趣的地方.也就是说,无论你操作的文件或图标格式是怎么样,
它取出的都是32X32的16色图标.而Delphi默认的那个图标就是这个格式的.
我们打开Delphi,新建一个工程.直接编译后退出.这个得到的EXE我们将用来做&quot;实验品&quot;
.再新建一个工程,这个才是我们真正要写的程序.往窗口添加两个名字分别为Next_Icon,
Prev_Icon的TSpeedButton.作用是枚举图标的.添加一个Image1用来显示图标.一个名为E
dit_SourceFile的TEdit用来显示选择要取出的EXE之类的文件名称.一个OpenDialog,一个
SaveDialog和三个Button.最后记得在Use部分添加ShellApi.全部代码如下:
unit Unit1;

interface

uses
ShellApi{必须添加此单元}, Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons;

type
TForm1 = class(TForm)
Next_Icon: TSpeedButton;
Prev_Icon: TSpeedButton;
Image1: TImage;
Edit_SourceFile: TEdit;
Button1: TButton;
Button2: TButton;
Button3: TButton;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
procedure Button1Click(Sender: TObject);
procedure Prev_IconClick(Sender: TObject);
procedure Next_IconClick(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
procedure Extract_Icon;
function ChangeExeIcon(ExeFile,IconFile:string;Index:Integer=0):Boolean;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
Icon_Index: integer;
implementation

{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption:='取出图标';
Button2.Caption:='保存图标';
Button3.Caption:='更换图标';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.Filter := '所有支持类型(*.EXE,*.DLL,*.OCX,*.ICL,*.ICO,*.BMP)|*.exe;*.dll;*.ocx;*.icl;*.ico;*.bmp|所有文件 (*.*)|*.*';
if OpenDialog1.Execute
then
begin
Edit_SourceFile.Text := OpenDialog1.Filename;
Icon_Index := 0;
Extract_Icon;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
SaveDialog1.Filter :='图标文件(*.ICO)|*.ico';
if SaveDialog1.Execute then
begin
if Copy(SaveDialog1.FileName, Length(SaveDialog1.FileName)-3, 1) = '.' then
Image1.Picture.Icon.SaveToFile(SaveDialog1.FileName)
else
Image1.Picture.Icon.SaveToFile(SaveDialog1.FileName + '.ico');
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
ExeFile:String;
begin
OpenDialog1.Filter := 'EXE文件(*.EXE)|*.exe';
OpenDialog1.Title:='请选择需要更换图标的EXE';
if OpenDialog1.Execute then
begin
ExeFile:=OpenDialog1.FileName;
OpenDialog1.Filter := '图标文件(*.ICO)|*.ico';
OpenDialog1.Title:='请选择需要更换的图标文件';
OpenDialog1.FileName:='';{Clear the Old Filename}
if OpenDialog1.Execute then
if ChangeExeIcon(ExeFile,OpenDialog1.FileName) then
Application.MessageBox('更换图标成功!',Pchar(Application.Title),MB_ICONINFORMATION+MB_OK)
else
Application.MessageBox('更换图标失败!',Pchar(Application.Title),MB_ICONERROR+MB_OK)
else
Exit; {Not Select Icon File}
end;
end;

procedure TForm1.Prev_IconClick(Sender: TObject); //枚举前一个图标
begin
if not (FileExists(Edit_SourceFile.Text)) or (Icon_Index <= 0) then Exit;
Icon_Index := Icon_Index - 1;
Extract_Icon;
end;

procedure TForm1.Next_IconClick(Sender: TObject);//枚举下一个图标
begin
if not (FileExists(Edit_SourceFile.Text)) then Exit;
Icon_Index := Icon_Index + 1;
Extract_Icon;
end;

procedure TForm1.Extract_Icon;
var
icon_handle: Longint;
buffer: array[0..1024] of Char;
begin
if not (FileExists(Edit_SourceFile.Text)) then Exit;

StrPCopy(Buffer, Edit_SourceFile.Text);
icon_handle := ExtractIcon(self.Handle, buffer, icon_index);

if Icon_Handle = 0 {Did we get a valid handle back?}
then
begin {No}
if Icon_Index = 0 {Is this the first icon in the file?}
then {Yes. There can't be any icons in this file}
begin
Application.MessageBox('这个文件没有发现图标,请重新选择!','信息',MB_ICONINFORMATION+MB_OK);
Image1.Visible := False;
end
else {No. We must have gone beyond the limit. Step back}
Icon_Index := Icon_Index - 1;
Exit;
end;
{We now have our extracted icon. Save it to a temp file in readiness for the modifocation}
Image1.Picture.Icon.Handle := icon_handle;
Image1.Visible := True;
end;

function TForm1.ChangeExeIcon(ExeFile,IconFile:string;Index:Integer=0):Boolean;
.
end;
end.
运行程序,点&quot;取出图标&quot;,选择一个EXE,然后点&quot;保存图标&quot;将其ICO保存为文件.
然后点&quot;更换图标&quot;,选择我们刚才编译得到的&quot;实验品&quot;和取出的图标,即可将图标更改掉了.
自定义函数ChangeExeIcon的实现过程如下:先用ExtractIcon将图标释放出来保存为文
件,然后将其与EXE比较在该EXE里面找到图标的位置,然后将新图标的内容覆盖原来的图标.
实际上,这个查找过程还不够完美,因为它将两者都转化为TStringStream再比较,如果EXE文件很大的话是很费内存的.Delphi本身提供了一个例子用来查找位置的,该例子位于Delphi5/Demos/Resxplor下,读者可以结合它来作出高效的图标更换工具.

★作者:

陈经韬

430074湖北省武汉市武昌民院路湖北经济管理大学计算机系(本)9801班
Home:http://www.138soft.com
E-Mail: Lovejingtao@21.cn.com
 
www.ysza.com 文件捆绑器或,免费资源,图标工具 qq:171833017
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
499
import
I
后退
顶部