Получить ScrollInfo для TNewCheckListBox (Inno Setup)

Я пытаюсь использовать код положения полосы прокрутки из эту статью, чтобы получить положение полосы прокрутки объекта TNewCheckListBox, который я определил.

Похоже, что параметр дескриптора недоступен.

Я хочу иметь возможность настроить соответствующее сообщение наведения в соответствии с положением прокрутки. В настоящее время, когда пользователь прокручивает страницу вниз, всплывающее сообщение остается относительно первых x элементов TNewCheckListBox.

    procedure OnScrollPosition(Wnd: HWND; Msg: UINT; TimerID: UINT_PTR; SysTime: DWORD);
    var
      ScrollInfo: TScrollInfo;
    begin
      ScrollInfo.cbSize  := SizeOf(ScrollInfo);
      ScrollInfo.fMask    := SIF_RANGE or SIF_POS or SIF_PAGE;
         if GetScrollInfo(WizardForm.LicenseMemo.Handle, SB_VERT, ScrollInfo) then
                       // Above ^ WizardForm.LicenceMemo.Handle needs to be the
                       // handle for my TNewCheckListBox object!
          if ScrollInfo.nPos = ScrollInfo.nMax - ScrollInfo.nPage then
            begin
              WizardForm.LicenseAcceptedRadio.Enabled := True;
              WizardForm.LicenseNotAcceptedRadio.Enabled := True;
            end;
    end;

Любая помощь/идеи будут высоко оценены!

