通过将数据放入EXE的资源信息中的方式制作自已的安装工具

免费的打包工具太千篇一律了,如今是个软件都会有自己的安装界面,别的不说,自行定制UI更好看那是绝对的,至于功能嘛,根本不需要专业安装工具那么多,通常有以下几页就可以了:语言选择、自定义安装位置、文件复制、后续处理、快捷方式等。

 

关键点:读取资源,然后使用;如果是动态添加的资源则应该在使用前检查。

一、资源导入:在Delphi XE版本中有个工具,可以直接将文件当做资源导入到程序中,编译时会自动编译到资源中去。

通过上面的步骤完成资源导入,则工程文件的program下应该多一行{$R *.dres}

二、资源使用

var
  rs: TResourceStream;
begin
  rs := TResourceStream.Create(HInstance, ResName, RT_RCDATA);
  try
    //资源流中可以是图片,文本等数据...
  finally
    rs.Free;
  end;
end;

三、多语言方案

安装包一般是将多种语言集成在一起,由用户选择安装语言,可以先将做一个中文的键值对文件,做为UI字典,通过方法一导入工程中,实现几上公共方法,用于加载字典和翻译:LoadDict,T(Key),这样UI中所有的需要文字描述的地方使用T(Key)的方式取得,以后再添加语言时也无需修改代码。

var
  UIDict: TDictionary<string,string> = nil;//全局变量
  UICurrentLang: string = 'EN';//当前UI语言

procedure LoadUIDict;
var
  rs: TResourceStream;
  sl: TStrings;
  I: Integer;
  UICode: Word;
  UIList: string;
  ResName, sLine: string;
begin
  //从资源中加载语言字典
  if not Assigned(UIDict) then
    UIDict := TDictionary<string,string>.Create;

  sl := TStringList.Create;
  try
    ResName := Format('UIDICT_', [UICurrentLang]);
    rs := TResourceStream.Create(HInstance, ResName, RT_RCDATA);
    try
      sl.LoadFromStream(rs);
      for I := 0 to sl.Count - 1 do
        if sl[I] <> '' then
          UIDict.AddOrSetValue(SL.Names[I], SL.ValueFromIndex[I]);
    finally
      rs.Free;
    end;
  finally
    sl.Free;
  end;
end;


function T(UIKey: string): string;
begin
  //翻译UIKey
  if not UIDict.TryGetValue(UIKey, Result) then
    Result := '(Unknow)';
end;

如果是文本且用于UI,则需要注意尽量使用UTF8对文本或文件进行编码,否则在非中文操作系统环境下会显示乱码。

四、动态添加资源

主要使用以下几个API实现:BeginUpdateResource、UpdateResource、EndUpdateResource

var 
  hrSrc: THandle;
  ResStream: TMemoryStream;
begin

  hrSrc := BeginUpdateResource(PChar(ExeFile), False);//一定是Exe或Dll
  if hrSrc = 0 then
  begin
    ShowMessage('BeginUpdateResource[Error]');
    Exit;
  end;

  //以下这段可以封装并多次使用,比如:添加LOGO图片,添加UI字典,添加程序压缩包等
  ResStream := TMemoryStream.Create;
  try
    ResStream.LoadFromFile('D:\dict_cn.txt');
    ResName := 'UIDICT_CN';//例子
    if not UpdateResource(hrSrc, RT_RCDATA, PChar(ResName), 0, ResStream.Memory, ResStream.Size) then
    begin
      ShowMessage('UpdateResource[Fail]');
      Exit;
    end;
  finally
    ResStream.Free;
  end;

  //将之前更新的资源写回文件中
  if not EndUpdateResource(hrSrc, False) then
  begin
    ShowMessage('EndUpdateResource[Error]');
    Exit;
  end;
end;

function CheckResExists(resList: TArray<string>): Boolean;
var
  hrSrc: THandle;
  resName: string;
begin
  //检查资源ID是否存在,如果是动态添加资源方式,在使用前一定要检查
  Result := False;
  for resName in resList do
  begin
    hrSrc := FindResource(HInstance, PChar(resName), RT_RCDATA);
    if hrSrc = 0 then
      Exit;
    FreeResource(hrSrc);
  end;
  Result := True;
end;

五、高级方案

可以写个控制台的构建工具,比如叫:BuildTool,通过分析配置文件将安装所需的信息动态添加到安装壳程序中

注意事项:如果是添加字符串资源,可以使用TStringStream,并指定编码方式为UTF8或Unicode

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值