You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Inno Setup脚本中组件预览图和描述无法加载?

问题修复方案

核心问题分析

你的代码存在两个主要问题:

  1. 按钮消失:不必要地修改了OuterNotebook和InnerNotebook的高度,破坏了向导表单的锚定布局;同时在初始化阶段就修改了组件列表高度,导致保存的原始位置不正确。
  2. 预览/描述不加载:FindControl函数可能无法正确识别嵌套的组件列表控件;HoverComponentChanged中未在鼠标离开时重置图片路径,导致逻辑错误。

修复后的完整代码

[Files] 部分(无需修改)

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

[Components] 部分(无需修改)

Name: "Component1"; Description: "1*"; Types: Component1;
Name: "Component2"; Description: "2*"; Types: Component2;
Name: "Component3"; Description: "3*"; Types: Component3;

[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 WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord; external 'wrapcallback@files:InnoCallback.dll stdcall';

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

procedure HoverComponentChanged(Index: Integer);
var 
  Description: string;
  Image: string;
  ImagePath: string;
begin
  Image := ''; // 初始化图片路径为空
  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
    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;
  ClientP: TPoint;
  Index: Integer;
begin
  GetCursorPos(P);
  if P <> LastMouse then
  begin
    LastMouse := P;
    // 直接检查鼠标是否在组件列表上,避免嵌套控件查找问题
    ClientP := P;
    ScreenToClient(WizardForm.ComponentsList.Handle, ClientP);
    if PtInRect(WizardForm.ComponentsList.ClientRect, ClientP) then
    begin
      // 使用内置方法获取鼠标指向的列表项索引
      Index := WizardForm.ComponentsList.ItemAtPos(ClientP, True);
    end
    else
    begin
      Index := -1;
    end;

    HoverComponentChanged(Index);
  end;
end;

type
  TPositionStorage = array of Integer;

var
  CompPageModified: Boolean;
  CompPagePositions: TPositionStorage;

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

  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.Bevel.Top;
  Storage[6] := WizardForm.BeveledLabel.Top;
  Storage[7] := WizardForm.ComponentsDiskSpaceLabel.Top;
end;

procedure LoadComponentsPage(const Storage: TPositionStorage;
  HeightOffset: Integer);
begin
  if GetArrayLength(Storage) <> 8 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;
  
  // 仅在进入组件页面时调整列表高度
  if HeightOffset > 0 then
    WizardForm.ComponentsList.Height := Storage[4] - CompLabel.Height - ScaleY(8)
  else
    WizardForm.ComponentsList.Height := Storage[4];
    
  WizardForm.Bevel.Top := Storage[5] + HeightOffset;
  WizardForm.BeveledLabel.Top := Storage[6] + HeightOffset;
  WizardForm.ComponentsDiskSpaceLabel.Top := Storage[7] + 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 + ScaleY(8);
  CompLabel.AutoSize := false;
  CompLabel.WordWrap := True;
  CompLabel.Anchors := [akLeft, akBottom]; // 锚定到左侧和页面底部

  CompImage := TBitmapImage.Create(WizardForm);
  CompImage.Parent := WizardForm.SelectComponentsPage;
  CompImage.Top := CompLabel.Top;
  CompImage.Width := ScaleX(128);
  CompImage.Height := ScaleY(128);
  CompImage.Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width - CompImage.Width;
  CompImage.Anchors := [akRight, akBottom]; // 锚定到右侧和页面底部
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;

关键修复点说明

  1. 移除不必要的控件高度修改:删除了对OuterNotebook和InnerNotebook的高度调整,依赖向导表单的锚定布局自动适配高度变化。
  2. 调整组件列表高度时机:将组件列表高度的修改移至进入组件页面时,确保保存的是原始布局位置。
  3. 简化鼠标悬停检测:直接检查鼠标是否在组件列表控件范围内,使用内置ItemAtPos方法获取列表项索引,避免嵌套控件查找的潜在问题。
  4. 修复图片路径重置逻辑:在HoverComponentChanged中初始化图片路径为空,确保鼠标离开组件时隐藏预览图。
  5. 添加控件锚定:为描述标签和预览图设置锚定属性,确保表单高度变化时控件位置正确。

内容的提问来源于stack exchange,提问作者Lilith Helsente

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:07:02