Вопрос Inno setup при повторном нажатие

wegi

Новичок
Здравствуйте, можно ли сделать что-то подобное при повторном запуске инсталятора(если программа установлена) или же при нажатие на кнопку "изменить"
Как это можно реализовать, что было три варианта
 

Вложения

Хамик

Старожил
Проще использовать Advanced Installer чем все это реализовывать в inno setup.
 

sergey3695

Ветеран
Модератор
а для 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;
 

El Sanchez

Новичок
Ну или что нибудь похожие
Форматирование (BB-код):
[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;
 

Вложения

Сверху