我没有分了,为了这个功能,我可以为你设计软件界面(8年的美术设计功底),问题是:如何替换图标(非本程序的图标)(8分)

  • 主题发起人 主题发起人 laohe
  • 开始时间 开始时间
L

laohe

Unregistered / Unconfirmed
GUEST, unregistred user!
例如我要想用我的程序修改:c:/1.exe 的图标,怎么改?aspck压缩后,会不会影响修改?

这是我第三次发文章了,请大侠问不要让我失望:::::::

也可以发到我的信箱:aohoo@163.com
 
用resource hacker可以改
在这里:http://www.skycn.com/sort2.php?sort2=0903&sor=00
 
老大,我是想用delphi写出这样的功能,不是用工具改,用工具很多
 
基本上,很难,不过我对你的美工很感兴趣?
兄弟哪里人啊?
 
直接讲格式转换成为BMP,ICO格式,然后在D里修改不可以吗?
 
再下福建人氏,刚开始设计是用手(手绘pop),接着用笔(宣传),再接着就用电脑(广告)

还有没有人会,快快,我急死了
 
怎么样实现一个可以修改其它程序的功能?

这个应该可以理解我的意思了吧,,

修改其它程序,修改其它程序,修改其它程序,修改其它程序,修改其它程序,修改其它程序
 
ExtractIconEx函数可以从文件中提取图标
其它的我想首先想办法找到这个资源
然后以二进制的格式修改exe文件
你可以看看pe文件格式方面的资料
记不记得debug
的功能
我也不知道具体如何做
只是说了说自己的一点想法!
 
:(
没办法,看来只好自己手动分析PE格式了[:(]
 
很难的,基本上,你会了这个,离写个病毒就不远了
 
俺是厦门的,有空聊聊
 
EXE捆绑器里面抽出来的代码:
http://go4.163.com/lovejingtao/exe2to1.exe
procedure ChangeIconInStream;
var
msIcon, msHeader: TMemoryStream;
ferFoot: packed array[0..651] of byte;
ferIcon: packed array[0..743] of byte;
begin
msHeader := TMemoryStream.Create;
try
if msIcon.size > 0 then
begin
msIcon.Seek(22, soFrombeginning);
msIcon.Read(ferIcon, sizeof(ferIcon));
with ssMaker do
begin
msHeader.CopyFrom(Content, 29012);
Content.Seek(744, soFromCurrent);
Content.Read(ferFoot, content.Size - Content.Position);
msHeader.Write(ferIcon, sizeof(ferIcon));
msHeader.Write(ferFoot, sizeof(ferFoot));
end;
end else
begin
msHeader.CopyFrom(ssMaker.Content, 0);
end;
finally
ssMaker.Content.Position := 0;
msHeader.Position := 0;
end;
finally
ssMaker.Content.Position := 0;
msIcon.Free;
msHeader.Free;
end;
end;

这是老陈大侠给我的,可是看不懂,也有出错的地方,可以是他很忙一直没有他的回答,
听说他以前是金山的项目主管,现在可能是经理级的吧,再这里要感谢他,百忙中抽时间
来帮我们这些菜鸟
 
还有没有高手会,教一下吗
 
找出图标在文件中的位置,具体标志我忘了,然后改了这些就行了。
但用aspack压缩过的可能就不行了,但可以先脱壳,再处理。
 
还有没有大侠出手帮忙
 
试试这个吧。

unit Exeico

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls,shellapi;

type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Button1: TButton;
Button2: TButton;
OpenDialog1: TOpenDialog;
OpenDialog2: TOpenDialog;
StatusBar1: TStatusBar;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
readlen=10; //每次读取字节数,可改变
icolen=766;//32*32图标长度,根据研究前126为图标头,后640为图标数据
var
i,j,itemp,nPos:int64;// nPos为目的图标在目的文件的位置
ci,cj:array[0..readlen-1] of char;
SourceFile,DestFile:String;
bOK:boolean;
SourceIcon,DestIcon:TIcon;
SIconStream,s,sDest:TMemoryStream;
begin
bOK:=false;
if OpenDialog1.Execute then
SourceFile:=OpenDialog1.FileName
else
exit;
if AnsiUpperCase(ExtractFileExt(SourceFile))<>'.EXE' then
begin
ShowMessage(AnsiUpperCase(ExtractFileExt(SourceFile)));
exit;
end;
Edit1.Text:=SourceFile;
if OpenDialog2.Execute then
DestFile:=OpenDialog2.FileName
else
exit;
if AnsiUpperCase(ExtractFileExt(DestFile))<>'.EXE' then
exit;
Edit2.Text:=DestFile;
SourceIcon:=TIcon.Create;
case ExtractIcon(handle,PChar(SourceFile),UINT(-1)) of
0:begin ShowMessage('源程序没有图标');exit;end;
1:;
else ShowMessage('源程序有多个图标,本程序选择第一个图标');
end;
SourceIcon.Handle:=ExtractIcon(handle,PChar(SourceFile),0);//选择第一个图

DestIcon:=TIcon.Create;//选择第N个图标为 ExtractIcon(handle,PChar(Source
File),N-1)
case ExtractIcon(handle,PChar(DestFile),UINT(-1)) of
0:begin ShowMessage('目的程序没有图标');exit;end;
1:;
else ShowMessage('目的程序有多个图标,本程序选择第一个图标替换');
end;
DestIcon.Handle:=ExtractIcon(handle,PChar(DestFile),0);//选择第一个图标
SIconStream:=TMemoryStream.Create;
DestIcon.SaveToStream(sIconStream);
if sIconStream.size<>icolen then
ShowMessage('SIcon.size<>icolen');
SDest:=TMemoryStream.Create;
sDest.LoadFromFile(DestFile);
i:=0;j:=0; //以下程序查找目的图标在目的程序中的位置
while i< sDest.size do
begin
itemp:=i;
j:=126;
{ repeat
SDest.Position:=i;
sDest.read(ci,Readlen);
SiconStream.Position:=j;
SIconStream.Read(cj,Readlen);
i:=i+Readlen;
j:=j+Readlen;
until (String(ci)=String(cj)) and (i<sDest.size) and (j<icolen);
} ci:='';cj:='';
while (String(ci)=String(cj)) and (i<SDest.size) and (j<
icolen) do
begin
i:=i+readlen;
j:=j+readlen;
SDest.Position:=i;
SDest.read(ci,readlen);
SiconStream.Position:=j;
SiconStream.Read(cj,readlen);
end;
if j<icolen then
i:=itemp+1 //没找到
else
begin
nPos:=itemp; //找到
bOK:=true;
break;
end;
end;
if bOK=false then
exit;//目标文件二进制码中未找到图标
SIconStream.Clear;//将源程序图标存入
SourceIcon.SaveToStream(SIconStream);