Вот полный код...

    [Setup]
    AppName=MyProg
    AppVersion=1.0
    CreateAppDir=No
    LicenseFile=Licence.rtf

    [Files]
    Source: Message1.rtf;  Flags: dontcopy;
    Source: Message2.rtf;  Flags: dontcopy;
    Source: Message3.rtf;  Flags: dontcopy;
    Source: Message4.rtf;  Flags: dontcopy;
    Source: Message5.rtf;  Flags: dontcopy;
    Source: Message6.rtf;  Flags: dontcopy;
    Source: Message7.rtf;  Flags: dontcopy;
    Source: Message8.rtf;  Flags: dontcopy;
    Source: Message9.rtf;  Flags: dontcopy;
    Source: Message10.rtf; Flags: dontcopy;
    Source: Message11.rtf; Flags: dontcopy;
    Source: Message12.rtf; Flags: dontcopy;
    Source: Message13.rtf; Flags: dontcopy;
    Source: Message14.rtf; Flags: dontcopy;
    Source: Message15.rtf; Flags: dontcopy;
    Source: Message16.rtf; Flags: dontcopy;
    Source: Message17.rtf; Flags: dontcopy;
    Source: Message18.rtf; Flags: dontcopy;
    Source: Message19.rtf; Flags: dontcopy;


    ;-- Window API .dll and Timer functions .dll
    Source: user32.dll;       Flags: dontcopy;
    Source: InnoCallback.dll; Flags: dontcopy; 

    [Code]

    //---------------------------------------------------------------------------
    // Setup for Windows API functions
    //---------------------------------------------------------------------------
    const
      SB_VERT   = 1;  // Indicate we want to know about the vertical bar (0 or 1)
      SIF_RANGE = 1;  // Copy the range of the scroll bar to nMin and nMax (0 or 1)
      SIF_POS   = 4;
      SIF_PAGE  = 2;

    type
      TScrollInfo = record
        cbSize   : UINT;
        fMask    : UINT;
        nMin     : Integer;
        nMax     : Integer;
        nPage    : UINT;
        nPos     : Integer;
        nTrackPos: Integer;
      end;


    var
      Page      : TWizardPage;
      ListBox   : TNewCheckListBox;
      Memo      : TRichEditViewer;
      CheckLabel: TLabel;
      MouseY    : integer;

    type
      TTimerProc = procedure(Wnd: HWND; Msg: UINT; TimerID: UINT_PTR; SysTime: DWORD);

    //---------------------------------------------------------------------------
    // Define Windows API functions
    //---------------------------------------------------------------------------
    function GetScrollInfo(hWnd: HWND; BarFlag: Integer; var ScrollInfo: TScrollInfo): BOOL;
              external '[email protected] stdcall';

    function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord;
              external 'wrapcallback@files:InnoCallback.dll stdcall';    
    function SetTimer(hWnd: HWND; nIDEvent, uElapse: UINT; lpTimerFunc: UINT): UINT; 
              external '[email protected] stdcall';
    function KillTimer(hWnd: HWND; uIDEvent: UINT): BOOL; 
              external '[email protected] stdcall';


    //---------------------------------------------------------------------------
    // Functions for checking scroll position via Windows API
    //---------------------------------------------------------------------------
    procedure OnScrollPosition(Wnd: HWND; Msg: UINT; TimerID: UINT_PTR; SysTime: DWORD);
    var
      ScrollInfo: TScrollInfo;
    begin
      ScrollInfo.cbSize  := SizeOf(ScrollInfo);
      ScrollInfo.fMask    := SIF_RANGE or SIF_POS or SIF_PAGE;
        if GetScrollInfo(WizardForm.LicenseMemo.Handle, SB_VERT, ScrollInfo) then
          if ScrollInfo.nPos = ScrollInfo.nMax - ScrollInfo.nPage then
            begin
              WizardForm.LicenseAcceptedRadio.Enabled := True;
              WizardForm.LicenseNotAcceptedRadio.Enabled := True;
            end;
    end;

    procedure ScrollPosition();
    var
      TimerCallback: LongWord;
      TimerID: UINT_PTR;
    begin
      TimerCallback := WrapTimerProc(@OnScrollPosition, 4);
      TimerID := SetTimer(0, 0, 500, TimerCallback);
    end;

    //---------------------------------------------------------------------------
    // Define what happens when a certain page is selected
    //---------------------------------------------------------------------------
    procedure CurPageChanged(CurPageID: Integer);
    var
      ScrollInfo: TScrollInfo;
    begin 

    if CurPageID = wpLicense then
      WizardForm.LicenseAcceptedRadio.Enabled := False;
      WizardForm.LicenseNotAcceptedRadio.Enabled := False;
      ScrollPosition
    end;

    //---------------------------------------------------------------------------
    // Functions to show hover messages and check boxes
    //---------------------------------------------------------------------------
    function CheckedBox(ItemNumber: integer): Boolean;
    begin                                    
      Result:= ListBox.Checked[ItemNumber]; 
    end;
    procedure CheckOnClick (Sender: TObject);
    begin
      if MouseY < ListBox.Items.Count then
        begin 
          ListBox.Checked[MouseY]:= Not(ListBox.Checked[MouseY]);
        end;
    end;

    procedure CheckMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    begin 
      MouseY:= Y/ScaleY(16);
      if MouseY < ListBox.Items.Count then
        begin
          Memo.RTFText:= TStrings(ListBox.ItemObject[MouseY]).Text;
        end;
    end;

    //---------------------------------------------------------------------------
    // Program entry point...
    //---------------------------------------------------------------------------
    procedure InitializeWizard();
    var
      Index: Integer;
    begin
      ExtractTemporaryFile('Message1.rtf'); 
      ExtractTemporaryFile('Message2.rtf');
      ExtractTemporaryFile('Message3.rtf');
      ExtractTemporaryFile('Message4.rtf'); 
      ExtractTemporaryFile('Message5.rtf');
      ExtractTemporaryFile('Message6.rtf');
      ExtractTemporaryFile('Message7.rtf'); 
      ExtractTemporaryFile('Message8.rtf');
      ExtractTemporaryFile('Message9.rtf');
      ExtractTemporaryFile('Message10.rtf'); 
      ExtractTemporaryFile('Message11.rtf');
      ExtractTemporaryFile('Message12.rtf');
      ExtractTemporaryFile('Message13.rtf'); 
      ExtractTemporaryFile('Message14.rtf');
      ExtractTemporaryFile('Message15.rtf');
      ExtractTemporaryFile('Message16.rtf'); 
      ExtractTemporaryFile('Message17.rtf');
      ExtractTemporaryFile('Message18.rtf');
      ExtractTemporaryFile('Message19.rtf');

      WizardForm.LicenseAcceptedRadio.Enabled := False;
      WizardForm.LicenseNotAcceptedRadio.Enabled := False;

      Page:=CreateCustomPage(wpLicense, 'A Page', 'This is a custom page with hover functionality.')

      ListBox:= TNewCheckListBox.Create(Page); 
      with ListBox do
        begin
          Left   := 15
          Top    := 0
          Width  := 200
          Height := 149
          Parent := Page.Surface
          AddCheckBox('Check Box Group Item', '', 0, True, True, True, True, TStringList.Create);
          AddCheckBox('Check Box Item 1', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 2', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 3', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 4', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 5', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 6', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 7', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 8', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 9', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 10', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 11', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 12', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 13', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 14', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 15', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 16', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 17', '', 1, True, True, False, True, TStringList.Create);
          AddCheckBox('Check Box Item 18', '', 1, True, True, False, True, TStringList.Create)

          TStrings(ItemObject[0]).LoadFromFile(ExpandConstant('{tmp}\Message1.rtf'));
          TStrings(ItemObject[1]).LoadFromFile(ExpandConstant('{tmp}\Message2.rtf'));
          TStrings(ItemObject[2]).LoadFromFile(ExpandConstant('{tmp}\Message3.rtf'));
          TStrings(ItemObject[3]).LoadFromFile(ExpandConstant('{tmp}\Message4.rtf'));
          TStrings(ItemObject[4]).LoadFromFile(ExpandConstant('{tmp}\Message5.rtf'));
          TStrings(ItemObject[5]).LoadFromFile(ExpandConstant('{tmp}\Message6.rtf'));
          TStrings(ItemObject[6]).LoadFromFile(ExpandConstant('{tmp}\Message7.rtf'));
          TStrings(ItemObject[7]).LoadFromFile(ExpandConstant('{tmp}\Message8.rtf'));
          TStrings(ItemObject[8]).LoadFromFile(ExpandConstant('{tmp}\Message9.rtf'));
          TStrings(ItemObject[9]).LoadFromFile(ExpandConstant('{tmp}\Message10.rtf'));
          TStrings(ItemObject[10]).LoadFromFile(ExpandConstant('{tmp}\Message11.rtf'));
          TStrings(ItemObject[11]).LoadFromFile(ExpandConstant('{tmp}\Message12.rtf'));
          TStrings(ItemObject[12]).LoadFromFile(ExpandConstant('{tmp}\Message13.rtf'));
          TStrings(ItemObject[13]).LoadFromFile(ExpandConstant('{tmp}\Message14.rtf'));
          TStrings(ItemObject[14]).LoadFromFile(ExpandConstant('{tmp}\Message15.rtf'));
          TStrings(ItemObject[15]).LoadFromFile(ExpandConstant('{tmp}\Message16.rtf'));
          TStrings(ItemObject[16]).LoadFromFile(ExpandConstant('{tmp}\Message17.rtf'));
          TStrings(ItemObject[17]).LoadFromFile(ExpandConstant('{tmp}\Message18.rtf'));
          TStrings(ItemObject[18]).LoadFromFile(ExpandConstant('{tmp}\Message19.rtf'));
        end;

      Memo:= TRichEditViewer.Create(Page); 
      with Memo do
        begin
          Left        := ListBox.Left + ListBox.Width + 8;
          Top         := ListBox.Top;
          Width       := ListBox.Width;
          Height      := ListBox.Height;
          Color       := clBtnFace;
          Enabled     := False;
          BorderStyle := bsNone;
          Parent      := Page.Surface;
        end;

      CheckLabel:= TLabel.Create(Page); 
      with CheckLabel do
        begin
          Width       := ListBox.Width;
          Height      := ListBox.Height;
          Autosize    := False;
          Transparent := True;
          OnMouseMove := @CheckMouseMove;
          OnClick     := @CheckOnClick;
          Parent      := ListBox;
          Cursor      := 1;
        end;
    end;

