Inno Setup:仅放大组件页面,包含预览和说明

时间:2016-11-15 18:15:58

标签: inno-setup

我需要您的帮助才能合并这里找到的两个脚本,以便在最大化的组件窗口上显示预览图像:

修改:感谢Martin Prikryl。凭借他的耐心和帮助,我成功合并了这两个脚本。

您的预览图片的分辨率应为208x165英寸.bmp

  

[文件]

...
Source: "1.bmp"; Flags: dontcopy
Source: "2.bmp"; Flags: dontcopy
Source: "3.bmp"; Flags: dontcopy
Source: "InnoCallback.dll"; Flags: dontcopy
  

[代码]

    var
  LastMouse: TPoint;

type
  TTimerProc = procedure(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);

function GetCursorPos(var lpPoint: TPoint): BOOL; external 'GetCursorPos@user32.dll stdcall';
function SetTimer(hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord; external 'SetTimer@user32.dll stdcall';
function ScreenToClient(hWnd: HWND; var lpPoint: TPoint): BOOL; external 'ScreenToClient@user32.dll stdcall';
function ClientToScreen(hWnd: HWND; var lpPoint: TPoint): BOOL; external 'ClientToScreen@user32.dll stdcall';
function ListBox_GetItemRect(const hWnd: HWND; const Msg: Integer; Index: LongInt; var Rect: TRect): LongInt; external 'SendMessageW@user32.dll stdcall';  

const
  LB_GETITEMRECT = $0198;
  LB_GETTOPINDEX = $018E;

function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord; external 'wrapcallback@files:InnoCallback.dll stdcall';

function FindControl(Parent: TWinControl; P: TPoint): TControl;
var
  Control: TControl;
  WinControl: TWinControl;
  I: Integer;
  P2: TPoint;
begin
  for I := 0 to Parent.ControlCount - 1 do
  begin
    Control := Parent.Controls[I];
    if Control.Visible and
       (Control.Left <= P.X) and (P.X < Control.Left + Control.Width) and
       (Control.Top <= P.Y) and (P.Y < Control.Top + Control.Height) then
    begin
      if Control is TWinControl then
      begin
        P2 := P;
        ClientToScreen(Parent.Handle, P2);
        WinControl := TWinControl(Control);
        ScreenToClient(WinControl.Handle, P2);
        Result := FindControl(WinControl, P2);
        if Result <> nil then Exit;
      end;

      Result := Control;
      Exit;
    end;
  end;

  Result := nil;
end;

function PointInRect(const Rect: TRect; const Point: TPoint): Boolean;
begin
  Result := (Point.X >= Rect.Left) and (Point.X <= Rect.Right) and
    (Point.Y >= Rect.Top) and (Point.Y <= Rect.Bottom);
end;

function ListBoxItemAtPos(ListBox: TCustomListBox; Pos: TPoint): Integer;
var
  Count: Integer;
  ItemRect: TRect;
begin
  Result := SendMessage(ListBox.Handle, LB_GETTOPINDEX, 0, 0);
  Count := ListBox.Items.Count;
  while Result < Count do
  begin
    ListBox_GetItemRect(ListBox.Handle, LB_GETITEMRECT, Result, ItemRect);
    if PointInRect(ItemRect, Pos) then Exit;
    Inc(Result);
  end;
  Result := -1;
end;

var
  CompLabel: TLabel;
  CompImage: TBitmapImage;
  LoadingImage: Boolean;

procedure HoverComponentChanged(Index: Integer);
var 
  Description: string;
  Image: string;
  ImagePath: string;
begin
  case Index of
    0: begin Description := 'Component 1'; Image := '1.bmp'; end;
    1: begin Description := 'Component 2'; Image := '2.bmp'; end;
    2: begin Description := 'Component 3'; Image := '3.bmp'; end;

  else
    Description := 'Move your mouse over a component to see its description.';
  end;
  CompLabel.Caption := Description;

  if Image <> '' then
  begin
    // The ExtractTemporaryFile pumps the message queue, prevent recursion
    if not LoadingImage then
    begin
      LoadingImage := True;
      try
        ImagePath := ExpandConstant('{tmp}\' + Image);
        if not FileExists(ImagePath) then
        begin
          ExtractTemporaryFile(Image);
        end;
        CompImage.Bitmap.LoadFromFile(ImagePath);
      finally
        LoadingImage := False;
      end;
    end;
    CompImage.Visible := True;
  end
    else
  begin
    CompImage.Visible := False;
  end;
end;

procedure HoverTimerProc(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
  P: TPoint;
  Control: TControl; 
  Index: Integer;
begin
  GetCursorPos(P);
  if P <> LastMouse then // just optimization
  begin
    LastMouse := P;
    ScreenToClient(WizardForm.Handle, P);

    if (P.X < 0) or (P.Y < 0) or
       (P.X > WizardForm.ClientWidth) or (P.Y > WizardForm.ClientHeight) then
    begin
      Control := nil;
    end
      else
    begin
      Control := FindControl(WizardForm, P);
    end;

    Index := -1;
    if Control = WizardForm.ComponentsList then
    begin
      P := LastMouse;
      ScreenToClient(WizardForm.ComponentsList.Handle, P);
      Index := ListBoxItemAtPos(WizardForm.ComponentsList, P);
    end;

    HoverComponentChanged(Index);
  end;
end;

type
  TPositionStorage = array of Integer;

var
  CompPageModified: Boolean;
  CompPagePositions: TPositionStorage;

procedure SaveComponentsPage(out Storage: TPositionStorage);
begin
  SetArrayLength(Storage, 10);

  Storage[0] := WizardForm.Height;
  Storage[1] := WizardForm.NextButton.Top;
  Storage[2] := WizardForm.BackButton.Top;
  Storage[3] := WizardForm.CancelButton.Top;
  Storage[4] := WizardForm.ComponentsList.Height;
  Storage[5] := WizardForm.OuterNotebook.Height;
  Storage[6] := WizardForm.InnerNotebook.Height;
  Storage[7] := WizardForm.Bevel.Top;
  Storage[8] := WizardForm.BeveledLabel.Top;
  Storage[9] := WizardForm.ComponentsDiskSpaceLabel.Top;
end;

procedure LoadComponentsPage(const Storage: TPositionStorage;
  HeightOffset: Integer);
begin
  if GetArrayLength(Storage) <> 10 then
    RaiseException('Invalid storage array length.');

  WizardForm.Height := Storage[0] + HeightOffset;
  WizardForm.NextButton.Top := Storage[1] + HeightOffset;
  WizardForm.BackButton.Top := Storage[2] + HeightOffset;
  WizardForm.CancelButton.Top := Storage[3] + HeightOffset;
  WizardForm.ComponentsList.Height := Storage[4] + ScaleY(150);
  WizardForm.OuterNotebook.Height := Storage[5] + HeightOffset;
  WizardForm.InnerNotebook.Height := Storage[6] + HeightOffset;
  WizardForm.Bevel.Top := Storage[7] + HeightOffset;
  WizardForm.BeveledLabel.Top := Storage[8] + HeightOffset;
  WizardForm.ComponentsDiskSpaceLabel.Top := Storage[9] + HeightOffset;
end;

procedure InitializeWizard1();
var
  HoverTimerCallback: LongWord;
begin
  HoverTimerCallback := WrapTimerProc(@HoverTimerProc, 4);

  SetTimer(0, 0, 50, HoverTimerCallback);

  CompLabel := TLabel.Create(WizardForm);
  CompLabel.Parent := WizardForm.SelectComponentsPage;
  CompLabel.Left := WizardForm.ComponentsList.Left;
  CompLabel.Width := WizardForm.ComponentsList.Width div 2;
  CompLabel.Height := ScaleY(64);
  CompLabel.Top := WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height - CompLabel.Height + ScaleY(150);
  CompLabel.AutoSize := false;
  CompLabel.WordWrap := True;

  CompImage := TBitmapImage.Create(WizardForm);
  CompImage.Parent := WizardForm.SelectComponentsPage;
  CompImage.Top := CompLabel.Top;
  CompImage.Width := CompImage.Width + ScaleX(128);
  CompImage.Height := CompLabel.Height + ScaleX(128);
  CompImage.Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width - CompLabel.Width;

  WizardForm.ComponentsList.Height := WizardForm.ComponentsList.Height - CompLabel.Height - ScaleY(8);
end;

procedure InitializeWizard2();
begin
  CompPageModified := False;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurpageID = wpSelectComponents then
  begin
    SaveComponentsPage(CompPagePositions);
    LoadComponentsPage(CompPagePositions, ScaleY(250));
    CompPageModified := True;
  end
  else
  if CompPageModified then
  begin
    LoadComponentsPage(CompPagePositions, 0);
    CompPageModified := False;
  end;
end;

procedure InitializeWizard();
begin 
  InitializeWizard1();
  InitializeWizard2();
end;

enter image description here

1 个答案:

答案 0 :(得分:2)

根据本指南,只需复制两个代码并合并InitializeWizard实现:
Merging event function (InitializeWizard) implementations from different sources

实际上,Larger “Select Components” page in Inno Setup中的InitializeWizard是noop。你可以跳过它。而且你不需要合并任何东西。

您需要做的唯一其他更改不是放大ComponentsList中的LoadComponentsPage