Вопрос Как добавить описание под картинку через botva2? [Или: вывод изображения и описания через botva2]

  • Автор темы Автор темы Toni12
  • Дата начала Дата начала
Опять я со своим 125% масштабом:acute: Как пофиксить?
и участок получения размера изображения:
Код:
  ComponentImg:=pImgLoad(ComponetForm.Handle, FileName, 0,0,0,0, False, False);
  ImgGetPosition(ComponentImg, Get_Left, Get_Top, Get_Width, Get_Height);

Лучше переписать на сам Inno Setup: Ссылка на пост

Тогда можно будет использовать:
Код:
ComponentImg:=pImgLoad(ComponetForm.Handle, FileName, ScaleX(0),ScaleY(0),ComponetForm.Width,ComponetForm.Height, True, False);
Чтобы растянуть картинку при увеличение формы
 
Этот код не стал работать на 6.2, выдал ошибку "Unknown identifier 'WrapTimerProc' ". Не подошло....
Так надо задать индификатор (и тащить библиотеку InnoCallBack.dll или CallbackCtrl.dll) или поменять (для Inno Setup 6.0 и выше):
Код:
WrapTimerProc(@..., 4)
на
Код:
CreateCallback(@...)
 
Так надо задать индификатор (и тащить библиотеку InnoCallBack.dll или CallbackCtrl.dll) или поменять (для Inno Setup 6.0 и выше):
Код:
WrapTimerProc(@..., 4)
на
Код:
CreateCallback(@...)

Библиотека и так подгружена, осталось от прошлых скриптов.
CreateCallback(@...)
Так же ошибку выдал.
 
Наконец-то дома. По сути сейчас на руках такой вариант скрипта, но без текстового описания, зато компилится на 6.2.

Был 2, но я его случайно удалил из-за путаницы в файлах...
 

Вложения

Библиотека и так подгружена, осталось от прошлых скриптов.
CreateCallback(@...)
Так же ошибку выдал.
Там полный код выглядит так:
Код:
[Setup]
AppName=My Application
AppVersion=1.5
CreateAppDir=no

[Components]
Name: comp1; Description: "Компонент 1";
Name: comp2; Description: "Компонент 2";
Name: comp3; Description: "Компонент 3";

[Files]
Source: "Main.bmp"; Flags: dontcopy
Source: "Additional.bmp"; Flags: dontcopy
Source: "Help.bmp"; Flags: dontcopy

[code]
var
  LastMouse: TPoint;
  CompLabel: TLabel;
  CompImage: TBitmapImage;
  LoadingImage: Boolean;

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;
  Image: string;
  ImagePath: string;
begin
  case Index of
    0: begin Description := 'This is the description of Main Files'; Image := 'main.bmp'; end;
    1: begin Description := 'This is the description of Additional Files'; Image := 'additional.bmp'; end;
    2: begin Description := 'This is the description of Help Files'; Image := 'help.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) 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 - ScaleX(16)) div 2;
  CompLabel.Height := ScaleY(64);
  CompLabel.Top := WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height - CompLabel.Height;
  CompLabel.AutoSize := False;
  CompLabel.WordWrap := True;

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

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

И он изначально подстроен под 6.0 и выше.
 
Там полный код выглядит так:
Код:
[Setup]
AppName=My Application
AppVersion=1.5
CreateAppDir=no

[Components]
Name: comp1; Description: "Компонент 1";
Name: comp2; Description: "Компонент 2";
Name: comp3; Description: "Компонент 3";

[Files]
Source: "Main.bmp"; Flags: dontcopy
Source: "Additional.bmp"; Flags: dontcopy
Source: "Help.bmp"; Flags: dontcopy

[code]
var
  LastMouse: TPoint;
  CompLabel: TLabel;
  CompImage: TBitmapImage;
  LoadingImage: Boolean;

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;
  Image: string;
  ImagePath: string;