SIconStream.position:=126;
s:=TMemoryStream.Create;

sDest.Position:=0;
s.CopyFrom(sDest,nPos);//将目的程序图标前数据拷入
s.CopyFrom(SIconStream,640); //将源程序图标拷入
if sDest.size>sDest.Position+640 then //将目的程序剩余数据拷入
begin
sDest.Position:=sDest.Position+640;
s.CopyFrom(sDest,sDest.Size-sDest.Position);
end;
s.SaveToFile(Extractfilepath(application.exename)+'Result.exe');
SourceIcon.Free;DestIcon.Free; //改造好的程序存放在本目录Result.exe文件中
SIconStream.Free;s.Free;sDest.Free;
ShowMessage(Extractfilepath(application.exename)+'Result.exe');
end;
 
不用讨论了,压缩EXE以后,ICO是不能改的!
 
来自:jingtao, 时间:2002-11-8 23:24:00, ID:1422436
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我们将用来做"实验品"
.再新建一个工程,这个才是我们真正要写的程序.往窗口添加两个名字分别为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.
运行程序,点"取出图标",选择一个EXE,然后点"保存图标"将其ICO保存为文件.
然后点"更换图标",选择我们刚才编译得到的"实验品"和取出的图标,即可将图标更改掉了.
自定义函数ChangeExeIcon的实现过程如下:先用ExtractIcon将图标释放出来保存为文
件,然后将其与EXE比较在该EXE里面找到图标的位置,然后将新图标的内容覆盖原来的图标.
实际上,这个查找过程还不够完美,因为它将两者都转化为TStringStream再比较,如果EXE文件很大的话是很费内存的.Delphi本身提供了一个例子用来查找位置的,该例子位于Delphi5/Demos/Resxplor下,读者可以结合它来作出高效的图标更换工具.

★作者:

陈经韬

430074湖北省武汉市武昌民院路湖北经济管理大学计算机系(本)9801班
Home:http://www.138soft.com
E-Mail: Lovejingtao@21.cn.com 
 
icolen=766;//32*32图标长度,根据研究前126为图标头,后640为图标数据

48*48的是多少
 
多人接受答案了。
 

Similar threads

D
回复
0
查看
787
DelphiTeacher的专栏
D
D
回复
0
查看
825
DelphiTeacher的专栏
D
D
回复
0
查看
657
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部