Я знаю что возможно не по теме но,вопрос:Кто-то сжимал GTA 4 и какой был размер репака?
» Inno Setup (создание инсталяционных пакетов)
insombia
Не по теме, поэтому сюда => http://forum.ru-board.com/topic.cgi?forum=5&topic=30239&start=0
Не по теме, поэтому сюда => http://forum.ru-board.com/topic.cgi?forum=5&topic=30239&start=0
скажите, как сделать чтоб если стоит виндовз 7 и выше то отображается одна картинка, если ниже то другая картинка, а еще лутше привязать это к поддержке прозрачности.
Люди, кто знает, как можно сжать деинсталлятор, а также нельзя ли решить проблему с отсутсвующими ; как-то автоматически?
bugron
А теперь еще раз и по-русски:
1. "как можно сжать деинсталлятор"
2. "нельзя ли решить проблему с отсутсвующими ; как-то автоматически"
А теперь еще раз и по-русски:
1. "как можно сжать деинсталлятор"
2. "нельзя ли решить проблему с отсутсвующими ; как-то автоматически"
Цитата:
скажите, как сделать чтоб если стоит виндовз 7 и выше то отображается одна картинка, если ниже то другая картинка, а еще лутше привязать это к поддержке прозрачности.
Возможно ты имеешь в виду iswin7?
insombia
У меня к скрипту прикреплен iswin7. И на прозрачном поле розмещена картинка с черным фоном(в iswin7 этот фон стает прозрачным). В windows7 это выглядит красиво, но когда я запустил на хр то там уже совсем другая картина, то прозрачное поле стало серым цветом, и картинка отображается в оригинале(с черным фоном).зрачное поле стало серым цветом, и картинка отображается в оригинале(с черным фоном).
У меня к скрипту прикреплен iswin7. И на прозрачном поле розмещена картинка с черным фоном(в iswin7 этот фон стает прозрачным). В windows7 это выглядит красиво, но когда я запустил на хр то там уже совсем другая картина, то прозрачное поле стало серым цветом, и картинка отображается в оригинале(с черным фоном).зрачное поле стало серым цветом, и картинка отображается в оригинале(с черным фоном).
Кромe botvы u сkpuпmа uз Inno Setup Scripting есmь возможносmь заменumь тексmypы кнопок?
Добавлено:
Делаю инсталлер как у Adobe Systems на Фотошоп ЦС5. Остались только кнопки. Из ботвы отдельно вырезать не получается.
Добавлено:
Делаю инсталлер как у Adobe Systems на Фотошоп ЦС5. Остались только кнопки. Из ботвы отдельно вырезать не получается.
alex0413 iswin7 работает исключительно на 7 и 8 на хр оно работает не актуально по этому и называеться iswin7 поэтому так и должно быть что на хр оно работает не правильно
alex0413
В свойствах своей картинки добавь :
Код: BackColor := clNone;
ReplaceColor := clBlack; // цвет ,который должен быть прозрачным.
В свойствах своей картинки добавь :
Код: BackColor := clNone;
ReplaceColor := clBlack; // цвет ,который должен быть прозрачным.
alex0413
Цитата:
нужно с прозрачным фоном
Цитата:
с черным фоном
нужно с прозрачным фоном
ALExey1995
В bmp наскоколько я знаю нету прозрачности
insombia
Ну я и говорю что изза того что оно неправильно работает я хочу подменить картинку на другую, чтобы выглядело нормально.
Gnom3
А куда именно это добавить???
В bmp наскоколько я знаю нету прозрачности
insombia
Ну я и говорю что изза того что оно неправильно работает я хочу подменить картинку на другую, чтобы выглядело нормально.
Gnom3
А куда именно это добавить???
Цитата:
А куда именно это добавить???
покажи код создания твоего рисунка.
Gnom3
вот весь код
[more];Расширенный пример распаковки FreeArc архива при помощи unarc.dll, с отображением прогресса распаковки в окне Inno Setup и запросом следующего диска.
;#define External GetEnv("ProgramFiles") + "\FreeArc\PowerPack\Max\*"
;Вынес в отдельный файл все функции связанные с текстурой из оригинального скрипта.
;#deifne Texture
;Добавляем архивы
#define Archives "{src}\setup-1.bin;DestDir:{app}\;Disk:1"
[Setup]
AppName=Need For Speed Underground 2
AppVerName=Need For Speed Underground 2
DefaultDirName={pf}\Need For Speed Underground 2
DirExistsWarning=yes
ShowLanguageDialog=auto
OutputDir=.
VersionInfoCopyright=aLLeXUs
WizardImageFile="D:\Прочее\InnoSetupProjects\Need For Speed Underground 2\Nfsu2_cover.bmp"
WizardSmallImageFile="D:\Прочее\InnoSetupProjects\Need For Speed Underground 2\SetupModernSmall25.bmp"
DefaultGroupName=Need For Speed Underground 2
SolidCompression=true
Compression=lzma/Ultra
InternalCompressLevel=Ultra
DiskSpanning=false
DiskSliceSize=736000000
SetupLogging=false
[UninstallDelete]
Type: filesandordirs; Name: {app}
[Languages]
Name: rus; MessagesFile: Russian.isl;
[CustomMessages]
rus.ArcBreak=Установка прервана!
rus.ArcError=Распаковщик вернул код ошибки: %1.
rus.ErrorUnknownError=Ошибка при распаковке архивов. Пожалуйста, обратитесь к разработчику программы.
rus.ErrorCompressMethod=Метод сжатия "%1" данного файла "%2" не поддерживается.
rus.ErrorOutBlockSize=Выходной блок данных файла "%1" слишком мал.
rus.ErrorNotEnoughRAMMemory=Недостаточно свободной оперативной памяти для распаковки "%1".
rus.ErrorReadData=Ошибка чтения данных файла "%1".
rus.ErrorBadCompressedData=Данные из файла "%1" не могут быть распакованы.
rus.ErrorNotImplement=Запрошенное действие не поддерживается.
rus.ErrorDataAlreadyDecompress=Запрошенный блок данных файла "%1" уже распакован.
rus.ErrorUnpackTerminated=Операция прервана пользователем.
rus.ErrorWriteData=Ошибка записи данных из файла "%1".
rus.ErrorBadCRC=Ошибка данных CRC в файле "%1".
rus.ErrorBadPassword=Пароль введенный для данного архива "%1" неверен.
rus.ErrorBadHeader=Заголовок файла "%1" поврежден.
rus.ErrorCodeException=Ошибка выполнения программы установки. Пожалуйста, обратитесь к разработчику программы.
rus.ErrorNotEnoughFreeSpace=Недостаточно свободного места на диске назначения для распаковки архива "%1".
rus.ArcTitle=Распаковка файлов...
rus.StatusInfo=Файлов: %1%2, %3%% выполнено, осталось ждать %4
rus.ArcInfo=Диск %1/%2, архив %3/%4, архив обработан на %5%%
rus.ArcFinish=Распаковано архивов: %1, получено файлов: %2 [%3]
rus.InsertDisk=Пожалуйста, вставьте диск № %1, содержащий файл "%2" и нажмите кнопку ОК.
rus.taskbar=%1%%, жди %2
rus.ending=Завершение
rus.hour= часов
rus.min= мин
rus.sec= сек
[ISToolPreCompile]
#define isFalse(any S) (S = LowerCase(Str(S))) == "no" || S == "false" || S == "off" ? "true" : "false"
[Files]
Source: dxwebsetup.exe; DestDir: {tmp}; Tasks: directx; Flags: deleteafterinstall;
Source: unarc.dll; DestDir: {tmp}; Flags: dontcopy
Source: iswin7.dll; DestDir: {tmp}; Flags: dontcopy
Source: InnoCallback.dll; DestDir: {tmp}; Flags: dontcopy
Source: Logo.bmp; DestDir: {tmp}; Flags: dontcopy
#ifdef precomp
;если указано, что архивы созданы с PRECOMP, в инсталлятор включаются необходимые при распаковке файлы
Source: {#External}; DestDir: {sys}; Flags: deleteafterinstall
Source: {#GetEnv("ProgramFiles")}\FreeArc\bin\arc.ini; DestDir: c:\; Flags: deleteafterinstall
#endif
[Code]
type
#ifdef UNICODE
#define A "W"
#else
#define A "A" ;// точка входа в SetWindowText, {#A} меняется на A или W в зависимости от версии
#if Ver < 84084736
PAnsiChar = PChar; // Required for Inno Setup 5.3.0 and lower. (требуется для Inno Setup версии 5.3.0 и ниже)
#endif
#endif
#if Ver < 84018176
AnsiString = String; // There is no need for this line in Inno Setup 5.2.4 and above (для Inno Setup версий 5.2.4 и выше эта строка не нужна)
#endif
TMessage = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
TFreeArcCallback = function (what: PAnsiChar; int1, int2: Integer; str: PAnsiChar): Integer;
TArc = record Path, Dest, comp, task, pass: string; allMb: Integer; Disks: Integer; UnPack, UnPacked: Boolean; end;
TBarInfo = record stage, name: string; size: Extended; perc: Integer; end;
TFAProgressInfo = record DiskSize, CurPos, LastPos, AllPos, FilesCount: Integer; LastSize, AllSize: Extended; end;
TFADiskStatus = record LastMaxCount, MaxCount, CurDisk, NextArc, RemainsArc: Integer; end;
TCWPSTRUCT = record lParam: LongWord; wParam: Word; Msg: LongWord; hwnd: HWnd; end;
TCWPSTRUCTProc = procedure(Code: Integer; wParam: Word; lParam: TCWPSTRUCT);
TTimerProc = procedure(HandleW, Msg, idEvent, TimeSys: LongWord);
var
StatusLabel, FileNameLabel, ExtractFile, StatusInfo: TLabel;
ProgressBar: TNewProgressBar;
CancelCode, n, ArcInd, UnPackError, StartInstall, LastTimerEvent, lastMb, baseMb: Integer;
FreeMB, TotalMB: Cardinal;
WndHookID, TimerID: LongWord;
Arcs, AllArchives: array of TArc;
msgError, CompressMethod: string;
Status: TBarInfo; Progress: TFAProgressInfo; DS: TFADiskStatus;
FreezeTimer, SuspendUpdate: Boolean;
origsize: Integer; // total uncompressed size of archive data in mb
const
CP_ACP = 0; CP_UTF8 = 65001;
oneMB=1024*1024;
Period = 250; // частота обновления кнопки таскбара и строки статуса
VK_ESCAPE = 27;
HC_ACTION = 0;
WM_PAINT = $F;
CancelDuringInstall = {#isFalse(SetupSetting("AllowCancelDuringInstall"))};
function WrapFreeArcCallback (callback: TFreeArcCallback; paramcount: integer):longword; external 'wrapcallback@files:innocallback.dll stdcall';
function FreeArcExtract (callback: longword; cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10: PAnsiChar): integer; external 'FreeArcExtract@files:unarc.dll cdecl';
Function OemToChar(lpszSrc, lpszDst: AnsiString): longint; external 'OemToCharA@user32.dll stdcall';
Function MultiByteToWideChar(CodePage: UINT; dwFlags: DWORD; lpMultiByteStr: PAnsiChar; cbMultiByte: integer; lpWideCharStr: PAnsiChar; cchWideChar: integer): longint; external 'MultiByteToWideChar@kernel32.dll stdcall';
Function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD; lpWideCharStr: PAnsiChar; cchWideChar: integer; lpMultiByteStr: PAnsiChar; cbMultiByte: integer; lpDefaultChar: integer; lpUsedDefaultChar: integer): longint; external 'WideCharToMultiByte@kernel32.dll stdcall';
function PeekMessage(var lpMsg: TMessage; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessageA@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMessage): BOOL; external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMessage): Longint; external 'DispatchMessageA@user32.dll stdcall';
function GetTickCount: DWord; external 'GetTickCount@kernel32';
function GetWindowLong(hWnd, nIndex: Integer): Longint; external 'GetWindowLongA@user32 stdcall delayload';
function SetWindowText(hWnd: Longint; lpString: String): Longint; external 'SetWindowText{#A}@user32 stdcall delayload';
function GetKeyState(nVirtKey: Integer): ShortInt; external 'GetKeyState@user32 stdcall delayload';
function GetCurrentThreadID: LongWord; external 'GetCurrentThreadId@kernel32 stdcall delayload';
function CallNextWNDPROC(idHook: LongWord; Code: Integer; wParam: Word; lParam: TCWPSTRUCT): LongWord; external 'CallNextHookEx@user32 stdcall delayload';
function SetWindowsHookEx(idHook: LongWord; callback: LongWord; hMod: LongWord; dwThreadID: HWND): LongWord; external 'SetWindowsHookExW@user32 stdcall delayload';
function UnhookWindowsHookEx(idHook: LongWord): LongWord; external 'UnhookWindowsHookEx@user32 stdcall delayload';
function WrapCWPSTRUCTProc(callback:TCWPSTRUCTProc; paramcount:integer): longword; external 'wrapcallback@files:innocallback.dll';
function WrapTimerProc(callback: TTimerProc; Paramcount: Integer): longword; external 'wrapcallback@files:innocallback.dll stdcall';
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): longword; external 'SetTimer@user32';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord; external 'KillTimer@user32 stdcall delayload';
procedure AppProcessMessage;
var Msg: TMessage;
begin
if not PeekMessage(Msg, 0, 0, 0, 1) then Exit;
TranslateMessage(Msg); DispatchMessage(Msg);
end;
Function FreeArcCmd(callback: longword; cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10: PAnsiChar): integer;
Begin
CancelCode:= 0; AppProcessMessage;
try
Result:= FreeArcExtract(callback, cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10); // Pass the specified arguments to 'unarc.dll'
if CancelCode < 0 then Result:= CancelCode;
except
Result:= -63; // ArcFail
end;
End;
// Sets the TaskBar title
Procedure SetTaskBarTitle(Title: String); var h: Integer;
Begin
h:= GetWindowLong(MainForm.Handle, -8); if h <> 0 then SetWindowText(h, Title);
End;
// Перевод числа в строку с точностью 2 знака (%.2n) с округлением дробной части, если она есть
Function NumToStr(Float: Extended): String;
Begin
Result:= Format('%.2n', [Float]); StringChange(Result, ',', '.');
while ((Result[Length(Result)] = '0') or (Result[Length(Result)] = '.')) and (Pos('.', Result) > 0) do
SetLength(Result, Length(Result)-1);
End;
Function ByteOrTB(Bytes: Extended; noMB: Boolean): String; {Перевод числа в значение бт/Кб/Мб/Гб/Тб (до 2х знаков после запятой)}
Begin
if not noMB then Result:= NumToStr(Int(Bytes)) +' Mb' else
if Bytes < 1024 then if Bytes = 0 then Result:= '0' else Result:= NumToStr(Int(Bytes)) +' Bt' else
if Bytes/1024 < 1024 then Result:= NumToStr(round((Bytes/1024)*10)/10) +' Kb' else
If Bytes/oneMB < 1024 then Result:= NumToStr(round(Bytes/oneMB*100)/100) +' Mb' else
If Bytes/oneMB/1000 < 1024 then Result:= NumToStr(round(Bytes/oneMB/1024*1000)/1000) +' Gb' else
Result:= NumToStr(round(Bytes/oneMB/oneMB*1000)/1000) +' Tb';
End;
Function StringToArray(Text, Cut: String): array of String; var i, k: Integer; // поместить строки текста в элементы массив. шаблон перевода строк может быть любым. шаблон в начале/конце текста игнорируются
Begin
SetArrayLength(Result, 0); if Cut = '' then Cut:= #1310; //если шаблон пуст, считаем переводы строк
Repeat k:= Pos(Cut,Text);
if k = 1 then begin Delete(Text, 1, Length(Cut)); CONTINUE
end;
SetArrayLength(Result, GetArrayLength(Result) +1); i:= GetArrayLength(Result) -1;
if k = 0 then
Result[i]:=Text
else begin
Result[i]:= Copy(Text, 1, k -1); Delete(Text, 1, Length(Result[i]) + Length(Cut));
end;
Until Length(Text) * k = 0;
End;
Function CreateLabel(Parent: TWinControl; AutoSize, WordWrap, Transparent: Boolean; FontName: String; FontStyle: TFontStyles; FontColor: TColor; Left, Top, Width, Height: Integer; Prefs: TObject): TLabel;
Begin
Result:=TLabel.Create(Parent); Result.parent:= Parent;
if Prefs <> Nil then begin
Top:= TWinControl(Prefs).Top; Left:= TWinControl(Prefs).Left; Width:= TWinControl(Prefs).Width; Height:= TWinControl(Prefs).Height;
end;
if Top > 0 then result.Top:=Top; if Left > 0 then result.Left:= Left; if Width > 0 then result.Width:= Width; if Height > 0 then result.Height:= Height;
if FontName <> '' then result.Font.Name:= FontName; if FontColor > 0 then result.Font.Color:= FontColor; if FontStyle <> [] then result.Font.Style:= FontStyle;
result.AutoSize:= AutoSize; result.WordWrap:= WordWrap; result.Transparent:=Transparent; result.ShowHint:= true;
End;
// Converts milliseconds to human-readable time
// Конвертирует милисекунды в человеко-читаемое изображение времени
Function TicksToTime(Ticks: DWord; h,m,s: String; detail: Boolean): String;
Begin
if detail then {hh:mm:ss format}
Result:= PADZ(IntToStr(Ticks/3600000), 2) +':'+ PADZ(IntToStr((Ticks/1000 - Ticks/1000/3600*3600)/60), 2) +':'+ PADZ(IntToStr(Ticks/1000 - Ticks/1000/60*60), 2)
else if Ticks/3600 >= 1000 then {more than hour}
Result:= IntToStr(Ticks/3600000) +h+' '+ PADZ(IntToStr((Ticks/1000 - Ticks/1000/3600*3600)/60), 2) +m
else if Ticks/60 >= 1000 then {1..60 minutes}
Result:= IntToStr(Ticks/60000) +m+' '+ IntToStr(Ticks/1000 - Ticks/1000/60*60) +s
else Result:= Format('%.1n', [Abs(Ticks/1000)]) +s {less than one minute}
End;
Function ExpandENV(string: String): String; var n: UINT; Begin // ExpandConstant + развёртывание DOS-переменных типа %SystemRoot%
if Pos('{',string) * Pos('}',string) = 0 then Result:= String else Result:= ExpandConstant(String); n:= Pos('%',result); if n = 0 then Exit;
Delete(result, n,1); Result:= Copy(Result,1, n-1) + ExpandConstant('{%'+Copy(Result, n, Pos('%',result) -n) +'}') + Copy(Result, Pos('%',result) +1, Length(result))
End;
Function cm(Message: String): String; Begin Result:= ExpandConstant('{cm:'+ Message +'}') End;
Function LoWord(lw: LongWord): LongWord; Begin Result:= lw shr 16; End;
// Converts OEM encoded string into ANSI (Преобразует OEM строку в ANSI кодировку)
function OemToAnsiStr(strSource: AnsiString): AnsiString;
begin
SetLength(Result, Length(strSource));
OemToChar(strSource, Result);
end;
// Converts ANSI encoded string into UTF-8 (Преобразует строку из ANSI в UTF-8 кодировку) by CTAC-Ko
function AnsiToUtf8(strSource: string): string;
var
nRet, nRet2: integer; WideCharBuf, MultiByteBuf: AnsiString;
begin
SetLength(WideCharBuf, Length(strSource) * 2);
SetLength(MultiByteBuf, Length(strSource) * 2);
nRet:= MultiByteToWideChar(CP_ACP, 0, strSource, -1, WideCharBuf, Length(WideCharBuf));
nRet2:= WideCharToMultiByte(CP_UTF8, 0, WideCharBuf, -1, MultiByteBuf, Length(MultiByteBuf), 0, 0);
//nRet2 возвращает число обработанных знаков (исключая различный мусор в конце строки)
MultiByteBuf:=Copy(MultiByteBuf, 1, nRet2); //Вот мы и обрубаем строку до этого числа знаков
Result:= MultiByteBuf;
end;
// ArcInd - текущий архив, счёт с 0
// baseMb - записано из пред. архива на диск
// lastMb - извлечено из тек. архива на диск
// Status.mb - позиция в текущем архиве
// Status.allsize - объём всех архивов
// Status.size - всего извлечено Мб на текущий момент
// totalUncompressedSize - точный объём данных в архивах
// общий прогресс нарастает по мере записи данных из архива на диск (точка 'write')
// прогресс архивов двигается в соответствии с позицией в текущем архиве (точка 'read')
Procedure UpdateStatus(Flags: Integer); // выполняется с периодичностью, заданной константой Period
var
Remaining, p: Integer; i, t: string;
Begin
if Flags and $1 > 0 then FreezeTimer:= Flags and $2 = 0; // bit 0 = 1 change start/stop, bit 1 = 0 stop, bit 1 = 1 start
if (Flags and $4 > 0) or (Status.size <> baseMb+lastMb) then LastTimerEvent:= 0; // bit 2 = 1 UpdateNow // обновить по флагу или записи из архива на диск
if (FreezeTimer=True)or(GetTickCount - LastTimerEvent <= Period)or(SuspendUpdate=True) then Exit else LastTimerEvent:= GetTickCount;
Status.size := baseMb+lastMb; // извлечено на текущий момент
Progress.Allsize:= Progress.LastSize + lastMb; //Извлечено всего
with WizardForm.ProgressGauge do begin
if Progress.DiskSize > 0 then begin
Progress.CurPos:= round(Max * Status.size/Progress.DiskSize);
if Progress.CurPos > Progress.LastPos then begin
Progress.AllPos:= Progress.AllPos + ((Progress.CurPos-Progress.LastPos)/DS.MaxCount);
Progress.LastPos:=Progress.CurPos
end;
Position:= Progress.AllPos
end;
n:= (Max - Min)/1000; if n > 0 then Status.perc:= (Position-Min)/n; // 1000 процентов
#ifndef External
// к сожалению, этот код иногда сбоит на очень больших архивах, созданных с использованием внешних упаковщиков
if Position > 0 then Remaining:= ((Max-Position)*(GetTickCount-StartInstall))/Position else
#endif
Remaining:= 0; t:= cm('ending'); i:= AnsiLowerCase(t);
if Remaining > 0 then begin
t:= FmtMessage(cm('taskbar'), [IntToStr(Status.perc/10), TicksToTime(Remaining, 'h', 'm', 's', false)])
i:= TicksToTime(Remaining, cm('hour'), cm('min'), cm('sec'), false)
end;
end;
SetTaskBarTitle(t); // проценты и оставшееся время на кнопке инсталлятора
StatusInfo.Caption:= FmtMessage(cm('StatusInfo'), [IntToStr(Progress.FilesCount), ' ['+ ByteOrTB(Progress.Allsize*oneMB, true) +']', Format('%.1n', [Abs(Status.perc/10)]), i]);
// второй прогрессбар движется по мере считывания текущего архива
if (Status.stage = cm('ArcTitle')) and (GetArrayLength(Arcs) > 0) then begin
if (Arcs[ArcInd].allMb > 0) then p:= ((LastMb*100)/Arcs[ArcInd].AllMb);
ExtractFile.Caption:= FmtMessage(cm('ArcInfo'), [IntToStr(DS.CurDisk), IntToStr(DS.MaxCount), IntToStr(ArcInd+1), IntToStr(GetArrayLength(Arcs)), IntToStr(p)]);
ProgressBar.Position:= LastMb;
end;
End;
Procedure MyTimerProc(h, msg, idevent, dwTime: Longword);
Begin
if WizardForm.CurPageID = wpInstalling then UpdateStatus(0);
End;
Procedure OnWndHook(Code: Integer; wParam: Word; lParam: TCWPSTRUCT);
Begin
if (Code = HC_ACTION) and (LoWord(lParam.msg) = WM_PAINT) then begin // подготовка данных для последующего отображения по таймеру
if (Status.name <> WizardForm.FileNameLabel.Caption) and (WizardForm.FileNameLabel.Caption <> '') then begin // имя файла, названия ярлыка и прочее
FileNameLabel.Caption:= WizardForm.FileNameLabel.Caption;
Status.name:= WizardForm.FileNameLabel.Caption; // начало извлечения или распаковки очередного файла
Case Status.stage of
SetupMessage(msgStatusExtractFiles): // этап извлечения файлов инсталлятором
Progress.FilesCount:= Progress.FilesCount +1; // кол-во файлов
End;
end;
if (Status.stage <> WizardForm.StatusLabel.Caption) and (WizardForm.StatusLabel.Caption <> '') then begin
StatusLabel.Caption:= WizardForm.StatusLabel.Caption;
Status.stage:= WizardForm.StatusLabel.Caption; // текущий этап установки
if Status.stage = SetupMessage(msgStatusRollback) then begin
WizardForm.StatusLabel.Hide; WizardForm.FileNameLabel.Hide; StatusInfo.Hide; ExtractFile.Hide; ProgressBar.Hide;
end;
end;
UpdateStatus(0);
end;
CallNextWNDPROC(WndHookID, Code, wParam, lParam) {освобождение события}
End;
// compsize: в Mb объём архива
// total_files: в int2 ? число файлов в архиве
// origsize: в Mb общий объём данных в архиве
// write: в Mb число записанных (распакованных из архива) на диск мегабайт
// read: в Mb число обработанных мегабайт, в int2 размер текущего архива
// filename: вызывается перед обработкой каждого файла
// The main callback function for unpacking FreeArc archives
function FreeArcCallback(what: PAnsiChar; Mb, int2: Integer; str: PAnsiChar): Integer; // вызывается не менее 100 раз в секунду, что заменяет вызов по таймеру
begin
case string(what) of
'origsize': origsize:= Mb; // данных в тек. архиве (при распаковке не вызывается)
'total_files': Null;
'filename': begin // Update FileName label
WizardForm.FileNameLabel.Caption:= OemToAnsiStr(str); // извлекаемый файл, их имена пишутся в журнал установки
Progress.FilesCount:= Progress.FilesCount + 1; // кол-во файлов, этап распаковки
end;
'read': Null; // позиция в текущем архиве
'write': lastMb:= Mb; // Assign to Mb *total* amount of data extracted to the moment from all archives
'quit': if (Mb = -2) then CompressMethod:= str;
end;
if WizardForm.CurPageID = wpInstalling then UpdateStatus(0); // обновить страницу установки, не сбрасывая таймер
if (GetKeyState(VK_ESCAPE) < 0) and not CancelDuringInstall then
WizardForm.Close; // опрашиваем Cancel (если разрешена отмена установки)
AppProcessMessage;
Result:= CancelCode;
end;
Function DeleteChars(S, Char: String): String; begin if (Pos(Char, S)>0) then
begin while (Pos(Char, S)>0) do StringChange(S, Char, ''); end; Result:=S; end;
Function CutStr(var S: String; Index, Length: Integer): String; var str: string;
begin str:= Copy(S, Index, Length); Delete(S, Index, Length); Result:=Str; end;
Function CutStrEx(var S: String; Code: String): String;
var str: string; pos1, pos2: integer; begin pos1:= Pos(Code, S); If (pos1>0) then begin
pos2:=pos1; while S[pos2]<>';' do if pos2<>length(S) then pos2:=pos2+1; str:=cutStr(S, pos1, (pos2-pos1)+1);
StringChange(str, Code, ''); if str[Length(str)]=';' then Setlength(str, Length(str)-1); end; Result:=str; end;
Function ArcDecode(Line: String): array of TArc; // разбор строки Archives
var tmp: array of String; cut: string; i, n: integer;
begin
SetArrayLength(Result, 0); If Line = '' then Exit;
tmp:= StringToArray(Line, '|');
for n:=0 to GetArrayLength(tmp)-1 do begin
i:= GetArrayLength(Result); SetArrayLength(Result, i+1); cut:=tmp[n]+';';
if (Pos('Tasks:', cut)>0) then Result[i].task:= DeleteChars(CutStrEx(cut, 'Tasks:'), ';');
if (Pos('Components:', cut)>0) then Result[i].comp:= DeleteChars(CutStrEx(cut, 'Components:'), ';');
if (Pos('Password:', cut)>0) then Result[i].pass:= DeleteChars(CutStrEx(cut, 'Password:'), ';');
if (Pos('Disk:', cut)>0) then Result[i].disks:= StrToInt(DeleteChars(CutStrEx(cut, 'Disk:'), ';')) else Result[i].disks:=1;
if (Pos('DestDir:', cut)>0) then Result[i].dest:= DeleteChars(CutStrEx(cut, 'DestDir:'), ';');
cut:=DeleteChars(cut, ';');
if (ExtractFileDrive(ExpandEnv(cut)) = '')and(ExpandEnv(cut) = cut) then
Result[i].Path:= '{src}\'+cut else Result[i].Path:= cut;
Result[i].Dest:= ExpandENV(result[i].Dest); Result[i].Path:= ExpandENV(result[i].Path);
end;
end;
// Scans the specified folders for archives and add them to list
function AddArcs(File: TArc; var ErrCode: Integer): Integer; // добавление архивов в общий список и подсчёт объёма распакованных данных
var i: integer; Password: string;
Begin
if FileExists(File.Path) then begin
Result:= 0; i:= GetArrayLength(Arcs);
if File.pass <> '' then Password:= '-p'+AnsiToUtf8(File.pass) else Password:= '';
SetArrayLength(Arcs, i +1); Arcs[i]:=File;
if Password <> '' then
ErrCode:= FreeArcCmd(WrapFreeArcCallback(@FreeArcCallback,4),'l',Password,'--',AnsiToUtf8(Arcs[i].Path),'','','','','','')
else
ErrCode:= FreeArcCmd(WrapFreeArcCallback(@FreeArcCallback,4),'l','--',AnsiToUtf8(Arcs[i].Path),'','','','','','',''); // код ошибки
if ErrCode >= 0 then begin Arcs[i].allMb:= origsize; result:= Arcs[i].allMb; origsize:=0; end;// размер распакованных данных успешно считан
end;
End;
function DispatchError(ErrorCode: Integer; Arc: TArc): String;
var ArcFile: String;
begin
ArcFile:= ExtractFilename(Arc.Path);
if (ErrorCode = -2) then StringChange(CompressMethod, 'ERROR: unsupported compression method ', '')
case ErrorCode of
-1: Result:= cm('ErrorUnknownError');
-2: Result:= FmtMessage(cm('ErrorCompressMethod'), [CompressMethod, ArcFile]);
-3: Null;
-4: Result:= FmtMessage(cm('ErrorOutBlockSize'), [ArcFile]);
-5: Result:= FmtMessage(cm('ErrorNotEnoughRAMMemory'), [ArcFile]);
-6: Result:= FmtMessage(cm('ErrorReadData'), [ArcFile]);
-7: Result:= FmtMessage(cm('ErrorBadCompressedData'), [ArcFile]);
-8: Result:= cm('ErrorNotImplement');
-9: Result:= FmtMessage(cm('ErrorDataAlreadyDecompress'), [ArcFile]);
-10: Result:= cm('ErrorUnpackTerminated');
-11: Result:= FmtMessage(cm('ErrorWriteData'), [ArcFile]);
-12: Result:= FmtMessage(cm('ErrorBadCRC'), [ArcFile]);
-13: Result:= FmtMessage(cm('ErrorBadPassword'), [ArcFile]);
-14: Result:= FmtMessage(cm('ErrorBadHeader'), [ArcFile]);
-15: Null;
-63: Result:= cm('ErrorCodeException');
-112: Result:= FmtMessage(cm('ErrorNotEnoughFreeSpace'), [ArcFile]);
end;
end;
function UnPackArchive(Archive: TArc): Integer;
var callback: longword; Password: String;
Begin
// если отмена установки разрешена, кнопка Cancel станет доступна
WizardForm.CancelButton.Enabled:= not CancelDuringInstall;
if Archive.pass <> '' then Password:= '-p'+AnsiToUtf8(Archive.pass) else Password:= '';
callback:= WrapFreeArcCallback(@FreeArcCallback,4); //FreeArcCallback has 4 arguments
if Password <> '' then
Result:= FreeArcCmd(callback,'x','-o+','-dp'+AnsiToUtf8(Archive.Dest),'-w'+AnsiToUtf8(Archive.Dest),Password,'--',AnsiToUtf8(Archive.Path),'','','')
else // код ошибки
Result:= FreeArcCmd(callback,'x','-o+','-dp'+AnsiToUtf8(Archive.Dest),'-w'+AnsiToUtf8(Archive.Dest),'--',AnsiToUtf8(Archive.Path),'','','','')
// Error occured
if Result = 0 then Exit;
msgError:= FmtMessage(cm('ArcError'), [IntToStr(Result)]);
WizardForm.StatusLabel.Caption:= msgError;
WizardForm.FileNameLabel.Caption:= ExtractFileName(Archive.Path);
GetSpaceOnDisk(ExtractFileDrive(Archive.Dest), True, FreeMB, TotalMB);
if FreeMB < (Archive.allMb-lastMb) then Result:= -112;
MsgError:= msgError+#13#10#13+DispatchError(Result, Archive)
Log(msgError); // записываем ошибку в лог, а также показываем её текст на странице завершения
End;
procedure SetUnpacked(File: TArc); var i: integer; begin
for i:=0 to GetArrayLength(AllArchives)-1 do begin
if(File.Path=AllArchives[i].Path)and(File.Dest=AllArchives[i].Dest)
then begin AllArchives[i].UnPacked:=True; Break; end; end; end;
function UpdateArcsList(): Integer;
var m, ErrorCode: integer; begin
AppProcessMessage; SetArrayLength(Arcs,0); Progress.DiskSize:=0; for m:=0 to (GetArrayLength(AllArchives)-1) do try
if (AllArchives[m].UnPack)and(AllArchives[m].UnPacked=False) then Progress.DiskSize:= Progress.DiskSize + AddArcs(AllArchives[m], ErrorCode);
if (ErrorCode < 0) then begin Result:=ErrorCode; Break; end; Except Result:=-63; end; end;
// Extracts all found archives
function UnPack(): Integer;
begin
Progress.CurPos:=0; Progress.LastPos:=0; baseMb:= 0; // обнулить полученные мегабайты, если ранее вёлся подсчёт объёма файлов инсталлятора
if (DS.LastMaxCount<>DS.MaxCount)and(DS.CurDisk>1) then begin
Progress.AllPos:= (WizardForm.ProgressGauge.Max/(DS.MaxCount))*(DS.CurDisk-1); end;
UpdateStatus(7); // немедленно обновить строку статуса
for ArcInd:= 0 to GetArrayLength(Arcs) -1 do begin // архивы в текущей папке, константы раскрыты в ArcDecode
lastMb:= 0; SuspendUpdate:=False; //отключаем паузу автоапдейта по таймеру на время распаковки
ProgressBar.Max:=Arcs[ArcInd].allMb;
Result:= UnPackArchive(Arcs[ArcInd]); // код ошибки
Progress.LastSize:= Progress.AllSize; SetUnPacked(Arcs[ArcInd]);
SuspendUpdate:=True; //ставим автоапдейт по таймеру на паузу - распаковка окончена (возможно временно)
if Result <> 0 then Break; // прервать цикл распаковки
baseMb:= baseMb + lastMb; // общий объём распакованных файлов
// отработанный архив автоматически удаляется, если находится в папке {app} или {tmp}
if (Pos(AnsiLowercase(ExpandConstant('{app}')), AnsiLowercase(Arcs[ArcInd].Path)) > 0) or (Pos(AnsiLowercase(ExpandConstant('{tmp}')), AnsiLowercase(Arcs[ArcInd].Path)) > 0) then
DeleteFile(Arcs[ArcInd].Path);
end;
end;
Function CheckBools(Bools: array of Boolean): Integer;
var c,l: integer; begin Result:=0; for l:=0 to GetArrayLength(Bools)-1 do begin
if (Bools[l] = True) then c:=c+1; end; if (c=(GetArrayLength(Bools)))then Result:=1;end;
function GetRemainArcs(): integer;
var c: integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
If (AllArchives[c].UnPack)and(not AllArchives[c].UnPacked)then Result:=Result+1; end; end;
Function GetNextArc(): Integer;
var c: Integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
if (AllArchives[c].UnPack)and(not AllArchives[c].UnPacked) then begin Result:=c; Exit; end; end; end;
Function GetUnpackedArcs(): Integer;
var c: Integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
if (AllArchives[c].UnPack)and(AllArchives[c].UnPacked) then Result:=Result+1; end; Result:=Result+1; end;
Function SetStatus(Value: String): Boolean;
begin WizardForm.StatusLabel.Caption:=Value; StatusLabel.Caption:=Value; Status.stage:=Value; end;
Function UnPackWithPrompts(Archives: string): Integer;
var MsBox, MaxArcs: Integer; FADiskMessage: string;
TmpArc: array of TArc; z, f, q, k, x, LastDisk: Integer; OneDisk, DiskCheck: Boolean;
begin
AppProcessMessage; SetStatus(cm('ArcTitle')) // начало этапa распаковки
ExtractFile.Show; ProgressBar.Show; StatusInfo.Show;
Progress.FilesCount:=0; MsBox:=IDOK; z:=0; OneDisk:=False;
AllArchives:= ArcDecode(Archives); DS.LastMaxCount:=DS.MaxCount;
MaxArcs:= GetArrayLength(AllArchives)-1; LastDisk:=1; q:=0; k:=0; x:=0;
DS.CurDisk:=1; DS.MaxCount:= AllArchives[MaxArcs].disks; DiskCheck:=False;
WizardForm.ProgressGauge.Position:=0; UpdateStatus(7); SuspendUpdate:=True;
WizardForm.ProgressGauge.Max:= 100000;
//инициализация параметров архивов
for f:=0 to MaxArcs do begin
AllArchives[f].UnPack:=True; AllArchives[f].UnPacked:=False; //Сначала активируем все архивы
if (AllArchives[f].comp<>'')and(not IsComponentSelected(AllArchives[f].comp)) then AllArchives[f].UnPack:=False; //Если компонент не выбран то деактивируем этот архив
if (AllArchives[f].task<>'')and(not IsTaskSelected(AllArchives[f].task)) then Allarchives[f].UnPack:=False; //То же что и выше, только с задачей (Task)
z:=z+CheckBools([FileExists(AllArchives[f].Path)]); k:=k+CheckBools([AllArchives[f].UnPack]);
x:=x+CheckBools([AllArchives[f].UnPack, FileExists(AllArchives[f].Path)]);
end;
if (z=(MaxArcs+1)) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; OneDisk:=True; end;
if (x=k) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; OneDisk:=True; end;
DS.NextArc:= GetNextArc; DS.RemainsArc:= GetRemainArcs;
//распаковка архивов на дисках
while (Result = 0) and (DS.RemainsArc>0) do begin
if (not OneDisk) then begin x:=0;
//проверка если на текущем диске находятся все требующиеся архивы (исключая уже распакованные)
for f:= DS.NextArc to MaxArcs do begin
x:=x+CheckBools([(AllArchives[f].UnPack), FileExists(AllArchives[f].Path)]);
if (x=((MaxArcs+1)-DS.NextArc)) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; end; end;
end;
while (msBox=IDOK)and(not(FileExists(AllArchives[DS.NextArc].Path))and(AllArchives[DS.NextArc].UnPack)) do begin
FADiskMessage:= FmtMessage(cm('InsertDisk'),[IntToStr(DS.CurDisk), ExtractFilename(AllArchives[DS.NextArc].Path)])
MsBox:= MsgBox(FADiskMessage, mbConfirmation, MB_OKCANCEL)
end;
//Отмена распаковки
if MsBox = IDCANCEL then Result:= -10;
//Проверка числа дисков
if (not OneDisk) then begin
//Если на n-ом диске находтся архивы привязанные к одному компоненту и этот компонент не выбран (проверяется один раз)
if (DS.MaxCount>1)and(DS.CurDisk<>DS.MaxCount)and(not DiskCheck) then begin
while (LastDisk<=DS.MaxCount)and(q<(MaxArcs+1)) do begin
SetArraylength(TmpArc, 0); k:=0;
for z:=q to GetArrayLength(AllArchives)-1 do begin
if AllArchives[z].disks=LastDisk then begin SetArrayLength(TmpArc, GetArrayLength(TmpArc)+1); TmpArc[GetArrayLength(TmpArc)-1]:= AllArchives[z]; end; end;
for z:=0 to GetArrayLength(tmpArc)-1 do begin if (not TmpArc[z].Unpack) then k:=k+1; end;
if k=GetArrayLength(tmpArc) then begin DS.LastMaxCount:= DS.MaxCount; DS.MaxCount:= DS.MaxCount-1; q:=q+GetArrayLength(TmpArc) end;
LastDisk:=LastDisk+1; end;
DiskCheck:=True; end;
//Если на текущем диске должен быть архив а его нет
if (DS.CurDisk=DS.MaxCount) then begin
SetArraylength(TmpArc, 0); k:=0;
for z:=DS.NextArc to GetArrayLength(AllArchives)-1 do begin
if AllArchives[z].disks=DS.CurDisk then begin SetArrayLength(TmpArc, GetArrayLength(TmpArc)+1); TmpArc[GetArrayLength(TmpArc)-1]:= AllArchives[z]; end; end;
for z:=0 to GetArrayLength(tmpArc)-1 do begin if (TmpArc[z].UnPack)and(FileExists(TmpArc[z].Path)) then k:=k+1 end;
if k<GetArrayLength(TmpArc)then begin DS.LastMaxCount:= DS.MaxCount; DS.MaxCount:= DS.MaxCount+1; end;
end;
end;
//Сама распаковка
if (MsBox<>IDCANCEL)and(DS.RemainsArc>0) then begin Result:=UpdateArcsList; Result:= UnPack(); DS.CurDisk:= DS.CurDisk+1; DS.NextArc:= GetNextArc; DS.RemainsArc:= GetRemainArcs; end;
end;
//Конец распаковки, скрытие надписей и прогрессбара
if (Result = 0) then begin WizardForm.StatusLabel.Caption:= FmtMessage(cm('ArcFinish'), [IntToStr(GetUnpackedArcs), IntToStr(Progress.FilesCount), ByteOrTB(Progress.AllSize*oneMB, true)]);
StatusInfo.Hide; ExtractFile.Hide; ProgressBar.Hide; end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssInstall then begin
StartInstall:= GetTickCount {время начала извлечения файлов}
WndHookID:= SetWindowsHookEx(4, WrapCWPSTRUCTProc(@OnWndHook, 3), 0, GetCurrentThreadID); {установка SendMessage хука}
TimerID:= SetTimer(0, 0, 500 {полсекунды}, WrapTimerProc(@MyTimerProc, 4)); {установка таймера}
end;
if CurStep = ssPostInstall then
begin
StartInstall:= GetTickCount {время начала распаковки}
UnPackError:= UnPackWithPrompts('{#Archives}')
if UnPackError <> 0 then begin // Error occured, uninstall it then
if not {#isFalse(SetupSetting("Uninstallable"))} then // деинсталляция разрешёна
Exec(ExpandConstant('{uninstallexe}'), '/SILENT','', sw_Hide, ewWaitUntilTerminated, n); // откат установки из-за ошибки unarc.dll
WizardForm.caption:= SetupMessage(msgErrorTitle) +' - '+ cm('ArcBreak')
SetTaskBarTitle(SetupMessage(msgErrorTitle))
end else
SetTaskBarTitle(SetupMessage(msgSetupAppTitle));
end;
end;
#ifdef Texture
#include "FATexture.iss"
#endif
Procedure CurPageChanged(CurPageID: Integer);
Begin
#ifdef Texture
SetTexture(CurPageID)
#endif
if (CurPageID = wpFinished) and (UnPackError <> 0) then
begin // Extraction was unsuccessful (распаковщик вернул ошибку)
// Show error message
WizardForm.FinishedLabel.Font.Color:= $0000C0; // red (красный)
WizardForm.FinishedLabel.Height:= WizardForm.FinishedLabel.Height * 2;
WizardForm.FinishedLabel.Caption:= SetupMessage(msgSetupAborted) + #13#10#13#10 + msgError;
end;
End;
procedure iswin7_add_glass(Handle:HWND; Left, Top, Right, Bottom : Integer; GDIPLoadMode: boolean);
external 'iswin7_add_glass@files:iswin7.dll stdcall';
procedure iswin7_add_button(Handle:HWND);
external 'iswin7_add_button@files:iswin7.dll stdcall';
procedure iswin7_free;
external 'iswin7_free@files:iswin7.dll stdcall';
//-----------start----------LOGO----------//
procedure LogoOnClick(Sender: TObject);
var ResCode: Integer;
begin
ShellExec('', 'http://vkontakte.ru/allexus', '' , '', SW_SHOW, ewNoWait, ResCode)
end;
//------------end--------------LOGO---------------//
procedure WizardClose(Sender: TObject; var Action: TCloseAction);
Begin
Action:= caNone; // так надо
if Status.stage = cm('ArcTitle') then begin // распаковка на этапе ssPostInstall
UpdateStatus(1); // остановить таймер
if MsgBox(SetupMessage(msgExitSetupMessage), mbInformation, MB_YESNO) = IDYES then
CancelCode:= -10; // прервать распаковку
UpdateStatus(7); // обновить информацию
end else
MainForm.Close; // стандартное нажатие кнопки закрытия окна, отмены или Escape.
End;
Procedure InitializeWizard();
var
BtnPanel: TPanel;
BtnImage: TBitmapImage;
Begin
// Create controls to show extended info
StatusLabel:= CreateLabel(WizardForm.InstallingPage,false,false,true,'',[],0,0,0,0,0, WizardForm.StatusLabel);
FileNameLabel:= CreateLabel(WizardForm.InstallingPage,false,false,true,'',[],0,0,0,0,0, WizardForm.FileNameLabel);
WizardForm.StatusLabel.Top:= WizardForm.ProgressGauge.Top; WizardForm.FileNameLabel.Top:= WizardForm.ProgressGauge.Top; // прячем под прогрессбар, тогда все события WM_PAINT перехватываются
with WizardForm.ProgressGauge do begin
StatusInfo:= CreateLabel(WizardForm.InstallingPage, false, true, true, '', [], 0, 0, Top + ScaleY(32), Width, 0, Nil);
ProgressBar := TNewProgressBar.Create(WizardForm);
ProgressBar.SetBounds(Left, StatusInfo.Top + StatusInfo.Height + ScaleY(16), Width, Height);
ProgressBar.Parent := WizardForm.InstallingPage;
ProgressBar.max := 65536;
ProgressBar.Hide; // будет показан при обработке нескольких архивов
ExtractFile:= CreateLabel(WizardForm.InstallingPage, false, true, true, '', [], 0, 0, ProgressBar.Top + ScaleY(32), Width, 0, Nil);
end;
WizardForm.OnClose:= @WizardClose // позволяет прервать распаковку архивов стандартными способами
#ifdef Texture
CreateTexture();
#endif
// Необходимо добавлять каждую кнопку расположенную на стекле
// до инициализации стекла для того что бы не было дыр ))
iswin7_add_button(WizardForm.BackButton.Handle);
iswin7_add_button(WizardForm.NextButton.Handle);
iswin7_add_button(WizardForm.CancelButton.Handle);
// Параметр True не трогать он для htuos ))
iswin7_add_glass(WizardForm.Handle, 0, 0, 0, 47, True);
//-----------start----------LOGO-----------//
ExtractTemporaryFile('Logo.bmp')
BtnPanel:=TPanel.Create(WizardForm)
with BtnPanel do begin
Left:=20
Top:=325
Width:=132
Height:=27
Cursor:=crHand
OnClick:=@logoOnClick
Parent:=WizardForm
end;
BtnImage:=TBitmapImage.Create(WizardForm)
with BtnImage do begin
AutoSize:=True;
Enabled:=False;
Bitmap.LoadFromFile(ExpandConstant('{tmp}')+'\Logo.bmp')
Parent:=BtnPanel
end;
End;
Procedure DeInitializeSetup;
Begin
KillTimer(0, TimerID) {удаление таймера}
UnhookWindowsHookEx(WndHookID) {удаление SendMessage хука}
iswin7_free;
End;
[Icons]
Name: "{group}\Запустить Need For Speed Underground 2"; Filename: {app}\speed2.exe; Languages: rus; Tasks: group;
Name: "{group}\Удалить Need For Speed Underground 2"; Filename: {app}\unins000.exe; Languages: rus; Tasks: group;
Name: "{commondesktop}\Need For Speed Underground 2"; Filename: {app}\speed2.exe; Languages: rus; Tasks: desktop;
[Run]
Filename: {tmp}\dxwebsetup.exe; WorkingDir: {tmp}; Parameters: /q; StatusMsg: "Установка DirectX"; Tasks: directx;
[Tasks]
Languages: rus; Name: desktop; Description: "Создать ярлык на робочем столе";
Languages: rus; Name: group; Description: "Создать группу в меню ""Пуск""";
Languages: rus; Name: directx; Description: "Установить DirectX (Требуется интернет подключение)";
[InnoIDE_Settings]
[/more]
вот весь код
[more];Расширенный пример распаковки FreeArc архива при помощи unarc.dll, с отображением прогресса распаковки в окне Inno Setup и запросом следующего диска.
;#define External GetEnv("ProgramFiles") + "\FreeArc\PowerPack\Max\*"
;Вынес в отдельный файл все функции связанные с текстурой из оригинального скрипта.
;#deifne Texture
;Добавляем архивы
#define Archives "{src}\setup-1.bin;DestDir:{app}\;Disk:1"
[Setup]
AppName=Need For Speed Underground 2
AppVerName=Need For Speed Underground 2
DefaultDirName={pf}\Need For Speed Underground 2
DirExistsWarning=yes
ShowLanguageDialog=auto
OutputDir=.
VersionInfoCopyright=aLLeXUs
WizardImageFile="D:\Прочее\InnoSetupProjects\Need For Speed Underground 2\Nfsu2_cover.bmp"
WizardSmallImageFile="D:\Прочее\InnoSetupProjects\Need For Speed Underground 2\SetupModernSmall25.bmp"
DefaultGroupName=Need For Speed Underground 2
SolidCompression=true
Compression=lzma/Ultra
InternalCompressLevel=Ultra
DiskSpanning=false
DiskSliceSize=736000000
SetupLogging=false
[UninstallDelete]
Type: filesandordirs; Name: {app}
[Languages]
Name: rus; MessagesFile: Russian.isl;
[CustomMessages]
rus.ArcBreak=Установка прервана!
rus.ArcError=Распаковщик вернул код ошибки: %1.
rus.ErrorUnknownError=Ошибка при распаковке архивов. Пожалуйста, обратитесь к разработчику программы.
rus.ErrorCompressMethod=Метод сжатия "%1" данного файла "%2" не поддерживается.
rus.ErrorOutBlockSize=Выходной блок данных файла "%1" слишком мал.
rus.ErrorNotEnoughRAMMemory=Недостаточно свободной оперативной памяти для распаковки "%1".
rus.ErrorReadData=Ошибка чтения данных файла "%1".
rus.ErrorBadCompressedData=Данные из файла "%1" не могут быть распакованы.
rus.ErrorNotImplement=Запрошенное действие не поддерживается.
rus.ErrorDataAlreadyDecompress=Запрошенный блок данных файла "%1" уже распакован.
rus.ErrorUnpackTerminated=Операция прервана пользователем.
rus.ErrorWriteData=Ошибка записи данных из файла "%1".
rus.ErrorBadCRC=Ошибка данных CRC в файле "%1".
rus.ErrorBadPassword=Пароль введенный для данного архива "%1" неверен.
rus.ErrorBadHeader=Заголовок файла "%1" поврежден.
rus.ErrorCodeException=Ошибка выполнения программы установки. Пожалуйста, обратитесь к разработчику программы.
rus.ErrorNotEnoughFreeSpace=Недостаточно свободного места на диске назначения для распаковки архива "%1".
rus.ArcTitle=Распаковка файлов...
rus.StatusInfo=Файлов: %1%2, %3%% выполнено, осталось ждать %4
rus.ArcInfo=Диск %1/%2, архив %3/%4, архив обработан на %5%%
rus.ArcFinish=Распаковано архивов: %1, получено файлов: %2 [%3]
rus.InsertDisk=Пожалуйста, вставьте диск № %1, содержащий файл "%2" и нажмите кнопку ОК.
rus.taskbar=%1%%, жди %2
rus.ending=Завершение
rus.hour= часов
rus.min= мин
rus.sec= сек
[ISToolPreCompile]
#define isFalse(any S) (S = LowerCase(Str(S))) == "no" || S == "false" || S == "off" ? "true" : "false"
[Files]
Source: dxwebsetup.exe; DestDir: {tmp}; Tasks: directx; Flags: deleteafterinstall;
Source: unarc.dll; DestDir: {tmp}; Flags: dontcopy
Source: iswin7.dll; DestDir: {tmp}; Flags: dontcopy
Source: InnoCallback.dll; DestDir: {tmp}; Flags: dontcopy
Source: Logo.bmp; DestDir: {tmp}; Flags: dontcopy
#ifdef precomp
;если указано, что архивы созданы с PRECOMP, в инсталлятор включаются необходимые при распаковке файлы
Source: {#External}; DestDir: {sys}; Flags: deleteafterinstall
Source: {#GetEnv("ProgramFiles")}\FreeArc\bin\arc.ini; DestDir: c:\; Flags: deleteafterinstall
#endif
[Code]
type
#ifdef UNICODE
#define A "W"
#else
#define A "A" ;// точка входа в SetWindowText, {#A} меняется на A или W в зависимости от версии
#if Ver < 84084736
PAnsiChar = PChar; // Required for Inno Setup 5.3.0 and lower. (требуется для Inno Setup версии 5.3.0 и ниже)
#endif
#endif
#if Ver < 84018176
AnsiString = String; // There is no need for this line in Inno Setup 5.2.4 and above (для Inno Setup версий 5.2.4 и выше эта строка не нужна)
#endif
TMessage = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
TFreeArcCallback = function (what: PAnsiChar; int1, int2: Integer; str: PAnsiChar): Integer;
TArc = record Path, Dest, comp, task, pass: string; allMb: Integer; Disks: Integer; UnPack, UnPacked: Boolean; end;
TBarInfo = record stage, name: string; size: Extended; perc: Integer; end;
TFAProgressInfo = record DiskSize, CurPos, LastPos, AllPos, FilesCount: Integer; LastSize, AllSize: Extended; end;
TFADiskStatus = record LastMaxCount, MaxCount, CurDisk, NextArc, RemainsArc: Integer; end;
TCWPSTRUCT = record lParam: LongWord; wParam: Word; Msg: LongWord; hwnd: HWnd; end;
TCWPSTRUCTProc = procedure(Code: Integer; wParam: Word; lParam: TCWPSTRUCT);
TTimerProc = procedure(HandleW, Msg, idEvent, TimeSys: LongWord);
var
StatusLabel, FileNameLabel, ExtractFile, StatusInfo: TLabel;
ProgressBar: TNewProgressBar;
CancelCode, n, ArcInd, UnPackError, StartInstall, LastTimerEvent, lastMb, baseMb: Integer;
FreeMB, TotalMB: Cardinal;
WndHookID, TimerID: LongWord;
Arcs, AllArchives: array of TArc;
msgError, CompressMethod: string;
Status: TBarInfo; Progress: TFAProgressInfo; DS: TFADiskStatus;
FreezeTimer, SuspendUpdate: Boolean;
origsize: Integer; // total uncompressed size of archive data in mb
const
CP_ACP = 0; CP_UTF8 = 65001;
oneMB=1024*1024;
Period = 250; // частота обновления кнопки таскбара и строки статуса
VK_ESCAPE = 27;
HC_ACTION = 0;
WM_PAINT = $F;
CancelDuringInstall = {#isFalse(SetupSetting("AllowCancelDuringInstall"))};
function WrapFreeArcCallback (callback: TFreeArcCallback; paramcount: integer):longword; external 'wrapcallback@files:innocallback.dll stdcall';
function FreeArcExtract (callback: longword; cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10: PAnsiChar): integer; external 'FreeArcExtract@files:unarc.dll cdecl';
Function OemToChar(lpszSrc, lpszDst: AnsiString): longint; external 'OemToCharA@user32.dll stdcall';
Function MultiByteToWideChar(CodePage: UINT; dwFlags: DWORD; lpMultiByteStr: PAnsiChar; cbMultiByte: integer; lpWideCharStr: PAnsiChar; cchWideChar: integer): longint; external 'MultiByteToWideChar@kernel32.dll stdcall';
Function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD; lpWideCharStr: PAnsiChar; cchWideChar: integer; lpMultiByteStr: PAnsiChar; cbMultiByte: integer; lpDefaultChar: integer; lpUsedDefaultChar: integer): longint; external 'WideCharToMultiByte@kernel32.dll stdcall';
function PeekMessage(var lpMsg: TMessage; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessageA@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMessage): BOOL; external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMessage): Longint; external 'DispatchMessageA@user32.dll stdcall';
function GetTickCount: DWord; external 'GetTickCount@kernel32';
function GetWindowLong(hWnd, nIndex: Integer): Longint; external 'GetWindowLongA@user32 stdcall delayload';
function SetWindowText(hWnd: Longint; lpString: String): Longint; external 'SetWindowText{#A}@user32 stdcall delayload';
function GetKeyState(nVirtKey: Integer): ShortInt; external 'GetKeyState@user32 stdcall delayload';
function GetCurrentThreadID: LongWord; external 'GetCurrentThreadId@kernel32 stdcall delayload';
function CallNextWNDPROC(idHook: LongWord; Code: Integer; wParam: Word; lParam: TCWPSTRUCT): LongWord; external 'CallNextHookEx@user32 stdcall delayload';
function SetWindowsHookEx(idHook: LongWord; callback: LongWord; hMod: LongWord; dwThreadID: HWND): LongWord; external 'SetWindowsHookExW@user32 stdcall delayload';
function UnhookWindowsHookEx(idHook: LongWord): LongWord; external 'UnhookWindowsHookEx@user32 stdcall delayload';
function WrapCWPSTRUCTProc(callback:TCWPSTRUCTProc; paramcount:integer): longword; external 'wrapcallback@files:innocallback.dll';
function WrapTimerProc(callback: TTimerProc; Paramcount: Integer): longword; external 'wrapcallback@files:innocallback.dll stdcall';
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): longword; external 'SetTimer@user32';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord; external 'KillTimer@user32 stdcall delayload';
procedure AppProcessMessage;
var Msg: TMessage;
begin
if not PeekMessage(Msg, 0, 0, 0, 1) then Exit;
TranslateMessage(Msg); DispatchMessage(Msg);
end;
Function FreeArcCmd(callback: longword; cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10: PAnsiChar): integer;
Begin
CancelCode:= 0; AppProcessMessage;
try
Result:= FreeArcExtract(callback, cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10); // Pass the specified arguments to 'unarc.dll'
if CancelCode < 0 then Result:= CancelCode;
except
Result:= -63; // ArcFail
end;
End;
// Sets the TaskBar title
Procedure SetTaskBarTitle(Title: String); var h: Integer;
Begin
h:= GetWindowLong(MainForm.Handle, -8); if h <> 0 then SetWindowText(h, Title);
End;
// Перевод числа в строку с точностью 2 знака (%.2n) с округлением дробной части, если она есть
Function NumToStr(Float: Extended): String;
Begin
Result:= Format('%.2n', [Float]); StringChange(Result, ',', '.');
while ((Result[Length(Result)] = '0') or (Result[Length(Result)] = '.')) and (Pos('.', Result) > 0) do
SetLength(Result, Length(Result)-1);
End;
Function ByteOrTB(Bytes: Extended; noMB: Boolean): String; {Перевод числа в значение бт/Кб/Мб/Гб/Тб (до 2х знаков после запятой)}
Begin
if not noMB then Result:= NumToStr(Int(Bytes)) +' Mb' else
if Bytes < 1024 then if Bytes = 0 then Result:= '0' else Result:= NumToStr(Int(Bytes)) +' Bt' else
if Bytes/1024 < 1024 then Result:= NumToStr(round((Bytes/1024)*10)/10) +' Kb' else
If Bytes/oneMB < 1024 then Result:= NumToStr(round(Bytes/oneMB*100)/100) +' Mb' else
If Bytes/oneMB/1000 < 1024 then Result:= NumToStr(round(Bytes/oneMB/1024*1000)/1000) +' Gb' else
Result:= NumToStr(round(Bytes/oneMB/oneMB*1000)/1000) +' Tb';
End;
Function StringToArray(Text, Cut: String): array of String; var i, k: Integer; // поместить строки текста в элементы массив. шаблон перевода строк может быть любым. шаблон в начале/конце текста игнорируются
Begin
SetArrayLength(Result, 0); if Cut = '' then Cut:= #1310; //если шаблон пуст, считаем переводы строк
Repeat k:= Pos(Cut,Text);
if k = 1 then begin Delete(Text, 1, Length(Cut)); CONTINUE
end;
SetArrayLength(Result, GetArrayLength(Result) +1); i:= GetArrayLength(Result) -1;
if k = 0 then
Result[i]:=Text
else begin
Result[i]:= Copy(Text, 1, k -1); Delete(Text, 1, Length(Result[i]) + Length(Cut));
end;
Until Length(Text) * k = 0;
End;
Function CreateLabel(Parent: TWinControl; AutoSize, WordWrap, Transparent: Boolean; FontName: String; FontStyle: TFontStyles; FontColor: TColor; Left, Top, Width, Height: Integer; Prefs: TObject): TLabel;
Begin
Result:=TLabel.Create(Parent); Result.parent:= Parent;
if Prefs <> Nil then begin
Top:= TWinControl(Prefs).Top; Left:= TWinControl(Prefs).Left; Width:= TWinControl(Prefs).Width; Height:= TWinControl(Prefs).Height;
end;
if Top > 0 then result.Top:=Top; if Left > 0 then result.Left:= Left; if Width > 0 then result.Width:= Width; if Height > 0 then result.Height:= Height;
if FontName <> '' then result.Font.Name:= FontName; if FontColor > 0 then result.Font.Color:= FontColor; if FontStyle <> [] then result.Font.Style:= FontStyle;
result.AutoSize:= AutoSize; result.WordWrap:= WordWrap; result.Transparent:=Transparent; result.ShowHint:= true;
End;
// Converts milliseconds to human-readable time
// Конвертирует милисекунды в человеко-читаемое изображение времени
Function TicksToTime(Ticks: DWord; h,m,s: String; detail: Boolean): String;
Begin
if detail then {hh:mm:ss format}
Result:= PADZ(IntToStr(Ticks/3600000), 2) +':'+ PADZ(IntToStr((Ticks/1000 - Ticks/1000/3600*3600)/60), 2) +':'+ PADZ(IntToStr(Ticks/1000 - Ticks/1000/60*60), 2)
else if Ticks/3600 >= 1000 then {more than hour}
Result:= IntToStr(Ticks/3600000) +h+' '+ PADZ(IntToStr((Ticks/1000 - Ticks/1000/3600*3600)/60), 2) +m
else if Ticks/60 >= 1000 then {1..60 minutes}
Result:= IntToStr(Ticks/60000) +m+' '+ IntToStr(Ticks/1000 - Ticks/1000/60*60) +s
else Result:= Format('%.1n', [Abs(Ticks/1000)]) +s {less than one minute}
End;
Function ExpandENV(string: String): String; var n: UINT; Begin // ExpandConstant + развёртывание DOS-переменных типа %SystemRoot%
if Pos('{',string) * Pos('}',string) = 0 then Result:= String else Result:= ExpandConstant(String); n:= Pos('%',result); if n = 0 then Exit;
Delete(result, n,1); Result:= Copy(Result,1, n-1) + ExpandConstant('{%'+Copy(Result, n, Pos('%',result) -n) +'}') + Copy(Result, Pos('%',result) +1, Length(result))
End;
Function cm(Message: String): String; Begin Result:= ExpandConstant('{cm:'+ Message +'}') End;
Function LoWord(lw: LongWord): LongWord; Begin Result:= lw shr 16; End;
// Converts OEM encoded string into ANSI (Преобразует OEM строку в ANSI кодировку)
function OemToAnsiStr(strSource: AnsiString): AnsiString;
begin
SetLength(Result, Length(strSource));
OemToChar(strSource, Result);
end;
// Converts ANSI encoded string into UTF-8 (Преобразует строку из ANSI в UTF-8 кодировку) by CTAC-Ko
function AnsiToUtf8(strSource: string): string;
var
nRet, nRet2: integer; WideCharBuf, MultiByteBuf: AnsiString;
begin
SetLength(WideCharBuf, Length(strSource) * 2);
SetLength(MultiByteBuf, Length(strSource) * 2);
nRet:= MultiByteToWideChar(CP_ACP, 0, strSource, -1, WideCharBuf, Length(WideCharBuf));
nRet2:= WideCharToMultiByte(CP_UTF8, 0, WideCharBuf, -1, MultiByteBuf, Length(MultiByteBuf), 0, 0);
//nRet2 возвращает число обработанных знаков (исключая различный мусор в конце строки)
MultiByteBuf:=Copy(MultiByteBuf, 1, nRet2); //Вот мы и обрубаем строку до этого числа знаков
Result:= MultiByteBuf;
end;
// ArcInd - текущий архив, счёт с 0
// baseMb - записано из пред. архива на диск
// lastMb - извлечено из тек. архива на диск
// Status.mb - позиция в текущем архиве
// Status.allsize - объём всех архивов
// Status.size - всего извлечено Мб на текущий момент
// totalUncompressedSize - точный объём данных в архивах
// общий прогресс нарастает по мере записи данных из архива на диск (точка 'write')
// прогресс архивов двигается в соответствии с позицией в текущем архиве (точка 'read')
Procedure UpdateStatus(Flags: Integer); // выполняется с периодичностью, заданной константой Period
var
Remaining, p: Integer; i, t: string;
Begin
if Flags and $1 > 0 then FreezeTimer:= Flags and $2 = 0; // bit 0 = 1 change start/stop, bit 1 = 0 stop, bit 1 = 1 start
if (Flags and $4 > 0) or (Status.size <> baseMb+lastMb) then LastTimerEvent:= 0; // bit 2 = 1 UpdateNow // обновить по флагу или записи из архива на диск
if (FreezeTimer=True)or(GetTickCount - LastTimerEvent <= Period)or(SuspendUpdate=True) then Exit else LastTimerEvent:= GetTickCount;
Status.size := baseMb+lastMb; // извлечено на текущий момент
Progress.Allsize:= Progress.LastSize + lastMb; //Извлечено всего
with WizardForm.ProgressGauge do begin
if Progress.DiskSize > 0 then begin
Progress.CurPos:= round(Max * Status.size/Progress.DiskSize);
if Progress.CurPos > Progress.LastPos then begin
Progress.AllPos:= Progress.AllPos + ((Progress.CurPos-Progress.LastPos)/DS.MaxCount);
Progress.LastPos:=Progress.CurPos
end;
Position:= Progress.AllPos
end;
n:= (Max - Min)/1000; if n > 0 then Status.perc:= (Position-Min)/n; // 1000 процентов
#ifndef External
// к сожалению, этот код иногда сбоит на очень больших архивах, созданных с использованием внешних упаковщиков
if Position > 0 then Remaining:= ((Max-Position)*(GetTickCount-StartInstall))/Position else
#endif
Remaining:= 0; t:= cm('ending'); i:= AnsiLowerCase(t);
if Remaining > 0 then begin
t:= FmtMessage(cm('taskbar'), [IntToStr(Status.perc/10), TicksToTime(Remaining, 'h', 'm', 's', false)])
i:= TicksToTime(Remaining, cm('hour'), cm('min'), cm('sec'), false)
end;
end;
SetTaskBarTitle(t); // проценты и оставшееся время на кнопке инсталлятора
StatusInfo.Caption:= FmtMessage(cm('StatusInfo'), [IntToStr(Progress.FilesCount), ' ['+ ByteOrTB(Progress.Allsize*oneMB, true) +']', Format('%.1n', [Abs(Status.perc/10)]), i]);
// второй прогрессбар движется по мере считывания текущего архива
if (Status.stage = cm('ArcTitle')) and (GetArrayLength(Arcs) > 0) then begin
if (Arcs[ArcInd].allMb > 0) then p:= ((LastMb*100)/Arcs[ArcInd].AllMb);
ExtractFile.Caption:= FmtMessage(cm('ArcInfo'), [IntToStr(DS.CurDisk), IntToStr(DS.MaxCount), IntToStr(ArcInd+1), IntToStr(GetArrayLength(Arcs)), IntToStr(p)]);
ProgressBar.Position:= LastMb;
end;
End;
Procedure MyTimerProc(h, msg, idevent, dwTime: Longword);
Begin
if WizardForm.CurPageID = wpInstalling then UpdateStatus(0);
End;
Procedure OnWndHook(Code: Integer; wParam: Word; lParam: TCWPSTRUCT);
Begin
if (Code = HC_ACTION) and (LoWord(lParam.msg) = WM_PAINT) then begin // подготовка данных для последующего отображения по таймеру
if (Status.name <> WizardForm.FileNameLabel.Caption) and (WizardForm.FileNameLabel.Caption <> '') then begin // имя файла, названия ярлыка и прочее
FileNameLabel.Caption:= WizardForm.FileNameLabel.Caption;
Status.name:= WizardForm.FileNameLabel.Caption; // начало извлечения или распаковки очередного файла
Case Status.stage of
SetupMessage(msgStatusExtractFiles): // этап извлечения файлов инсталлятором
Progress.FilesCount:= Progress.FilesCount +1; // кол-во файлов
End;
end;
if (Status.stage <> WizardForm.StatusLabel.Caption) and (WizardForm.StatusLabel.Caption <> '') then begin
StatusLabel.Caption:= WizardForm.StatusLabel.Caption;
Status.stage:= WizardForm.StatusLabel.Caption; // текущий этап установки
if Status.stage = SetupMessage(msgStatusRollback) then begin
WizardForm.StatusLabel.Hide; WizardForm.FileNameLabel.Hide; StatusInfo.Hide; ExtractFile.Hide; ProgressBar.Hide;
end;
end;
UpdateStatus(0);
end;
CallNextWNDPROC(WndHookID, Code, wParam, lParam) {освобождение события}
End;
// compsize: в Mb объём архива
// total_files: в int2 ? число файлов в архиве
// origsize: в Mb общий объём данных в архиве
// write: в Mb число записанных (распакованных из архива) на диск мегабайт
// read: в Mb число обработанных мегабайт, в int2 размер текущего архива
// filename: вызывается перед обработкой каждого файла
// The main callback function for unpacking FreeArc archives
function FreeArcCallback(what: PAnsiChar; Mb, int2: Integer; str: PAnsiChar): Integer; // вызывается не менее 100 раз в секунду, что заменяет вызов по таймеру
begin
case string(what) of
'origsize': origsize:= Mb; // данных в тек. архиве (при распаковке не вызывается)
'total_files': Null;
'filename': begin // Update FileName label
WizardForm.FileNameLabel.Caption:= OemToAnsiStr(str); // извлекаемый файл, их имена пишутся в журнал установки
Progress.FilesCount:= Progress.FilesCount + 1; // кол-во файлов, этап распаковки
end;
'read': Null; // позиция в текущем архиве
'write': lastMb:= Mb; // Assign to Mb *total* amount of data extracted to the moment from all archives
'quit': if (Mb = -2) then CompressMethod:= str;
end;
if WizardForm.CurPageID = wpInstalling then UpdateStatus(0); // обновить страницу установки, не сбрасывая таймер
if (GetKeyState(VK_ESCAPE) < 0) and not CancelDuringInstall then
WizardForm.Close; // опрашиваем Cancel (если разрешена отмена установки)
AppProcessMessage;
Result:= CancelCode;
end;
Function DeleteChars(S, Char: String): String; begin if (Pos(Char, S)>0) then
begin while (Pos(Char, S)>0) do StringChange(S, Char, ''); end; Result:=S; end;
Function CutStr(var S: String; Index, Length: Integer): String; var str: string;
begin str:= Copy(S, Index, Length); Delete(S, Index, Length); Result:=Str; end;
Function CutStrEx(var S: String; Code: String): String;
var str: string; pos1, pos2: integer; begin pos1:= Pos(Code, S); If (pos1>0) then begin
pos2:=pos1; while S[pos2]<>';' do if pos2<>length(S) then pos2:=pos2+1; str:=cutStr(S, pos1, (pos2-pos1)+1);
StringChange(str, Code, ''); if str[Length(str)]=';' then Setlength(str, Length(str)-1); end; Result:=str; end;
Function ArcDecode(Line: String): array of TArc; // разбор строки Archives
var tmp: array of String; cut: string; i, n: integer;
begin
SetArrayLength(Result, 0); If Line = '' then Exit;
tmp:= StringToArray(Line, '|');
for n:=0 to GetArrayLength(tmp)-1 do begin
i:= GetArrayLength(Result); SetArrayLength(Result, i+1); cut:=tmp[n]+';';
if (Pos('Tasks:', cut)>0) then Result[i].task:= DeleteChars(CutStrEx(cut, 'Tasks:'), ';');
if (Pos('Components:', cut)>0) then Result[i].comp:= DeleteChars(CutStrEx(cut, 'Components:'), ';');
if (Pos('Password:', cut)>0) then Result[i].pass:= DeleteChars(CutStrEx(cut, 'Password:'), ';');
if (Pos('Disk:', cut)>0) then Result[i].disks:= StrToInt(DeleteChars(CutStrEx(cut, 'Disk:'), ';')) else Result[i].disks:=1;
if (Pos('DestDir:', cut)>0) then Result[i].dest:= DeleteChars(CutStrEx(cut, 'DestDir:'), ';');
cut:=DeleteChars(cut, ';');
if (ExtractFileDrive(ExpandEnv(cut)) = '')and(ExpandEnv(cut) = cut) then
Result[i].Path:= '{src}\'+cut else Result[i].Path:= cut;
Result[i].Dest:= ExpandENV(result[i].Dest); Result[i].Path:= ExpandENV(result[i].Path);
end;
end;
// Scans the specified folders for archives and add them to list
function AddArcs(File: TArc; var ErrCode: Integer): Integer; // добавление архивов в общий список и подсчёт объёма распакованных данных
var i: integer; Password: string;
Begin
if FileExists(File.Path) then begin
Result:= 0; i:= GetArrayLength(Arcs);
if File.pass <> '' then Password:= '-p'+AnsiToUtf8(File.pass) else Password:= '';
SetArrayLength(Arcs, i +1); Arcs[i]:=File;
if Password <> '' then
ErrCode:= FreeArcCmd(WrapFreeArcCallback(@FreeArcCallback,4),'l',Password,'--',AnsiToUtf8(Arcs[i].Path),'','','','','','')
else
ErrCode:= FreeArcCmd(WrapFreeArcCallback(@FreeArcCallback,4),'l','--',AnsiToUtf8(Arcs[i].Path),'','','','','','',''); // код ошибки
if ErrCode >= 0 then begin Arcs[i].allMb:= origsize; result:= Arcs[i].allMb; origsize:=0; end;// размер распакованных данных успешно считан
end;
End;
function DispatchError(ErrorCode: Integer; Arc: TArc): String;
var ArcFile: String;
begin
ArcFile:= ExtractFilename(Arc.Path);
if (ErrorCode = -2) then StringChange(CompressMethod, 'ERROR: unsupported compression method ', '')
case ErrorCode of
-1: Result:= cm('ErrorUnknownError');
-2: Result:= FmtMessage(cm('ErrorCompressMethod'), [CompressMethod, ArcFile]);
-3: Null;
-4: Result:= FmtMessage(cm('ErrorOutBlockSize'), [ArcFile]);
-5: Result:= FmtMessage(cm('ErrorNotEnoughRAMMemory'), [ArcFile]);
-6: Result:= FmtMessage(cm('ErrorReadData'), [ArcFile]);
-7: Result:= FmtMessage(cm('ErrorBadCompressedData'), [ArcFile]);
-8: Result:= cm('ErrorNotImplement');
-9: Result:= FmtMessage(cm('ErrorDataAlreadyDecompress'), [ArcFile]);
-10: Result:= cm('ErrorUnpackTerminated');
-11: Result:= FmtMessage(cm('ErrorWriteData'), [ArcFile]);
-12: Result:= FmtMessage(cm('ErrorBadCRC'), [ArcFile]);
-13: Result:= FmtMessage(cm('ErrorBadPassword'), [ArcFile]);
-14: Result:= FmtMessage(cm('ErrorBadHeader'), [ArcFile]);
-15: Null;
-63: Result:= cm('ErrorCodeException');
-112: Result:= FmtMessage(cm('ErrorNotEnoughFreeSpace'), [ArcFile]);
end;
end;
function UnPackArchive(Archive: TArc): Integer;
var callback: longword; Password: String;
Begin
// если отмена установки разрешена, кнопка Cancel станет доступна
WizardForm.CancelButton.Enabled:= not CancelDuringInstall;
if Archive.pass <> '' then Password:= '-p'+AnsiToUtf8(Archive.pass) else Password:= '';
callback:= WrapFreeArcCallback(@FreeArcCallback,4); //FreeArcCallback has 4 arguments
if Password <> '' then
Result:= FreeArcCmd(callback,'x','-o+','-dp'+AnsiToUtf8(Archive.Dest),'-w'+AnsiToUtf8(Archive.Dest),Password,'--',AnsiToUtf8(Archive.Path),'','','')
else // код ошибки
Result:= FreeArcCmd(callback,'x','-o+','-dp'+AnsiToUtf8(Archive.Dest),'-w'+AnsiToUtf8(Archive.Dest),'--',AnsiToUtf8(Archive.Path),'','','','')
// Error occured
if Result = 0 then Exit;
msgError:= FmtMessage(cm('ArcError'), [IntToStr(Result)]);
WizardForm.StatusLabel.Caption:= msgError;
WizardForm.FileNameLabel.Caption:= ExtractFileName(Archive.Path);
GetSpaceOnDisk(ExtractFileDrive(Archive.Dest), True, FreeMB, TotalMB);
if FreeMB < (Archive.allMb-lastMb) then Result:= -112;
MsgError:= msgError+#13#10#13+DispatchError(Result, Archive)
Log(msgError); // записываем ошибку в лог, а также показываем её текст на странице завершения
End;
procedure SetUnpacked(File: TArc); var i: integer; begin
for i:=0 to GetArrayLength(AllArchives)-1 do begin
if(File.Path=AllArchives[i].Path)and(File.Dest=AllArchives[i].Dest)
then begin AllArchives[i].UnPacked:=True; Break; end; end; end;
function UpdateArcsList(): Integer;
var m, ErrorCode: integer; begin
AppProcessMessage; SetArrayLength(Arcs,0); Progress.DiskSize:=0; for m:=0 to (GetArrayLength(AllArchives)-1) do try
if (AllArchives[m].UnPack)and(AllArchives[m].UnPacked=False) then Progress.DiskSize:= Progress.DiskSize + AddArcs(AllArchives[m], ErrorCode);
if (ErrorCode < 0) then begin Result:=ErrorCode; Break; end; Except Result:=-63; end; end;
// Extracts all found archives
function UnPack(): Integer;
begin
Progress.CurPos:=0; Progress.LastPos:=0; baseMb:= 0; // обнулить полученные мегабайты, если ранее вёлся подсчёт объёма файлов инсталлятора
if (DS.LastMaxCount<>DS.MaxCount)and(DS.CurDisk>1) then begin
Progress.AllPos:= (WizardForm.ProgressGauge.Max/(DS.MaxCount))*(DS.CurDisk-1); end;
UpdateStatus(7); // немедленно обновить строку статуса
for ArcInd:= 0 to GetArrayLength(Arcs) -1 do begin // архивы в текущей папке, константы раскрыты в ArcDecode
lastMb:= 0; SuspendUpdate:=False; //отключаем паузу автоапдейта по таймеру на время распаковки
ProgressBar.Max:=Arcs[ArcInd].allMb;
Result:= UnPackArchive(Arcs[ArcInd]); // код ошибки
Progress.LastSize:= Progress.AllSize; SetUnPacked(Arcs[ArcInd]);
SuspendUpdate:=True; //ставим автоапдейт по таймеру на паузу - распаковка окончена (возможно временно)
if Result <> 0 then Break; // прервать цикл распаковки
baseMb:= baseMb + lastMb; // общий объём распакованных файлов
// отработанный архив автоматически удаляется, если находится в папке {app} или {tmp}
if (Pos(AnsiLowercase(ExpandConstant('{app}')), AnsiLowercase(Arcs[ArcInd].Path)) > 0) or (Pos(AnsiLowercase(ExpandConstant('{tmp}')), AnsiLowercase(Arcs[ArcInd].Path)) > 0) then
DeleteFile(Arcs[ArcInd].Path);
end;
end;
Function CheckBools(Bools: array of Boolean): Integer;
var c,l: integer; begin Result:=0; for l:=0 to GetArrayLength(Bools)-1 do begin
if (Bools[l] = True) then c:=c+1; end; if (c=(GetArrayLength(Bools)))then Result:=1;end;
function GetRemainArcs(): integer;
var c: integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
If (AllArchives[c].UnPack)and(not AllArchives[c].UnPacked)then Result:=Result+1; end; end;
Function GetNextArc(): Integer;
var c: Integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
if (AllArchives[c].UnPack)and(not AllArchives[c].UnPacked) then begin Result:=c; Exit; end; end; end;
Function GetUnpackedArcs(): Integer;
var c: Integer; Begin Result:=0; for c:=0 to GetArrayLength(AllArchives)-1 do begin
if (AllArchives[c].UnPack)and(AllArchives[c].UnPacked) then Result:=Result+1; end; Result:=Result+1; end;
Function SetStatus(Value: String): Boolean;
begin WizardForm.StatusLabel.Caption:=Value; StatusLabel.Caption:=Value; Status.stage:=Value; end;
Function UnPackWithPrompts(Archives: string): Integer;
var MsBox, MaxArcs: Integer; FADiskMessage: string;
TmpArc: array of TArc; z, f, q, k, x, LastDisk: Integer; OneDisk, DiskCheck: Boolean;
begin
AppProcessMessage; SetStatus(cm('ArcTitle')) // начало этапa распаковки
ExtractFile.Show; ProgressBar.Show; StatusInfo.Show;
Progress.FilesCount:=0; MsBox:=IDOK; z:=0; OneDisk:=False;
AllArchives:= ArcDecode(Archives); DS.LastMaxCount:=DS.MaxCount;
MaxArcs:= GetArrayLength(AllArchives)-1; LastDisk:=1; q:=0; k:=0; x:=0;
DS.CurDisk:=1; DS.MaxCount:= AllArchives[MaxArcs].disks; DiskCheck:=False;
WizardForm.ProgressGauge.Position:=0; UpdateStatus(7); SuspendUpdate:=True;
WizardForm.ProgressGauge.Max:= 100000;
//инициализация параметров архивов
for f:=0 to MaxArcs do begin
AllArchives[f].UnPack:=True; AllArchives[f].UnPacked:=False; //Сначала активируем все архивы
if (AllArchives[f].comp<>'')and(not IsComponentSelected(AllArchives[f].comp)) then AllArchives[f].UnPack:=False; //Если компонент не выбран то деактивируем этот архив
if (AllArchives[f].task<>'')and(not IsTaskSelected(AllArchives[f].task)) then Allarchives[f].UnPack:=False; //То же что и выше, только с задачей (Task)
z:=z+CheckBools([FileExists(AllArchives[f].Path)]); k:=k+CheckBools([AllArchives[f].UnPack]);
x:=x+CheckBools([AllArchives[f].UnPack, FileExists(AllArchives[f].Path)]);
end;
if (z=(MaxArcs+1)) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; OneDisk:=True; end;
if (x=k) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; OneDisk:=True; end;
DS.NextArc:= GetNextArc; DS.RemainsArc:= GetRemainArcs;
//распаковка архивов на дисках
while (Result = 0) and (DS.RemainsArc>0) do begin
if (not OneDisk) then begin x:=0;
//проверка если на текущем диске находятся все требующиеся архивы (исключая уже распакованные)
for f:= DS.NextArc to MaxArcs do begin
x:=x+CheckBools([(AllArchives[f].UnPack), FileExists(AllArchives[f].Path)]);
if (x=((MaxArcs+1)-DS.NextArc)) then begin DS.LastMaxCount:=DS.MaxCount; DS.MaxCount:=DS.CurDisk; end; end;
end;
while (msBox=IDOK)and(not(FileExists(AllArchives[DS.NextArc].Path))and(AllArchives[DS.NextArc].UnPack)) do begin
FADiskMessage:= FmtMessage(cm('InsertDisk'),[IntToStr(DS.CurDisk), ExtractFilename(AllArchives[DS.NextArc].Path)])
MsBox:= MsgBox(FADiskMessage, mbConfirmation, MB_OKCANCEL)
end;
//Отмена распаковки
if MsBox = IDCANCEL then Result:= -10;
//Проверка числа дисков
if (not OneDisk) then begin
//Если на n-ом диске находтся архивы привязанные к одному компоненту и этот компонент не выбран (проверяется один раз)
if (DS.MaxCount>1)and(DS.CurDisk<>DS.MaxCount)and(not DiskCheck) then begin
while (LastDisk<=DS.MaxCount)and(q<(MaxArcs+1)) do begin
SetArraylength(TmpArc, 0); k:=0;
for z:=q to GetArrayLength(AllArchives)-1 do begin
if AllArchives[z].disks=LastDisk then begin SetArrayLength(TmpArc, GetArrayLength(TmpArc)+1); TmpArc[GetArrayLength(TmpArc)-1]:= AllArchives[z]; end; end;
for z:=0 to GetArrayLength(tmpArc)-1 do begin if (not TmpArc[z].Unpack) then k:=k+1; end;
if k=GetArrayLength(tmpArc) then begin DS.LastMaxCount:= DS.MaxCount; DS.MaxCount:= DS.MaxCount-1; q:=q+GetArrayLength(TmpArc) end;
LastDisk:=LastDisk+1; end;
DiskCheck:=True; end;
//Если на текущем диске должен быть архив а его нет
if (DS.CurDisk=DS.MaxCount) then begin
SetArraylength(TmpArc, 0); k:=0;
for z:=DS.NextArc to GetArrayLength(AllArchives)-1 do begin
if AllArchives[z].disks=DS.CurDisk then begin SetArrayLength(TmpArc, GetArrayLength(TmpArc)+1); TmpArc[GetArrayLength(TmpArc)-1]:= AllArchives[z]; end; end;
for z:=0 to GetArrayLength(tmpArc)-1 do begin if (TmpArc[z].UnPack)and(FileExists(TmpArc[z].Path)) then k:=k+1 end;
if k<GetArrayLength(TmpArc)then begin DS.LastMaxCount:= DS.MaxCount; DS.MaxCount:= DS.MaxCount+1; end;
end;
end;
//Сама распаковка
if (MsBox<>IDCANCEL)and(DS.RemainsArc>0) then begin Result:=UpdateArcsList; Result:= UnPack(); DS.CurDisk:= DS.CurDisk+1; DS.NextArc:= GetNextArc; DS.RemainsArc:= GetRemainArcs; end;
end;
//Конец распаковки, скрытие надписей и прогрессбара
if (Result = 0) then begin WizardForm.StatusLabel.Caption:= FmtMessage(cm('ArcFinish'), [IntToStr(GetUnpackedArcs), IntToStr(Progress.FilesCount), ByteOrTB(Progress.AllSize*oneMB, true)]);
StatusInfo.Hide; ExtractFile.Hide; ProgressBar.Hide; end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssInstall then begin
StartInstall:= GetTickCount {время начала извлечения файлов}
WndHookID:= SetWindowsHookEx(4, WrapCWPSTRUCTProc(@OnWndHook, 3), 0, GetCurrentThreadID); {установка SendMessage хука}
TimerID:= SetTimer(0, 0, 500 {полсекунды}, WrapTimerProc(@MyTimerProc, 4)); {установка таймера}
end;
if CurStep = ssPostInstall then
begin
StartInstall:= GetTickCount {время начала распаковки}
UnPackError:= UnPackWithPrompts('{#Archives}')
if UnPackError <> 0 then begin // Error occured, uninstall it then
if not {#isFalse(SetupSetting("Uninstallable"))} then // деинсталляция разрешёна
Exec(ExpandConstant('{uninstallexe}'), '/SILENT','', sw_Hide, ewWaitUntilTerminated, n); // откат установки из-за ошибки unarc.dll
WizardForm.caption:= SetupMessage(msgErrorTitle) +' - '+ cm('ArcBreak')
SetTaskBarTitle(SetupMessage(msgErrorTitle))
end else
SetTaskBarTitle(SetupMessage(msgSetupAppTitle));
end;
end;
#ifdef Texture
#include "FATexture.iss"
#endif
Procedure CurPageChanged(CurPageID: Integer);
Begin
#ifdef Texture
SetTexture(CurPageID)
#endif
if (CurPageID = wpFinished) and (UnPackError <> 0) then
begin // Extraction was unsuccessful (распаковщик вернул ошибку)
// Show error message
WizardForm.FinishedLabel.Font.Color:= $0000C0; // red (красный)
WizardForm.FinishedLabel.Height:= WizardForm.FinishedLabel.Height * 2;
WizardForm.FinishedLabel.Caption:= SetupMessage(msgSetupAborted) + #13#10#13#10 + msgError;
end;
End;
procedure iswin7_add_glass(Handle:HWND; Left, Top, Right, Bottom : Integer; GDIPLoadMode: boolean);
external 'iswin7_add_glass@files:iswin7.dll stdcall';
procedure iswin7_add_button(Handle:HWND);
external 'iswin7_add_button@files:iswin7.dll stdcall';
procedure iswin7_free;
external 'iswin7_free@files:iswin7.dll stdcall';
//-----------start----------LOGO----------//
procedure LogoOnClick(Sender: TObject);
var ResCode: Integer;
begin
ShellExec('', 'http://vkontakte.ru/allexus', '' , '', SW_SHOW, ewNoWait, ResCode)
end;
//------------end--------------LOGO---------------//
procedure WizardClose(Sender: TObject; var Action: TCloseAction);
Begin
Action:= caNone; // так надо
if Status.stage = cm('ArcTitle') then begin // распаковка на этапе ssPostInstall
UpdateStatus(1); // остановить таймер
if MsgBox(SetupMessage(msgExitSetupMessage), mbInformation, MB_YESNO) = IDYES then
CancelCode:= -10; // прервать распаковку
UpdateStatus(7); // обновить информацию
end else
MainForm.Close; // стандартное нажатие кнопки закрытия окна, отмены или Escape.
End;
Procedure InitializeWizard();
var
BtnPanel: TPanel;
BtnImage: TBitmapImage;
Begin
// Create controls to show extended info
StatusLabel:= CreateLabel(WizardForm.InstallingPage,false,false,true,'',[],0,0,0,0,0, WizardForm.StatusLabel);
FileNameLabel:= CreateLabel(WizardForm.InstallingPage,false,false,true,'',[],0,0,0,0,0, WizardForm.FileNameLabel);
WizardForm.StatusLabel.Top:= WizardForm.ProgressGauge.Top; WizardForm.FileNameLabel.Top:= WizardForm.ProgressGauge.Top; // прячем под прогрессбар, тогда все события WM_PAINT перехватываются
with WizardForm.ProgressGauge do begin
StatusInfo:= CreateLabel(WizardForm.InstallingPage, false, true, true, '', [], 0, 0, Top + ScaleY(32), Width, 0, Nil);
ProgressBar := TNewProgressBar.Create(WizardForm);
ProgressBar.SetBounds(Left, StatusInfo.Top + StatusInfo.Height + ScaleY(16), Width, Height);
ProgressBar.Parent := WizardForm.InstallingPage;
ProgressBar.max := 65536;
ProgressBar.Hide; // будет показан при обработке нескольких архивов
ExtractFile:= CreateLabel(WizardForm.InstallingPage, false, true, true, '', [], 0, 0, ProgressBar.Top + ScaleY(32), Width, 0, Nil);
end;
WizardForm.OnClose:= @WizardClose // позволяет прервать распаковку архивов стандартными способами
#ifdef Texture
CreateTexture();
#endif
// Необходимо добавлять каждую кнопку расположенную на стекле
// до инициализации стекла для того что бы не было дыр ))
iswin7_add_button(WizardForm.BackButton.Handle);
iswin7_add_button(WizardForm.NextButton.Handle);
iswin7_add_button(WizardForm.CancelButton.Handle);
// Параметр True не трогать он для htuos ))
iswin7_add_glass(WizardForm.Handle, 0, 0, 0, 47, True);
//-----------start----------LOGO-----------//
ExtractTemporaryFile('Logo.bmp')
BtnPanel:=TPanel.Create(WizardForm)
with BtnPanel do begin
Left:=20
Top:=325
Width:=132
Height:=27
Cursor:=crHand
OnClick:=@logoOnClick
Parent:=WizardForm
end;
BtnImage:=TBitmapImage.Create(WizardForm)
with BtnImage do begin
AutoSize:=True;
Enabled:=False;
Bitmap.LoadFromFile(ExpandConstant('{tmp}')+'\Logo.bmp')
Parent:=BtnPanel
end;
End;
Procedure DeInitializeSetup;
Begin
KillTimer(0, TimerID) {удаление таймера}
UnhookWindowsHookEx(WndHookID) {удаление SendMessage хука}
iswin7_free;
End;
[Icons]
Name: "{group}\Запустить Need For Speed Underground 2"; Filename: {app}\speed2.exe; Languages: rus; Tasks: group;
Name: "{group}\Удалить Need For Speed Underground 2"; Filename: {app}\unins000.exe; Languages: rus; Tasks: group;
Name: "{commondesktop}\Need For Speed Underground 2"; Filename: {app}\speed2.exe; Languages: rus; Tasks: desktop;
[Run]
Filename: {tmp}\dxwebsetup.exe; WorkingDir: {tmp}; Parameters: /q; StatusMsg: "Установка DirectX"; Tasks: directx;
[Tasks]
Languages: rus; Name: desktop; Description: "Создать ярлык на робочем столе";
Languages: rus; Name: group; Description: "Создать группу в меню ""Пуск""";
Languages: rus; Name: directx; Description: "Установить DirectX (Требуется интернет подключение)";
[InnoIDE_Settings]
[/more]
log1stable
Так есть же куча примеров! В сборнике от Krinkels есть пример:
[more]======================================
Inno Setup Faq. Текстурирование кнопок через botva2.dll
======================================
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
[Files]
Source: botva2.dll; DestDir: {tmp}; Flags: dontcopy
Source: compiler:innocallback.dll; DestDir: {tmp}; Flags: dontcopy
Source: Button.png; DestDir: {tmp}; Flags: dontcopy
[_code]
type
TButtonInfo = record ButtonName: array of TButton; Handle: array of HWND; Count: Integer; end;
TBtnEventProc = procedure(h:HWND);
const
BtnClickEventID = 1;
BtnMouseEnterEventID = 2;
BtnMouseLeaveEventID = 3;
BtnMouseMoveEventID = 4;
balLeft = 0;
balCenter = 1;
var
ButtonsBuff: TButtonInfo;
HCancelButton, HNextButton, HBackButton, HDirBrowseButton, HGroupBrowseButton: HWND;
function WrapBtnCallback(Callback: TBtnEventProc; ParamCount: Integer): Longword; external 'wrapcallback@files:innocallback.dll stdcall';
function BtnCreate(hParent:HWND; Left,Top,Width,Height:integer; FileName:PChar; ShadowWidth:integer; IsCheckBtn:boolean):HWND; external 'BtnCreate@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetPosition(h:HWND; NewLeft, NewTop, NewWidth, NewHeight: integer); external 'BtnSetPosition@files:botva2.dll stdcall';
procedure BtnRefresh(h:HWND); external 'BtnRefresh@files:botva2.dll stdcall';
function BtnGetChecked(h:HWND):boolean; external 'BtnGetChecked@files:botva2.dll stdcall';
procedure BtnSetChecked(h:HWND; Value:boolean); external 'BtnSetChecked@files:botva2.dll stdcall';
procedure BtnSetText(h:HWND; Text:PAnsiChar); external 'BtnSetText@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetTextAlignment(h:HWND; HorIndent, VertIndent:integer; Alignment:DWORD); external 'BtnSetTextAlignment@files:botva2.dll stdcall';
procedure BtnSetVisibility(h:HWND; Value:boolean); external 'BtnSetVisibility@files:botva2.dll stdcall';
function BtnGetEnabled(h:HWND):boolean; external 'BtnGetEnabled@files:botva2.dll stdcall';
procedure BtnSetEnabled(h:HWND; Value:boolean); external 'BtnSetEnabled@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFont(h:HWND; Font:Cardinal); external 'BtnSetFont@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFontColor(h:HWND; NormalFontColor, FocusedFontColor, PressedFontColor, DisabledFontColor: Cardinal); external 'BtnSetFontColor@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetEvent(h:HWND; EventID:integer; Event:Longword); external 'BtnSetEvent@files:botva2.dll stdcall';
procedure BtnSetCursor(h:HWND; hCur:Cardinal); external 'BtnSetCursor@files:botva2.dll stdcall';
function GetSysCursorHandle(id:integer):Cardinal; external 'GetSysCursorHandle@files:botva2.dll stdcall';
procedure gdipShutdown; external 'gdipShutdown@files:botva2.dll stdcall';
procedure UpdateButtons();
var I: integer;
begin
for I:=0 to (ButtonsBuff.Count-1) do begin
BtnSetEnabled(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Enabled)
BtnSetVisibility(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Visible)
BtnSetText(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Caption)
BtnRefresh(ButtonsBuff.Handle[I])
end;
end;
procedure ButtonOnClick(hBtn: HWND);
var Btn: TButton; I: Integer;
begin
for I:=0 to (ButtonsBuff.Count-1) do begin
if hBtn = ButtonsBuff.Handle[I] then Btn:= ButtonsBuff.ButtonName[I];
end;
Btn.OnClick(Btn)
UpdateButtons;
end;
function EffectTextureButton(Handle: HWND; Button: TButton; ImageName: PAnsiChar; ShadowWidth: Integer; EnterEvent, MoveEvent, LeaveEvent: TbtnEventProc): HWND;
begin
Result:=BtnCreate(Handle, Button.Left-8, Button.Top-8, Button.Width+16, Button.Height+16, ImageName, ShadowWidth, False) //Размеры подобраны для текущей текстуры
BtnSetEvent(Result, BtnClickEventID, WrapBtnCallback(@ButtonOnClick, 1))
if EnterEvent <> nil then BtnSetEvent(Result, BtnMouseEnterEventID, WrapBtnCallback(EnterEvent, 1));
if MoveEvent <> nil then BtnSetEvent(Result, BtnMouseMoveEventID, WrapBtnCallback(MoveEvent, 1));
if LeaveEvent <> nil then BtnSetEvent(Result, BtnMouseLeaveEventID, WrapBtnCallback(LeaveEvent, 1));
BtnSetFont(Result, Button.Font.Handle)
BtnSetText(Result, Button.Caption);
BtnSetVisibility(Result, Button.Visible);
BtnSetFontColor(Result,clBlack,clBlack,clBlack,clGray);
BtnSetCursor(Result,GetSysCursorHandle(32649));
Button.Width:=0; Button.Height:= 0;
SetArrayLength(ButtonsBuff.Handle, ButtonsBuff.Count+1);SetArrayLength(ButtonsBuff.ButtonName, ButtonsBuff.Count+1);
ButtonsBuff.ButtonName[ButtonsBuff.Count]:= Button; ButtonsBuff.Handle[ButtonsBuff.Count]:= Result;
ButtonsBuff.Count:= ButtonsBuff.Count+1;
end;
procedure ButtonChangeFont(ButtonHandle: HWND; Font: TFont; NormalColor, FocusedColor, PressedColor, DisabledColor: Cardinal);
begin
if Font <> nil then BtnSetFont(ButtonHandle, Font.Handle);
BtnSetFontColor(ButtonHandle, NormalColor, FocusedColor, PressedColor, DisabledColor)
end;
procedure InitializeWizard();
begin
ExtractTemporaryFile('Button.png')
HNextButton:= EffectTextureButton(WizardForm.Handle, WizardForm.NextButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HCancelButton:= EffectTextureButton(WizardForm.Handle, WizardForm.CancelButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HBackButton:= EffectTextureButton(WizardForm.Handle, WizardForm.BackButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HDirBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.DirBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HGroupBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.GroupBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
end;
procedure CurPageChanged(CurPageId: Integer);
begin
UpdateButtons
end;
procedure DeinitializeSetup();
begin
gdipShutdown
end;
[/more]
Так есть же куча примеров! В сборнике от Krinkels есть пример:
[more]======================================
Inno Setup Faq. Текстурирование кнопок через botva2.dll
======================================
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
[Files]
Source: botva2.dll; DestDir: {tmp}; Flags: dontcopy
Source: compiler:innocallback.dll; DestDir: {tmp}; Flags: dontcopy
Source: Button.png; DestDir: {tmp}; Flags: dontcopy
[_code]
type
TButtonInfo = record ButtonName: array of TButton; Handle: array of HWND; Count: Integer; end;
TBtnEventProc = procedure(h:HWND);
const
BtnClickEventID = 1;
BtnMouseEnterEventID = 2;
BtnMouseLeaveEventID = 3;
BtnMouseMoveEventID = 4;
balLeft = 0;
balCenter = 1;
var
ButtonsBuff: TButtonInfo;
HCancelButton, HNextButton, HBackButton, HDirBrowseButton, HGroupBrowseButton: HWND;
function WrapBtnCallback(Callback: TBtnEventProc; ParamCount: Integer): Longword; external 'wrapcallback@files:innocallback.dll stdcall';
function BtnCreate(hParent:HWND; Left,Top,Width,Height:integer; FileName:PChar; ShadowWidth:integer; IsCheckBtn:boolean):HWND; external 'BtnCreate@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetPosition(h:HWND; NewLeft, NewTop, NewWidth, NewHeight: integer); external 'BtnSetPosition@files:botva2.dll stdcall';
procedure BtnRefresh(h:HWND); external 'BtnRefresh@files:botva2.dll stdcall';
function BtnGetChecked(h:HWND):boolean; external 'BtnGetChecked@files:botva2.dll stdcall';
procedure BtnSetChecked(h:HWND; Value:boolean); external 'BtnSetChecked@files:botva2.dll stdcall';
procedure BtnSetText(h:HWND; Text:PAnsiChar); external 'BtnSetText@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetTextAlignment(h:HWND; HorIndent, VertIndent:integer; Alignment:DWORD); external 'BtnSetTextAlignment@files:botva2.dll stdcall';
procedure BtnSetVisibility(h:HWND; Value:boolean); external 'BtnSetVisibility@files:botva2.dll stdcall';
function BtnGetEnabled(h:HWND):boolean; external 'BtnGetEnabled@files:botva2.dll stdcall';
procedure BtnSetEnabled(h:HWND; Value:boolean); external 'BtnSetEnabled@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFont(h:HWND; Font:Cardinal); external 'BtnSetFont@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFontColor(h:HWND; NormalFontColor, FocusedFontColor, PressedFontColor, DisabledFontColor: Cardinal); external 'BtnSetFontColor@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetEvent(h:HWND; EventID:integer; Event:Longword); external 'BtnSetEvent@files:botva2.dll stdcall';
procedure BtnSetCursor(h:HWND; hCur:Cardinal); external 'BtnSetCursor@files:botva2.dll stdcall';
function GetSysCursorHandle(id:integer):Cardinal; external 'GetSysCursorHandle@files:botva2.dll stdcall';
procedure gdipShutdown; external 'gdipShutdown@files:botva2.dll stdcall';
procedure UpdateButtons();
var I: integer;
begin
for I:=0 to (ButtonsBuff.Count-1) do begin
BtnSetEnabled(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Enabled)
BtnSetVisibility(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Visible)
BtnSetText(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Caption)
BtnRefresh(ButtonsBuff.Handle[I])
end;
end;
procedure ButtonOnClick(hBtn: HWND);
var Btn: TButton; I: Integer;
begin
for I:=0 to (ButtonsBuff.Count-1) do begin
if hBtn = ButtonsBuff.Handle[I] then Btn:= ButtonsBuff.ButtonName[I];
end;
Btn.OnClick(Btn)
UpdateButtons;
end;
function EffectTextureButton(Handle: HWND; Button: TButton; ImageName: PAnsiChar; ShadowWidth: Integer; EnterEvent, MoveEvent, LeaveEvent: TbtnEventProc): HWND;
begin
Result:=BtnCreate(Handle, Button.Left-8, Button.Top-8, Button.Width+16, Button.Height+16, ImageName, ShadowWidth, False) //Размеры подобраны для текущей текстуры
BtnSetEvent(Result, BtnClickEventID, WrapBtnCallback(@ButtonOnClick, 1))
if EnterEvent <> nil then BtnSetEvent(Result, BtnMouseEnterEventID, WrapBtnCallback(EnterEvent, 1));
if MoveEvent <> nil then BtnSetEvent(Result, BtnMouseMoveEventID, WrapBtnCallback(MoveEvent, 1));
if LeaveEvent <> nil then BtnSetEvent(Result, BtnMouseLeaveEventID, WrapBtnCallback(LeaveEvent, 1));
BtnSetFont(Result, Button.Font.Handle)
BtnSetText(Result, Button.Caption);
BtnSetVisibility(Result, Button.Visible);
BtnSetFontColor(Result,clBlack,clBlack,clBlack,clGray);
BtnSetCursor(Result,GetSysCursorHandle(32649));
Button.Width:=0; Button.Height:= 0;
SetArrayLength(ButtonsBuff.Handle, ButtonsBuff.Count+1);SetArrayLength(ButtonsBuff.ButtonName, ButtonsBuff.Count+1);
ButtonsBuff.ButtonName[ButtonsBuff.Count]:= Button; ButtonsBuff.Handle[ButtonsBuff.Count]:= Result;
ButtonsBuff.Count:= ButtonsBuff.Count+1;
end;
procedure ButtonChangeFont(ButtonHandle: HWND; Font: TFont; NormalColor, FocusedColor, PressedColor, DisabledColor: Cardinal);
begin
if Font <> nil then BtnSetFont(ButtonHandle, Font.Handle);
BtnSetFontColor(ButtonHandle, NormalColor, FocusedColor, PressedColor, DisabledColor)
end;
procedure InitializeWizard();
begin
ExtractTemporaryFile('Button.png')
HNextButton:= EffectTextureButton(WizardForm.Handle, WizardForm.NextButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HCancelButton:= EffectTextureButton(WizardForm.Handle, WizardForm.CancelButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HBackButton:= EffectTextureButton(WizardForm.Handle, WizardForm.BackButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HDirBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.DirBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HGroupBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.GroupBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
end;
procedure CurPageChanged(CurPageId: Integer);
begin
UpdateButtons
end;
procedure DeinitializeSetup();
begin
gdipShutdown
end;
[/more]
alex0413
используй fairy.dll она позволяет вставлять изображения в .png .bmp .jpg форматах.
ссыль = http://rghost.ru/5030700
используй fairy.dll она позволяет вставлять изображения в .png .bmp .jpg форматах.
ссыль = http://rghost.ru/5030700
Помогите со скриптом, распаковщик не распаковывает архив, вот скрипт http://rghost.ru/17214131
Помогите, пожалуйста. Есть инсталлятор (русификатор). Во время установки он должен будет скопироваться в {app} и оттуда запуститься, но проблема в том, что он хочет в другое место распаковать файлы, а надо именно в ту же {app} и в "тихом" режиме. Может быть как-нибудь через батник? Надеюсь вы меня поняли).
SotM
Цитата:
Может вы не заметили, но после установки инсталлятор создает деинсталлятор, размер каторого большой - около 1 Мб, вот я и спрашиваю можно как-то уменьшить его размер, скажем с помощью сжатия пакером (В NSIS-е такая возвожность есть - директива !packhdr). Понимаю что NSIS и Inno Setup написаны на разных языках, но выход должен же быть?
Что касается второго вопроса. Иногда при компиляции вылетает ошибка связанная с отсутствием точки с запяпой после оператора в секции Code. Неужели вы с этим тоже не сталкивались, а? Компилятор же знает конкретно где отсутствует ;, тогда она может добавить ; без каких либо предупреждений и потом в логе написать скажем "Найдено столько ошибок, исправлено столько". Думаю, что для модификации компилятора не нужно много усилий и милионы строк кода. Мне было интерестно, именно поэтому я задал второй вопрос.
Цитата:
А теперь еще раз и по-русски:
1. "как можно сжать деинсталлятор"
2. "нельзя ли решить проблему с отсутсвующими ; как-то автоматически"
Может вы не заметили, но после установки инсталлятор создает деинсталлятор, размер каторого большой - около 1 Мб, вот я и спрашиваю можно как-то уменьшить его размер, скажем с помощью сжатия пакером (В NSIS-е такая возвожность есть - директива !packhdr). Понимаю что NSIS и Inno Setup написаны на разных языках, но выход должен же быть?
Что касается второго вопроса. Иногда при компиляции вылетает ошибка связанная с отсутствием точки с запяпой после оператора в секции Code. Неужели вы с этим тоже не сталкивались, а? Компилятор же знает конкретно где отсутствует ;, тогда она может добавить ; без каких либо предупреждений и потом в логе написать скажем "Найдено столько ошибок, исправлено столько". Думаю, что для модификации компилятора не нужно много усилий и милионы строк кода. Мне было интерестно, именно поэтому я задал второй вопрос.
Цитата:
Помогите со скриптом, распаковщик не распаковывает архив, вот скрипт http://rghost.ru/17214131
Там нужно указать какой архив именно(где он находится)и указать точное количество файлов в архиве
Denis_T
А не проще распаковать файлы из установщика (русификатора) и отдельно их скопировать в {app}? Без лишнего инсталла )))
А не проще распаковать файлы из установщика (русификатора) и отдельно их скопировать в {app}? Без лишнего инсталла )))
Здравствуйте
Интересно узнать, как сделать следующее:
В папке с игрой есть файл config.ini, и там есть строчка показывающая испольняемому файлу где находится папка datas, скажем так:
[INSTALL]
PATH=С:\Game\datas
Как реализовать чтобы инсталлятор прописывал в эту строчку куда установлена игра? Что-то вроде этого
[INSTALL]
PATH={app}\datas
Интересно узнать, как сделать следующее:
В папке с игрой есть файл config.ini, и там есть строчка показывающая испольняемому файлу где находится папка datas, скажем так:
[INSTALL]
PATH=С:\Game\datas
Как реализовать чтобы инсталлятор прописывал в эту строчку куда установлена игра? Что-то вроде этого
[INSTALL]
PATH={app}\datas
DRIFTER2592
procedure CurStepChanged(CurStep: TSetupStep);
var
path, name: String;
begin
if CurStep = ssPostInstall then begin
CreateDir(ExpandConstant('{app}\datas'))
SetIniString('PATH', 'INSTALL', ExpandConstant('{app}\datas'), ExpandConstant('{app}\config.ini'));
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
path, name: String;
begin
if CurStep = ssPostInstall then begin
CreateDir(ExpandConstant('{app}\datas'))
SetIniString('PATH', 'INSTALL', ExpandConstant('{app}\datas'), ExpandConstant('{app}\config.ini'));
end;
end;
Есть ли у кого примерчик прогрессбара с процентами на нем и остатком времени установки?
Sten23
А вот тут уже начинается гемморой. В установочнике русификатора есть команда, распаковывающая POD архивы (в BloodRayne), заменяет в них файлы и обратно запаковывает, а её я, к сожаленю, не знаю и выудить никак, так как запаролен инсталл. Хотя вопрос уже снят, я уже сделал проще.
А вот тут уже начинается гемморой. В установочнике русификатора есть команда, распаковывающая POD архивы (в BloodRayne), заменяет в них файлы и обратно запаковывает, а её я, к сожаленю, не знаю и выудить никак, так как запаролен инсталл. Хотя вопрос уже снят, я уже сделал проще.
Sergey_Demchuk
Юзай справку от Krinkels, а сколько осталось времени встроено в ISDone.
insombia
Можешь написать пример?
Юзай справку от Krinkels, а сколько осталось времени встроено в ISDone.
insombia
Можешь написать пример?
Не подскажете код добавления своего значения в определенную секцию и параметр ini-файла, где значение вписывается прямо в инсталляторе? В поиске нашел что-то подобное, не работает:
Код: [Code]
var
Page: TInputQueryWizardPage;
procedure InitializeWizard();
begin
Page := CreateInputQueryPage(wpWelcome, 'Text_1', 'Text_2', 'Text_3');
Page.Add('Name:', False);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
SetIniString('main', 'user', Page.Values[0], ExpandConstant('{app}\MyIni.ini'));
end;
Код: [Code]
var
Page: TInputQueryWizardPage;
procedure InitializeWizard();
begin
Page := CreateInputQueryPage(wpWelcome, 'Text_1', 'Text_2', 'Text_3');
Page.Add('Name:', False);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
SetIniString('main', 'user', Page.Values[0], ExpandConstant('{app}\MyIni.ini'));
end;
Цитата:
Можешь написать пример?
здесь сделана проверка файлов после распаковки архивов если их не вписать или поставить не правельно то будет идти удаление вот это строчка
/// проверка количества файлов, посли установки, если не совпадает, то выводится сообщение об ошибке и откат
if i < 708 then /// задаём количество файлов в папке, в данном случаи их 708 шт!!
я сделал архив у меня в нем 14 файлов в скрипте я поставил 14 все распаковалось нормально
P.S.Это мне подсказал vint56 так что его благодари
insombia
Не знаю где ты нашёл эту строчку, но спасибо тебе и vint56!
Не знаю где ты нашёл эту строчку, но спасибо тебе и vint56!
tema001в твоем скрипте нет проверки после распаковки
ArcExtract('{src}\data.bin', '{app}'); вот строчка для распаковки твоего архива архив должен лежать возле setup.exe и архив должен называтся data.bin это переменованый arc на bin
ArcExtract('{src}\data.bin', '{app}'); вот строчка для распаковки твоего архива архив должен лежать возле setup.exe и архив должен называтся data.bin это переменованый arc на bin
Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
Предыдущая тема: поиск
Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.