Смотрите видео ниже, чтобы узнать, как установить наш сайт в качестве веб-приложения на домашнем экране.
Примечание: Эта возможность может быть недоступна в некоторых браузерах.
а для inno setup есть ли пример?Проще использовать Advanced Installer чем все это реализовывать в inno setup.
а для inno setup есть ли пример?
#ifndef IS_ENHANCED
#error Enhanced edition of Inno Setup (restools) is required to compile this script
#endif
#define MyAppId "{{C6B1C937-16B6-4221-8E4D-C763F7EE78A1}"
[Setup]
AppId={#MyAppId}
AppName=My Application
AppVersion=1.5
DefaultDirName={pf}\My Application
DefaultGroupName=My Application
UninstallDisplayIcon={app}\MyProg.exe
SolidCompression=yes
Compression=lzma/ultra
OutputDir=.
[Files]
Source: "MyProg.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "MyProg1.chm"; DestDir: "{app}"; DestName: "MyProg.chm"; Flags: ignoreversion
Source: "Readme1.txt"; DestDir: "{app}"; DestName: "Readme.txt"; Flags: ignoreversion
//Source: "{win}\help\*"; DestDir: "{app}\help"; Flags: external recursesubdirs ignoreversion
[Icons]
Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"
Name: "{group}\My Program Documentation"; Filename: "{app}\MyProg.chm";
Name: "{group}\My Program Readme"; Filename: "{app}\Readme.txt";
Name: "{group}\Modify or Remove My Program"; Filename: "{uninstallexe}";
[code]
var
CanModifyRemove, Uninstalled: Boolean;
OrgUninstallData, NewUninstallData: String;
SetupOptions, UninstallPage: TWizardPage;
UninstallProgressBar: TNewProgressBar;
ModifyChk, RemoveChk: TNewRadioButton;
procedure InitializeWizard();
begin
SetupOptions := CreateCustomPage(wpWelcome, 'Uninstall My Application Program Maintenance', 'Modify or remove the program.');
UninstallPage := CreateCustomPage(SetupOptions.ID, 'Uninstall Status', 'Uninstalling......');
UninstallProgressBar := TNewProgressBar.Create(WizardForm);
with UninstallProgressBar do
begin
Parent := UninstallPage.Surface;
SetBounds(0, ScaleY(42), UninstallPage.SurfaceWidth, ScaleY(21));
end;
ModifyChk := TNewRadioButton.Create(WizardForm);
with ModifyChk do
begin
Parent := SetupOptions.Surface;
SetBounds(ScaleX(32), ScaleY(64), ScaleX(113), ScaleY(17));
Caption := 'Modify';
Checked := True;
end;
RemoveChk := TNewRadioButton.Create(WizardForm);
with RemoveChk do
begin
Parent := SetupOptions.Surface;
SetBounds(ScaleX(32), ScaleY(104), ScaleX(113), ScaleY(17));
Caption := 'Remove';
end;
CanModifyRemove := False;
Uninstalled := False;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
var
UninstallDataFile: String;
begin
if PageID = wpWelcome then
begin
if Uninstalled then
Result := False
else begin
UninstallDataFile := RemoveQuotes(GetSetupPreviousData('UninstallDataFile', ''));
CanModifyRemove := UninstallDataFile<>'';
Result := CanModifyRemove;
end;
end else
if PageID = SetupOptions.ID then
begin
Result := Uninstalled or (not CanModifyRemove);
end else
if PageID = UninstallPage.ID then
begin
Result := Uninstalled or (not RemoveChk.Checked);
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = UninstallPage.ID then
begin
WizardForm.BackButton.Visible := False;
WizardForm.NextButton.Visible := False;
WizardForm.CancelButton.Enabled := False;
PerformPreviousUninstall(UninstallProgressBar);
WizardForm.CancelButton.Caption := 'Finish';
WizardForm.CancelButton.Enabled := True;
UninstallProgressBar.Visible := False;
WizardForm.PageDescriptionLabel.Caption := 'Finish';
Uninstalled := True;
end;
end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
Confirm := not Uninstalled;
end;
procedure RegisterPreviousData(PreviousDataKey: Integer);
var
PathKeyName: String;
begin
PathKeyName := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppId}_is1');
RegWriteDWordValue(HKLM, PathKeyName, 'NoModify', 0);
RegWriteDWordValue(HKLM, PathKeyName, 'NoRepair', 0);
end;
Ну или что нибудь похожие
[Setup]
AppName=test
AppVerName=test
DefaultDirName={pf}\test
[Files]
Source: custicon.ico; Flags: dontcopy
Source: repairic.ico; Flags: dontcopy
Source: removico.ico; Flags: dontcopy
[Components]
Name: "main"; Description: "Main Files"; Types: full compact custom; Flags: fixed
Name: "help"; Description: "Help Files"; Types: full
Name: "help\english"; Description: "English"; Types: full
Name: "help\dutch"; Description: "Dutch"; Types: full
[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl
[CustomMessages]
ru.MaintenancePageNameLabel=Обслуживание установки
ru.MaintenancePageDescriptionLabel=Выберите операцию для выполнения.
ru.ModifyButtonHeader=Изменить
ru.RepairButtonHeader=Исправить
ru.RemoveButtonHeader=Удалить
ru.ModifyButtonNote=Изменение установленных компонентов.
ru.RepairButtonNote=Восстановление недостающих или поврежденных файлов, ярлыков и записей реестра.
ru.RemoveButtonNote=Удаление {#SetupSetting("AppName")} с вашего компьютера.
[Code]
const
LAYOUT_RTL = $0001;
DT_RTLREADING = $20000;
DT_NOPREFIX = $0800;
DT_CALCRECT = $400;
DT_WORDBREAK = $10;
DT_VCENTER = 4;
PBS_NORMAL = 1;
PBS_HOT = 2;
PBS_PRESSED = 3;
PBS_DISABLED = 4;
PBS_DEFAULTED = 5;
DI_NORMAL = 3;
ILC_COLOR32 = $0020;
BUTTON_IMAGELIST_ALIGN_CENTER = 4;
NM_FIRST = 0;
NM_CUSTOMDRAW = NM_FIRST - 12;
BCN_FIRST = -1250;
BCN_HOTITEMCHANGE = BCN_FIRST + 1;
BCM_FIRST = $1600;
BCM_SETIMAGELIST = BCM_FIRST + $0002;
BCM_GETIMAGELIST = BCM_FIRST + $0003;
WM_NOTIFY = $004E;
WM_THEMECHANGED = $031A;
WM_SIZE = $0005;
BM_CLICK = $00F5;
CDRF_DODEFAULT = $0000;
CDRF_SKIPDEFAULT = $0004;
CDDS_PREERASE = $0003;
CDIS_SELECTED = $0001;
CDIS_DISABLED = $0004;
CDIS_FOCUS = $0010;
CDIS_HOT = $0040;
HICF_ENTERING = $0010;
HICF_LEAVING = $0020;
SM_CXICON = 11;
SM_CYICON = 12;
IMAGE_ICON = 1;
LR_DEFAULTSIZE = $0040;
LR_LOADFROMFILE = $0010;
type
TButtonImageList = record
himl: THandle;
margin: TRect;
uAlign: UINT;
end;
TNMHdr = record
hwndFrom: HWND;
idFrom: UINT_PTR;
code: Integer;
end;
TNMCustomDraw = record
hdr: TNMHdr;
dwDrawStage: DWORD;
hdc: THandle;
rc: TRect;
dwItemSpec: DWORD_PTR;
uItemState: UINT;
lItemlParam: Longint;
end;
TNMBCHotItem = record
hdr: TNMHdr;
dwFlags: DWORD;
end;
TMaintenanceMode = (mmNone, mmModify, mmRepair, mmRemove);
// Rectangle Functions
function SetRect(var lprc: TRect; xLeft, yTop, xRight, yBottom: Integer): BOOL; external 'SetRect@user32.dll stdcall';
function OffsetRect(var lprc: TRect; dx, dy: Integer): BOOL; external 'OffsetRect@user32.dll stdcall';
function InflateRect(var lprc: TRect; dx, dy: Integer): BOOL; external 'InflateRect@user32.dll stdcall';
// Font and Text Functions
function DrawTextEx(DC: THandle; lpchText: string; cchText: Integer; var lprc: TRect;
dwDTFormat: UINT; DTParams: LongWord): Integer; external 'DrawTextExW@user32.dll stdcall';
// Icon Functions
function DrawIconEx(hdc: THandle; xLeft, yTop: Integer; hIcon: THandle; cxWidth, cyWidth: Integer;
istepIfAniCur: UINT; hbrFlickerFreeDraw: THandle; diFlags: UINT): BOOL; external 'DrawIconEx@user32.dll stdcall';
function DestroyIcon(hIcon: THandle): BOOL; external 'DestroyIcon@user32.dll stdcall';
// Image List Functions
function ImageList_Create(CX, CY: Integer; Flags: UINT; Initial, Grow: Integer): THandle; external 'ImageList_Create@comctl32.dll stdcall';
function ImageList_Destroy(ImageList: THandle): BOOL; external 'ImageList_Destroy@comctl32.dll stdcall';
function ImageList_Add(ImageList: THandle; Image, Mask: HBITMAP): Integer; external 'ImageList_Add@comctl32.dll stdcall';
function ImageList_Draw(himl: THandle; i: Integer; hdcDst: THandle; x, y: Integer; fStyle: UINT): BOOL; external 'ImageList_Draw@comctl32.dll stdcall';
function ImageList_Remove(himl: THandle; i: Integer): BOOL; external 'ImageList_Remove@comctl32.dll stdcall';
function ImageList_SetIconSize(himl: THandle; cx, cy: Integer): BOOL; external 'ImageList_SetIconSize@comctl32.dll stdcall';
// Shell Functions
function SetWindowSubclass(hWnd: HWND; pfnSubclass, uIdSubclass, dwRefData: LongWord): BOOL; external 'SetWindowSubclass@comctl32.dll stdcall';
function RemoveWindowSubclass(hWnd: HWND; pfnSubclass, uIdSubclass: LongWord): BOOL; external 'RemoveWindowSubclass@comctl32.dll stdcall';
function DefSubclassProc(hWnd: HWND; uMsg: UINT; wParam, lParam: LongWord): LongWord; external 'DefSubclassProc@comctl32.dll stdcall';
// Run-Time Library (RTL) Routines
procedure RtlMoveMemoryNMHdr(var Destination: TNMHdr; Source: LongWord; len: Integer); external 'RtlMoveMemory@kernel32.dll stdcall';
function RtlMoveMemoryNMCustomDraw(var Destination: TNMCustomDraw; Source: LongWord; len: Integer): Integer; external 'RtlMoveMemory@kernel32.dll stdcall';
function RtlMoveMemoryNMBCHotItem(var Destination: TNMBCHotItem; Source: LongWord; len: Integer): Integer; external 'RtlMoveMemory@kernel32.dll stdcall';
// Message Functions
function SendMessageButtonImageList(hWnd: HWND; Msg: UINT; wParam: LongWord; var lParam: TButtonImageList): LongWord; external 'SendMessageW@user32.dll stdcall';
function SendMessageNMCustomDraw(hWnd: HWND; Msg: UINT; wParam: LongWord; var lParam: TNMCustomDraw): LongWord; external 'SendMessageW@user32.dll stdcall';
// Window Functions
function GetClientRect(hWnd: HWND; out lpRect: TRect): BOOL; external 'GetClientRect@user32.dll stdcall';
// Visual Styles Functions
function IsAppThemed: BOOL; external 'IsAppThemed@uxtheme.dll stdcall';
// Painting and Drawing Functions
function GetDC(hWnd: HWND): THandle; external 'GetDC@User32.dll stdcall';
// Device Context Functions
function SetLayout(hdc: THandle; dwLayout: DWORD): DWORD; external 'SetLayout@gdi32.dll stdcall';
function ReleaseDC(hWnd: HWND; hDC: THandle): Integer; external 'ReleaseDC@user32.dll stdcall';
// Keyboard Input Functions
function GetFocus: HWND; external 'GetFocus@user32.dll stdcall';
// Resource Functions
function LoadImage(hInst: THandle; lpszName: string; uType: UINT; cxDesired, cyDesired: Integer; fuLoad: UINT): THandle; external 'LoadImageW@user32.dll stdcall';
// Configuration Reference
function GetSystemMetrics(nIndex: Integer): Integer; external 'GetSystemMetrics@user32.dll stdcall';
var
MaintenancePage: TWizardPage;
ModifyButton, RepairButton, RemoveButton: TButton;
MaintenanceMode: TMaintenanceMode;
PMaintenancePageWndProc: LongWord;
function CreateButtonImage(const AHeaderText, ANoteText: string;
AButton: TButton; AButtonState: DWORD): Integer;
var
ButtonImageList: TButtonImageList;
ButtonBitmap, LogoBitmap: TBitmap;
ButtonRect, LogoRect, HeaderRect, NoteRect: TRect;
LogoIcon: THandle;
LogoName: string;
DTFormat: UINT;
begin
Result := -1;
ButtonBitmap := TBitmap.Create;
with ButtonBitmap.Canvas do
try
ButtonBitmap.Width := AButton.Width;
ButtonBitmap.Height := AButton.Height;
if WizardForm.RightToLeft then
SetLayout(Handle, LAYOUT_RTL);
Font.Name := AButton.Font.Name;
{ Load icon. }
case AButton of
ModifyButton: LogoName := 'custicon.ico';
RepairButton: LogoName := 'repairic.ico';
RemoveButton: LogoName := 'removico.ico';
end;
if not FileExists(ExpandConstant('{tmp}\') + LogoName) then
ExtractTemporaryFile(LogoName);
LogoIcon := LoadImage(0, ExpandConstant('{tmp}\') + LogoName, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE or LR_LOADFROMFILE);
{ Parts metrics. }
DTFormat := DT_NOPREFIX or DT_CALCRECT or DT_WORDBREAK or DT_VCENTER;
if WizardForm.RightToLeft then
DTFormat := DTFormat or DT_RTLREADING;
SetRect(ButtonRect, 0, 0, ButtonBitmap.Width, ButtonBitmap.Height);
SetRect(LogoRect, 0, 0, ScaleX(48), ScaleY(48));
OffsetRect(LogoRect, ((ButtonRect.Bottom - ButtonRect.Top) - (LogoRect.Bottom - LogoRect.Top)) div 2,
((ButtonRect.Bottom - ButtonRect.Top) - (LogoRect.Bottom - LogoRect.Top)) div 2);
Font.Assign(WizardForm.PageNameLabel.Font);
SetRect(HeaderRect, 0, 0, ButtonRect.Right - ButtonRect.Left - 2 * LogoRect.Left - LogoRect.Right - ScaleX(20), ButtonRect.Bottom - ButtonRect.Top);
DrawTextEx(Handle, AHeaderText, -1, HeaderRect, DTFormat, 0);
Font.Assign(WizardForm.PageDescriptionLabel.Font);
SetRect(NoteRect, 0, 0, ButtonRect.Right - ButtonRect.Left - 2 * LogoRect.Left - LogoRect.Right - ScaleX(20), ButtonRect.Bottom - ButtonRect.Top);
DrawTextEx(Handle, ANoteText, -1, NoteRect, DTFormat, 0);
OffsetRect(HeaderRect, LogoRect.Right + ScaleX(20), (ButtonRect.Bottom - ButtonRect.Top -
(HeaderRect.Bottom - HeaderRect.Top) - (NoteRect.Bottom - NoteRect.Top)) div 2);
OffsetRect(NoteRect, LogoRect.Right + ScaleX(20), HeaderRect.Bottom);
{ Draw background. }
Brush.Color := WizardForm.Color;
FillRect(ButtonRect);
{ Draw logo. }
Pen.Width := 1;
case AButtonState of
PBS_NORMAL, PBS_DISABLED:
begin
Brush.Color := $E1E1E1;
Pen.Color := $ADADAD;
end;
PBS_HOT:
begin
Brush.Color := $FBF1E5;
Pen.Color := $D97801;
end;
PBS_PRESSED:
begin
Brush.Color := $F8E5CC;
Pen.Color := $975100;
end;
PBS_DEFAULTED:
begin
Brush.Color := $E1E1E1;
Pen.Color := $D97801;
Pen.Width := 2;
end;
end;
Rectangle(LogoRect.Left, LogoRect.Top, LogoRect.Right, LogoRect.Bottom);
InflateRect(LogoRect,
-(LogoRect.Right - LogoRect.Left - GetSystemMetrics(SM_CXICON)) div 2,
-(LogoRect.Bottom - LogoRect.Top - GetSystemMetrics(SM_CYICON)) div 2);
DrawIconEx(Handle, LogoRect.Left, LogoRect.Top, LogoIcon,
LogoRect.Right - LogoRect.Left, LogoRect.Bottom - LogoRect.Top, 0, 0, DI_NORMAL);
Brush.Color := WizardForm.Color;
{ Draw header. }
DTFormat := DTFormat and not DT_CALCRECT;
Font.Assign(WizardForm.PageNameLabel.Font);
if AButtonState = PBS_DISABLED then
Font.Color := clGrayText;
DrawTextEx(Handle, AHeaderText, -1, HeaderRect, DTFormat, 0);
{ Draw note. }
Font.Assign(WizardForm.PageDescriptionLabel.Font);
if AButtonState = PBS_DISABLED then
Font.Color := clGrayText;
DrawTextEx(Handle, ANoteText, -1, NoteRect, DTFormat, 0);
SendMessageButtonImageList(AButton.Handle, BCM_GETIMAGELIST, 0, ButtonImageList);
Result := ImageList_Add(ButtonImageList.himl, ButtonBitmap.Handle, 0);
finally
DestroyIcon(LogoIcon);
ButtonBitmap.Free;
end;
end;
procedure UpdateButtonImageList(AButton: TButton;
const AHeaderText, ANoteText: string; ARecreate: Boolean);
var
ButtonImageList: TButtonImageList;
begin
SendMessageButtonImageList(AButton.Handle, BCM_GETIMAGELIST, 0, ButtonImageList);
if not ARecreate then
ImageList_Remove(ButtonImageList.himl, -1) else
ImageList_SetIconSize(ButtonImageList.himl, AButton.Width, AButton.Height);
CreateButtonImage(AHeaderText, ANoteText, AButton, PBS_NORMAL);
CreateButtonImage(AHeaderText, ANoteText, AButton, PBS_HOT);
CreateButtonImage(AHeaderText, ANoteText, AButton, PBS_PRESSED);
CreateButtonImage(AHeaderText, ANoteText, AButton, PBS_DISABLED);
CreateButtonImage(AHeaderText, ANoteText, AButton, PBS_DEFAULTED);
end;
procedure CreateButtonImageList(AButton: TButton;
const AHeaderText, ANoteText: string);
var
ButtonImageList: TButtonImageList;
begin
with AButton do
begin
ButtonImageList.himl := ImageList_Create(Width, Height, ILC_COLOR32, 5, 0);
ButtonImageList.uAlign := BUTTON_IMAGELIST_ALIGN_CENTER;
SendMessageButtonImageList(Handle, BCM_SETIMAGELIST, 0, ButtonImageList);
UpdateButtonImageList(AButton, AHeaderText, ANoteText, False);
end;
end;
function MaintenancePageWndProc(hWnd: HWND; uMsg: UINT;
wParam, lParam, uIdSubclass, dwRefData: LongWord): LongWord;
var
NMHdr: TNMHdr;
NMCustomDraw: TNMCustomDraw;
NMBCHotItem: TNMBCHotItem;
ButtonImageList: TButtonImageList;
begin
case uMsg of
WM_THEMECHANGED:
begin
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
UpdateButtonImageList(ModifyButton,
CustomMessage('ModifyButtonHeader'),
CustomMessage('ModifyButtonNote'), False);
UpdateButtonImageList(RepairButton,
CustomMessage('RepairButtonHeader'),
CustomMessage('RepairButtonNote'), False);
UpdateButtonImageList(RemoveButton,
CustomMessage('RemoveButtonHeader'),
CustomMessage('RemoveButtonNote'), False);
end;
WM_SIZE:
begin
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
ModifyButton.Height := ModifyButton.Parent.ClientHeight div 3;
UpdateButtonImageList(ModifyButton,
CustomMessage('ModifyButtonHeader'),
CustomMessage('ModifyButtonNote'), True);
RepairButton.Height := RepairButton.Parent.ClientHeight div 3;
UpdateButtonImageList(RepairButton,
CustomMessage('RepairButtonHeader'),
CustomMessage('RepairButtonNote'), True);
RemoveButton.Height := RemoveButton.Parent.ClientHeight div 3;
UpdateButtonImageList(RemoveButton,
CustomMessage('RemoveButtonHeader'),
CustomMessage('RemoveButtonNote'), True);
end;
WM_NOTIFY:
begin
RtlMoveMemoryNMHdr(NMHdr, lParam, SizeOf(NMHdr));
case NMHdr.code of
NM_CUSTOMDRAW:
begin
RtlMoveMemoryNMCustomDraw(NMCustomDraw, lParam, SizeOf(NMCustomDraw));
case NMCustomDraw.dwDrawStage of
CDDS_PREERASE:
begin
SendMessageButtonImageList(NMHdr.hwndFrom, BCM_GETIMAGELIST, 0, ButtonImageList);
if NMCustomDraw.uItemState and CDIS_DISABLED = CDIS_DISABLED then // $04
ImageList_Draw(ButtonImageList.himl, PBS_DISABLED - 1, NMCustomDraw.hdc, 0, 0, 0)
else if NMCustomDraw.uItemState and CDIS_HOT = CDIS_HOT then // $40
begin
if NMCustomDraw.uItemState and CDIS_FOCUS = CDIS_FOCUS then // +$10
begin
if NMCustomDraw.uItemState and CDIS_SELECTED = CDIS_SELECTED then // $51
ImageList_Draw(ButtonImageList.himl, PBS_PRESSED - 1, NMCustomDraw.hdc, 0, 0, 0)
else // $50
ImageList_Draw(ButtonImageList.himl, PBS_HOT - 1, NMCustomDraw.hdc, 0, 0, 0);
end else
ImageList_Draw(ButtonImageList.himl, PBS_HOT - 1, NMCustomDraw.hdc, 0, 0, 0);
end
else if NMCustomDraw.uItemState and CDIS_FOCUS = CDIS_FOCUS then // $10
begin
if NMCustomDraw.uItemState and CDIS_SELECTED = CDIS_SELECTED then // $11
ImageList_Draw(ButtonImageList.himl, PBS_PRESSED - 1, NMCustomDraw.hdc, 0, 0, 0)
else
ImageList_Draw(ButtonImageList.himl, PBS_DEFAULTED - 1, NMCustomDraw.hdc, 0, 0, 0);
end else
ImageList_Draw(ButtonImageList.himl, PBS_NORMAL - 1, NMCustomDraw.hdc, 0, 0, 0);
Result := CDRF_SKIPDEFAULT;
end;
else
Result := CDRF_DODEFAULT;
end;
end;
BCN_HOTITEMCHANGE:
begin
RtlMoveMemoryNMBCHotItem(NMBCHotItem, lParam, SizeOf(NMBCHotItem));
if BOOL((GetWindowsVersion > $06010000) and
(GetWindowsVersion < $06020000)) and
IsAppThemed then Exit; // skip on themed Win7
NMCustomDraw.hdr := NMBCHotItem.hdr;
NMCustomDraw.hdr.code := NM_CUSTOMDRAW;
NMCustomDraw.dwDrawStage := CDDS_PREERASE;
NMCustomDraw.hdc := GetDC(NMHdr.hwndFrom);
GetClientRect(NMHdr.hwndFrom, NMCustomDraw.rc);
if NMBCHotItem.dwFlags and HICF_ENTERING = HICF_ENTERING then
begin
NMCustomDraw.uItemState := CDIS_HOT;
if GetFocus = NMHdr.hwndFrom then
NMCustomDraw.uItemState := CDIS_HOT or CDIS_FOCUS;
end
else if NMBCHotItem.dwFlags and HICF_LEAVING = HICF_LEAVING then
begin
NMCustomDraw.uItemState := $0;
if GetFocus = NMHdr.hwndFrom then
NMCustomDraw.uItemState := CDIS_FOCUS;
end;
SendMessageNMCustomDraw(hWnd, WM_NOTIFY, NMBCHotItem.hdr.idFrom, NMCustomDraw);
ReleaseDC(NMHdr.hwndFrom, NMCustomDraw.hdc);
end;
else
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
end;
end;
else
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
end;
end;
procedure MaintenanceButtonOnClick(Sender: TObject);
var
LSubKeyName, LUninstallString: string;
LResultCode: Integer;
begin
case Sender of
ModifyButton:
begin
MaintenanceMode := mmModify;
SendMessage(WizardForm.NextButton.Handle, BM_CLICK, 0, 0);
end;
RepairButton:
begin
MaintenanceMode := mmRepair;
SendMessage(WizardForm.NextButton.Handle, BM_CLICK, 0, 0);
end;
RemoveButton:
begin
MaintenanceMode := mmRemove;
LSubKeyName := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")!="" ? SetupSetting("AppId") : SetupSetting("AppName")}_is1';
if RegQueryStringValue(HKCU, LSubKeyName, 'UninstallString', LUninstallString) or
RegQueryStringValue(HKLM, LSubKeyName, 'UninstallString', LUninstallString) then
begin
Exec(RemoveQuotes(LUninstallString), '/SILENT /NORESTART /SUPPRESSMSGBOXES', '', SW_SHOWNORMAL, ewNoWait, LResultCode);
WizardForm.Close;
end;
end;
end;
end;
procedure CreateMaintenancePage;
var
LSubKeyName, LUninstallString: string;
begin
MaintenancePage := CreateCustomPage(wpWelcome,
CustomMessage('MaintenancePageNameLabel'),
CustomMessage('MaintenancePageDescriptionLabel'));
{ ModifyButton. }
ModifyButton := TButton.Create(MaintenancePage);
with ModifyButton do
begin
Parent := MaintenancePage.Surface;
Top := Parent.ClientHeight;
Align := alTop;
Height := Parent.ClientHeight div 3;
OnClick := @MaintenanceButtonOnClick;
end;
CreateButtonImageList(ModifyButton,
CustomMessage('ModifyButtonHeader'),
CustomMessage('ModifyButtonNote'));
{ RepairButton. }
RepairButton := TButton.Create(MaintenancePage);
with RepairButton do
begin
Parent := MaintenancePage.Surface;
Top := Parent.ClientHeight;
Align := alTop;
Height := Parent.ClientHeight div 3;
OnClick := @MaintenanceButtonOnClick;
end;
CreateButtonImageList(RepairButton,
CustomMessage('RepairButtonHeader'),
CustomMessage('RepairButtonNote'));
{ RemoveButton. }
RemoveButton := TButton.Create(MaintenancePage);
with RemoveButton do
begin
Parent := MaintenancePage.Surface;
Top := Parent.ClientHeight;
Align := alTop;
Height := Parent.ClientHeight div 3;
OnClick := @MaintenanceButtonOnClick;
end;
CreateButtonImageList(RemoveButton,
CustomMessage('RemoveButtonHeader'),
CustomMessage('RemoveButtonNote'));
LSubKeyName := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")!="" ? SetupSetting("AppId") : SetupSetting("AppName")}_is1';
ModifyButton.Visible := (WizardForm.PrevAppDir <> '') and
(WizardSelectedComponents(False) <> '');
RepairButton.Visible := WizardForm.PrevAppDir <> '';
RemoveButton.Visible := (WizardForm.PrevAppDir <> '') and
(RegQueryStringValue(HKCU, LSubKeyName, 'UninstallString', LUninstallString) or
RegQueryStringValue(HKLM, LSubKeyName, 'UninstallString', LUninstallString)) and
FileExists(RemoveQuotes(LUninstallString));
PMaintenancePageWndProc := {#ifdef IS_ENHANCED}CallbackAddr('MaintenancePageWndProc'){#else}CreateCallback(@MaintenancePageWndProc){#endif};
SetWindowSubclass(MaintenancePage.Surface.Handle, PMaintenancePageWndProc, 0, 0);
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := False;
case PageID of
wpWelcome: Result := RepairButton.Visible and (ModifyButton.Visible or RemoveButton.Visible);
wpLicense..wpSelectDir:
Result := (MaintenanceMode = mmModify) or (MaintenanceMode = mmRepair);
wpSelectComponents..wpFinished:
Result := MaintenanceMode = mmRepair;
MaintenancePage.ID: Result := not(RepairButton.Visible and (ModifyButton.Visible or RemoveButton.Visible));
end;
end;
procedure InitializeWizard;
begin
CreateMaintenancePage;
end;
procedure DestroyMaintenancePage;
var
ButtonImageList: TButtonImageList;
begin
if PMaintenancePageWndProc <> 0 then
begin
RemoveWindowSubclass(MaintenancePage.Surface.Handle, PMaintenancePageWndProc, 0);
SendMessageButtonImageList(ModifyButton.Handle, BCM_GETIMAGELIST, 0, ButtonImageList);
ImageList_Destroy(ButtonImageList.himl);
SendMessageButtonImageList(RepairButton.Handle, BCM_GETIMAGELIST, 0, ButtonImageList);
ImageList_Destroy(ButtonImageList.himl);
SendMessageButtonImageList(RemoveButton.Handle, BCM_GETIMAGELIST, 0, ButtonImageList);
ImageList_Destroy(ButtonImageList.himl);
end;
end;
procedure DeinitializeSetup;
begin
DestroyMaintenancePage;
end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
case CurPageID of
MaintenancePage.ID:
Confirm := MaintenanceMode <> mmRemove;
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
MaintenancePage.ID: WizardForm.NextButton.Hide;
end;
end;