Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  

Показать сообщение отдельно

Аватара для El Sanchez

Ветеран


Contributor


Сообщения: 1271
Благодарности: 1029

Профиль | Отправить PM | Цитировать


Цитата Rikill:
а можно пример "хука на событие установки"? »
Rikill, событие отрисовки.

Цитата South:
смысла нет использовать для такой задачи хуки, достаточно сабклассинга »
South, спасибо, различия в терминах усвоил.

Пример кода отрисовки кастомного чекбокса. Реализовал 12 состояний. В качестве изображения для чекбокса взял btnimage.bmp из примеров Restools.
читать дальше »

Код: Выделить весь код
[Setup]
AppName=test
AppVerName=test
CreateAppDir=false
DefaultDirName={tmp}
UsePreviousAppDir=false
UsePreviousGroup=false
AlwaysShowComponentsList=true
FlatComponentsList=false
UsePreviousSetupType=false
UsePreviousTasks=false
UsePreviousUserInfo=false
DisableStartupPrompt=true
Uninstallable=false
AllowNoIcons=yes
BitmapResource=btn:{app}\btnimage.bmp

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[code]
type
    TPaintStruct = record
        hdc: Longint;
        fErase: BOOL;
        rcPaint: TRect;
        fRestore: BOOL;
        fIncUpdate: BOOL;
        rgbReserved: array [0..31] of byte;
    end;

    TCheckBoxArray = array of record
        Control: TWinControl;
        PrevWndProc: Longint;
    end;

const
    BM_GETCHECK = $F0;
    BM_GETSTATE = $F2;
    BST_UNCHECKED = $0;
    BST_CHECKED = $1;
    BST_INDETERMINATE = $2;
    BST_FOCUS = $8;
    BST_HOT = $200;
    BST_PUSHED = $4;
    CN_CTLCOLORSTATIC = $BD38;
    WM_PAINT = $F;
    COLOR_GRAYTEXT = 17;
    COLOR_BTNTEXT = 18;

var
    btn: TBitmapImage;
    ControlArray: TCheckBoxArray;

