; ////////////////////////////////////////////////////////////
; // Graphical Installer for Inno Setup //
; // Version 3.9.01 (Radka) //
; // Copyright (c) 2011 - 2016 unSigned, s. r. o. //
; // www.unsigned.sk www.graphical-installer.com //
; // customers@unsigned.sk //
; // All Rights Reserved. //
; ////////////////////////////////////////////////////////////
; This file contains core drawing functions and procedures
; Do not modify this file manually!
; Defines for
WinAPI functions
; ProgressBar
#ifndef PBM_SETBARCOLOR
#define PBM_SETBARCOLOR 0x0409
#endif
#ifndef PBM_SETBKCOLOR
#define PBM_SETBKCOLOR 0x2001
#endif
[ Code ]
{ Constants, Types and Enumerators }
const
{ Maximum pages allowed in installer }
coMaxPageCount = 30; // Usually installer uses 15 pages so 30 should be enough for everybody :)
{ Default DPI: Zoom 100%. DPI below 96 is not supported! }
coDefaultDPI = 96;
{ Maximum custom created buttons }
coMaxButtons = 10;
{ WizardForm dimensions - images properties [in pixels for 96 DPI - 100% zoom] }
coBackgroundWidth = 690;
coBackgroundHeight = 496;
coTopWidth = 413;
coInnerLeftTop = 0;
coInnerWidth = 417;
coInnerHeight = 237;
coBottomPosition = 413;
coBottomWidth = 83;
{ Button properties [in pixels for 96 DPI - 100% zoom] }
coButtonMaxPath = 1024; // Characters
coButtonWidth = 80; // Pixels
coButtonHeight = 34; // Pixels
coButtonShadow = 0; // Pixels [not scaled]
{ Button events }
ButtonClickEventID = 1;
ButtonMouseEnterEventID = 2;
ButtonMouseLeaveEventID = 3;
ButtonMouseMoveEventID = 4;
BtnMouseDownEventID = 5;
BtnMouseUpEventID = 6;
{ Button text alignment }
balLeft = 0;
balCenter = 1;
balRight = 2;
balVCenter = 4;
type
#ifndef
UNICODE
AnsiChar = Char;
#endif
{ Button procedure }
TButtonEventProc = procedure(
Handle: HWND);
TTextBuf = array [0..coButtonMaxPath-1] of AnsiChar;
{ Miscellaneous routines from DLLs }
function GetSysCursorHandle(id: Integer): Cardinal; external 'GetSysCursorHandle@{tmp}\botva2.dll stdcall delayload';
procedure GdiPlusShutdown; external 'gdipShutdown@{tmp}\botva2.dll stdcall delayload';
function WrapButtonCallback(Callback: TButtonEventProc; ParamCount: Integer): Longword; external 'wrapcallback@{tmp}\InnoCallback.dll stdcall delayload';
{ For ProgressBar }
function SetWindowTheme(
Handle: HWND; pszSubAppName, pszSubIdList: PAnsiChar): Integer; external 'SetWindowTheme@UxTheme.dll stdcall';
function ArrayOfAnsiCharToAnsiString(ansiCharsBuffer: TTextBuf): AnsiString;
var
i: Integer;
begin
i := 0;
Result := '';
while ansiCharsBuffer[i] <> #0 do
begin
Result := Result + ansiCharsBuffer[i];
i := i + 1;
end;
end;
{ Button routines from DLLs }
function ButtonCreate(hParent: HWND; Left, Top, Width, Height: Integer; FileName: PAnsiChar; ShadowWidth: Integer; IsCheckButton: Boolean): HWND; external 'BtnCreate@{tmp}\botva2.dll stdcall delayload';
{ Supported formats: jpg, png, gif, tif, bmp }
function ButtonGetEnabled(h: HWND): Boolean; external 'BtnGetEnabled@{tmp}\botva2.dll stdcall delayload';
function ButtonGetChecked(h: HWND): Boolean; external 'BtnGetChecked@{tmp}\botva2.dll stdcall delayload';
function ButtonGetTextAsCharArray(h: HWND; var Text: TTextBuf): Integer; external 'BtnGetText@{tmp}\botva2.dll stdcall delayload';
function ButtonGetText(hButton: HWND): AnsiString;
var
buffer: TTextBuf;
begin
ButtonGetTextAsCharArray(hButton, buffer);
Result := ArrayOfAnsiCharToAnsiString(buffer);
end;
function ButtonGetVisibility(h: HWND): Boolean; external 'BtnGetVisibility@{tmp}\botva2.dll stdcall delayload';
procedure ButtonGetPosition(h: HWND; var Left, Top, Width, Height: Integer); external 'BtnGetPosition@{tmp}\botva2.dll stdcall delayload';
procedure ButtonRefresh(h: HWND); external 'BtnRefresh@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetCursor(h: HWND; hCur: Cardinal); external 'BtnSetCursor@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetEnabled(h: HWND; Value: Boolean); external 'BtnSetEnabled@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetEvent(h: HWND; EventID: Integer; Event: Longword); external 'BtnSetEvent@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetFont(h: HWND; Font: Cardinal); external 'BtnSetFont@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetFontColor(h: HWND; NormalFontColor, FocusedFontColor, PressedFontColor, DisabledFontColor: Cardinal); external 'BtnSetFontColor@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetChecked(h: HWND; Value: Boolean); external 'BtnSetChecked@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetPosition(h: HWND; NewLeft, NewTop, NewWidth, NewHeight: Integer); external 'BtnSetPosition@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetText(h: HWND; Text: PAnsiChar); external 'BtnSetText@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetTextAlignment(h: HWND; HorIndent, VertIndent: Integer; Alignment: DWORD); external 'BtnSetTextAlignment@{tmp}\botva2.dll stdcall delayload';
procedure ButtonSetVisibility(h: HWND; Value: Boolean); external 'BtnSetVisibility@{tmp}\botva2.dll stdcall delayload';
{ Image routines from DLLs }
function ImgLoad(h: HWND; FileName: PAnsiChar; Left, Top, Width, Height: Integer; Stretch, IsBackground: Boolean): Longint; external 'ImgLoad@{tmp}\botva2.dll stdcall delayload';
{ Supported formats: jpg, png, gif, tif, bmp }
procedure ImgSetVisiblePart(image: Longint; NewLeft, NewTop, NewWidth, NewHeight: Integer); external 'ImgSetVisiblePart@{tmp}\botva2.dll stdcall delayload';
procedure ImgGetVisiblePart(image: Longint; var Left, Top, Width, Height: Integer); external 'ImgGetVisiblePart@{tmp}\botva2.dll stdcall delayload';
procedure ImgSetPosition(image: Longint; NewLeft, NewTop, NewWidth, NewHeight: Integer); external 'ImgSetPosition@{tmp}\botva2.dll stdcall delayload';
procedure ImgGetPosition(image: Longint; var Left, Top, Width, Height: Integer); external 'ImgGetPosition@{tmp}\botva2.dll stdcall delayload';
procedure ImgSetVisibility(image: Longint; Visible: boolean); external 'ImgSetVisibility@{tmp}\botva2.dll stdcall delayload';
function ImgGetVisibility(image: Longint): boolean; external 'ImgGetVisibility@{tmp}\botva2.dll stdcall delayload';
procedure ImgSetTransparent(image: Longint; Value: Integer); external 'ImgSetTransparent@{tmp}\botva2.dll stdcall delayload';
function ImgGetTransparent(image: Longint): Integer; external 'ImgGetTransparent@{tmp}\botva2.dll stdcall delayload';
procedure ImgRelease(image: Longint); external 'ImgRelease@{tmp}\botva2.dll stdcall delayload';
procedure ImgApplyChanges(h: HWND); external 'ImgApplyChanges@{tmp}\botva2.dll stdcall delayload';
{ Global variables }
var
ButtonFont: TFont;
DPI: Integer;
swButtonNormalColor: TColor;
swButtonFocusedColor: TColor;
swButtonPressedColor: TColor;
swButtonDisabledColor: TColor;
swTextsColor, swHeadersColor, swInversedColor: TColor;
{ Buttons dimensions }
ButtonWidth: Integer;
ButtonHeight: Integer;
{ Images dimensions }
BackgroundWidth: Integer;
BackgroundHeight: Integer;
TopWidth: Integer;
InnerLeftTop: Integer;
InnerWidth: Integer;
InnerHeight: Integer;
BottomPosition: Integer;
BottomWidth: Integer;
{ Main buttons }
hNextButton, hBackButton, hDirBrowseButton, hGroupBrowseButton, hCancelButton: HWND;
{ Custom created buttons }
ButtonEvents: array[0..coMaxButtons] of TNotifyEvent;
ButtonHandles: array[0..coMaxButtons] of HWND;
EventsCount: Integer;
{ Inner pages' images }
PagesImages: array[1..coMaxPageCount] of Longint;
procedure SetButtonsState;
begin
with WizardForm.BackButton do
begin
ButtonSetText(hBackButton, PAnsiChar(Caption));
ButtonSetVisibility(hBackButton, Visible);
ButtonSetEnabled(hBackButton, Enabled);
end;
with WizardForm.NextButton do
begin
ButtonSetText(hNextButton, PAnsiChar(Caption));
ButtonSetVisibility(hNextButton, Visible);
ButtonSetEnabled(hNextButton, Enabled);
end;
with WizardForm.CancelButton do
begin
ButtonSetText(hCancelButton, PAnsiChar(Caption));
ButtonSetVisibility(hCancelButton, Visible);
ButtonSetEnabled(hCancelButton, Enabled);
end;
ButtonSetText(hDirBrowseButton, PAnsiChar(WizardForm.DirBrowseButton.Caption));
ButtonSetText(hGroupBrowseButton, PAnsiChar(WizardForm.GroupBrowseButton.Caption));
end;
procedure WizardFormButtonClick(hButton: HWND);
var
Button: TButton;
I: Integer;
Handle: HWND;
begin
Button := nil;
case hButton of
hCancelButton: Button := WizardForm.CancelButton;
hNextButton: Button := WizardForm.NextButton;
hBackButton: Button := WizardForm.BackButton;
hDirBrowseButton: Button := WizardForm.DirBrowseButton;
hGroupBrowseButton: Button := WizardForm.GroupBrowseButton;
end;
if(Button <> nil) then
begin
Button.OnClick(Button);
SetButtonsState;
ButtonRefresh(hButton);
end
else
begin
{ Custom created buttons }
for I := 0 to EventsCount do
begin
if(ButtonHandles[I] = hButton) then
ButtonEvents[I](nil);
end;
end;
end;
function SwitchColorFormat(Color: String): TColor;
var
RR, GG, BB: String;
Dec: Integer;
begin
{ Change string Color from $RRGGBB to $BBGGRR and then convert to TColor }
if((Length(Color) <> 7) or (Color[1] <> '$')) then
Result := $000000
else
begin
RR := Color[2] + Color[3];
GG := Color[4] + Color[5];
BB := Color[6] + Color[7];
Dec := StrToInt('$' + BB + GG + RR);
Result := TColor(
Dec);
end;
end;
procedure CreateButtons;
begin
ButtonFont := TFont.Create;
{ Detect current DPI and scale buttons [compute dimensions] }
case DPI of
coDefaultDPI:
begin
// Use default values
// 96 DPI: This is default zoom 100%
ButtonWidth := coButtonWidth;
ButtonHeight := coButtonHeight;
end
else
begin
// Scale dimensions and positions
// 120 DPI: Zoom 125%
// 144 DPI: Zoom 150%
// 192 DPI: Zoom 200%
// All other DPIs over 192 use this same scale system
ButtonWidth := ScaleX(coButtonWidth);
ButtonHeight := ScaleY(coButtonHeight);
end;
end;
{ Switch colors of Buttons' texts from $RRGGBB to $BBGGRR }
swButtonNormalColor := SwitchColorFormat(ExpandConstant('{#ButtonNormalColor}'));
swButtonFocusedColor := SwitchColorFormat(ExpandConstant('{#ButtonFocusedColor}'));
swButtonPressedColor := SwitchColorFormat(ExpandConstant('{#ButtonPressedColor}'));
swButtonDisabledColor := SwitchColorFormat(ExpandConstant('{#ButtonDisabledColor}'));
{ Back button }
with WizardForm.BackButton do
begin
hBackButton := ButtonCreate(WizardForm.Handle, Left-50, Top,
ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hBackButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hBackButton, ButtonFont.Handle);
ButtonSetFontColor(hBackButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
Width := 0;
Height := 0;
end;
{ Next button }
with WizardForm.NextButton do
begin
hNextButton := ButtonCreate(WizardForm.Handle, Left-40, Top,
ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hNextButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hNextButton, ButtonFont.Handle);
ButtonSetFontColor(hNextButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
Width := 0;
Height := 0;
end;
{ Cancel button }
with WizardForm.CancelButton do
begin
hCancelButton := ButtonCreate(WizardForm.Handle, Left-40, Top,
ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hCancelButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hCancelButton, ButtonFont.Handle);
ButtonSetFontColor(hCancelButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
Width := 0;
Height := 0;
end;
{ Directory Browse button }
with WizardForm.DirBrowseButton do
begin
hDirBrowseButton := ButtonCreate(WizardForm.SelectDirPage.Handle, WizardForm.DirBrowseButton.Left-2, WizardForm.DirBrowseButton.Top-6,
ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hDirBrowseButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hDirBrowseButton, ButtonFont.Handle);
ButtonSetFontColor(hDirBrowseButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
Width := 0;
Height := 0;
end;
{ Group Browse button }
with WizardForm.GroupBrowseButton do
begin
hGroupBrowseButton := ButtonCreate(WizardForm.SelectProgramGroupPage.Handle, WizardForm.GroupBrowseButton.Left, WizardForm.GroupBrowseButton.Top-6,
ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hGroupBrowseButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hGroupBrowseButton, ButtonFont.Handle);
ButtonSetFontColor(hGroupBrowseButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
Width := 0;
Height := 0;
end;
end;
function CreateSkinnedButton(
Handle: HWND; Left, Top: Integer; Caption: String; ClickEvent: TNotifyEvent): HWND;
var
hButton: HWND;
begin
{ Create skinned button }
hButton := ButtonCreate(
Handle, Left, Top, ButtonWidth, ButtonHeight, ExpandConstant('{tmp}\{#ButtonPicture}'), coButtonShadow, False);
ButtonSetEvent(hButton, ButtonClickEventID, WrapButtonCallback(@WizardFormButtonClick, 1));
ButtonSetFont(hButton, ButtonFont.Handle);
ButtonSetFontColor(hButton, swButtonNormalColor, swButtonFocusedColor, swButtonPressedColor, swButtonDisabledColor);
ButtonSetText(hButton, PAnsiChar(Caption));
ButtonSetVisibility(hButton, True);
ButtonSetEnabled(hButton, True);
ButtonRefresh(hButton);
{ Register button for callback event }
if(hButton > 0) then
begin
ButtonEvents[EventsCount] := ClickEvent;
ButtonHandles[EventsCount] := hButton;
EventsCount := EventsCount + 1;
end;
Result := hButton;
end;
procedure SetProgressBarColors(
Handle: HWND; Foreground, Background: String);
var
swFgColor, swBgColor: TColor;
Msg: Integer;
begin
{ Turn off Themes for this control }
SetWindowTheme(
Handle, ' ', ' ');
swFgColor := SwitchColorFormat(Foreground);
swBgColor := SwitchColorFormat(Background);
Msg := StrToInt(ExpandConstant('{#PBM_SETBARCOLOR}'));
SendMessage(
Handle, Msg, 0, swFgColor);
Msg := StrToInt(ExpandConstant('{#PBM_SETBKCOLOR}'));
SendMessage(
Handle, Msg, 0, swBgColor);
end;
{ Events on License page - RadioButton Yes/No clicks - enable/disable Next button }
procedure LicenseYesRadioClick(Sender: TObject);
begin
ButtonSetEnabled(hNextButton, True);
end;
procedure LicenseNoRadioClick(Sender: TObject);
begin
ButtonSetEnabled(hNextButton, False);
end;
procedure InitGraphicalInstaller();
var
I: Integer;
TopImage, BottomImage: Longint;
InnerImageFileName, TopImageFileName, BottomImageFileName, ButtonFileName: String;
WelcomePageImage, FinishedPageImage: Longint;
begin
{ Extract all necessary files into Temp directory }
// DLLs
ExtractTemporaryFile('InnoCallback.dll');
ExtractTemporaryFile('botva2.dll');
{ Detect current DPI and scale images [compute dimensions] }
I := ScaleX(coBackgroundWidth);
if (I = coBackgroundWidth) then
DPI := coDefaultDPI // Zoom = 100%
else
DPI := 12345; // Zoom > 100%
case DPI of
coDefaultDPI:
begin
// Use default values
// 96 DPI [690px]: This is default zoom 100%
BackgroundWidth := coBackgroundWidth;
BackgroundHeight := coBackgroundHeight;
TopWidth := coTopWidth;
InnerLeftTop := coInnerLeftTop;
InnerWidth := coInnerWidth;
InnerHeight := coInnerHeight;
BottomPosition := coBottomPosition;
BottomWidth := coBottomWidth;
end
else
begin
// Scale dimensions and positions
// 120 DPI [805px] : Zoom 125%
// 144 DPI [1035px]: Zoom 150%
// 192 DPI [1380px]: Zoom 200%
// All other DPIs over 192 use this same scale system
BackgroundWidth := ScaleX(coBackgroundWidth);
BackgroundHeight := ScaleY(coBackgroundHeight);
TopWidth := ScaleY(coTopWidth) + 1;
InnerLeftTop := coInnerLeftTop - 1;
InnerWidth := ScaleX(coInnerWidth) + 2;
InnerHeight := ScaleY(coInnerHeight) + 2;
BottomPosition := ScaleY(coBottomPosition) - 1;
BottomWidth := ScaleY(coBottomWidth) + 2;
end;
end;
// Create images
TopImageFilename := ExpandConstant('{tmp}\{#TopPicture}');
ExtractTemporaryFile(ExtractFileName(TopImageFilename));
InnerImageFileName := ExpandConstant('{tmp}\{#InnerPicture}');
ExtractTemporaryFile(ExtractFileName(InnerImageFileName));
BottomImageFileName := ExpandConstant('{tmp}\{#BottomPicture}');
ExtractTemporaryFile(ExtractFileName(BottomImageFileName));
ButtonFileName := ExpandConstant('{tmp}\{#ButtonPicture}');
ExtractTemporaryFile(ExtractFileName(ButtonFileName));
{ Welcome and Finished pages images }
WizardForm.WizardBitmapImage.Visible := False;
WelcomePageImage := ImgLoad(WizardForm.WelcomePage.Handle, TopImageFilename, 0, 0, BackgroundWidth, TopWidth, True, True);
ImgApplyChanges(WizardForm.WelcomePage.Handle);
WizardForm.WizardBitmapImage2.Visible := False;
FinishedPageImage := ImgLoad(WizardForm.FinishedPage.Handle, TopImageFilename, 0, 0, BackgroundWidth, TopWidth, True, True);
ImgApplyChanges(WizardForm.FinishedPage.Handle);
{ Initialize all Inner pages [inner images] }
For I:=1 To WizardForm.InnerNotebook.PageCount Do
Begin
PagesImages[I] := ImgLoad(WizardForm.InnerNotebook.Pages[I-1].Handle, InnerImageFileName, InnerLeftTop, InnerLeftTop, InnerWidth, InnerHeight, True, True);
ImgApplyChanges(WizardForm.InnerNotebook.Pages[I-1].Handle);
End;
// Top image - on each page
TopImage := ImgLoad(WizardForm.InnerPage.Handle, TopImageFilename, 0, 0, BackgroundWidth, TopWidth, True, True);
ImgApplyChanges(WizardForm.InnerPage.Handle);
// Bottom image - one each page
BottomImage := ImgLoad(WizardForm.Handle, BottomImageFilename, 0, BottomPosition, BackgroundWidth, BottomWidth, True, True);
ImgApplyChanges(WizardForm.Handle);
{ Create buttons and set their state }
#ifdef GRAPHICAL_INSTALLER_VCL
// Not needed if
VCL Styles for Inno Setup is used
#else
CreateButtons;
SetButtonsState;
#endif
{ Add events to License page RadioButtons }
WizardForm.LicenseAcceptedRadio.OnClick := @LicenseYesRadioClick;
WizardForm.LicenseNotAcceptedRadio.OnClick := @LicenseNoRadioClick;
{ Set colors of texts }
swTextsColor := SwitchColorFormat(ExpandConstant('{#TextsColor}'));
swInversedColor := SwitchColorFormat(ExpandConstant('{#InversedColor}'));
WizardForm.SetTextsColors(swTextsColor, swInversedColor);
{ Init Global Variable(s) }
EventsCount := 0;
end;
procedure PageChangedGraphicalInstaller(CurPageID: Integer);
begin
SetButtonsState;
{ Change color of header labes on each page }
swHeadersColor := SwitchColorFormat(ExpandConstant('{#HeadersColor}'));
WizardForm.PageDescriptionLabel.TextColor := swHeadersColor;
WizardForm.PageNameLabel.TextColor := swHeadersColor;
// List of possible pages [CurPageID]:
{
wpWelcome:
wpLicense:
wpPassword:
wpInfoBefore:
wpUserInfo:
wpSelectDir:
wpSelectComponents:
wpSelectProgramGroup:
wpSelectTasks:
wpReady:
wpPreparing:
wpInstalling:
wpInfoAfter:
wpFinished:
}
end;
procedure DeInitGraphicalInstaller();
begin
// Unload ComCtrls functions
GdiPlusShutdown;
end;
// End of file