I have two #Martin Prikryl codes that I can't get them to work together.
Larger "Select Components" page in Inno Setup
Long descriptions on Inno Setup components
I followed all the instructions Martin said about the #TLama code, but the codes didn't work together.
Component captions do not appear when I activate the code to change the page height.
I would like a way to merge them and make them work together.
I solved the problem by adding the page's custom height value to the CompLabel.Top of the component captions code.
I also had to change the procedure to CurPageChanged and created an <event( ' ' )> to merge the two codes and created a directive #define CustomPageHeight "ScaleY(200)" to define the custom height of the page.
// Set page height here
#define CustomPageHeight "ScaleY(200)"
[Code]
// Final part of code for component captions
Var StopCall: Boolean;
<event('CurPageChanged')> // Added event here
Procedure CurPageChanged1(CurPageID: Integer);
Begin
If StopCall = false Then
Begin
If CurPageID = wpWelcome Then
Begin
SetTimer(0, 0, 50, CreateCallback(#HoverTimerProc));
CompLabel := TLabel.Create(WizardForm);
CompLabel.Parent := WizardForm.SelectComponentsPage;
CompLabel.Left := WizardForm.ComponentsList.Left;
CompLabel.Width := WizardForm.ComponentsList.Width;
CompLabel.Height := ScaleY(37); // Added here
CompLabel.Top := WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height + {#CustomPageHeight} - CompLabel.Height;
CompLabel.AutoSize := False;
CompLabel.WordWrap := True;
WizardForm.ComponentsList.Height := WizardForm.ComponentsList.Height - CompLabel.Height - ScaleY(2);
StopCall := true;
End;
End;
End;
// Code for custom height page
var
CompPageModified: Boolean;
<event('CurPageChanged')> // Added event here
procedure CurPageChanged2(CurPageID: Integer);
begin
if CurpageID = wpSelectComponents then
begin // Changed here
WizardForm.Height := WizardForm.Height + {#CustomPageHeight};
CompPageModified := True;
end
else
if CompPageModified then
begin // Changed here
WizardForm.Height := WizardForm.Height - {#CustomPageHeight};
CompPageModified := False;
end;
end;
Related
I am refactoring an old application to make it a bit more responsive and I have a form that is using devExpress components and it creates a custom grid using the CallbackCustomDrawPreviewCell, the problem is that this function is very slow it takes about 0.09s per call but it is call about 30 to 60 times each time the form is open so the form can take 2.8s to 5.6s to open.
I normally program with C# and Object-C/Swift where we can dispatch a block to be process in the background, but as far as my research go we don't have nothing similar in Delphi, it seems that normally in Delphi a new thread has to be a whole new and independent piece of code. Is my assumptions correct?
If so what is the best type of solution to improve speed in this kind of situation? (I am using Delphi XE)
(in case it helps: I also just bought AQTime to try help me figure out how to improve this but I had no luck so far with it, still need to dig into the manuals a little more. But it did help me find the problem in the speed in this particular callback)
Thanks in advance.
The function is:
procedure TtvdAvaOutageManagementForm.CallbackCustomDrawPreviewCell(Sender: TcxCustomTreeList; ACanvas: TcxCanvas;
AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean);
const
AlignFlag = DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX or DT_END_ELLIPSIS;
cnFontColor = clBlue;
var
AFaultId: variant;
aFault: TtvdFault;
aLocalities, aFaultLocalities: TStringList;
i: integer;
aLocality: string;
Rect: TRect;
size: TSize;
AText: string;
begin
{ colour the preview text blue }
ACanvas.Font.Color := cnFontColor;
AText := AViewInfo.DisplayValue;
aLocalities := TStringList.Create;
aFaultLocalities := TStringList.Create;
try
AFaultId := AViewInfo.Node.Values[FtvdTree.GetColumnByFieldName('FaultId').ItemIndex];
if (not VarIsNull(AFaultId)) then
begin
ACanvas.Brush.Color := COLOR_FAULT;
aFault := FtvdFaults.tvdGetFault(AFaultId);
if Assigned(aFault) then
begin
ACanvas.Brush.Color := aFault.tvdFaultColor;
ACanvas.Brush.Color := aFault.tvdFaultColor;
ACanvas.FillRect(AViewInfo.BoundsRect);
CopyRect(Rect, AViewInfo.BoundsRect);
InflateRect(Rect, -1, -1);
Inc(Rect.Left, FtvdTree.OptionsView.IndicatorWidth);
ACanvas.Font.Color := cnFontColor;
{ if all the localities are in the fault then bold the preview text,
else need to do it manually (i.e. only bold the localities that are
in the fault }
if aFault.tvdAllLocalities then
begin
ACanvas.Font.Style := [fsBold];
ACanvas.DrawTexT(AText, AViewInfo.BoundsRect, AlignFlag);
end
else
begin
CopyRect(Rect, AViewInfo.BoundsRect);
aLocalities.Text := StringReplace(AText, ', ', #13#10, [rfReplaceAll]);
aFaultLocalities.Text := StringReplace(aFault.tvdLocalities, ', ', #13#10, [rfReplaceAll]);
for i := 0 to aLocalities.Count - 1 do
begin
ACanvas.Font.Style := [];
{ draw a comma if this is not the first locality }
if i > 0 then
begin
size := ACanvas.TextExtent(',');
DrawText(ACanvas.Handle, ',', 1, Rect, DT_LEFT or DT_NOPREFIX);
Inc(Rect.Left, size.cx);
end;
aLocality := aLocalities[i];
if aFaultLocalities.IndexOf(aLocality) >= 0 then
begin
ACanvas.Font.Style := [fsBold];
end;
size := ACanvas.TextExtent(aLocality);
if (Rect.Left + size.cx) > Rect.Right then
begin
Rect.Left := AViewInfo.BoundsRect.Left;
Inc(Rect.Top, size.cy);
end;
{ draw the text item }
DrawText(ACanvas.Handle, pchar(aLocality), Length(aLocality), Rect, DT_LEFT or DT_NOPREFIX);
Inc(Rect.Left, size.cx);
end;
end;
ADone := true;
end;
end;
finally
aLocalities.Free;
aFaultLocalities.Free;
end;
end;
If you sum up my comments then it should be more or less this.
Try that at let us know how it worked out for you. Since I don't have a working example it might not be 100% correct.
procedure TtvdAvaOutageManagementForm.CallbackCustomDrawPreviewCell(Sender: TcxCustomTreeList; ACanvas: TcxCanvas;
AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean);
const
AlignFlag = DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX or DT_END_ELLIPSIS;
cnFontColor = clBlue;
var
AFaultId: variant;
aFault: TtvdFault;
aLocalities, aFaultLocalities: TStringList;
i: integer;
aLocality: string;
Rect: TRect;
size: TSize;
AText: string;
begin
{ colour the preview text blue }
ACanvas.Font.Color := cnFontColor;
AText := AViewInfo.DisplayValue;
aLocalities := TStringList.Create;
aFaultLocalities := TStringList.Create;
try
AFaultId := AViewInfo.Node.Values[FaultIdColumn.ItemIndex];
if not VarIsNull(AFaultId) then
begin
ACanvas.Brush.Color := COLOR_FAULT;
aFault := FtvdFaults.tvdGetFault(AFaultId);
if Assigned(aFault) then
begin
ACanvas.Brush.Color := aFault.tvdFaultColor;
ACanvas.Brush.Color := aFault.tvdFaultColor;
ACanvas.FillRect(AViewInfo.BoundsRect);
CopyRect(Rect, AViewInfo.BoundsRect);
InflateRect(Rect, -1, -1);
Inc(Rect.Left, FtvdTree.OptionsView.IndicatorWidth);
ACanvas.Font.Color := cnFontColor;
{ if all the localities are in the fault then bold the preview text,
else need to do it manually (i.e. only bold the localities that are
in the fault }
if aFault.tvdAllLocalities then
begin
ACanvas.Font.Style := [fsBold];
ACanvas.DrawTexT(AText, AViewInfo.BoundsRect, AlignFlag);
end
else
begin
CopyRect(Rect, AViewInfo.BoundsRect);
aLocalities.CommaText:= AText;
aFaultLocalities.CommaText := aFault.tvdLocalities;
aFaultLocalities.Sorted := True;
for i := 0 to aLocalities.Count - 1 do
begin
ACanvas.Font.Style := [];
{ draw a comma if this is not the first locality }
if i > 0 then
begin
size := ACanvas.TextExtent(',');
DrawText(ACanvas.Handle, ', ', 1, Rect, DT_LEFT or DT_NOPREFIX);
Inc(Rect.Left, size.cx);
end;
aLocality := aLocalities[i];
if aFaultLocalities.IndexOf(aLocality) >= 0 then
begin
ACanvas.Font.Style := [fsBold];
end;
size := ACanvas.TextExtent(aLocality);
if (Rect.Left + size.cx) > Rect.Right then
begin
Rect.Left := AViewInfo.BoundsRect.Left;
Inc(Rect.Top, size.cy);
end;
{ draw the text item }
DrawText(ACanvas.Handle, pchar(aLocality), Length(aLocality), Rect, DT_LEFT or DT_NOPREFIX);
Inc(Rect.Left, size.cx);
end;
end;
ADone := true;
end;
end;
finally
aLocalities.Free;
aFaultLocalities.Free;
end;
end;
I am searching for a possibility to show a user a note on how to proceed during install of a redistributable.
Background:
I have some Components that require 3rd party installations which are quit complex. If a user selects one of these components a message box with instructions are shown. After this box the resistributables are executet via exec/shellExec with 'ewWaitUntilTerminated'. Unfortunately the user cannot see the box during installation.
I tried to just open the notes in notepad and use 'ewNoWait', but than it will not close automatically after each installation of the redistributalbe. The user can chose more than one of these components and this help should only be visible during the specific installation. To kill the notepad with taskkill is not an option, it could kill opened notepad from the user.
Is there any elegant way to get such behaviour?
Create TOutputProgressWizardPage with function http://www.jrsoftware.org/ishelp/index.php?topic=isxfunc_createoutputprogresspage
function CreateOutputProgressPage(const ACaption, ADescription: String): TOutputProgressWizardPage;
[Code]
var
ProgressPage: TOutputProgressWizardPage;
procedure InitializeWizard;
begin
ProgressPage := CreateOutputProgressPage('Finalization of installation','');
end;
procedure CurPageChanged(CurPageID: Integer);
var
I: Integer;
begin
// Page is shown after installation when Finish page is shown
if CurPageID = wpFinish then begin
ProgressPage.SetText('Installing some 3rd party stuff...', '');
ProgressPage.SetProgress(0, 0);
ProgressPage.Show;
try
// Use exec/shellExec here to execute 3rd party app
// Also you can adjust progress barr position here:
for I := 0 to 10 do begin
ProgressPage.SetProgress(I, 10);
Sleep(100);
end;
finally
ProgressPage.Hide;
end;
end else
Result := True;
end;
I finally found a solution for my problem. On the basis of the answer of Slappy I used a std MsgPage and resize it for my need. Thx to TLama for his answer in a different topic for the resize code!
[Code]
var
RedistPage: TOutputMsgWizardPage;
DefaultTop,
DefaultLeft,
DefaultHeight,
DefaultBackTop,
DefaultNextTop,
DefaultCancelTop,
DefaultBevelTop,
DefaultBeveledLabelTop,
DefaultInnerHeight,
DefaultOuterHeight: Integer;
procedure InitializeWizard();
var
ReadMe: AnsiString;
begin
DefaultTop := WizardForm.Top;
DefaultLeft := WizardForm.Left;
DefaultHeight := WizardForm.Height;
DefaultBackTop := WizardForm.BackButton.Top;
DefaultNextTop := WizardForm.NextButton.Top;
DefaultCancelTop := WizardForm.CancelButton.Top;
DefaultBevelTop := WizardForm.Bevel.Top;
DefaultBeveledLabelTop := WizardForm.BeveledLabel.Top;
DefaultOuterHeight := WizardForm.OuterNotebook.Height;
DefaultInnerHeight := WizardForm.InnerNotebook.Height;
// save the contents of Readme.txt (non Unicode) in a string and build custom page
try
ExtractTemporaryFiles('{tmp}\readme.txt');
if LoadStringFromFile(ExpandConstant('{tmp}\readme.txt'), ReadMe) then
RedistPage := CreateOutputMsgPage(wpReady,
'Information', 'Please read the following important information about the installation before continuing.',ReadMe);
except
ShowExceptionMessage;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := False; // initialize result to not skip any page (not necessary, but safer)
if PageID = RedistPage.ID then // if the page that is asked to be skipped is your custom page, then...
Result := not IsTaskSelected('dexela_API'); // if the task is not selected, skip the page
end;
procedure ChangePageSize(HeightOffset: Integer);
begin
WizardForm.Top := DefaultTop - (HeightOffset - DefaultHeight) div 2;
WizardForm.Height := WizardForm.Height + (HeightOffset - DefaultHeight);
WizardForm.InnerPage.Height := WizardForm.InnerPage.Height + (HeightOffset - DefaultHeight);
WizardForm.InnerNotebook.Height := WizardForm.InnerNotebook.Height + (HeightOffset - DefaultHeight);
WizardForm.OuterNotebook.Height := WizardForm.OuterNotebook.Height + (HeightOffset - DefaultHeight);
WizardForm.CancelButton.Top := DefaultCancelTop + (HeightOffset - DefaultHeight);
WizardForm.NextButton.Top := DefaultNextTop + (HeightOffset - DefaultHeight);
WizardForm.BackButton.Top := DefaultBackTop + (HeightOffset - DefaultHeight);
WizardForm.Bevel.Top := DefaultBevelTop + (HeightOffset - DefaultHeight);
end;
procedure CurPageChanged(CurPageID: Integer);
var
ComponentsPageTextHeight: Integer;
begin
if (CurPageID = RedistPage.ID) and (IsTaskSelected('dexela_API'))then begin
ChangePageSize(650);
//Sleep(2000); // time for the user to recognize the text, before it is hidden by installer
// Extract all Dexela files and launch them.
try
ExtractTemporaryFiles('{tmp}\Setup.msi');
except
ShowExceptionMessage;
end;
ShellExec('',ExpandConstant('{tmp}\Setup.msi'), '', '',SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
end;
i Was Created one setup for slide show code is perfectly running as you given. But the images are flipping with in short span of time. So in between images i want to set timer so that i can able to see those images clearly. Is that possible ? if possible how to do please help me to do that
[code]
function InitializeSetup: Boolean;
begin
ExtractTemporaryFile('01.bmp');
ExtractTemporaryFile('02.bmp');
Result := True;
end;
procedure CurPageChanged(CurPageID: Integer);
var
BmpFile1, BmpFile2: TBitmapImage;
begin
if CurPageID = wpInstalling then begin
msgbox ('1. where are you' , mbinformation,mb_ok);
BmpFile1:= TBitmapImage.Create(WizardForm);
BmpFile1.Bitmap.LoadFromFile(ExpandConstant('{tmp}\01.bmp'));
BmpFile1.Width:= ScaleX(976);
// here you set Width (417px is Width of ProgressBar) for 1st BMP
BmpFile1.Height:= ScaleY(80);
// here you set Height for 1st BMP
BmpFile1.Stretch := True;
BmpFile1.Left := WizardForm.ProgressGauge.Left + ScaleX(0);
// here you set Left position for 1st BMP
BmpFile1.Top := WizardForm.ProgressGauge.Top + ScaleY(35);
// here you set Top posision for 1st BMP
BmpFile1.Parent:= WizardForm.InstallingPage;
BmpFile2:= TBitmapImage.Create(WizardForm);
BmpFile2.Bitmap.LoadFromFile(ExpandConstant('{tmp}\02.bmp'));
BmpFile2.Width:= ScaleX(976);
BmpFile2.Height:= ScaleY(80);
BmpFile2.Stretch := True;
BmpFile2.Left := WizardForm.ProgressGauge.Left + ScaleX(0);
BmpFile2.Top := BmpFile1.Top + BmpFile1.Height + ScaleY(8);
BmpFile2.Parent:= WizardForm.InstallingPage;
end;
end;
I'm creating a setup using Inno Setup, and I changed license page to not show license, but to link to it instead. I also added a StaticText to show some text, and the problem is that when I add too much text, I need WordWrap := true, and AutoSize := false, and this makes StaticText width in Setup created really small. Why it is sized if AutoSize = false? What to do to prevent it from minimizing when WordWrap = true. Change parent?
procedure InitializeWizard;
var
FormButton: TNewButton;
Page: TWizardPage;
ComboBox: TNewComboBox;
begin
WizardForm.LicenseAcceptedRadio.Hide;
WizardForm.LicenseNotAcceptedRadio.Hide;
LicenseContextText := TNewStaticText.Create(WizardForm.InnerPage);
with LicenseContextText do
begin
Parent := WizardForm.InnerPage;
//TODO: check if we need
Left := ScaleX(250);
Top := ScaleY(50);
Height := ScaleY(100);
Width := ScaleX(1000); //200;
//Color := clBlack;
Font.Color := clGray;
//WordWrap := true;
//AutoSize := false;
Caption := 'Some content text, Some content text, Some content text';//
Visible := false;
end;
LicenseLinkLabel := TNewStaticText.Create(WizardForm.InnerPage);
with LicenseLinkLabel do
begin
Parent := WizardForm.InnerPage;
//TODO: check if we need
Left := 340;
Top := 240;
Height := 100;
Cursor := crHand;
Font.Color := clBlue;
Font.Style := [fsUnderline];
Caption := 'the License Agreement';
OnClick := #LicenseLinkLabelClick;
Visible := false;
end;
LicenseLinkURL := TNewCheckBox.Create(WizardForm.InnerPage);
with LicenseLinkURL do
begin
Parent := WizardForm.InnerPage;
Left := 277;
Top := 238;
Width := 60;
Caption := ' I accept';
OnClick := #OnLicenseCheckBoxClick;
Visible := false;
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if (CurPageID = wpLicense) then
begin
WizardForm.Bevel1.Visible := false;
WizardForm.MainPanel.Visible := false;
WizardForm.InnerNotebook.Visible := false;
LicenseLinkLabel.Visible := true;
LicenseLinkURL.Visible := true;
LicenseContextText.Visible := true;
Set the AutoSize and WordWrap properties before you set the Width and Height properties.
This is unrelated, but also rather than hard-coding specific values for the sizes you might want to consider using sizes relative to existing elements in the WizardForm, to eg. have it automatically fit to the width of the page area within the form.
How to change the Next/Cancel button captions on a custom page ?
You can use:
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = YourPageName.ID then begin
WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall);
//or := 'YourNewNextButtonText' or := ExpandConstant('{cm:YourCmTitleForNext}')
WizardForm.CancelButton.Caption := ExpandConstant('{cm:YourCmTitleForCancel}');
end; //begin + end to make changes only for this single page
end;