Ветеран
Сообщения: 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 состояний чекбокса
|