2014-04-09 1 views
2
와 커서 변경처럼 초점에 .Font.Style을 변경

우리가 .Cursor를 사용할 때 커서로 일처럼 초점 TLabel 또는 TNewStaticText.Font.Style을 변경할 수 있습니까?TLabel 또는 TNewStaticText - .Cursor

+1

의견을 보내주십시오. 단지 DownVoting이 문제를 해결하는 데 도움이되지 않습니다. – RobeN

답변

1

현재 Inno Setup에서 마우스 유혹을 추적 할 수있는 내장 지원 기능이 없습니다. 그러나 컨트롤의 창 프로 시저를 가로 채서 직접 추적 할 수 있습니다. 다음 명령 나를 위해

[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) 나에게 다음과 같은 오류를주는 다음 예를 들어 당신은 InnoCallback 라이브러리가 필요합니다 알 수없는 식별자를 "높음"으로, 나는 그것이 유니 코드 이노에만 사용할 수 High 있다고 생각 ?? (틀 렸으면 고쳐줘 :-).)

High(ControlList)GetArrayLength(ControlList)-1으로 바꾸어 제작했습니다.

+0

예, 저는 항상 Unicode Inno Setup을 다루고 있습니다. 2014 년에 ANSI를 사용할 합리적인 이유는 없습니다.) – TLama