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

wegi

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

Вложения

  • Безымянный.png
    Безымянный.png
    20 KB · Просмотры: 37
Проще использовать 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;
 
Ну или что нибудь похожие
Форматирование (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;
 

Вложения

Назад
Сверху