Long descriptions on Inno Setup components

前端 未结 2 1501
花落未央
花落未央 2020-11-27 20:59

I am building an install with Inno Setup and I am using the components section to allow the end user to select optional items to install.

Some of these items need a

相关标签:
2条回答
  • 2020-11-27 21:06

    This solution uses only Inno Setup proper (not the obsolete 3rd party build of the Inno Setup of suspicious origin).

    The solution is partially based on my answer to Inno Setup: OnHover event.

    Adjust the HoverComponentChanged procedure to your needs.

    [Code]
    
    var
      LastMouse: TPoint;
      CompLabel: TLabel;
    
    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 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;
    
    procedure HoverComponentChanged(Index: Integer);
    var 
      Description: string;
    begin
      case Index of
        0: Description := 'This is the description of Main Files';
        1: Description := 'This is the description of Additional Files';
        2: Description := 'This is the description of Help Files';
      else
        Description := 'Move your mouse over a component to see its description.';
      end;
      CompLabel.Caption := Description;
    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) and
           (not WizardForm.TypesCombo.DroppedDown) then
        begin
          P := LastMouse;
          ScreenToClient(WizardForm.ComponentsList.Handle, P);
          Index := ListBoxItemAtPos(WizardForm.ComponentsList, P);
        end;
    
        HoverComponentChanged(Index);
      end;
    end;
    
    procedure InitializeWizard();
    begin
      SetTimer(0, 0, 50, CreateCallback(@HoverTimerProc));
    
      CompLabel := TLabel.Create(WizardForm);
      CompLabel.Parent := WizardForm.SelectComponentsPage;
      CompLabel.Left := WizardForm.ComponentsList.Left;
      CompLabel.Width := WizardForm.ComponentsList.Width;
      CompLabel.Height := ScaleY(32);
      CompLabel.Top :=
        WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height - CompLabel.Height;
      CompLabel.AutoSize := False;
      CompLabel.WordWrap := True;
    
      WizardForm.ComponentsList.Height :=
        WizardForm.ComponentsList.Height - CompLabel.Height - ScaleY(8);
    end;
    

    For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library. Use the Unicode version of Inno Setup 5.

    0 讨论(0)
  • 2020-11-27 21:19

    Use this advanced compiler (download link is somewhere below).

    It supports more classes and events than the standard compiler. You can access the property "OnItemMouseMove". Using this you can store a description for every item that is shown by a label. Here is an example:

    var
    CompLabel: TLabel;
    
    procedure OnItemMouseMove(Sender: TObject; X, Y: Integer; Index: Integer; Area: TItemArea);
    begin
      case Index of
        0: CompLabel.Caption := 'This is the description of Component 1';
        1: CompLabel.Caption := 'This is the description of Component 2';
        2: CompLabel.Caption := 'This is the description of Component 3';
        3: CompLabel.Caption := 'This is the description of Component 4'
      else
        CompLabel.Caption := 'Move your mouse over a component to see its description.';
      end;
    end;
    
    procedure OnMouseLeave(Sender: TObject);
    begin
      CompLabel.Caption := 'Move your mouse over a component to see its description.';
    end;
    
    procedure InitializeWizard();
    begin
      CompLabel := TLabel.Create(WizardForm);
      CompLabel.Parent := WizardForm.SelectComponentsPage;
      CompLabel.SetBounds(WizardForm.ComponentsList.Left,180,WizardForm.ComponentsList.Width,200);
      CompLabel.Caption := 'Move your mouse over a component to see its description.';
      WizardForm.ComponentsList.OnItemMouseMove := @OnItemMouseMove;
      WizardForm.ComponentsList.OnMouseLeave := @OnMouseLeave;
      WizardForm.ComponentsList.Height := WizardForm.ComponentsList.Height - 40;
    end;
    
    0 讨论(0)
提交回复
热议问题