是否可以像使用.Cursor
时使用光标那样更改Focus TLabel
或TNewStaticText
上的.Font.Style
?
目前没有内置支持在Inno设置中跟踪鼠标悬停。不过,通过截取控件的窗口过程,您可以自己跟踪它。对于以下示例,您将需要InnoCallback
库:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}My Program
OutputDir=userdocs:Inno Setup Examples Output
[Files]
Source: "InnoCallback.dll"; DestDir: "{tmp}"; Flags: dontcopy
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
GWL_WNDPROC = -4;
WM_MOUSEMOVE = $0200;
type
WPARAM = UINT_PTR;
LPARAM = LongInt;
LRESULT = LongInt;
TWindowProc = function(hwnd: HWND; uMsg: UINT; wParam: WPARAM;
lParam: LPARAM): LRESULT;
function SetCapture(hWnd: HWND): HWND;
external 'SetCapture@user32.dll stdcall';
function ReleaseCapture: BOOL;
external 'ReleaseCapture@user32.dll stdcall';
function GetMessagePos: DWORD;
external 'GetMessagePos@user32.dll stdcall';
function GetWindowRect(hWnd: HWND; out lpRect: TRect): BOOL;
external 'GetWindowRect@user32.dll stdcall';
function CallWindowProc(lpPrevWndFunc: LongInt; hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: LPARAM): LRESULT;
external 'CallWindowProc{#AW}@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer;
dwNewLong: LongInt): LongInt;
external 'SetWindowLong{#AW}@user32.dll stdcall';
function WrapWindowProc(Callback: TWindowProc; ParamCount: Integer): LongWord;
external 'wrapcallback@files:InnoCallback.dll stdcall';
type
TControlRec = record
Hovered: Boolean; // hovering state
WndProc: LongInt; // original window proc
Control: TWinControl; // control instance
end;
var
StaticText1: TNewStaticText;
StaticText2: TNewStaticText;
ControlList: array of TControlRec;
// helper function for finding control by handle
function GetControlRec(Handle: HWND): TControlRec;
var
I: Integer;
begin
for I := 0 to High(ControlList) do
if ControlList[I].Control.Handle = Handle then
begin
Result := ControlList[I];
Exit;
end;
end;
// function which attaches the intercepting window procedure to the control
// and creates and adds the control record to the control list
procedure AttachWndProc(Control: TWinControl; WindowProc: TWindowProc);
begin
SetArrayLength(ControlList, GetArrayLength(ControlList) + 1);
ControlList[High(ControlList)].Hovered := False;
ControlList[High(ControlList)].Control := Control;
ControlList[High(ControlList)].WndProc := SetWindowLong(Control.Handle,
GWL_WNDPROC, WrapWindowProc(WindowProc, 4));
end;
// function to restore windows procedures to all controls in the list
procedure RestoreWndProcs;
var
I: Integer;
begin
for I := 0 to High(ControlList) do
SetWindowLong(ControlList[I].Control.Handle, GWL_WNDPROC, ControlList[I].WndProc);
end;
// helper function to create a TPoint structure from the result of GetMessagePos
// function call
function MakePoint(Value: DWORD): TPoint;
begin
Result.X := Value and $FFFF;
Result.Y := Value shr 16;
end;
// helper function which substitutes PtInRect Windows API function which I wasn't
// able to import for some reason
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;
// interceptor window procedure
function StaticTextWndProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM;
lParam: LPARAM): LRESULT;
var
P: TPoint;
R: TRect;
ControlRec: TControlRec;
begin
// get control record
ControlRec := GetControlRec(hwnd);
// if the cursor moves, then...
if uMsg = WM_MOUSEMOVE then
begin
// set mouse capture for this control to be notified by the WM_MOUSEMOVE even if
// we leave the control
SetCapture(ControlRec.Control.Handle);
// get the current cursor position and control rectangle (both screen relative)
P := MakePoint(GetMessagePos);
GetWindowRect(ControlRec.Control.Handle, R);
// check if the cursor is inside the control; if yes, then...
if PointInRect(R, P) then
begin
// if the hovering flag was not yet set, it means we just entered the control
// with the mouse, so let's change the style and remember the hovering state
if not ControlRec.Hovered then
begin
if ControlRec.Control is TNewStaticText then
TNewStaticText(ControlRec.Control).Font.Style := [fsBold];
ControlRec.Hovered := True;
end;
end
else
begin
// the cursor is not over the control, so let's release the mouse capture, set
// the style and remember the hovering state
ReleaseCapture;
if ControlRec.Control is TNewStaticText then
TNewStaticText(ControlRec.Control).Font.Style := [];
ControlRec.Hovered := False;
end;
end;
// call the original window procedure
Result := CallWindowProc(ControlRec.WndProc, hwnd, uMsg, wParam, lParam);
end;
procedure InitializeWizard;
begin
StaticText1 := TNewStaticText.Create(WizardForm);
StaticText1.Parent := WizardForm;
StaticText1.Left := 12;
StaticText1.Top := 336;
StaticText1.Caption := 'Hello';
StaticText2 := TNewStaticText.Create(WizardForm);
StaticText2.Parent := WizardForm;
StaticText2.Left := 43;
StaticText2.Top := 336;
StaticText2.Caption := 'world!';
AttachWndProc(StaticText1, @StaticTextWndProc);
AttachWndProc(StaticText2, @StaticTextWndProc);
end;
procedure DeinitializeSetup;
begin
RestoreWndProcs;
end;
对我来说,以下命令:High(ControlList)
给了我以下错误:未知标识符"High",我相信High
它只适用于Unicode Inno??(如果我错了,请纠正我:-)
我用GetArrayLength(ControlList)-1
替换了High(ControlList)
,使它发挥了作用。