2014-04-09 4 views
2

Можно ли изменить .Font.Style на Фокус TLabel или TNewStaticText, как это происходит с курсором, когда мы используем .Cursor?TLabel или TNewStaticText - изменить .Font.Style на Фокус, как изменения курсора с .Cursor

+1

Пожалуйста, сделайте комментарий - просто DownVoting не поможет решить проблему. – RobeN

ответ

1

В настоящее время нет встроенной поддержки для отслеживания наведения курсора в Inno Setup. Однако, перехватывая оконную процедуру элементов управления, вы можете отслеживать это самостоятельно. В следующем примере вам потребуется 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 '[email protected] stdcall'; 
function ReleaseCapture: BOOL; 
    external '[email protected] stdcall'; 
function GetMessagePos: DWORD; 
    external '[email protected] stdcall'; 
function GetWindowRect(hWnd: HWND; out lpRect: TRect): BOOL; 
    external '[email protected] 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 '[email protected]: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; 
+0

Это именно то, чего я хотел достичь, и я ожидал, что это будет не простая функция :-) Спасибо! – RobeN

+0

Добро пожаловать! – TLama

+0

Можно ли подключить такую ​​функцию к 'TBitmapImage'? – RobeN

1

для меня следующая команда: High(ControlList) дает мне следующее сообщение об ошибке: Неизвестный идентификатор «High», я считаю, что High он доступен только для Unicode Inno ?? (Поправьте меня если я ошибаюсь :-).)

Я заработал, заменив High(ControlList) на GetArrayLength(ControlList)-1.

+0

Да, я всегда работаю с Unicode Inno Setup. Нет разумной причины использовать ANSI в 2014 году;) – TLama