Видоизменяем чекбоксы в Delphi
01.01.2007
В WIN3.1 чекбоксы заполняются символом "X". В WIN95 и WINNT - символом "V". В тандартной палитре Delphi чекбоксы заполняются символом "X". Спрашивается - почему фирма Borland/Inprise не исправила значёк чекбокса для W95/W98 ?. Данный пример позволяет заполнять чекбокс такими значками как: "X", "V", "o", "закрашенным прямоугольником", или бриллиантиком.
Пример тестировался под WIN95 и WINNT.
{ ==================================================================== Обозначения ==================================================================== X = крестик V = галочка o = кружок +-+ |W| = заполненный прямоугольник +-+ /\ = бриллиантик \/ ==================================================================== Преимущества этого чекбокса ==================================================================== Вы можете найти множество чекбоксов в интернете. Но у них есть недостаток, они не обрабатывают сообщение WM_KILLFOCUS. Приведённый ниже пример делает это. ==================================================================== } Unit CheckBoxX; Interface Uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Const { другие константы } fRBoxWidth : Integer = 13; // ширина квадрата checkbox fRBoxHeight : Integer = 13; // высота квадрата checkbox Type TState = (cbUnchecked,cbChecked,cbGrayed); // такой же как в Delphi TType = (cbCross,cbMark,cbBullet,cbDiamond,cbRect); // добавленный TMouseState = (msMouseUp,msMouseDown); TAlignment = (taRightJustify,taLeftJustify); // The same TCheckBoxX = class(TCustomControl) Private { Private declarations } fChecked : Boolean; fCaption : String; fColor : TColor; fState : TState; fFont : TFont; fAllowGrayed : Boolean; fFocus : Boolean; fType : TType; fMouseState : TMouseState; fAlignment : TAlignment; fTextTop : Integer; // отступ текта с верху fTextLeft : Integer; // отступ текта с лева fBoxTop : Integer; // координата чекбокса сверху fBoxLeft : Integer; // координата чекбокса слева Procedure fSetChecked(Bo : Boolean); Procedure fSetCaption(S : String); Procedure fSetColor(C : TColor); Procedure fSetState(cbState : TState); Procedure fSetFont(cbFont : TFont); Procedure fSetAllowGrayed(Bo : Boolean); Procedure fSetType(T : TType); Procedure fSetAlignment(A : TAlignment); Protected { Protected declarations } Procedure Paint; override; Procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; Procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; Procedure WMKillFocus(var Message : TWMKillFocus); Message WM_KILLFOCUS; // это убирает контур фокуса! Procedure WMSetFocus(var Message : TWMSetFocus); Message WM_SETFOCUS; // Если вы используете клавишу TAB или Shift-Tab Procedure KeyDown(var Key : Word; Shift : TShiftState); override; // перехват KeyDown Procedure KeyUp(var Key : Word; Shift : TShiftState); override; // перехват KeyUp Public { Public declarations } // Если поместить Create и Destroy в раздел protected, // то Delphi начинает ругаться. Constructor Create(AOwner : TComponent); override; Destructor Destroy; override; Published { Published declarations } { --- Свойства --- } Property Action; Property Alignment : TAlignment read fAlignment write fSetAlignment; Property AllowGrayed : Boolean read fAllowGrayed write fSetAllowGrayed; Property Anchors; Property BiDiMode; Property Caption : String read fCaption write fSetCaption; Property CheckBoxType : TType read fType write fSetType; Property Checked : Boolean read fChecked write fSetChecked; Property Color : TColor read fColor write fSetColor; Property Constraints; //Property Ctrl3D; Property Cursor; Property DragCursor; Property DragKind; Property DragMode; Property Enabled; Property Font : TFont read fFont write fSetFont; //Property Height; Property HelpContext; Property Hint; Property Left; Property Name; //Property PartenBiDiMode; Property ParentColor; //Property ParentCtrl3D; Property ParentFont; Property ParentShowHint; //Property PopMenu; Property ShowHint; Property State : TState read fState write fSetState; Property TabOrder; Property TabStop; Property Tag; Property Top; Property Visible; //Property Width; { --- Events --- } Property OnClick; Property OnContextPopup; Property OnDragDrop; Property OnDragOver; Property OnEndDock; Property OnEndDrag; Property OnEnter; Property OnExit; Property OnKeyDown; Property OnKeyPress; Property OnKeyUp; Property OnMouseDown; Property OnMouseMove; Property OnMouseUp; Property OnStartDock; Property OnStartDrag; End; Procedure Register; //Hello! Implementation {-------------------------------------------------------------------} Procedure TCheckBoxX.KeyDown(var Key : Word; Shift : TShiftState); Begin If fFocus then If Shift = [] then If Key = 0032 then Begin fMouseState := msMouseDown; If fState <> cbGrayed then Begin SetFocus; // Устанавливаем фокус на этот компонент // всем другим компонентам Windows посылает сообщение WM_KILLFOCUS. fFocus := True; Invalidate; End; End; Inherited KeyDown(Key,Shift); End; {-------------------------------------------------------------------} Procedure TCheckBoxX.KeyUp(var Key : Word; Shift : TShiftState); Begin If fFocus then If Shift = [] then If Key = 0032 then Begin If fState <> cbGrayed then fSetChecked(not fChecked); // Изменяем состояние fMouseState := msMouseUp; End; Inherited KeyUp(Key,Shift); End; {-------------------------------------------------------------------} Procedure TCheckBoxX.WMSetFocus(var Message : TWMSetFocus); Begin fFocus := True; Invalidate; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.WMKillFocus(var Message : TWMKillFocus); Begin fFocus := False; // Удаляем фокус у всех компонент, которые не имеют фокуса. Invalidate; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetAlignment(A : TAlignment); Begin If A <> fAlignment then Begin fAlignment := A; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetType(T : TType); Begin If fType <> T then Begin fType := T; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetFont(cbFont : TFont); Var FontChanged : Boolean; Begin FontChanged := False; If fFont.Style <> cbFont.Style then Begin fFont.Style := cbFont.Style; FontChanged := True; End; If fFont.CharSet <> cbFont.Charset then Begin fFont.Charset := cbFont.Charset; FontChanged := True; End; If fFont.Size <> cbFont.Size then Begin fFont.Size := cbFont.Size; FontChanged := True; End; If fFont.Name <> cbFont.Name then Begin fFont.Name := cbFont.Name; FontChanged := True; End; If fFont.Color <> cbFont.Color then Begin fFont.Color := cbFont.Color; FontChanged := True; End; If FontChanged then Invalidate; End; {-------------------------------------------------------------------} procedure TCheckBoxX.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Begin // Процедура MouseDown вызывается, когда кнопка мышки нажимается в пределах // кнопки, соответственно мы не можем получить значения координат X и Y. inherited MouseDown(Button, Shift, X, Y); fMouseState := msMouseDown; If fState <> cbGrayed then Begin SetFocus; // Устанавливаем фокус на этот компонент // всем другим компонентам Windows посылает сообщение WM_KILLFOCUS. fFocus := True; Invalidate; End; End; {-------------------------------------------------------------------} procedure TCheckBoxX.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Begin // Процедура MouseUp вызывается, когда кнопка мышки отпускается в пределах // кнопки, соответственно мы не можем получить значения координат X и Y. inherited MouseUp(Button, Shift, X, Y); If fState <> cbGrayed then fSetChecked(not fChecked); // Изменяем состояние fMouseState := msMouseUp; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetAllowGrayed(Bo : Boolean); Begin If fAllowGrayed <> Bo then Begin fAllowGrayed := Bo; If not fAllowGrayed then If fState = cbGrayed then Begin If fChecked then fState := cbChecked else fState := cbUnChecked; End; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetState(cbState : TState); Begin If fState <> cbState then Begin fState := cbState; If (fState = cbChecked) then fChecked := True; If (fState = cbGrayed) then fAllowGrayed := True; If fState = cbUnChecked then fChecked := False; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetColor(C : TColor); Begin If fColor <> C then Begin fColor := C; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetCaption(S : String); Begin If fCaption <> S then Begin fCaption := S; Invalidate; End; End; {-------------------------------------------------------------------} Procedure TCheckBoxX.fSetChecked(Bo : Boolean); Begin If fChecked <> Bo then Begin fChecked := Bo; If fState <> cbGrayed then Begin If fChecked then fState := cbChecked else fState := cbUnChecked; End; Invalidate; End; End; {-------------------------------------------------------------------} procedure TCheckBoxX.Paint; var Buffer: array[0..127] of Char; I: Integer; fTextWidth, fTextHeight: Integer; begin {Get Delphi's componentname and initially write it in the caption} GetTextBuf(Buffer, SizeOf(Buffer)); if Buffer <> '' then fCaption := Buffer; Canvas.Font.Size := Font.Size; Canvas.Font.Style := Font.Style; Canvas.Font.Color := Font.Color; Canvas.Font.Charset := Font.CharSet; fTextWidth := Canvas.TextWidth(fCaption); fTextHeight := Canvas.TextHeight('Q'); if fAlignment = taRightJustify then begin fBoxTop := (Height - fRBoxHeight) div 2; fBoxLeft := 0; fTextTop := (Height - fTextHeight) div 2; fTextLeft := fBoxLeft + fRBoxWidth + 4; end else begin fBoxTop := (Height - fRBoxHeight) div 2; fBoxLeft := Width - fRBoxWidth; fTextTop := (Height - fTextHeight) div 2; fTextLeft := 1; //If fTextWidth > (Width - fBoxWidth - 4) then // fTextLeft := (Width - fBoxWidth - 4) - fTextWidth; end; // выводим текст в caption Canvas.Pen.Color := fFont.Color; Canvas.Brush.Color := fColor; Canvas.TextOut(fTextLeft, fTextTop, fCaption); // Рисуем контур фокуса if fFocus = True then Canvas.DrawFocusRect(Rect(fTextLeft - 1, fTextTop - 2, fTextLeft + fTextWidth + 1, fTextTop + fTextHeight + 2)); if (fState = cbChecked) then Canvas.Brush.Color := clWindow; if (fState = cbUnChecked) then Canvas.Brush.Color := clWindow; if (fState = cbGrayed) then begin fAllowGrayed := True; Canvas.Brush.Color := clBtnFace; end; // Создаём бокс clBtnFace когда кнопка мыши нажимается // наподобие "стандартного" CheckBox if fMouseState = msMouseDown then Canvas.Brush.Color := clBtnFace; Canvas.FillRect(Rect(fBoxLeft + 2, fBoxTop + 2, fBoxLeft + fRBoxWidth - 2, fBoxTop + fRBoxHeight - 2)); // Рисуем прямоугольный чекбокс Canvas.Brush.Color := clBtnFace; Canvas.Pen.Color := clGray; Canvas.MoveTo(fBoxLeft + fRBoxWidth - 1, fBoxTop); Canvas.LineTo(fBoxLeft, fBoxTop); Canvas.LineTo(fBoxLeft, fBoxTop + fRBoxHeight); Canvas.Pen.Color := clWhite; Canvas.MoveTo(fBoxLeft + fRBoxWidth - 1, fBoxTop); Canvas.LineTo(fBoxLeft + fRBoxWidth - 1, fBoxTop + fRBoxHeight - 1); Canvas.LineTo(fBoxLeft - 1, fBoxTop + fRBoxHeight - 1); Canvas.Pen.Color := clBlack; Canvas.MoveTo(fBoxLeft + fRBoxWidth - 3, fBoxTop + 1); Canvas.LineTo(fBoxLeft + 1, fBoxTop + 1); Canvas.LineTo(fBoxLeft + 1, fBoxTop + fRBoxHeight - 2); Canvas.Pen.Color := clBtnFace; Canvas.MoveTo(fBoxLeft + fRBoxWidth - 2, fBoxTop + 1); Canvas.LineTo(fBoxLeft + fRBoxWidth - 2, fBoxTop + fRBoxHeight - 2); Canvas.LineTo(fBoxLeft, fBoxTop + fRBoxHeight - 2); // Теперь он должен быть таким же как чекбокс в Delphi if fChecked then begin Canvas.Pen.Color := clBlack; Canvas.Brush.Color := clBlack; // Рисуем прямоугольник if fType = cbRect then begin Canvas.FillRect(Rect(fBoxLeft + 4, fBoxTop + 4, fBoxLeft + fRBoxWidth - 4, fBoxTop + fRBoxHeight - 4)); end; // Рисуем значёк "о" if fType = cbBullet then begin Canvas.Ellipse(fBoxLeft + 4, fBoxTop + 4, fBoxLeft + fRBoxWidth - 4, fBoxTop + fRBoxHeight - 4); end; // Рисуем крестик if fType = cbCross then begin {Right-top to left-bottom} Canvas.MoveTo(fBoxLeft + fRBoxWidth - 5, fBoxTop + 3); Canvas.LineTo(fBoxLeft + 2, fBoxTop + fRBoxHeight - 4); Canvas.MoveTo(fBoxLeft + fRBoxWidth - 4, fBoxTop + 3); Canvas.LineTo(fBoxLeft + 2, fBoxTop + fRBoxHeight - 3); Canvas.MoveTo(fBoxLeft + fRBoxWidth - 4, fBoxTop + 4); Canvas.LineTo(fBoxLeft + 3, fBoxTop + fRBoxHeight - 3); {Left-top to right-bottom} Canvas.MoveTo(fBoxLeft + 3, fBoxTop + 4); Canvas.LineTo(fBoxLeft + fRBoxWidth - 4, fBoxTop + fRBoxHeight - 3); Canvas.MoveTo(fBoxLeft + 3, fBoxTop + 3); Canvas.LineTo(fBoxLeft + fRBoxWidth - 3, fBoxTop + fRBoxHeight - 3); //mid Canvas.MoveTo(fBoxLeft + 4, fBoxTop + 3); Canvas.LineTo(fBoxLeft + fRBoxWidth - 3, fBoxTop + fRBoxHeight - 4); end; // Рисуем галочку if fType = cbMark then for I := 0 to 2 do begin {Left-mid to left-bottom} Canvas.MoveTo(fBoxLeft + 3, fBoxTop + 5 + I); Canvas.LineTo(fBoxLeft + 6, fBoxTop + 8 + I); {Left-bottom to right-top} Canvas.MoveTo(fBoxLeft + 6, fBoxTop + 6 + I); Canvas.LineTo(fBoxLeft + 10, fBoxTop + 2 + I); end; // Рисуем бриллиантик if fType = cbDiamond then begin Canvas.Pixels[fBoxLeft + 06, fBoxTop + 03] := clBlack; Canvas.Pixels[fBoxLeft + 06, fBoxTop + 09] := clBlack; Canvas.MoveTo(fBoxLeft + 05, fBoxTop + 04); Canvas.LineTo(fBoxLeft + 08, fBoxTop + 04); Canvas.MoveTo(fBoxLeft + 05, fBoxTop + 08); Canvas.LineTo(fBoxLeft + 08, fBoxTop + 08); Canvas.MoveTo(fBoxLeft + 04, fBoxTop + 05); Canvas.LineTo(fBoxLeft + 09, fBoxTop + 05); Canvas.MoveTo(fBoxLeft + 04, fBoxTop + 07); Canvas.LineTo(fBoxLeft + 09, fBoxTop + 07); Canvas.MoveTo(fBoxLeft + 03, fBoxTop + 06); Canvas.LineTo(fBoxLeft + 10, fBoxTop + 06); // middle line end; end; end; {-------------------------------------------------------------------} procedure Register; begin RegisterComponents('Samples', [TCheckBoxX]); end; {-------------------------------------------------------------------} destructor TCheckBoxX.Destroy; begin inherited Destroy; end; {-------------------------------------------------------------------} constructor TCheckBoxX.Create(AOwner: TComponent); begin inherited Create(AOwner); Height := 17; Width := 97; fChecked := False; fColor := clBtnFace; fState := cbUnChecked; fFont := inherited Font; fAllowGrayed := False; fFocus := False; fMouseState := msMouseUp; fAlignment := taRightJustify; TabStop := True; // Sorry end; {-------------------------------------------------------------------} end. {===================================================================}
Взято из https://forum.sources.ru