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 library which can help?
Asked
Active
Viewed 1,127 times
1

Martin Prikryl
- 188,800
- 56
- 490
- 992

Alexander Smith
- 369
- 2
- 16
2 Answers
3
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.

Martin Prikryl
- 188,800
- 56
- 490
- 992
0
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;

Ken White
- 123,280
- 14
- 225
- 444

Ramiro Cruzo
- 73
- 5
-
1Enhanced Ver is (chinese/russian) tweaked and unofficial (= unsupported) version of Inno Setup ?? – Slappy May 21 '16 at 12:31
-
I've been using it for about 5 years. It got better functionality & its in English too :D – Ramiro Cruzo May 21 '16 at 15:47