Да, я сразу протестировал свойства Offset и, написав "не дало результата", я собственно и имел ввиду, что Мне это не чего не дает именно относительно ожидаемого мной результата. Позвольте еще немного вас помучить своими вопросами, выше на форуме давали [more= код][Setup]
AppName=Components Descriptions
AppVerName=Components Descriptions
CreateAppDir=false
[Languages]
Name: ru; MessagesFile: compiler:Languages\Russian.isl
[Types]
Name: tweak; Description: Оптимальный выбор
Name: full; Description: Выбрать все компоненты
Name: deselect; Description: Сбросить все компоненты
Name: custom; Description: Пользовательский режим; Flags: iscustom
[Components]
Name: Safe; Description: Параметры безопасности; Types: deselect
Name: Safe\wscsvc; Description: Отключить 'Центр обеспечения безопасности'; Types: full tweak
Name: Safe\Signing; Description: Разрешить установку неподписанных драйверов; Types: full
Name: WB; Description: 'Мой компьютер' - Настройки; Types: deselect
Name: WB\Computer; Description: Добавить ярлыки - Корзина, Сетевые подключения; Types: full tweak
Name: WB\Low; Description: Уведомление о недостатке свободного места на диске
Name: WB\Low\1; Description: Изменить порог срабатывания с 10 % до 1%; Flags: exclusive; Types: tweak
Name: WB\Low\No; Description: Не предупреждать о переполнении дисков; Flags: exclusive; Types: full
Name: IE; Description: Настройки обозревателя Internet Explorer; Types: deselect
Name: IE\Cache; Description: Временные файлы Internet - использовать сжатие; Types: full tweak
Name: User; Description: Параметры входа в систему
Name: User\Logon; Description: Пользователи - использовать страницу приветствия; Flags: exclusive; Types: full
Name: User\Logon2K; Description: Классический вид - выводить запрос имени и пароля; Flags: exclusive; Types: tweak
Name: User\Autologon; Description: Задействовать автоматический вход в систему; Types: full tweak
Name: User\Sound; Description: Не сопровождать звуком загрузку и завершение работы; Types: full
Name: User\English; Description: Английский язык ввода по умолчанию для всех; Types: full
Name: Sys; Description: Настройки системы и оборудования; Types: deselect
Name: Sys\Memory; Description: Память - оптимизировать работу ядра Windows
Name: Sys\Memory\1024; Description: 1024Мб физической памяти на этом компьютере; Flags: exclusive
Name: Sys\Timeout; Description: Разрешить быстрое завершение работы; Types: full tweak
[Files]
Source: compiler:descctrl.dll; Flags: dontcopy
; скачать библиотеку descctrl.dll (6 кб) можно здесь:
http://victor-dobrov.narod.ru/inno_descctrl.7z [_Code]
var Point: TPoint; CompDesc: TEdit; MessageForm: TForm; MessagePanel: TPanel; MessageLabel: TLabel; n, frame: integer; CompUpKey: Boolean; Descriptions: String; Messages: array of String;
function EnableDesc(ComponentsListHandle, DescLabelHandle: HWND; DescStrings: PChar): BOOL; external 'enabledesc@files:descctrl.dll stdcall';
function disabledesc(): BOOL; external 'disabledesc@files:descctrl.dll stdcall';
procedure GetCursorPos(var Point: TPoint); external 'GetCursorPos@user32 stdcall delayload';
function SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, wFlags: Longint):Boolean; external 'SetWindowPos@user32.dll stdcall';
function ExtractIcon(hInst: LongInt; lpszExeFileName: PChar; nIconIndex: LongInt): LongInt; external 'ExtractIconA@shell32 stdcall delayload';
function DrawIconEx(hdc, x, y, hIcon, cx, cy, AniCur, Draw, Flags: Longint): Longint; external 'DrawIconEx@user32 stdcall delayload';
function GetModuleHandle(lpModuleName: LongInt): LongInt; external 'GetModuleHandleA@kernel32 stdcall delayload';
Procedure DrawIcon(Form: TWinControl; File: String; nIcon, Left, Top, Size, BColor: Integer); var Panel: TPanel; Rect: TRect; Begin
Panel:= TPanel.Create(Form); Panel.SetBounds(Left, Top, Size, Size); Panel.Parent:= Form
with TBitmapImage.Create(Panel) do begin Parent:= Panel; with Bitmap do begin
Width:= Size; Height:= Size; Rect.Right:= Size; Rect.Bottom:= Size; Canvas.Brush.Color:= BColor; Canvas.FillRect(Rect);
DrawIconEx(Canvas.Handle, 0,0, ExtractIcon(GetModuleHandle(0), ExpandConstant(File), nIcon), Size, Size,0,0,3); end; end;
End;
Function StringToArray(Text, Cut: String): array of String; var t, i, k: Integer; Begin { создать массив из текста}
Repeat SetArrayLength(Result, GetArrayLength(Result) + 1); t:= 1; k:= Pos(Cut, Text); if k > 0 then t:= Length(Cut) else k:= Pos(#10, Text); i:= GetArrayLength(Result) - 1;
if k > 0 then begin Result[i]:= Copy(Text, 1, k - 1); Text:= Copy(Text, k + t, Length(Text)) end else begin Result[i]:= Text; SetLength(Text, 0) end;
Until Length(Text) = 0
End;
Procedure ResizeLabel(Obj: TLabel; Text: String; MaxWidth: Integer); var k, w, h: integer; Begin { размер формы подгоняется под текст}
Obj.AutoSize:= true; Obj.WordWrap:= false; Obj.Caption:= Text; { авторазмер}
w:= Obj.Width; h:= Obj.Height; n:= (w + frame*2)/MaxWidth + 1
Repeat
Obj.Width:= w/n + frame*2*n + k
Obj.Height:= h * n
Obj.WordWrap:= true; k:= k + 4
Until Obj.Height/h = n
End;
Procedure ShowHint(String: string; AIndex: Integer; XCenter, YCenter: Bool); Begin { размер формы подгоняется под текст, если AIndex = 0, значок не рисуется}
frame:= 10; if AIndex <> 0 then String:= ' '+ String;
GetCursorPos(Point); MessageLabel.Left:= frame; MessageLabel.Top:= frame
ResizeLabel(MessageLabel, String, WizardForm.ClientWidth)
if XCenter then Point.X:= WizardForm.Left + WizardForm.Width/2 - (MessageLabel.Width + frame*2 -2)/2 else Point.X:= Point.X + 12;
if YCenter then Point.Y:= WizardForm.Top + WizardForm.BeveledLabel.Top else Point.Y:= Point.Y + 12;
MessageForm.SetBounds(Point.X, Point.Y, MessageLabel.Width + frame*2 -2, MessageLabel.Height + frame*2 -2)
if AIndex <> 0 then DrawIcon(MessageForm, '{sys}\shell32.dll', AIndex, 9, 8, 16, MessagePanel.Color);
MessageForm.Show; SetWindowPos(MessageForm.Handle, -1, 0, 0, 0, 0, 3);
End;
Procedure CompKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); Begin
CompUpKey:= true
n:= WizardForm.ComponentsList.ItemIndex
if n >= 0 then ShowHint(Messages[n], -1001, true, true) else MessageForm.Hide;
End;
Procedure ObjectOnClick(Sender: TObject);
Begin
Case TObject(Sender) of { событие объекта}
CompDesc:
if CompDesc.Text > '' then
if CompUpKey then CompUpKey:= false else ShowHint(CompDesc.Text, -1001, false, false)
else MessageForm.Hide;
MessageForm:
WizardForm.BringToFront;
end;
End;
Procedure DeinitializeSetup();
Begin
disabledesc();
End;
Procedure CurStepChanged(CurStep: TSetupStep);
Begin
if CurStep = ssInstall then disabledesc;
End;
Procedure CurPageChanged(CurPageID: Integer);
Begin
if CurPageID = wpSelectComponents then enableDesc(WizardForm.ComponentsList.Handle,CompDesc.Handle,Descriptions) else MessageForm.Hide;
End;
Procedure InitializeWizard;
Begin
CompDesc:= TEdit.Create(WizardForm)
CompDesc.Parent:= WizardForm
CompDesc.Visible:= false
CompDesc.OnChange:= @ObjectOnClick
MessageForm:= CreateCustomForm;
MessageForm.BorderStyle:= bsNone
MessageForm.OnActivate:= @ObjectOnClick
MessagePanel:= TPanel.Create(MessageForm)
MessagePanel.BevelInner:= bvLowered;
MessagePanel.Align:= alClient;
MessagePanel.Color:= $E1FFFF;
MessagePanel.Parent:= MessageForm
MessageLabel:= TLabel.Create(MessagePanel)
MessageLabel.Transparent:= true
MessageLabel.Font.Name:= 'Arial'
MessageLabel.Font.Size:= WizardForm.Font.Size + 1
MessageLabel.Parent:= MessagePanel
WizardForm.ComponentsList.OnKeyUp:= @CompKeyUp
Descriptions:=
'Демонстрационный режим. Действия по изменению настроек системы или параметров безопасности не выполняются. Компоненты и их описания даны только для примера. Описания отделяются друг от друга точкой с запятой и должны содержать не более 255 символов.;' +
'Отключить «Центр обеспечения безопасности» (рекомендуется отключить эту практически бесполезную службу);' +
'Разрешить установку неподписанных драйверов (упрощает настройку компьютера сразу после установки системы);' +
'«Мой компьютер» - Секция настроек, влияющих на работу компьютера;' +
'ярлыки Корзина и Сетевые подключения будут созданы в папке «Мой компьютер»;' +
'Изменить порог срабатывание уведомления о недостатке свободного места на диске;' +
'Изменить порог срабатывания с 10 % (значение по-умолчанию) до 1% (необходимо для дисков большой ёмкости);' +
'Выдача всплывающей подсказки о переполнении дисков будет отключена;' +
'Общие настройки обозревателя Internet Explorer;' +
'Папка временных файлов Internet Explorer будет сжата средствами файловой системы NTFS;' +
'Параметры входа в систему;' +
'Пользователи - использовать страницу приветствия (новый экран загрузки, появившийся в Windows XP);' +
'Классический вид - выводить запрос имени и пароля (экран загрузки, использующийся в Windows 2000);' +
'Задействовать автоматический вход в систему для текущего пользователя без запроса имени и пароля;' +
'Не сопровождать звуком загрузку и завершение работы (немного ускоряет загрузку «Рабочего стола»);' +
'Английский язык ввода по умолчанию для всех (для новых пользователей);' +
'Настройка системы на имеющийся объём оперативной памяти и процессорного кэша, оптимизация файловой подсистемы;' +
'После установке данной опции уменьшать объём оперативной памяти НЕЖЕЛАТЕЛЬНО;' +
'Вычисленный объём установленной физической памяти на этом компьютере;' +
'Разрешить быстрое завершение работы (сетевые соединения могут быть разорваны преждевременно)';
Messages:= StringToArray(Descriptions,';')
End;[/more] о компонентах, где всплывают подсказки при навиденнии курсора мышки, как в Виндовс, если с вашим [more=кодом][Setup]
AppName=My Program
AppVerName=My Program v.1.2
DefaultDirName={pf}\My Program
[Files]
Source: Files\*; DestDir: {app}
[_Code]
const
bidDelAll = 1;
bidSkipAll = 2;
var
Form: TSetupForm;
CheckListBox: TNewCheckListBox;
AllButton, UnAllButton: TButton;
CancelButton, DelButton: TButton;
StaticText: TNewStaticText;
MsgForm: TSetupForm;
MsgAllButton, MsgSkipAllButton: TButton;
MsgCancelButton, MsgDelButton: TButton;
DelAllReadOnly: Boolean;
SkipAllReadOnly: Boolean;
CheckDirs, CheckFiles: Boolean;
function Size64(Hi, Lo: integer): Extended;
var
i: integer;
begin
Result:= Lo;
if Lo < 0 then
Result:= Result + 2147483647 + 2147483647 + 2;
i:= Hi;
while i > 0 do
begin
Result:= Result + 2147483647 + 2147483647 + 2;
i:= i - 1;
end;
end;
procedure FillListBox(const fromDir, fileMask: string; Level: Byte);
var
FSR, DSR: TFindRec;
FindResult: Boolean;
APath: string;
i: integer;
begin
APath := AddBackslash(fromDir);
FindResult := FindFirst(APath + fileMask, FSR);
try
while FindResult and CheckFiles do
begin
if FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
{files} i:= CheckListBox.AddCheckBox(FSR.Name,
FloatToStr(Size64(FSR.SizeHigh, FSR.SizeLow)) + ' byte',
Level, True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[i]).Text:= APath + FSR.Name;
end;
FindResult := FindNext(FSR);
end;
FindResult := FindFirst(APath + '*.*', DSR);
while FindResult and CheckDirs do
begin
CheckFiles:= True;
if ((DSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) and
not ((DSR.Name = '.') or (DSR.Name = '..')) then
begin
{dir} i:= CheckListBox.AddCheckBox(DSR.Name,'DIR', Level,
True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[i]).Text:= APath + DSR.Name;
{Recursion} FillListBox(APath + DSR.Name, fileMask, Level+1);
end;
FindResult := FindNext(DSR);
end;
finally
FindClose(FSR);
FindClose(DSR);
end;
end;
procedure ButtonOnClick(Sender: TObject);
begin
if TButton(Sender).Tag = 0 then
CheckListBox.CheckItem(0, coCheckWithChildren)
else
CheckListBox.CheckItem(0, coUnCheck);
end;
procedure MsgButtonOnClick(Sender: TObject);
begin
Case TButton(Sender).Tag of
bidDelAll : DelAllReadOnly:= True;
bidSkipAll: SkipAllReadOnly:= True;
end;
MsgForm.Close;
end;
function DelMsgBox(FileName: string): Boolean;
var
MsgLabel: TLabel;
begin
MsgForm:= CreateCustomForm;
MsgForm.ClientWidth := ScaleX(400);
MsgForm.ClientHeight := ScaleY(120);
MsgForm.Caption := 'Files to delete';
MsgForm.Center;
MsgLabel := TLabel.Create(MsgForm);
MsgLabel.Left := ScaleX(20);
MsgLabel.Top := ScaleY(20);
MsgLabel.Caption:= FileName + ' is protected file or directory!' + #10#10#13 + 'Do you want to delete the file with READONLY attribute?';
MsgLabel.Parent := MsgForm;
MsgAllButton := TButton.Create(MsgForm);
MsgAllButton.Parent := MsgForm;
MsgAllButton.Width := ScaleX(75);
MsgAllButton.Height := ScaleY(23);
MsgAllButton.Left := ScaleX(20);
MsgAllButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgAllButton.Caption := 'Delete All';
MsgAllButton.Tag:= bidDelAll;
MsgAllButton.OnClick := @MsgButtonOnClick;
MsgSkipAllButton := TButton.Create(MsgForm);
MsgSkipAllButton.Parent := MsgForm;
MsgSkipAllButton.Width := ScaleX(75);
MsgSkipAllButton.Height := ScaleY(23);
MsgSkipAllButton.Left := MsgAllButton.Left + MsgAllButton.Width + ScaleX(10);
MsgSkipAllButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgSkipAllButton.Caption := 'Skip All';
MsgSkipAllButton.Tag:= bidSkipAll;
MsgSkipAllButton.OnClick := @MsgButtonOnClick;
MsgCancelButton := TButton.Create(MsgForm);
MsgCancelButton.Parent := MsgForm;
MsgCancelButton.Width := ScaleX(75);
MsgCancelButton.Height := ScaleY(23);
MsgCancelButton.Left := MsgForm.ClientWidth - MsgCancelButton.Width - ScaleX(20);
MsgCancelButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgCancelButton.Caption := 'Skip';
MsgCancelButton.ModalResult := mrCancel;
MsgDelButton := TButton.Create(MsgForm);
MsgDelButton.Parent := MsgForm;
MsgDelButton.Width := ScaleX(75);
MsgDelButton.Height := ScaleY(23);
MsgDelButton.Left := MsgCancelButton.Left - MsgDelButton.Width - ScaleX(10);
MsgDelButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgDelButton.Caption := 'Delete';
MsgDelButton.ModalResult := mrOk;
MsgForm.ActiveControl:= MsgCancelButton;
if MsgForm.ShowModal() = mrOk then
Result:= True
else
Result:= False;
end;
procedure DeleteFiles();
var
SR: TFindRec;
i: integer;
str: string;
ResultCode: Integer;
begin
DelAllReadOnly:= False;
SkipAllReadOnly:= False;
for i:= CheckListBox.Items.Count - 1 downto 0 do
begin
if CheckListBox.State[i] = cbChecked then
begin
str:= Trim(TStrings(CheckListBox.ItemObject[i]).Text);
FindFirst(str, SR);
if ((SR.Attributes and FILE_ATTRIBUTE_READONLY) = FILE_ATTRIBUTE_READONLY) then
if Not (DelAllReadOnly or SkipAllReadOnly) then
if DelMsgBox(SR.Name) then
Exec('attrib', ' -h -s -r ' + '"' + str + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
if DelAllReadOnly then
Exec('attrib', ' -h -s -r ' + '"' + str + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
FindClose(SR);
DeleteFile(str);
RemoveDir(str);
end;
end;
end;
procedure BrowseRemainedFiles();
begin
Form:= CreateCustomForm;
Form.ClientWidth := ScaleX(400);
Form.ClientHeight := ScaleY(400);
Form.Caption := 'Files to delete';
Form.Center;
StaticText := TNewStaticText.Create(Form);
StaticText.Left:= ScaleX(20);
StaticText.Top := ScaleY(8);
StaticText.Caption := 'Some elements could not be removed.' + #10#13 +
'These can be removed manually.' + #10#13#13 +
'Choose which are necessary to delete' + #10#13 +
'or press Cancel button.';
StaticText.Font.Color:= clBlue;
StaticText.Font.Style:= [fsBold];
StaticText.AutoSize := True;
StaticText.Parent := Form;
CheckListBox := TNewCheckListBox.Create(Form);
CheckListBox.Left:= ScaleX(20);
CheckListBox.Top:= ScaleY(20);
CheckListBox.Width:= Form.ClientWidth - ScaleX(20*2);
CheckListBox.Height:= Form.ClientHeight - ScaleY(23*2 + 20);
// CheckListBox.Offset:= 0;
CheckListBox.Parent:= Form;
AllButton := TButton.Create(Form);
AllButton.Parent := Form;
AllButton.Width := ScaleX(75);
AllButton.Height := ScaleY(23);
AllButton.Left := ScaleX(20);
AllButton.Top := Form.ClientHeight - ScaleY(23 + 10);
AllButton.Caption := 'Select All';
AllButton.Tag:= 0;
AllButton.OnClick := @ButtonOnClick;
UnAllButton := TButton.Create(Form);
UnAllButton.Parent := Form;
UnAllButton.Width := ScaleX(75);
UnAllButton.Height := ScaleY(23);
UnAllButton.Left := AllButton.Left + AllButton.Width + ScaleX(10);
UnAllButton.Top := Form.ClientHeight - ScaleY(23 + 10);
UnAllButton.Caption := 'Clear All';
UnAllButton.Tag:= 1;
UnAllButton.OnClick := @ButtonOnClick;
CancelButton := TButton.Create(Form);
CancelButton.Parent := Form;
CancelButton.Width := ScaleX(75);
CancelButton.Height := ScaleY(23);
CancelButton.Left := Form.ClientWidth - CancelButton.Width - ScaleX(20);
CancelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
CancelButton.Caption := 'Cancel';
CancelButton.ModalResult := mrCancel;
CancelButton.Cancel := True;
DelButton := TButton.Create(Form);
DelButton.Parent := Form;
DelButton.Width := ScaleX(75);
DelButton.Height := ScaleY(23);
DelButton.Left := CancelButton.Left - DelButton.Width - ScaleX(10);
DelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
DelButton.Caption := 'Delete';
DelButton.ModalResult := mrOk;
Form.ActiveControl:= CancelButton;
CheckListBox.AddCheckBox(ExpandConstant('{app}'), '', 0, True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[0]).Text:= ExpandConstant('{app}');
CheckDirs:= True;
FillListBox(ExpandConstant('{app}'), '*', 1);
CheckDirs:= False;
FillListBox(ExpandConstant('{app}'), '*', 1);
if Form.ShowModal() = mrOk then DeleteFiles();
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if DirExists(ExpandConstant('{app}')) and (CurUninstallStep = usPostUninstall) then
BrowseRemainedFiles();
end;[/more] сделать то же самое, то это будет, на мой взгляд, даже еще лучше. Сам я точно не перенесу. В программе, для которой мне нужен этот код создается 4 (четыре) одинаково длинных и без пробела файла, реально из них нужен только один и определить его можно только по расширению.
А по второму вопросу, не знаю как другие, но мне удобней и Привычней когда папки сверху, я проверил у меня во всех программах папки сверху. Я по этому и задал этот вопрос по тому, что мне было не удобно в первоначальном варианте.
Добавлено: Genri