person Tom Clarke    schedule 19.09.2014    source источник
comment
Что такое объекты, не созданные WizardForm? Или какую проблему вы пытаетесь решить? Вы спрашиваете, как получить информацию о прокрутке для вашего TNewCheckListBox? Кстати. не включайте библиотеку user32.dll в вашу установку.   -  person TLama    schedule 19.09.2014
comment
Извините, да, именно об этом я и спрашиваю. Спасибо, что предупредили меня не включать user32.dll. Как лучше всего получить доступ к Windows API?   -  person Tom Clarke    schedule 19.09.2014
comment
Да я вижу. Что ж, вы объявили свой объект как глобальную переменную ListBox (что необходимо для методов, чтобы видеть ваш объект), так что давайте просто передадим ListBox.Handle вместо WizardForm.LicenseMemo.Handle. На ваш вопрос о Windows API: функции Windows API являются частью системы пользователя и встроены в библиотеки, из которых вы их импортируете (точно так же, как вы импортировали GetScrollInfo из user32.dll), поэтому лучшего< /i> путь. Есть только один способ; как вы это делаете. Вы просто включили user32.dll в свою настройку, которая в любом случае не будет использоваться.   -  person TLama    schedule 19.09.2014
comment
Большое спасибо за ваши быстрые ответы. Сначала я попытался сослаться на объект ListBox через Page.ListBox.Handle, поэтому ошибся. Я также попытался включить библиотеку user32.dll, используя Source: "{sys}\user32.dll;" в качестве пути, но Inno, похоже, не распознает константу и вместо этого использует путь к папке установки с добавленным к ней исходным путем. Передать ли «внешний» флаг файлу?   -  person Tom Clarke    schedule 19.09.2014
comment
Нет нет. Если вы внимательно посмотрите на импорт функций, вы увидите основную разницу. Функция GetScrollInfo (которая является Windows API) имеет хвост, подобный @user32.dll, в то время как WrapTimerProc (которая является функцией из пользовательской библиотеки) использует @files:InnoCallback.dll. Этот префикс files: указывает Inno Setup извлечь InnoCallback.dll из раздела [Files], поэтому эта библиотека должна быть включена туда. Импорт функции GetScrollInfo не имеет такого префикса и поэтому ищется по these rules...   -  person TLama    schedule 19.09.2014
comment
...в системе. Не включайте user32.dll в настройки. Это часть системы. Поэтому просто удалите запись user32.dll из раздела [Files]. Он так и не был использован.   -  person TLama    schedule 19.09.2014
comment
Спасибо, что прояснили это.   -  person Tom Clarke    schedule 19.09.2014