0

I need help from you to merge two scripts found here to have preview image on a maximized components windows:


Edit: Thanks to Martin Prikryl. With his patience and his help, I successfully merge these two scripts.

Your preview image should have a resolution of 208x165 in .bmp

[Files]

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

[Code]

    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

Community
  • 1
  • 1
yaya 070
  • 45
  • 1
  • 6
  • Possible duplicate of [Merging event function (InitializeWizard) implementations from different sources](http://stackoverflow.com/questions/40512631/merging-event-function-initializewizard-implementations-from-different-sources) – Martin Prikryl Nov 15 '16 at 20:55
  • first message edited – yaya 070 Nov 16 '16 at 00:18
  • I was able to enlarge the size of the preview With a component window size of 250 `LoadComponentsPage (CompPagePositions, ScaleY (250));` `CompImage.Width: = CompImage.Width + ScaleX (128);` `CompLabel.Width: = WizardForm.ComponentsList.Width div 2;` `CompLabel.Height: = (WizardForm.ComponentsList.Height - ScaleY (64)) div 2;` – yaya 070 Nov 16 '16 at 13:24
  • You did not copy the `CurPageChanged` event function implementation from the [Larger “Select Components” page in Inno Setup](http://stackoverflow.com/q/20584671/850848). – Martin Prikryl Nov 16 '16 at 13:51
  • Actually because I can not do it – yaya 070 Nov 16 '16 at 14:05
  • First, if you have this specific problem, you should have told us from the very beginning and not having us guess. Second, why you cannot do it? Just copy it over! – Martin Prikryl Nov 16 '16 at 14:11
  • All my apologies if I misunderstood, I wanted to know how to merge the 2 scripts, reading the link on "Merging event function" but I did not understand. I'm not an encoder. I will retry, if I do not arrive tampis. Thank you for your help and your time, sorry – yaya 070 Nov 16 '16 at 14:34
  • Actually, the `InitializeWizard` in the [Larger “Select Components” page in Inno Setup](http://stackoverflow.com/q/20584671/850848) is noop. You can skip that. And you do not need to merge anything. – Martin Prikryl Nov 16 '16 at 14:41
  • Use `ScaleY(150)`, instead of fixed `150`. – Martin Prikryl Nov 16 '16 at 21:51
  • oh thx i made that – yaya 070 Nov 16 '16 at 22:47

1 Answers1

2

Just copy both codes and merge the InitializeWizard implementations according to this guide:
Merging event function (InitializeWizard) implementations from different sources.

Though, actually, the InitializeWizard in the Larger “Select Components” page in Inno Setup is noop. You can skip that. And you do not need to merge anything.

The only other change you need to do, is not to enlarge the ComponentsList in the LoadComponentsPage.

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • But if I do not put the initializewizard of Larger "Select Components" page in Inno Setup how I can have this [link](http://i.imgur.com/AUOgRuL.png) – yaya 070 Nov 16 '16 at 14:54
  • As I wrote above, the `InitializeWizard` in the "Larger "Select Components" page in Inno Setup" does nothing! So if you do not copy it, it won't have any effect on the functionality. – Martin Prikryl Nov 16 '16 at 15:21
  • OK! I do not understand. I drop and continue to use the code that allows me to display the enlarged component window with description and preview maximized at 208x165.bmp. But with all the windows enlarged ... Thank you for your patience and your help I put my last code in my first message. THX again and great job – yaya 070 Nov 16 '16 at 16:08
  • What is it that you do not understand? Once again: take both codes. Append them one after another. And just remove the `InitializeWizard` function from the "Larger "Select Components" page in Inno Setup". And comment out the `WizardForm.ComponentsList.Height := Storage[4] + HeightOffset;` line. I cannot be any more clear. – Martin Prikryl Nov 16 '16 at 18:58