begin
  case Index of
    0: begin Description := 'This is the description of Main Files'; Image := 'main.bmp'; end;
    1: begin Description := 'This is the description of Additional Files'; Image := 'additional.bmp'; end;
    2: begin Description := 'This is the description of Help Files'; Image := 'help.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) 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 - ScaleX(16)) div 2;
  CompLabel.Height := ScaleY(64);
  CompLabel.Top := WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height - CompLabel.Height;
  CompLabel.AutoSize := False;
  CompLabel.WordWrap := True;

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

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

И он изначально подстроен под 6.0 и выше.


Думал я где-то ошибся, но нет, он действительно не выводит текст и изображение у меня
 
@Toni12, вот вам рабочее решение (напримере кода от Nemko) по выводу формы с описанием и картинкой для любых версий inno:

2 варианта для botva и на расширенной версии от Leserg
Размер высоты участка текста регулируется через #define HeightInfo "желаемое число высоты"
 

Вложения

Последнее редактирование:
@Toni12, вот вам рабочее решение (напримере кода от Nemko) по выводу формы с описанием и картинкой для любых версий inno:

2 варианта для botva и на расширенной версии от Leserg
Размер высоты участка текста регулируется через #define HeightInfo "желаемое число высоты"

Спасибо! Первый вариант на Ботве подошёл)
 
Не знаю зачем это здесь, но пусть будет.
Закинул пару комментариев. (Место изменения подложки под текстом и автоматическое масштабирование текста в рамке)
 

Вложения

и автоматическое масштабирование текста в рамке
не надо вывешивать свойства масштабирование на обновление окна, а добавить в сам задаваемый элемент:
Код:
ComponetLabel:= TLabel.Create(ComponetForm);
  with ComponetLabel do
  begin
    Parent:= ComponetForm;
    Caption:= '';
    AutoSize := True;   // Перенос строки
    WordWrap:= True;     //
    Transparent:= True; //
  end;
 
Последнее редактирование:
Просматривал на днях ветку ISDone ради полезной информации и случайно наткнулся на эту форму компонентов. Естественно стало интересно на чём она подготовлена. Я так понял, что там botva2 не задействована. Есть ли интерпретация данной формы под стиль modern с использованием превью изображений jpg/png? Хотелось бы её поковырять в Inno Setup VCL ради интереса.

Пример.jpg
 
Есть ли интерпретация данной формы под стиль modern с использованием превью изображений jpg/png? Хотелось бы её поковырять в Inno Setup VCL ради интереса.
Что-то вроде этого . На форуме есть несколько реализаций, поищите
 
Что-то вроде этого . На форуме есть несколько реализаций, поищите
На 45-й строчке компилятор выдаёт ошибку, мол неизвестный тип Area: TItemArea и соответственно весь блок procedure ShowCompDescription(Sender: TObject; X, Y, Index: Integer; Area: TItemArea); уже не рабочий. С чем может быть связана данная проблема?
 
@Cyberworm, нет такого функционала в чистой inno и расширенной от leserg, пример чисто для китайской версии.
 
@Cyberworm, нет такого функционала в чистой inno и расширенной от leserg, пример чисто для китайской версии.
Значит только один выход в этом случае - это botva2. Главное теперь подогнать размер блоков описания компонентов и их превью под WizardStyle=modern
 
Спасибо, всё работает. Правда пришлось немного повозиться с габаритами блоков ради WizardStyle=modern
Компоненты.jpg
Тем не менее Info Picture Form считаю более продвинутым (или универсальным) решением за счёт вызова внешней функции просмотра кастомного разрешения и прикрученного к картинке текста. И самый главный плюс, что в наличии имеется готовая форма для Inno Setup VCL. Поэтому всего скорей буду его использовать для переработки старого русификатора к игре Arma: Cold War Assault, который в бородатые времена был собран в NSIS. Ещё иногда смотрю в сторону FMXInno, но там сдерживающим фактором является то, что его используют для репаков. Я этим не промышляю, так что насколько целесообразно использовать комплекс FMXInno для русификации игр?
 
Назад
Сверху