function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint;  external 'GetWindowLongA@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function BeginPaint(hWnd: HWND; var lpPaint: TPaintStruct): Longint; external 'BeginPaint@user32.dll stdcall';
function EndPaint(hWnd: HWND; const lpPaint: TPaintStruct): Boolean; external 'EndPaint@user32.dll stdcall';
function InvalidateRect(hWnd: HWND; lpRect: Longint; bErase: Boolean): Boolean; external 'InvalidateRect@user32.dll stdcall';
function GdiTransparentBlt(hdcDest: Longint; xoriginDest, yoriginDest, wDest, hDest: Integer; hdcSrc: Longint; xoriginSrc, yoriginSrc, wSrc, hSrc: Integer; crTransparent: UINT): Boolean; external 'GdiTransparentBlt@gdi32.dll stdcall';
function DrawText(hDC: Longint; lpchText: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; external 'DrawTextA@user32.dll stdcall';
function SetTextColor(hdc: Longint; crColor: DWORD): DWORD; external 'SetTextColor@gdi32.dll stdcall';
function SetBkMode(hdc: Longint; iBkMode: Integer): Integer; external 'SetBkMode@gdi32.dll stdcall';
function SelectObject(hdc: Longint; hgdiobj: Longint): LongWord; external 'SelectObject@gdi32.dll stdcall';
function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall';


function WndProc(hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint;
var
    i, id: Integer;
    ps: TPaintStruct;
    rs: TRect;
begin
    Result := 0;
    i := GetWindowLong(hWnd, -21);
    case Msg of
        CN_CTLCOLORSTATIC: InvalidateRect(hWnd, 0, False);
        WM_PAINT: begin
            InvalidateRect(hWnd, 0, True);
            BeginPaint(hWnd, ps);
            case SendMessage(hWnd, BM_GETSTATE, 0, 0) of
                BST_UNCHECKED + BST_FOCUS: id := 9;                                  
                BST_CHECKED + BST_FOCUS: id := 13;
                BST_INDETERMINATE + BST_FOCUS: id := 17;

                BST_UNCHECKED + BST_HOT: id := 10;
                BST_CHECKED + BST_HOT: id := 14;
                BST_INDETERMINATE + BST_HOT: id := 18;

                BST_UNCHECKED + BST_FOCUS + BST_HOT: id := 10;
                BST_CHECKED + BST_FOCUS + BST_HOT: id := 14;
                BST_INDETERMINATE + BST_FOCUS + BST_HOT: id := 18;

                BST_UNCHECKED + BST_FOCUS + BST_HOT + 100: id := 11;
                BST_CHECKED + BST_FOCUS + BST_HOT + 100: id := 15;
                BST_INDETERMINATE + BST_FOCUS + BST_HOT + 100: id := 19;
                
                BST_UNCHECKED + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 11;
                BST_CHECKED + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 15;
                BST_INDETERMINATE + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 19;
                
                BST_UNCHECKED: id := 9;
                BST_CHECKED: id := 13;
                BST_INDETERMINATE: id := 17;
            end;
            if not TNewCheckBox(ControlArray[i].Control).Enabled then
            case SendMessage(hWnd, BM_GETCHECK, 0, 0) of
                BST_UNCHECKED: id := 12;
                BST_CHECKED: id := 16;
                BST_INDETERMINATE: id := 20;
            end;
            GdiTransparentBlt(ps.hdc, 0, 0, ps.rcPaint.Bottom, ps.rcPaint.Bottom, btn.Bitmap.Canvas.Handle, id*btn.Bitmap.Height, 0, btn.Bitmap.Height, btn.Bitmap.Height, clFuchsia);
            SelectObject(ps.hdc, TNewCheckBox(ControlArray[i].Control).Font.Handle);
            SetBkMode(ps.hdc, 1);
            if TNewCheckBox(ControlArray[i].Control).Enabled then
                SetTextColor(ps.hdc, GetSysColor(COLOR_BTNTEXT))  //ãëîáàëüíûé öâåò òåêñòà ÷åêáîêñà
            else
                SetTextColor(ps.hdc, GetSysColor(COLOR_GRAYTEXT));
            rs.Left := ps.rcPaint.Bottom;
            rs.Top := (ps.rcPaint.Bottom - TNewCheckBox(ControlArray[i].Control).Font.Size) div 4;  //ïîäãîíêà ïî âåðòèêàëè, íåîïòèìàëüíî
            rs.Right := ps.rcPaint.Right - rs.Left;
            rs.Bottom := ps.rcPaint.Bottom;
            DrawText(ps.hdc, TNewCheckBox(ControlArray[i].Control).Caption, Length(TNewCheckBox(ControlArray[i].Control).Caption), rs, 0);
            EndPaint(hWnd, ps);
        end;
        else Result := CallWindowProc(ControlArray[i].PrevWndProc, hWnd, Msg, wParam, lParam);
    end;
end;

procedure SetOwnerDrawCheckBox(Ctrl: TWinControl);
var
    i: Integer;
begin
    if Assigned(Ctrl) then
    begin
        for i := 0 to Ctrl.ControlCount-1 do if Ctrl.Controls[i] is TWinControl then
        begin
            if (Ctrl.Controls[i] is TNewCheckBox) then
            begin
                SetArrayLength(ControlArray, GetArrayLength(ControlArray)+1);
                ControlArray[GetArrayLength(ControlArray)-1].Control := TWinControl(Ctrl.Controls[i]);
                ControlArray[GetArrayLength(ControlArray)-1].PrevWndProc := SetWindowLong(TWinControl(Ctrl.Controls[i]).Handle, -4, CallbackAddr('WndProc'));
                SetWindowLong(TWinControl(Ctrl.Controls[i]).Handle, -21, GetArrayLength(ControlArray)-1);
            end;
            if TWinControl(Ctrl.Controls[i]).ControlCount > 0 then SetOwnerDrawCheckBox(TWinControl(Ctrl.Controls[i]));
        end;
    end;
    if not Assigned(Ctrl) then
    begin
        for i := 0 to GetArrayLength(ControlArray)-1 do SetWindowLong(ControlArray[i].Control.Handle, -4, ControlArray[i].PrevWndProc);
        SetArrayLength(ControlArray, 0);
    end;
end;


procedure InitializeWizard();
begin
    with WizardForm do
    begin
        OuterNotebook.Hide;
        NoIconsCheck.Parent := WizardForm;
        NoIconsCheck.Left := 100;
        //NoIconsCheck.Height := 24;
        NoIconsCheck.Show;
        NoIconsCheck.AllowGrayed := True;
        //NoIconsCheck.Enabled := False;
        btn := TBitmapImage.Create(WizardForm);
        btn.Bitmap.LoadFromResourceName(HInstance, '_IS_BTN');
    end;
    SetOwnerDrawCheckBox(WizardForm);
end;

procedure DeinitializeSetup();
begin
    SetOwnerDrawCheckBox(nil);
end;


upd
Доработал еще 9 состояний чекбокса

Последний раз редактировалось El Sanchez, 20-11-2011 в 18:01. Причина: допилил скрипт

Это сообщение посчитали полезным следующие участники:

Отправлено: 19:00, 18-11-2011 | #166