Inno Setup: OnHover event

前端 未结 2 1041
北海茫月
北海茫月 2020-12-20 04:45

Is it possible to simulate OnMouseHover event (to call a function when mouse is over some Inno Setup control) for Inno Setup controls, or is there any DLL libra

相关标签:
2条回答
  • 2020-12-20 04:56

    You can implement it by:

    • scheduling a very frequent timer (say 50 ms)
    • when the timer is triggered, find a control over which the cursor is positioned and check for changes.

    The following example displays name of the control with cursor over it on a label, like:

    [Code]
    
    var
      HoverLabel:TLabel;
      LastMouse: TPoint;
      LastHoverControl: TControl;
    
    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 FindControl(Parent: TWinControl; P: TPoint): TControl;
    var
      Control: TControl;
      WinControl: TWinControl;
      I: Integer;
      P2: TPoint;
    begin
      { Top-most controls are the last. We want to start with those. }
      for I := Parent.ControlCount - 1 downto 0 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;
    
    procedure HoverControlChanged(Control: TControl);
    begin
      if Control = nil then
      begin
        HoverLabel.Caption := 'no control';
      end
        else
      begin
        HoverLabel.Caption := Control.Name;
      end;
    end;
    
    procedure HoverTimerProc(
      H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
    var
      P: TPoint;
      Control: TControl; 
    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;
        
        if Control <> LastHoverControl then
        begin
          HoverControlChanged(Control);
          LastHoverControl := Control;
        end;
      end;
    end;
    
    procedure InitializeWizard();
    begin
      SetTimer(0, 0, 50, CreateCallback(@HoverTimerProc));
     
      HoverLabel := TLabel.Create(WizardForm);
      HoverLabel.Left := ScaleX(8);
      HoverLabel.Top := WizardForm.ClientHeight - ScaleY(32);
      HoverLabel.Parent := WizardForm;
      HoverLabel.Caption := 'starting';
    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.


    An alternative way to implement this without a timer is to handle relevant windows messages in a handler set using GWL_WNDPROC. For an example how to set the handler, see WM_CONTEXTMENU handling in Adding context menu to Inno Setup page.

    0 讨论(0)
  • 2020-12-20 05:00

    The following code is from the documentation of Inno Unicode Enhanced Ver. As you can see the OnMouseEnter & OnMouseLeave functions, you can use them to implement your OnHover function.

      TButton = class(TButtonControl)
        procedure Click;
        property OnMouseEnter: TNotifyEvent; read write;
        property OnMouseLeave: TNotifyEvent; read write;
      end;
    
    0 讨论(0)
提交回复
热议问题