{********************************************************************} { } { Developer Express Visual Component Library } { ExpressEditors } { } { Copyright (c) 1998-2009 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL } { ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {********************************************************************} unit cxCheckBox; {$I cxVer.inc} interface uses Messages, Windows, {$IFDEF DELPHI6} Types, Variants, {$ENDIF} Classes, Controls, Forms, Graphics, SysUtils, cxClasses, cxContainer, cxControls, cxCustomData, cxDataStorage, cxEdit, cxGraphics, cxLookAndFeels, cxTextEdit, cxDropDownEdit, cxVariants, cxFilterControlUtils, cxLookAndFeelPainters; const cxEditCheckBoxSingleBorderDefaultColor = clBtnShadow; type TcxCheckBoxNullValueShowingStyle = (nssUnchecked, nssInactive, nssGrayedChecked); TcxCheckStatesValueFormatEx = (cvfCaptions, cvfIndices, cvfInteger, cvfStatesString, cvfCustom); TcxCheckStatesValueFormat = cvfCaptions..cvfStatesString; TcxCheckStates = array of TcxCheckBoxState; TcxEditCheckBoxBorderStyle = TcxEditBorderStyle; TcxEditCheckState = (ecsNormal, ecsHot, ecsPressed, ecsDisabled); TcxCheckStatesToValueEvent = procedure(Sender: TObject; const ACheckStates: TcxCheckStates; out AValue: TcxEditValue) of object; TcxValueToCheckStatesEvent = procedure(Sender: TObject; const AValue: TcxEditValue; var ACheckStates: TcxCheckStates) of object; { IcxCheckItems } IcxCheckItems = interface ['{5BF13228-CF05-4741-9833-F2B8FBFD57ED}'] function GetCaption(Index: Integer): string; function GetCount: Integer; property Captions[Index: Integer]: string read GetCaption; property Count: Integer read GetCount; end; { TcxCaptionItem } TcxCaptionItem = class(TCollectionItem) private FCaption: TCaption; FTag: TcxTag; function IsTagStored: Boolean; procedure SetCaption(AValue: TCaption); protected property Caption: TCaption read FCaption write SetCaption; property Tag: TcxTag read FTag write FTag stored IsTagStored; public procedure Assign(Source: TPersistent); override; end; { TcxCaptionItems } TcxCaptionItems = class(TcxOwnedInterfacedCollection, IcxCheckItems) private function GetItem(AIndex: Integer): TcxCaptionItem; procedure SetItem(AIndex: Integer; AValue: TcxCaptionItem); protected function DoCompareItems(AItem1, AItem2: TcxInterfacedCollectionItem): Integer; override; // IcxCheckItems function GetCaption(AIndex: Integer): string; function GetCount: Integer; public property Items[AIndex: Integer]: TcxCaptionItem read GetItem write SetItem; default; end; { TcxCustomCheckBoxViewInfo } TcxCustomCheckBox = class; TcxCustomCheckBoxViewInfo = class(TcxCustomTextEditViewInfo) private function GetEdit: TcxCustomCheckBox; protected procedure InternalPaint(ACanvas: TcxCanvas); override; function IsTextEnabled: Boolean; public Alignment: TAlignment; CheckBorderOffset: Integer; CheckBoxBorderStyle: TcxEditCheckBoxBorderStyle; CheckBoxGlyph: TBitmap; CheckBoxGlyphCount: Integer; CheckBoxRect: TRect; CheckBoxState: TcxEditCheckState; DrawCaptionFlags: Integer; FocusRect: TRect; HasGlyph: Boolean; IsTextColorAssigned: Boolean; NullValueShowingStyle: TcxCheckBoxNullValueShowingStyle; State: TcxCheckBoxState; procedure Assign(Source: TObject); override; procedure DrawText(ACanvas: TcxCanvas); override; function GetUpdateRegion(AViewInfo: TcxContainerViewInfo): TcxRegion; override; function IsHotTrack: Boolean; override; function IsHotTrack(P: TPoint): Boolean; override; function NeedShowHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect): Boolean; override; procedure Offset(DX, DY: Integer); override; function Repaint(AControl: TWinControl; const AInnerEditRect: TRect; AViewInfo: TcxContainerViewInfo = nil): Boolean; override; property Edit: TcxCustomCheckBox read GetEdit; end; { TcxCustomCheckBoxViewData } TcxCustomCheckBoxProperties = class; TcxCustomCheckBoxViewData = class(TcxCustomEditViewData) private function GetProperties: TcxCustomCheckBoxProperties; protected function InternalGetEditConstantPartSize(ACanvas: TcxCanvas; AIsInplace: Boolean; AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo): TSize; override; function GetDrawTextFlags: Integer; virtual; function GetIsEditClass: Boolean; function IsCheckPressed: Boolean; public procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override; procedure EditValueToDrawValue(ACanvas: TcxCanvas; const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); override; function GetBorderStyle: TcxEditBorderStyle; override; property Properties: TcxCustomCheckBoxProperties read GetProperties; end; { TcxCheckBoxStyle } TcxCheckBoxStyle = class(TcxEditStyle) public function HasBorder: Boolean; override; end; { TcxCustomCheckBoxProperties } TcxCustomCheckBoxProperties = class(TcxCustomEditProperties) private FAllowGrayed: Boolean; FCaption: TCaption; // obsolete FDisplayChecked: WideString; FDisplayGrayed: WideString; FDisplayUnchecked: WideString; FFullFocusRect: Boolean; FGlyph: TBitmap; FGlyphCount: Integer; FIsCaptionAssigned: Boolean; // obsolete FMultiLine: Boolean; FNullStyle: TcxCheckBoxNullValueShowingStyle; FUseAlignmentWhenInplace: Boolean; FValueChecked: TcxEditValue; FValueGrayed: TcxEditValue; FValueUnchecked: TcxEditValue; function GetAlignment: TAlignment; function GetGlyph: TBitmap; function GetInternalAlignment: TcxEditAlignment; procedure GlyphChanged(Sender: TObject); function IsAlignmentStored: Boolean; function IsDisplayCheckedStored: Boolean; function IsDisplayGrayedStored: Boolean; function IsDisplayUncheckedStored: Boolean; function IsLoading: Boolean; function IsValueCheckedStored: Boolean; function IsValueGrayedStored: Boolean; function IsValueUncheckedStored: Boolean; procedure ReadCaption(Reader: TReader); // obsolete procedure SetAlignment(Value: TAlignment); procedure SetCaption(const Value: TCaption); // obsolete procedure SetFullFocusRect(Value: Boolean); procedure SetGlyph(Value: TBitmap); procedure SetGlyphCount(Value: Integer); procedure SetMultiLine(Value: Boolean); procedure SetNullStyle(Value: TcxCheckBoxNullValueShowingStyle); procedure SetStateValues(const AValueChecked, AValueGrayed, AValueUnchecked: TcxEditValue); procedure SetUseAlignmentWhenInplace(Value: Boolean); procedure SetValueChecked(const Value: TcxEditValue); procedure SetValueGrayed(const Value: TcxEditValue); procedure SetValueUnchecked(const Value: TcxEditValue); protected function CanValidate: Boolean; override; procedure DefineProperties(Filer: TFiler); override; class function GetViewDataClass: TcxCustomEditViewDataClass; override; function HasDisplayValue: Boolean; override; function CheckValue(const AValue: TcxEditValue): Boolean; function GetState(const AEditValue: TcxEditValue): TcxCheckBoxState; function InternalGetGlyph: TBitmap; virtual; function IsEmbeddedEdit: Boolean; virtual; property InternalAlignment: TcxEditAlignment read GetInternalAlignment; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function CanCompareEditValue: Boolean; override; function CompareDisplayValues( const AEditValue1, AEditValue2: TcxEditValue): Boolean; override; class function GetContainerClass: TcxContainerClass; override; function GetDisplayText(const AEditValue: TcxEditValue; AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; override; class function GetStyleClass: TcxCustomEditStyleClass; override; function GetSpecialFeatures: TcxEditSpecialFeatures; override; function GetSupportedOperations: TcxEditSupportedOperations; override; class function GetViewInfoClass: TcxContainerViewInfoClass; override; function IsActivationKey(AKey: Char): Boolean; override; function IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override; function IsResetEditClass: Boolean; override; procedure PrepareDisplayValue(const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; AEditFocused: Boolean); override; // !!! property Alignment: TAlignment read GetAlignment write SetAlignment stored IsAlignmentStored; // property AlignmentVert: TcxAlignmentVert read GetAlignmentVert // write SetAlignmentVert stored IsAlignmentVertStored; property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed default False; property Caption: TCaption read FCaption write SetCaption stored False; // obsolete property DisplayChecked: WideString read FDisplayChecked write FDisplayChecked stored IsDisplayCheckedStored; property DisplayGrayed: WideString read FDisplayGrayed write FDisplayGrayed stored IsDisplayGrayedStored; property DisplayUnchecked: WideString read FDisplayUnchecked write FDisplayUnchecked stored IsDisplayUncheckedStored; property FullFocusRect: Boolean read FFullFocusRect write SetFullFocusRect default False; property Glyph: TBitmap read GetGlyph write SetGlyph; property GlyphCount: Integer read FGlyphCount write SetGlyphCount default 6; property MultiLine: Boolean read FMultiLine write SetMultiLine default False; property NullStyle: TcxCheckBoxNullValueShowingStyle read FNullStyle write SetNullStyle default nssGrayedChecked; property UseAlignmentWhenInplace: Boolean read FUseAlignmentWhenInplace write SetUseAlignmentWhenInplace default False; property ValueChecked: TcxEditValue read FValueChecked write SetValueChecked stored IsValueCheckedStored; property ValueGrayed: TcxEditValue read FValueGrayed write SetValueGrayed stored IsValueGrayedStored; property ValueUnchecked: TcxEditValue read FValueUnchecked write SetValueUnchecked stored IsValueUncheckedStored; end; { TcxCheckBoxProperties } TcxCheckBoxProperties = class(TcxCustomCheckBoxProperties) published property Alignment; property AllowGrayed; property AssignedValues; property Caption; // obsolete property ClearKey; property DisplayChecked; property DisplayUnchecked; property DisplayGrayed; property FullFocusRect; property Glyph; property GlyphCount; property ImmediatePost; property MultiLine; property NullStyle; property ReadOnly; property UseAlignmentWhenInplace; property ValueChecked; property ValueGrayed; property ValueUnchecked; property OnChange; property OnEditValueChanged; property OnValidate; end; { TcxCustomCheckBox } TcxCustomCheckBox = class(TcxCustomEdit) private FIsCheckPressed: Boolean; FIsLoaded: Boolean; FIsLoadingStateAssigned: Boolean; FLoadingState: TcxCheckBoxState; function GetChecked: Boolean; function GetProperties: TcxCustomCheckBoxProperties; function GetActiveProperties: TcxCustomCheckBoxProperties; function GetState: TcxCheckBoxState; function GetStyle: TcxCheckBoxStyle; function GetViewInfo: TcxCustomCheckBoxViewInfo; function IsStateStored: Boolean; procedure SetChecked(Value: Boolean); procedure SetProperties(Value: TcxCustomCheckBoxProperties); procedure SetState(Value: TcxCheckBoxState); procedure SetStyle(Value: TcxCheckBoxStyle); procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP; procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; protected procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; function CanHaveTransparentBorder: Boolean; override; function DefaultParentColor: Boolean; override; procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override; procedure DoEditKeyPress(var Key: Char); override; procedure DoEditKeyUp(var Key: Word; Shift: TShiftState); override; procedure DoExit; override; procedure FillSizeProperties(var AEditSizeProperties: TcxEditSizeProperties); override; function GetActionLinkClass: TControlActionLinkClass; override; function GetEditStateColorKind: TcxEditStateColorKind; override; function GetShadowBounds: TRect; override; procedure Initialize; override; function InternalGetNotPublishedStyleValues: TcxEditStyleValues; override; procedure InternalSetEditValue(const Value: TcxEditValue; AValidateEditValue: Boolean); override; function IsClickEnabledDuringLoading: Boolean; override; function IsNativeBackground: Boolean; override; procedure Loaded; override; procedure ProcessViewInfoChanges(APrevViewInfo: TcxCustomEditViewInfo; AIsMouseDownUpEvent: Boolean); override; procedure PropertiesChanged(Sender: TObject); override; procedure TextChanged; override; procedure InvalidateCheckRect; procedure Toggle; virtual; property Caption; property Checked: Boolean read GetChecked write SetChecked stored False; property ViewInfo: TcxCustomCheckBoxViewInfo read GetViewInfo; public procedure Clear; override; class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; procedure PrepareEditValue(const ADisplayValue: TcxEditValue; out EditValue: TcxEditValue; AEditFocused: Boolean); override; property ActiveProperties: TcxCustomCheckBoxProperties read GetActiveProperties; property Properties: TcxCustomCheckBoxProperties read GetProperties write SetProperties; property State: TcxCheckBoxState read GetState write SetState stored IsStateStored default cbsUnchecked; property Style: TcxCheckBoxStyle read GetStyle write SetStyle; property Transparent; end; { TcxCheckBox } TcxCheckBox = class(TcxCustomCheckBox) private function GetActiveProperties: TcxCheckBoxProperties; function GetProperties: TcxCheckBoxProperties; procedure SetProperties(Value: TcxCheckBoxProperties); public class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; property ActiveProperties: TcxCheckBoxProperties read GetActiveProperties; published property Action; property Align; property Anchors; property AutoSize; property Caption; property Checked; property Constraints; property DragCursor; property DragKind; property DragMode; property Enabled; property ParentBackground; property ParentColor; property ParentFont; property ParentShowHint; property PopupMenu; property Properties: TcxCheckBoxProperties read GetProperties write SetProperties; property ShowHint; property State; property Style; property StyleDisabled; property StyleFocused; property StyleHot; property TabOrder; property TabStop; property Transparent; property Visible; property OnClick; property OnContextPopup; property OnDragDrop; property OnDragOver; property OnEditing; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseEnter; property OnMouseLeave; property OnMouseMove; property OnMouseUp; property OnStartDock; property OnStartDrag; end; { TcxFilterCheckBoxHelper } TcxFilterCheckBoxHelper = class(TcxFilterComboBoxHelper) public class procedure GetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; var V: Variant; var S: TCaption); override; class function GetSupportedFilterOperators( AProperties: TcxCustomEditProperties; AValueTypeClass: TcxValueTypeClass; AExtendedSet: Boolean = False): TcxFilterControlOperators; override; class procedure InitializeProperties(AProperties, AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); override; class procedure SetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; AValue: Variant); override; class function UseDisplayValue: Boolean; override; end; { TcxCheckBoxActionLink } TcxCheckBoxActionLink = class(TWinControlActionLink) protected FClient: TcxCustomCheckBox; procedure AssignClient(AClient: TObject); override; function IsCheckedLinked: Boolean; override; procedure SetChecked(Value: Boolean); override; procedure InternalSetChecked(Value: Boolean); end; var CheckStates: TcxCheckStates = nil; function CalculateCheckStatesValue(const ACheckStates: TcxCheckStates; AItems: IcxCheckItems; AValueFormat: TcxCheckStatesValueFormat): TcxEditValue; function CalculateCheckStates(const AValue: TcxEditValue; AItems: IcxCheckItems; AValueFormat: TcxCheckStatesValueFormat; var ACheckStates: TcxCheckStates): Boolean; procedure DrawEditCheck(ACanvas: TcxCanvas; const ACheckRect: TRect; AState: TcxCheckBoxState; ACheckState: TcxEditCheckState; AGlyph: TBitmap; AGlyphCount: Integer; ABorderStyle: TcxEditCheckBoxBorderStyle; ANativeStyle: Boolean; ABorderColor: TColor; ABackgroundColor: TColor; ADrawBackground, AIsDesigning, AFocused, ASupportGrayed: Boolean; APainter: TcxCustomLookAndFeelPainterClass; AGrayedShowingStyle: TcxCheckBoxNullValueShowingStyle = nssGrayedChecked); function GetEditCheckBorderOffset(ACheckBorderStyle: TcxContainerBorderStyle; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; overload; function GetEditCheckBorderOffset(ACheckBorderStyle: TcxEditBorderStyle; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; overload; function GetEditCheckBorderOffset(ALookAndFeelKind: TcxLookAndFeelKind; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; overload; function GetEditCheckGlyphIndex(AState: TcxCheckBoxState; ACheckState: TcxEditCheckState; ASupportGrayed: Boolean; AGlyphCount: Integer): Integer; function GetEditCheckSize(ACanvas: TcxCanvas; ANativeStyle: Boolean; AGlyph: TBitmap; AGlyphCount: Integer; APainter: TcxCustomLookAndFeelPainterClass): TSize; procedure DrawCheckBoxText(ACanvas: TcxCanvas; AText: string; AFont: TFont; ATextColor: TColor; ATextRect: TRect; ADrawTextFlags: Integer; AEnabled: Boolean); implementation uses Math, ActnList, cxGeometry, dxThemeConsts, dxThemeManager, dxUxTheme, cxEditConsts, cxEditPaintUtils, cxDrawTextUtils, cxEditUtils; var FCheckMask: TBitmap; procedure PrepareCheckMask; procedure InternalPrepareCheckMask(AButtonsBitmap: HBITMAP); var AMemDC: HDC; APrevBitmap: HBITMAP; I, J: Integer; begin FCheckMask := TBitmap.Create; with TcxCustomLookAndFeelPainter do begin FCheckMask.Width := CheckButtonSize.cx; FCheckMask.Height := CheckButtonSize.cy; end; AMemDC := CreateCompatibleDC(0); APrevBitmap := 0; try APrevBitmap := SelectObject(AMemDC, AButtonsBitmap); with FCheckMask.Canvas do for I := 0 to FCheckMask.Height - 1 do for J := 0 to FCheckMask.Width - 1 do if Windows.GetPixel(AMemDC, J, I) = Windows.GetPixel(AMemDC, J + FCheckMask.Width, I) then Pixels[J, I] := clWhite else Pixels[J, I] := 0; finally if APrevBitmap <> 0 then SelectObject(AMemDC, APrevBitmap); DeleteDC(AMemDC); end; end; var AButtonsBitmap: HBITMAP; begin AButtonsBitmap := LoadBitmap(0, PChar(OBM_CHECKBOXES)); try InternalPrepareCheckMask(AButtonsBitmap); finally DeleteObject(AButtonsBitmap); end; end; procedure CalculateCheckBoxViewInfo(AViewData: TcxCustomCheckBoxViewData; AViewInfo: TcxCustomCheckBoxViewInfo; AIsMouseEvent: Boolean); begin with AViewInfo do begin AViewData.CalculateViewInfo(AViewInfo, AIsMouseEvent); TextRect := ClientRect; ExtendRect(TextRect, GetTextEditDrawTextOffset(AViewData)); end; end; function CalculateCheckStatesValue(const ACheckStates: TcxCheckStates; AItems: IcxCheckItems; AValueFormat: TcxCheckStatesValueFormat): TcxEditValue; function CalculateCaptionsValue: TcxEditValue; var ACheckedCaptions, AGrayedCaptions: string; I: Integer; begin ACheckedCaptions := ''; AGrayedCaptions := ''; for I := 0 to Length(ACheckStates) - 1 do begin if ACheckStates[I] <> cbsUnchecked then if ACheckStates[I] = cbsGrayed then AGrayedCaptions := AGrayedCaptions + IntToStr(Length(AItems.Captions[I])) + ':' + AItems.Captions[I] else ACheckedCaptions := ACheckedCaptions + IntToStr(Length(AItems.Captions[I])) + ':' + AItems.Captions[I]; end; Result := AGrayedCaptions; if Length(ACheckedCaptions) > 0 then Result := Result + ';' + ACheckedCaptions; end; function CalculateIndicesValue: TcxEditValue; var ACheckedCaptions, AGrayedCaptions: string; I: Integer; begin ACheckedCaptions := ''; AGrayedCaptions := ''; for I := 0 to Length(ACheckStates) - 1 do if ACheckStates[I] <> cbsUnchecked then if ACheckStates[I] = cbsGrayed then begin if AGrayedCaptions <> '' then AGrayedCaptions := AGrayedCaptions + ','; AGrayedCaptions := AGrayedCaptions + IntToStr(I); end else begin if ACheckedCaptions <> '' then ACheckedCaptions := ACheckedCaptions + ','; ACheckedCaptions := ACheckedCaptions + IntToStr(I); end; Result := AGrayedCaptions; if Length(ACheckedCaptions) > 0 then Result := Result + ';' + ACheckedCaptions; end; function CalculateStatesIntegerValue: TcxEditValue; var V: {$IFDEF DELPHI6}Int64{$ELSE}Integer{$ENDIF}; I, L: Integer; begin V := 0; L := Length(ACheckStates); if L > SizeOf({$IFDEF DELPHI6}Int64{$ELSE}Integer{$ENDIF}) * 8 then L := SizeOf({$IFDEF DELPHI6}Int64{$ELSE}Integer{$ENDIF}) * 8; for I := L - 1 downto 0 do begin V := V shl 1; V := V + {$IFDEF DELPHI6}Int64{$ELSE}Integer{$ENDIF}(ACheckStates[I] = cbsChecked); end; Result := V; VarCast(Result, Result, {$IFDEF DELPHI6}varInt64{$ELSE}varInteger{$ENDIF}); end; function CalculateStatesStringValue: TcxEditValue; var I: Integer; S: string; begin SetLength(S, Length(ACheckStates)); for I := 0 to High(ACheckStates) do S[I + 1] := Char(Integer(ACheckStates[I]) + Ord('0')); Result := S; end; begin Result := Null; case AValueFormat of cvfCaptions: Result := CalculateCaptionsValue; cvfIndices: Result := CalculateIndicesValue; cvfInteger: Result := CalculateStatesIntegerValue; cvfStatesString: Result := CalculateStatesStringValue; end; end; function CalculateCheckStates(const AValue: TcxEditValue; AItems: IcxCheckItems; AValueFormat: TcxCheckStatesValueFormat; var ACheckStates: TcxCheckStates): Boolean; function GetNumber(var ANumber, AIndex: Integer; const S: string): Boolean; function IsDigit(C: Char): Boolean; begin Result := (C >= '0') and (C <= '9'); end; const AMaxLength = MaxInt div 10; AMaxIntLastDigit = MaxInt mod 10; var L: Integer; D: Integer; begin Result := False; L := Length(S); if (AIndex > L) or not IsDigit(S[AIndex]) then Exit; ANumber := 0; repeat D := StrToInt(S[AIndex]); if (ANumber > AMaxLength) or ((ANumber = AMaxLength) and (D > AMaxIntLastDigit)) then Exit; ANumber := ANumber * 10 + D; Inc(AIndex); until (AIndex > L) or not IsDigit(S[AIndex]); Result := True; end; function CalculateItemsByCaptionsValue: Boolean; function GetCaptions(ACaptions: TStringList): Boolean; var S: string; ACaptionLength, AIndex, AValueLength: Integer; AChecked: Boolean; begin S := VarToStr(AValue); Result := S = ''; if Result then Exit; Result := False; AChecked := False; AValueLength := Length(S); AIndex := 1; repeat if (S[AIndex] = ';') and not AChecked then begin AChecked := True; Inc(AIndex); end; if not GetNumber(ACaptionLength, AIndex, S) then Exit; if (AIndex > AValueLength) or (S[AIndex] <> ':') then Exit; Inc(AIndex); if AIndex + ACaptionLength - 1 > AValueLength then Exit; ACaptions.AddObject(Copy(S, AIndex, ACaptionLength), Pointer(AChecked)); Inc(AIndex, ACaptionLength); if AIndex > AValueLength then Break; until (AIndex > AValueLength); Result := True; end; function CalculateStates(ACaptions: TStringList): Boolean; var AIndex, I: Integer; begin for I := 0 to AItems.Count - 1 do begin AIndex := ACaptions.IndexOf(AItems.Captions[I]); if AIndex = -1 then ACheckStates[I] := cbsUnchecked else begin if Boolean(ACaptions.Objects[AIndex]) then ACheckStates[I] := cbsChecked else ACheckStates[I] := cbsGrayed; ACaptions.Delete(AIndex); end; end; Result := ACaptions.Count = 0; end; var ACaptions: TStringList; begin if not(VarIsNull(AValue) or VarIsStr(AValue)) then begin Result := False; Exit; end; ACaptions := TStringList.Create; try Result := GetCaptions(ACaptions); if not Result then Exit; ACaptions.Sort; Result := CalculateStates(ACaptions); finally FreeAndNil(ACaptions); end; end; procedure SetStatesToUnchecked; var I: Integer; begin for I := 0 to AItems.Count - 1 do ACheckStates[I] := cbsUnchecked; end; function CalculateItemsByIndicesValue: Boolean; var AChecked: Boolean; AIndex, AItemIndex, L: Integer; S: string; begin Result := VarIsNull(AValue) or VarIsStr(AValue); if not Result then Exit; S := VarToStr(AValue); SetStatesToUnchecked; if S = '' then Exit; Result := False; AIndex := 1; L := Length(S); AChecked := False; repeat if (S[AIndex] = ';') and not AChecked then begin AChecked := True; Inc(AIndex); end; if not GetNumber(AItemIndex, AIndex, S) or (AItemIndex >= AItems.Count) then Exit; if AChecked then ACheckStates[AItemIndex] := cbsChecked else ACheckStates[AItemIndex] := cbsGrayed; if AIndex > L then Break; if S[AIndex] = ',' then Inc(AIndex); until AIndex > L; Result := True; end; function CalculateItemsByStatesIntegerValue: Boolean; var V: {$IFDEF DELPHI6}Int64{$ELSE}Integer{$ENDIF}; I, ACode: Integer; begin Result := VarIsNumericEx(AValue) or VarIsStr(AValue) or VarIsDate(AValue) or VarIsNull(AValue); if Result then begin if VarIsNull(AValue) then V := 0 else if VarIsStr(AValue) then begin Val(AValue, V, ACode); Result := ACode = 0; if not Result then Exit; end else V := VarAsType(AValue, {$IFDEF DELPHI6}varInt64{$ELSE}varInteger{$ENDIF}); for I := 0 to AItems.Count - 1 do begin if V and 1 = 0 then ACheckStates[I] := cbsUnchecked else ACheckStates[I] := cbsChecked; V := V shr 1; end; end end; function CalculateItemsByStatesStringValue: Boolean; var AItemCount, I: Integer; S: string; begin Result := VarIsNull(AValue) or VarIsStr(AValue); if not Result then Exit; Result := False; S := VarToStr(AValue); AItemCount := Length(S); if AItemCount > AItems.Count then AItemCount := AItems.Count; for I := 1 to AItemCount do if (S[I] < '0') or (S[I] > '2') then Exit else ACheckStates[I - 1] := TcxCheckBoxState(Ord(S[I]) - Ord('0')); if AItemCount < AItems.Count then for I := AItemCount to AItems.Count - 1 do ACheckStates[I] := cbsUnchecked; Result := True; end; var I: Integer; begin SetLength(ACheckStates, AItems.Count); case AValueFormat of cvfCaptions: Result := CalculateItemsByCaptionsValue; cvfIndices: Result := CalculateItemsByIndicesValue; cvfInteger: Result := CalculateItemsByStatesIntegerValue; cvfStatesString: Result := CalculateItemsByStatesStringValue; else Result := False; end; if not Result then for I := 0 to AItems.Count - 1 do ACheckStates[I] := cbsUnchecked; end; procedure CalculateCustomCheckBoxViewInfo(ACanvas: TcxCanvas; AViewData: TcxCustomCheckBoxViewData; AViewInfo: TcxCustomCheckBoxViewInfo); procedure CheckFocusRectBounds; var AMaxRect: TRect; begin with AViewInfo do begin if Alignment = taCenter then AMaxRect := Rect(FocusRect.Left, ClientRect.Top, FocusRect.Right, ClientRect.Bottom) else begin AMaxRect := Rect(TextRect.Left - 1, TextRect.Top - 1 + 2 * Integer(IsInplace), TextRect.Right + 1, TextRect.Bottom + 1 - 2 * Integer(IsInplace)); if AMaxRect.Right > BorderRect.Right - 1 then AMaxRect.Right := BorderRect.Right - 1; end; if FocusRect.Left < AMaxRect.Left then FocusRect.Left := AMaxRect.Left; if FocusRect.Top < AMaxRect.Top then FocusRect.Top := AMaxRect.Top; if FocusRect.Right > AMaxRect.Right then FocusRect.Right := AMaxRect.Right; if FocusRect.Bottom > AMaxRect.Bottom then FocusRect.Bottom := AMaxRect.Bottom; end; end; begin with AViewInfo do begin BackgroundColor := AViewData.Style.Color; if Focused and ((not IsInplace or AViewData.Properties.IsEmbeddedEdit) and (Alignment <> taCenter) or IsInplace and (Alignment = taCenter) and (epoShowFocusRectWhenInplace in PaintOptions)) then begin if Alignment = taCenter then begin FocusRect := ClientRect; InflateRect(FocusRect, -1, -1); end else if Length(Text) <> 0 then begin FocusRect := TextRect; if not AViewData.Properties.FullFocusRect then begin ACanvas.Font := Font; ACanvas.TextExtent(Text, FocusRect, DrawTextFlags); end; InflateRect(FocusRect, 1, 1); Inc(FocusRect.Bottom); end else FocusRect := cxEmptyRect; end else FocusRect := cxEmptyRect; if not IsRectEmpty(FocusRect) then CheckFocusRectBounds; end; end; procedure DrawCheckBoxText(ACanvas: TcxCanvas; AText: string; AFont: TFont; ATextColor: TColor; ATextRect: TRect; ADrawTextFlags: Integer; AEnabled: Boolean); begin ACanvas.Font := AFont; ACanvas.Font.Color := ATextColor; ACanvas.Brush.Style := bsClear; ACanvas.DrawText(AText, ATextRect, ADrawTextFlags, AEnabled); ACanvas.Brush.Style := bsSolid; end; function IsGlyphValid(AGlyph: TBitmap; AGlyphCount: Integer): Boolean; begin Result := (AGlyphCount > 0) and VerifyBitmap(AGlyph); end; function GetCheckNativeState(AState: TcxCheckBoxState; ACheckState: TcxEditCheckState): Integer; const ANativeCheckStateMap: array[TcxCheckBoxState, TcxEditCheckState] of Integer = ( (CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDDISABLED), (CBS_CHECKEDNORMAL, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDDISABLED), (CBS_MIXEDNORMAL, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDDISABLED) ); begin Result := ANativeCheckStateMap[AState, ACheckState]; end; procedure DrawCustomCheckBox(ACanvas: TcxCanvas; AViewInfo: TcxCustomCheckBoxViewInfo); overload; var AIsBackgroundTransparent: Boolean; ACheckRect: TRect; ACheckTransparent: Boolean; begin AIsBackgroundTransparent := AViewInfo.IsBackgroundTransparent; // ACanvas.Brush.Color := AViewInfo.BackgroundColor; // to fix problem with DC color after RestoreDC ACheckRect := AViewInfo.CheckBoxRect; InflateRect(ACheckRect, -AViewInfo.CheckBorderOffset, -AViewInfo.CheckBorderOffset); ACheckTransparent := AIsBackgroundTransparent and (Assigned(AViewInfo.Painter) or AViewInfo.HasGlyph or AViewInfo.NativeStyle and IsThemeBackgroundPartiallyTransparent( OpenTheme(totButton), BP_CHECKBOX, GetCheckNativeState(AViewInfo.State, AViewInfo.CheckBoxState))); AViewInfo.DrawEditBackground(ACanvas, AViewInfo.Bounds, ACheckRect, ACheckTransparent); DrawEditCheck(ACanvas, AViewInfo.CheckBoxRect, AViewInfo.State, AViewInfo.CheckBoxState, AViewInfo.CheckBoxGlyph, AViewInfo.CheckBoxGlyphCount, AViewInfo.CheckBoxBorderStyle, AViewInfo.NativeStyle, AViewInfo.BorderColor, AViewInfo.BackgroundColor, not AIsBackgroundTransparent, AViewInfo.IsDesigning, AViewInfo.Focused, True, AViewInfo.Painter, AViewInfo.NullValueShowingStyle); if AViewInfo.Alignment <> taCenter then DrawCheckBoxText(ACanvas, AViewInfo.Text, AViewInfo.Font, AViewInfo.TextColor, AViewInfo.TextRect, AViewInfo.DrawTextFlags, AViewInfo.IsTextEnabled); if not IsRectEmpty(AViewInfo.FocusRect) then ACanvas.DrawFocusRect(AViewInfo.FocusRect); end; procedure DrawEditCheck(ACanvas: TcxCanvas; const ACheckRect: TRect; AState: TcxCheckBoxState; ACheckState: TcxEditCheckState; AGlyph: TBitmap; AGlyphCount: Integer; ABorderStyle: TcxEditCheckBoxBorderStyle; ANativeStyle: Boolean; ABorderColor: TColor; ABackgroundColor: TColor; ADrawBackground, AIsDesigning, AFocused, ASupportGrayed: Boolean; APainter: TcxCustomLookAndFeelPainterClass; AGrayedShowingStyle: TcxCheckBoxNullValueShowingStyle = nssGrayedChecked); const CheckState2ButtonState: array[TcxEditCheckState] of TcxButtonState = (cxbsNormal, cxbsHot, cxbsPressed, cxbsDisabled); procedure DrawCheckBoxGlyph; var ABitmap: TBitmap; AGlyphIndex: Integer; R: TRect; begin AGlyphIndex := GetEditCheckGlyphIndex(AState, ACheckState, ASupportGrayed, AGlyphCount); ABitmap := TBitmap.Create; try ABitmap.Assign(AGlyph); ABitmap.Height := ACheckRect.Bottom - ACheckRect.Top; ABitmap.Width := ACheckRect.Right - ACheckRect.Left; R.Left := (AGlyph.Width div AGlyphCount) * AGlyphIndex; R.Right := R.Left + ABitmap.Width; R.Top := (AGlyph.Height - ABitmap.Height) div 2; R.Bottom := R.Top + ABitmap.Height; ABitmap.Canvas.CopyRect(Rect(0, 0, ABitmap.Width, ABitmap.Height), AGlyph.Canvas, R); DrawGlyph(ACanvas, ACheckRect.Left, ACheckRect.Top, ABitmap, ACheckState <> ecsDisabled, ColorToRGB(ABackgroundColor)); finally ABitmap.Free; end; end; procedure DrawCheckBoxBorder; const ACheckBoxStateToButtonStateMap: array [TcxEditCheckState] of TcxButtonState = (cxbsNormal, cxbsHot, cxbsPressed, cxbsDisabled); var ACheckBorderOffset: Integer; R: TRect; begin if ANativeStyle then begin DrawThemeBackground(OpenTheme(totButton), ACanvas.Handle, BP_CHECKBOX, GetCheckNativeState(AState, ACheckState), ACheckRect); Exit; end; R := ACheckRect; ACheckBorderOffset := GetEditCheckBorderOffset(ABorderStyle, False, False, APainter); if ADrawBackground and (ACheckBorderOffset > 0) then ACanvas.FrameRect(R, ABackgroundColor, ACheckBorderOffset); InflateRect(R, -ACheckBorderOffset, -ACheckBorderOffset); with ACanvas do begin case ABorderStyle of ebsSingle: FrameRect(R, ABorderColor); ebsThick: FrameRect(R, ABorderColor, 2); ebsFlat: begin DrawEdge(R, True, True, cxBordersAll); InflateRect(R, -1, -1); FrameRect(R, clBtnFace); end; ebs3D: begin DrawEdge(R, True, True, cxBordersAll); InflateRect(R, -1, -1); DrawComplexFrame(R, cl3DDkShadow, cl3DLight, cxBordersAll); end; ebsUltraFlat, ebsOffice11: begin if (ABorderStyle = ebsOffice11) and (ACheckState = ecsNormal) and not AIsDesigning and not AFocused then ABorderColor := clBtnText else if (ACheckState in [ecsHot, ecsPressed]) or AIsDesigning and (ACheckState <> ecsDisabled) or (ACheckState = ecsNormal) and AFocused then ABorderColor := GetEditBorderHighlightColor( ABorderStyle = ebsOffice11) else ABorderColor := clBtnShadow; FrameRect(R, ABorderColor); end; end; end; end; procedure DrawCheck(R: TRect; AColor: TColor); const ROP_PSDPxax = $B8074A; var APrevClipRgn: TcxRegion; begin APrevClipRgn := ACanvas.GetClipRegion; try ACanvas.SetClipRegion(TcxRegion.Create(R), roIntersect); InflateRect(R, cxEditMaxCheckBoxBorderWidth, cxEditMaxCheckBoxBorderWidth); ACanvas.Brush.Color := AColor; BitBlt(ACanvas.Handle, R.Left, R.Top, FCheckMask.Width, FCheckMask.Height, FCheckMask.Canvas.Handle, 0, 0, ROP_PSDPxax); finally ACanvas.SetClipRegion(APrevClipRgn, roSet); end; end; function GetCheckBoxContentColor: TColor; const AColors: array[TcxEditCheckState] of TColor = (clWindow, clWindow, clBtnFace, clBtnFace); begin if ABorderStyle in [ebsUltraFlat, ebsOffice11] then case ACheckState of ecsNormal: if (AState = cbsGrayed) and (AGrayedShowingStyle = nssInactive) then Result := clBtnFace else Result := clWindow; ecsHot, ecsPressed: Result := GetEditButtonHighlightColor( ACheckState = ecsPressed, ABorderStyle = ebsOffice11); else Result := clBtnFace; end else if (AState = cbsGrayed) and (AGrayedShowingStyle = nssInactive) then Result := clBtnFace else Result := AColors[ACheckState]; end; procedure InternalDrawCheckBoxContent(AContentRect: TRect); const AButtonStateMap: array [TcxEditCheckState] of TcxButtonState = (cxbsNormal, cxbsHot, cxbsPressed, cxbsDisabled); var ACheckColor: TColor; begin cxEditFillRect(ACanvas.Handle, AContentRect, GetSolidBrush(GetCheckBoxContentColor)); if (AState = cbsUnchecked) or (AState = cbsGrayed) and (AGrayedShowingStyle <> nssGrayedChecked) then Exit; if (ACheckState = ecsDisabled) or (AState = cbsGrayed) then ACheckColor := clBtnShadow else ACheckColor := clBtnText; DrawCheck(AContentRect, ACheckColor); end; procedure DrawWindowsCheckBoxContent(AContentRect: TRect); const ABorder3DStyleMap: array [Boolean] of Integer = (DFCS_FLAT, 0); AGrayedShowingStyleMap: array [TcxCheckBoxNullValueShowingStyle] of Integer = (0, DFCS_INACTIVE, DFCS_CHECKED); var AClipRgnExists: Boolean; AFlags: Integer; APrevClipRgn: HRGN; begin if ACheckState = ecsDisabled then begin AFlags := DFCS_BUTTON3STATE or DFCS_PUSHED; if (AState = cbsUnchecked) or ((AState = cbsGrayed) and (AGrayedShowingStyle <> nssGrayedChecked)) then AFlags := AFlags or DFCS_INACTIVE else AFlags := AFlags or DFCS_CHECKED; end else begin AFlags := 0; case AState of cbsGrayed: AFlags := DFCS_BUTTON3STATE or AGrayedShowingStyleMap[AGrayedShowingStyle]; cbsChecked: AFlags := DFCS_CHECKED; end; if ACheckState = ecsPressed then AFlags := AFlags or DFCS_PUSHED; end; APrevClipRgn := CreateRectRgn(0, 0, 0, 0); AClipRgnExists := GetClipRgn(ACanvas.Handle, APrevClipRgn) = 1; with AContentRect do IntersectClipRect(ACanvas.Handle, Left, Top, Right, Bottom); InflateRect(AContentRect, cxEditMaxCheckBoxBorderWidth, cxEditMaxCheckBoxBorderWidth); DrawFrameControl(ACanvas.Handle, AContentRect, DFC_BUTTON, DFCS_BUTTONCHECK or AFlags or ABorder3DStyleMap[ABorderStyle = ebs3D]); if AClipRgnExists then SelectClipRgn(ACanvas.Handle, APrevClipRgn) else SelectClipRgn(ACanvas.Handle, 0); DeleteObject(APrevClipRgn); end; procedure DrawCheckBoxContent; var ACheckBoxBorderWidth: Integer; R: TRect; begin if ANativeStyle then Exit; ACheckBoxBorderWidth := cxEditMaxCheckBoxBorderWidth; R := ACheckRect; InflateRect(R, -ACheckBoxBorderWidth, -ACheckBoxBorderWidth); if ABorderStyle in [ebsUltraFlat, ebsOffice11] then InternalDrawCheckBoxContent(R) else DrawWindowsCheckBoxContent(R); end; begin if not ADrawBackground then ABackgroundColor := clNone; if (AState = cbsGrayed) and (AGrayedShowingStyle = nssUnchecked) then AState := cbsUnchecked; if IsGlyphValid(AGlyph, AGlyphCount) then DrawCheckBoxGlyph else begin if APainter <> nil then begin if ADrawBackground then ACanvas.FillRect(ACheckRect, ABackgroundColor); APainter.DrawCheckButton(ACanvas, ACheckRect, CheckState2ButtonState[ACheckState], AState); end else begin DrawCheckBoxBorder; DrawCheckBoxContent; end; end; end; function GetEditCheckBorderOffset(ACheckBorderStyle: TcxContainerBorderStyle; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; begin if ANativeStyle or AHasGlyph or (APainter <> nil) then Result := 0 else Result := cxContainerMaxBorderWidth - GetContainerBorderWidth(ACheckBorderStyle); end; function GetEditCheckBorderOffset(ACheckBorderStyle: TcxEditBorderStyle; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; overload; begin Result := GetEditCheckBorderOffset( TcxContainerBorderStyle(ACheckBorderStyle), ANativeStyle, AHasGlyph, APainter); end; function GetEditCheckBorderOffset(ALookAndFeelKind: TcxLookAndFeelKind; ANativeStyle, AHasGlyph: Boolean; APainter: TcxCustomLookAndFeelPainterClass): Integer; begin if ANativeStyle or AHasGlyph or (APainter <> nil) then Result := 0 else Result := cxContainerMaxBorderWidth - GetContainerBorderWidth(ALookAndFeelKind); end; function GetEditCheckGlyphIndex(AState: TcxCheckBoxState; ACheckState: TcxEditCheckState; ASupportGrayed: Boolean; AGlyphCount: Integer): Integer; var AStateCount: Integer; begin AStateCount := Integer(High(TcxCheckBoxState)) - Integer(Low(TcxCheckBoxState)) + 1; if not ASupportGrayed and (AGlyphCount mod 3 <> 0) and (AGlyphCount mod 2 = 0) then Dec(AStateCount); case AState of cbsUnchecked: Result := 0; cbsChecked: Result := 1; else Result := 2; end; if ACheckState = ecsPressed then Inc(Result, AStateCount); if (Result >= AGlyphCount) and (Result > AStateCount - 1) then Result := Result mod AStateCount; end; function GetEditCheckSize(ACanvas: TcxCanvas; ANativeStyle: Boolean; AGlyph: TBitmap; AGlyphCount: Integer; APainter: TcxCustomLookAndFeelPainterClass): TSize; var AHasGlyph: Boolean; begin AHasGlyph := IsGlyphValid(AGlyph, AGlyphCount); if AHasGlyph then begin Result.cx := AGlyph.Width div AGlyphCount; Result.cy := AGlyph.Height; end else if APainter <> nil then Result := APainter.CheckButtonSize else if AreVisualStylesMustBeUsed(ANativeStyle, totButton) then with TcxWinXPLookAndFeelPainter do Result := CheckButtonSize else with TcxCustomLookAndFeelPainter do Result := CheckButtonSize; end; { TcxCaptionItem } procedure TcxCaptionItem.Assign(Source: TPersistent); begin if Source is TcxCaptionItem then begin Caption := TcxCaptionItem(Source).Caption; Tag := TcxCaptionItem(Source).Tag; end else inherited; end; function TcxCaptionItem.IsTagStored: Boolean; begin Result := FTag <> 0; end; procedure TcxCaptionItem.SetCaption(AValue: TCaption); begin if Caption <> AValue then begin FCaption := AValue; if (Collection <> nil) and TcxCaptionItems(Collection).Sorted then TcxCaptionItems(Collection).Sort else Changed(False); end; end; { TcxCaptionItems } function TcxCaptionItems.DoCompareItems(AItem1, AItem2: TcxInterfacedCollectionItem): Integer; begin Result := AnsiCompareText(TcxCaptionItem(AItem1).Caption, TcxCaptionItem(AItem2).Caption); end; function TcxCaptionItems.GetCaption(AIndex: Integer): string; begin Result := Items[Aindex].Caption; end; function TcxCaptionItems.GetCount: Integer; begin Result := Count; end; function TcxCaptionItems.GetItem(AIndex: Integer): TcxCaptionItem; begin Result := TcxCaptionItem(inherited Items[AIndex]); end; procedure TcxCaptionItems.SetItem(AIndex: Integer; AValue: TcxCaptionItem); begin inherited Items[AIndex] := AValue; end; { TcxCustomCheckBoxViewInfo } procedure TcxCustomCheckBoxViewInfo.Assign(Source: TObject); begin if Source is TcxCustomCheckBoxViewInfo then with Source as TcxCustomCheckBoxViewInfo do begin Self.CheckBoxState := CheckBoxState; Self.State := State; end; inherited Assign(Source); end; procedure TcxCustomCheckBoxViewInfo.DrawText(ACanvas: TcxCanvas); begin DrawCheckBoxText(ACanvas, Text, Font, TextColor, TextRect, DrawTextFlags, IsTextEnabled); end; function TcxCustomCheckBoxViewInfo.GetUpdateRegion(AViewInfo: TcxContainerViewInfo): TcxRegion; var AEquals: Boolean; ATempRgn: TcxRegion; begin Result := inherited GetUpdateRegion(AViewInfo); if not(AViewInfo is TcxCustomCheckBoxViewInfo) then Exit; with TcxCustomCheckBoxViewInfo(AViewInfo) do AEquals := (Self.CheckBoxState = CheckBoxState) and (Self.State = State); if not AEquals then begin ATempRgn := TcxRegion.Create(CheckBoxRect); UniteRegions(Result, ATempRgn); ATempRgn.Free; end; end; function TcxCustomCheckBoxViewInfo.IsHotTrack: Boolean; begin Result := True; end; function TcxCustomCheckBoxViewInfo.IsHotTrack(P: TPoint): Boolean; begin Result := IsHotTrack; end; function TcxCustomCheckBoxViewInfo.NeedShowHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect): Boolean; begin Result := False; end; procedure TcxCustomCheckBoxViewInfo.Offset(DX, DY: Integer); begin inherited Offset(DX, DY); OffsetRect(CheckBoxRect, DX, DY); OffsetRect(FocusRect, DX, DY); end; function TcxCustomCheckBoxViewInfo.Repaint(AControl: TWinControl; const AInnerEditRect: TRect; AViewInfo: TcxContainerViewInfo = nil): Boolean; var R: TRect; begin Result := AControl.HandleAllocated; if not Result then Exit; Result := inherited Repaint(AControl, AInnerEditRect, AViewInfo); with TcxCustomCheckBoxViewInfo(AViewInfo) do begin Result := Result or (AViewInfo <> nil) and ((Self.CheckBoxState <> CheckBoxState) or (Self.State <> State)); if (AViewInfo = nil) or (Self.CheckBoxState <> CheckBoxState) or (Self.State <> State) then begin R := Self.CheckBoxRect; OffsetRect(R, Self.Left, Self.Top); InternalInvalidate(AControl.Handle, R, cxEmptyRect, False); end; end; end; function TcxCustomCheckBoxViewInfo.IsTextEnabled: Boolean; begin Result := IsContainerInnerControl or Enabled or IsTextColorAssigned or NativeStyle; end; procedure TcxCustomCheckBoxViewInfo.InternalPaint(ACanvas: TcxCanvas); begin DrawCustomCheckBox(ACanvas, Self); end; function TcxCustomCheckBoxViewInfo.GetEdit: TcxCustomCheckBox; begin Result := TcxCustomCheckBox(FEdit); end; { TcxCustomCheckBoxViewData } procedure TcxCustomCheckBoxViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); procedure CalculateCheckBoxRect(ACheckBoxViewInfo: TcxCustomCheckBoxViewInfo; const ACheckSize: TSize); var ACheckBoxRect, AAvailableArea: TRect; AAlignment: TAlignment; begin AAlignment := ACheckBoxViewInfo.Alignment; AAvailableArea := AViewInfo.ClientRect; if IsInplace and not Properties.IsEmbeddedEdit then case AAlignment of taLeftJustify: Inc(AAvailableArea.Left, 2); taRightJustify: Dec(AAvailableArea.Right, 2); end; if not (IsInplace or AreVisualStylesMustBeUsed(AViewInfo.NativeStyle, totButton) and Properties.IsEmbeddedEdit) then InflateRect(AAvailableArea, -2, -2); ACheckBoxRect := cxRectCenter(AAvailableArea, Min(ACheckSize.cx, cxRectWidth(AAvailableArea)), ACheckSize.cy); if cxRectWidth(AAvailableArea) > ACheckSize.cx then case AAlignment of taLeftJustify: begin ACheckBoxRect.Left := AAvailableArea.Left; ACheckBoxRect.Right := ACheckBoxRect.Left + ACheckSize.cx; end; taRightJustify: begin ACheckBoxRect.Right := AAvailableArea.Right; ACheckBoxRect.Left := ACheckBoxRect.Right - ACheckSize.cx; end; end; ACheckBoxViewInfo.CheckBoxRect := ACheckBoxRect; end; procedure CalculateTextRect(ACheckBoxViewInfo: TcxCustomCheckBoxViewInfo); var ACaptionRect: TRect; AAlignment: TAlignment; begin AAlignment := ACheckBoxViewInfo.Alignment; ACaptionRect := AViewInfo.ClientRect; if IsInplace then begin case AAlignment of taLeftJustify: Dec(ACaptionRect.Right, 2); taRightJustify: Inc(ACaptionRect.Left, 2); end; Inc(ACaptionRect.Top, EditContentParams.Offsets.Top); Dec(ACaptionRect.Bottom, EditContentParams.Offsets.Bottom); end else begin InflateRect(ACaptionRect, -2, -2); if not Properties.IsEmbeddedEdit and (not EmulateStandardControlDrawing or not AreVisualStylesMustBeUsed(AViewInfo.NativeStyle, totButton) and (Style.LookAndFeel.SkinPainter = nil)) then Dec(ACaptionRect.Top); end; if cxRectWidth(ACheckBoxViewInfo.CheckBoxRect) < cxRectWidth(AViewInfo.ClientRect) then case AAlignment of taLeftJustify: ACaptionRect.Left := ACheckBoxViewInfo.CheckBoxRect.Right + 3; taRightJustify: ACaptionRect.Right := ACheckBoxViewInfo.CheckBoxRect.Left - 3 + Integer(IsInplace and Properties.IsEmbeddedEdit); end else ACaptionRect.Right := ACaptionRect.Left; if not ACheckBoxViewInfo.IsTextEnabled and (Style.LookAndFeel.SkinPainter = nil) then begin Inc(ACaptionRect.Right); Inc(ACaptionRect.Bottom); end; ACheckBoxViewInfo.TextRect := ACaptionRect; end; function GetCheckBoxBorderStyle(AEditHotState: TcxContainerHotState): TcxEditBorderStyle; const ABorderStyles: array[TcxContainerHotState, TcxEditBorderStyle] of TcxEditBorderStyle = ( (ebsNone, ebsSingle, ebsThick, ebsFlat, ebs3D, ebsUltraFlat, ebsOffice11), (ebsNone, ebsSingle, ebsThick, ebsFlat, ebs3D, ebsUltraFlat, ebsOffice11), (ebsFlat, ebsThick, ebsThick, ebs3D, ebs3D, ebsUltraFlat, ebsOffice11) ); begin Result := ABorderStyles[AEditHotState, Style.BorderStyle]; end; var ACheckBoxViewInfo: TcxCustomCheckBoxViewInfo; begin inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent); ACheckBoxViewInfo := TcxCustomCheckBoxViewInfo(AViewInfo); ACheckBoxViewInfo.IsEditClass := GetIsEditClass; ACheckBoxViewInfo.DrawSelectionBar := False; ACheckBoxViewInfo.HasPopupWindow := False; ACheckBoxViewInfo.DrawTextFlags := GetDrawTextFlags; CalculateCheckBoxViewInfo(Self, ACheckBoxViewInfo, AIsMouseEvent); if Edit <> nil then ACheckBoxViewInfo.Text := TcxCustomCheckBox(Edit).Caption; if IsInplace and not (Properties.IsEmbeddedEdit or Properties.UseAlignmentWhenInplace or (ACheckBoxViewInfo.Text <> '')) then ACheckBoxViewInfo.Alignment := taCenter else ACheckBoxViewInfo.Alignment := Properties.Alignment; ACheckBoxViewInfo.CheckBoxBorderStyle := GetCheckBoxBorderStyle(AViewInfo.HotState); ACheckBoxViewInfo.CheckBoxGlyph := Properties.Glyph; ACheckBoxViewInfo.CheckBoxGlyphCount := Properties.GlyphCount; ACheckBoxViewInfo.NullValueShowingStyle := Properties.NullStyle; ACheckBoxViewInfo.HasGlyph := IsGlyphValid(Properties.Glyph, Properties.GlyphCount); ACheckBoxViewInfo.CheckBorderOffset := GetEditCheckBorderOffset(ACheckBoxViewInfo.CheckBoxBorderStyle, NativeStyle, ACheckBoxViewInfo.HasGlyph, ACheckBoxViewInfo.Painter); ACheckBoxViewInfo.IsTextColorAssigned := Style.IsValueAssigned(svTextColor) or ((ACheckBoxViewInfo.Painter <> nil) and (ACheckBoxViewInfo.Painter.DefaultEditorTextColor(True) <> clDefault)); CalculateCheckBoxRect(ACheckBoxViewInfo, GetEditCheckSize(ACanvas, NativeStyle, Properties.Glyph, Properties.GlyphCount, AViewInfo.Painter)); CalculateTextRect(ACheckBoxViewInfo); if not Enabled then ACheckBoxViewInfo.CheckBoxState := ecsDisabled else if IsCheckPressed then ACheckBoxViewInfo.CheckBoxState := ecsPressed else if not IsDesigning and PtInRect(ACheckBoxViewInfo.BorderRect, P) then if ([ssLeft, ssRight, ssMiddle] * Shift) = [] then ACheckBoxViewInfo.CheckBoxState := ecsHot else if (ssLeft in Shift) and ((Button = cxmbLeft) or (ACheckBoxViewInfo.CheckBoxState = ecsPressed)) then ACheckBoxViewInfo.CheckBoxState := ecsPressed else ACheckBoxViewInfo.CheckBoxState := ecsNormal else ACheckBoxViewInfo.CheckBoxState := ecsNormal; CalculateCustomCheckBoxViewInfo(ACanvas, Self, ACheckBoxViewInfo); if IsInplace and (ACheckBoxViewInfo.CheckBoxBorderStyle = ebsSingle) then if (ACheckBoxViewInfo.CheckBoxState = ecsHot) or (IsDesigning and (ACheckBoxViewInfo.CheckBoxState <> ecsDisabled)) then ACheckBoxViewInfo.BorderColor := clHighlight else ACheckBoxViewInfo.BorderColor := clBtnShadow; end; procedure TcxCustomCheckBoxViewData.EditValueToDrawValue(ACanvas: TcxCanvas; const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); begin if PreviewMode then TcxCustomCheckBoxViewInfo(AViewInfo).State := cbsChecked else TcxCustomCheckBoxViewInfo(AViewInfo).State := Properties.GetState(AEditValue); if IsInplace and not Properties.IsEmbeddedEdit then TcxCustomCheckBoxViewInfo(AViewInfo).Text := ''; CalculateCustomCheckBoxViewInfo(ACanvas, Self, TcxCustomCheckBoxViewInfo(AViewInfo)); end; function TcxCustomCheckBoxViewData.GetBorderStyle: TcxEditBorderStyle; begin Result := ebsNone; end; function TcxCustomCheckBoxViewData.InternalGetEditConstantPartSize(ACanvas: TcxCanvas; AIsInplace: Boolean; AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo): TSize; var ACheckBoxViewInfo: TcxCustomCheckBoxViewInfo; ASize1, ASize2: TSize; AText: string; begin Result := inherited InternalGetEditConstantPartSize(ACanvas, AIsInplace, AEditSizeProperties, MinContentSize, AViewInfo); ACheckBoxViewInfo := TcxCustomCheckBoxViewInfo(AViewInfo); with ACheckBoxViewInfo.CheckBoxRect do ASize1 := Size(Right - Left, Bottom - Top); if IsInplace then if (ACheckBoxViewInfo.Alignment <> taCenter) and (ACheckBoxViewInfo.Text <> '') then begin ACanvas.Font := Style.GetVisibleFont; ASize1.cx := ACheckBoxViewInfo.TextRect.Left - ACheckBoxViewInfo.Bounds.Left + ACanvas.TextWidth(RemoveAccelChars(ACheckBoxViewInfo.Text)) + (ACheckBoxViewInfo.Bounds.Right - ACheckBoxViewInfo.TextRect.Right); end else ASize1.cx := ASize1.cx + 2 * 2; if IsInplace then ASize1.cy := ASize1.cy + (1 - ACheckBoxViewInfo.CheckBorderOffset) * 2 else ASize1.cy := ASize1.cy + 2 * 2; if (Properties.Alignment = taCenter) or IsInplace then AText := 'Gg' else AText := RemoveAccelChars(TcxCustomCheckBox(Edit).Caption); if not Enabled and not IsNativeStyle(Style.LookAndFeel) then Dec(AEditSizeProperties.Width); ASize2 := GetTextEditContentSize(ACanvas, Self, AText, DrawTextFlagsTocxTextOutFlags(GetDrawTextFlags) or CXTO_SINGLELINE or CXTO_CHARBREAK, AEditSizeProperties, 0, False); if ASize1.cy < ASize2.cy then ASize1.cy := ASize2.cy; Result.cx := Result.cx + ASize1.cx; Result.cy := Result.cy + ASize1.cy; end; function TcxCustomCheckBoxViewData.GetDrawTextFlags: Integer; const AHorzAlignmentFlags: array [TcxEditHorzAlignment] of Integer = ( cxAlignLeft, cxAlignLeft, cxAlignHCenter ); begin with Properties.InternalAlignment do begin Result := AHorzAlignmentFlags[Horz]; Result := Result or cxSingleLine; end; Result := Result or cxShowPrefix; if Properties.MultiLine then begin Result := Result and (not cxSingleLine); Result := Result or cxDontClip; Result := Result or cxWordBreak; end; if IsInplace or not Properties.MultiLine then Result := Result or cxAlignVCenter else Result := Result or cxAlignTop; end; function TcxCustomCheckBoxViewData.GetIsEditClass: Boolean; begin Result := True; end; function TcxCustomCheckBoxViewData.IsCheckPressed: Boolean; begin Result := (Edit <> nil) and TcxCustomCheckBox(Edit).FIsCheckPressed; end; function TcxCustomCheckBoxViewData.GetProperties: TcxCustomCheckBoxProperties; begin Result := TcxCustomCheckBoxProperties(FProperties); end; { TcxCheckBoxStyle } function TcxCheckBoxStyle.HasBorder: Boolean; begin Result := False; end; { TcxCustomCheckBoxProperties } constructor TcxCustomCheckBoxProperties.Create(AOwner: TPersistent); begin inherited Create(AOwner); FDisplayChecked := cxGetResourceString(@cxSEditCheckBoxChecked); FDisplayUnchecked := cxGetResourceString(@cxSEditCheckBoxUnchecked); FDisplayGrayed := cxGetResourceString(@cxSEditCheckBoxGrayed); FGlyphCount := 6; FNullStyle := nssGrayedChecked; FValueChecked := True; FValueGrayed := Null; FValueUnchecked := False; end; destructor TcxCustomCheckBoxProperties.Destroy; begin if FGlyph <> nil then FreeAndNil(FGlyph); inherited Destroy; end; procedure TcxCustomCheckBoxProperties.Assign(Source: TPersistent); begin if Source is TcxCustomCheckBoxProperties then begin BeginUpdate; try inherited Assign(Source); with Source as TcxCustomCheckBoxProperties do begin Self.AllowGrayed := AllowGrayed; Self.DisplayChecked := DisplayChecked; Self.DisplayGrayed := DisplayGrayed; Self.DisplayUnchecked := DisplayUnchecked; Self.FullFocusRect := FullFocusRect; Self.Glyph := Glyph; Self.GlyphCount := GlyphCount; Self.MultiLine := MultiLine; Self.NullStyle := NullStyle; Self.UseAlignmentWhenInplace := UseAlignmentWhenInplace; Self.SetStateValues(ValueChecked, ValueGrayed, ValueUnchecked); end; finally EndUpdate; end end else inherited Assign(Source); end; function TcxCustomCheckBoxProperties.CanCompareEditValue: Boolean; begin Result := True; end; function TcxCustomCheckBoxProperties.CompareDisplayValues( const AEditValue1, AEditValue2: TcxEditValue): Boolean; begin Result := GetState(AEditValue1) = GetState(AEditValue2); end; class function TcxCustomCheckBoxProperties.GetContainerClass: TcxContainerClass; begin Result := TcxCheckBox; end; function TcxCustomCheckBoxProperties.GetDisplayText(const AEditValue: TcxEditValue; AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; begin case GetState(AEditValue) of cbsChecked: Result := FDisplayChecked; cbsUnchecked: Result := FDisplayUnchecked; cbsGrayed: Result := FDisplayGrayed; end; end; class function TcxCustomCheckBoxProperties.GetStyleClass: TcxCustomEditStyleClass; begin Result := TcxCheckBoxStyle; end; function TcxCustomCheckBoxProperties.GetSpecialFeatures: TcxEditSpecialFeatures; begin Result := inherited GetSpecialFeatures + [esfNoContentPart]; end; function TcxCustomCheckBoxProperties.GetSupportedOperations: TcxEditSupportedOperations; begin Result := [esoAlwaysHotTrack, esoEditing, esoFiltering, esoHotTrack, esoShowingCaption, esoSorting, esoTransparency]; end; class function TcxCustomCheckBoxProperties.GetViewInfoClass: TcxContainerViewInfoClass; begin Result := TcxCustomCheckBoxViewInfo; end; function TcxCustomCheckBoxProperties.IsActivationKey(AKey: Char): Boolean; begin Result := AKey = ' '; end; function TcxCustomCheckBoxProperties.IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; begin Result := inherited IsEditValueValid(EditValue, AEditFocused); if Result then Result := not CheckValue(EditValue); end; function TcxCustomCheckBoxProperties.IsResetEditClass: Boolean; begin Result := True; end; procedure TcxCustomCheckBoxProperties.PrepareDisplayValue(const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; AEditFocused: Boolean); begin if VarEqualsExact(AEditValue, FValueChecked) then DisplayValue := Integer(cbsChecked) else if VarEqualsExact(AEditValue, FValueUnchecked) then DisplayValue := Integer(cbsUnchecked) else DisplayValue := Integer(cbsGrayed); end; function TcxCustomCheckBoxProperties.CanValidate: Boolean; begin Result := True; end; procedure TcxCustomCheckBoxProperties.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineProperty('Caption', ReadCaption, nil, False); end; class function TcxCustomCheckBoxProperties.GetViewDataClass: TcxCustomEditViewDataClass; begin Result := TcxCustomCheckBoxViewData; end; function TcxCustomCheckBoxProperties.HasDisplayValue: Boolean; begin Result := True; end; function TcxCustomCheckBoxProperties.CheckValue(const AValue: TcxEditValue): Boolean; begin Result := not(InternalVarEqualsExact(AValue, FValueChecked) or InternalVarEqualsExact(AValue, FValueGrayed) or InternalVarEqualsExact(AValue, FValueUnchecked)); end; function TcxCustomCheckBoxProperties.GetState( const AEditValue: TcxEditValue): TcxCheckBoxState; var ADisplayValue: TcxEditValue; begin PrepareDisplayValue(AEditValue, ADisplayValue, False); Result := TcxCheckBoxState(Integer(ADisplayValue)); end; function TcxCustomCheckBoxProperties.InternalGetGlyph: TBitmap; begin if FGlyph = nil then begin FGlyph := TBitmap.Create; FGlyph.OnChange := GlyphChanged; end; Result := FGlyph; end; function TcxCustomCheckBoxProperties.IsEmbeddedEdit: Boolean; begin Result := False; end; function TcxCustomCheckBoxProperties.GetAlignment: TAlignment; begin Result := inherited Alignment.Horz; end; function TcxCustomCheckBoxProperties.GetGlyph: TBitmap; begin Result := InternalGetGlyph; end; function TcxCustomCheckBoxProperties.GetInternalAlignment: TcxEditAlignment; begin Result := inherited Alignment; end; procedure TcxCustomCheckBoxProperties.GlyphChanged(Sender: TObject); begin Changed; end; function TcxCustomCheckBoxProperties.IsAlignmentStored: Boolean; begin Result := inherited Alignment.IsHorzStored; end; function TcxCustomCheckBoxProperties.IsDisplayCheckedStored: Boolean; begin Result := not InternalCompareString(FDisplayChecked, cxGetResourceString(@cxSEditCheckBoxChecked), True); end; function TcxCustomCheckBoxProperties.IsDisplayGrayedStored: Boolean; begin Result := not InternalCompareString(FDisplayGrayed, cxGetResourceString(@cxSEditCheckBoxGrayed), True); end; function TcxCustomCheckBoxProperties.IsDisplayUncheckedStored: Boolean; begin Result := not InternalCompareString(FDisplayUnchecked, cxGetResourceString(@cxSEditCheckBoxUnchecked), True); end; function TcxCustomCheckBoxProperties.IsLoading: Boolean; begin Result := (GetOwnerComponent(Self) <> nil) and (csLoading in GetOwnerComponent(Self).ComponentState); end; function TcxCustomCheckBoxProperties.IsValueCheckedStored: Boolean; begin Result := not InternalVarEqualsExact(FValueChecked, True); end; function TcxCustomCheckBoxProperties.IsValueGrayedStored: Boolean; begin Result := not VarIsNull(FValueGrayed); end; function TcxCustomCheckBoxProperties.IsValueUncheckedStored: Boolean; begin Result := not InternalVarEqualsExact(FValueUnchecked, False); end; // obsolete procedure TcxCustomCheckBoxProperties.ReadCaption(Reader: TReader); begin Caption := Reader.ReadString; end; procedure TcxCustomCheckBoxProperties.SetAlignment(Value: TAlignment); begin inherited Alignment.Horz := Value; end; // obsolete procedure TcxCustomCheckBoxProperties.SetCaption(const Value: TCaption); begin FIsCaptionAssigned := True; if not InternalCompareString(Value, FCaption, True) then begin FCaption := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetFullFocusRect(Value: Boolean); begin if Value <> FFullFocusRect then begin FFullFocusRect := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetGlyph(Value: TBitmap); begin if Value = nil then FreeAndNil(FGlyph) else Glyph.Assign(Value); Changed; end; procedure TcxCustomCheckBoxProperties.SetGlyphCount(Value: Integer); begin if FGlyphCount <> Value then begin FGlyphCount := Value; if FGlyph <> nil then Changed; end; end; procedure TcxCustomCheckBoxProperties.SetMultiLine(Value: Boolean); begin if Value <> FMultiLine then begin FMultiLine := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetNullStyle(Value: TcxCheckBoxNullValueShowingStyle); begin if Value <> FNullStyle then begin FNullStyle := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetStateValues(const AValueChecked, AValueGrayed, AValueUnchecked: TcxEditValue); var AIsValuesValid: Boolean; begin AIsValuesValid := not(InternalVarEqualsExact(AValueChecked, AValueGrayed) or InternalVarEqualsExact(AValueGrayed, AValueUnchecked) or InternalVarEqualsExact(AValueChecked, AValueUnchecked) or VarIsNull(AValueChecked) or VarIsNull(AValueUnchecked)); if AIsValuesValid then begin FValueChecked := AValueChecked; FValueGrayed := AValueGrayed; FValueUnchecked := AValueUnchecked; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetUseAlignmentWhenInplace(Value: Boolean); begin if Value <> FUseAlignmentWhenInplace then begin FUseAlignmentWhenInplace := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetValueChecked(const Value: TcxEditValue); begin if IsLoading or CheckValue(Value) and not VarIsNull(Value) then begin FValueChecked := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetValueGrayed(const Value: TcxEditValue); begin if IsLoading or CheckValue(Value) then begin FValueGrayed := Value; Changed; end; end; procedure TcxCustomCheckBoxProperties.SetValueUnchecked(const Value: TcxEditValue); begin if IsLoading or CheckValue(Value) and not VarIsNull(Value) then begin FValueUnchecked := Value; Changed; end; end; { TcxCustomCheckBox } procedure TcxCustomCheckBox.Clear; begin Checked := False; end; class function TcxCustomCheckBox.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxCustomCheckBoxProperties; end; procedure TcxCustomCheckBox.PrepareEditValue(const ADisplayValue: TcxEditValue; out EditValue: TcxEditValue; AEditFocused: Boolean); begin case TcxCheckBoxState(Integer(ADisplayValue)) of cbsUnchecked: EditValue := ActiveProperties.FValueUnchecked; cbsChecked: EditValue := ActiveProperties.FValueChecked; cbsGrayed: EditValue := ActiveProperties.FValueGrayed; end; end; procedure TcxCustomCheckBox.ActionChange(Sender: TObject; CheckDefaults: Boolean); begin inherited ActionChange(Sender, CheckDefaults); if (IsLoading or FIsLoaded) and FIsLoadingStateAssigned or not(Sender is TCustomAction) then Exit; if not CheckDefaults or (Checked = False) then TcxCheckBoxActionLink(ActionLink).InternalSetChecked(TCustomAction(Sender).Checked); end; function TcxCustomCheckBox.CanHaveTransparentBorder: Boolean; begin Result := not IsInplace and not ActiveProperties.IsEmbeddedEdit or inherited CanHaveTransparentBorder; end; function TcxCustomCheckBox.DefaultParentColor: Boolean; begin Result := True; end; procedure TcxCustomCheckBox.DoEditKeyDown(var Key: Word; Shift: TShiftState); begin inherited DoEditKeyDown(Key, Shift); if Key = 0 then Exit; case Key of VK_SPACE: begin with ViewInfo do if CheckBoxState in [ecsNormal, ecsHot] then begin FIsCheckPressed := True; CheckBoxState := ecsPressed; ShortRefreshContainer(False); Key := 0; end; end; end; end; procedure TcxCustomCheckBox.DoEditKeyPress(var Key: Char); begin inherited DoEditKeyPress(Key); if Key = #0 then Exit; if IsInplace and (Key = #32) and (ViewInfo.CheckBoxState in [ecsNormal, ecsHot]) then begin Toggle; Key := #0; end; end; procedure TcxCustomCheckBox.DoEditKeyUp(var Key: Word; Shift: TShiftState); begin inherited DoEditKeyUp(Key, Shift); if Key = 0 then Exit; case Key of VK_SPACE: begin if ViewInfo.CheckBoxState = ecsPressed then begin FIsCheckPressed := False; ViewInfo.CheckBoxState := ecsNormal; InvalidateCheckRect; Toggle; end; end; end; end; procedure TcxCustomCheckBox.DoExit; begin FIsCheckPressed := False; inherited DoExit; end; procedure TcxCustomCheckBox.FillSizeProperties(var AEditSizeProperties: TcxEditSizeProperties); begin AEditSizeProperties := DefaultcxEditSizeProperties; if not ActiveProperties.MultiLine then AEditSizeProperties.MaxLineCount := 1; AEditSizeProperties.Width := cxRectWidth(ViewInfo.TextRect); end; function TcxCustomCheckBox.GetActionLinkClass: TControlActionLinkClass; begin Result := TcxCheckBoxActionLink; end; function TcxCustomCheckBox.GetEditStateColorKind: TcxEditStateColorKind; begin Result := cxEditStateColorKindMap[Enabled]; end; function TcxCustomCheckBox.GetShadowBounds: TRect; begin if not IsInplace and not ActiveProperties.IsEmbeddedEdit and ViewInfo.NativeStyle and Style.TransparentBorder then begin Result := GetControlRect(Self); InflateRect(Result, -cxContainerMaxBorderWidth, -cxContainerMaxBorderWidth); end else Result := inherited GetShadowBounds; end; procedure TcxCustomCheckBox.Initialize; begin inherited Initialize; ControlStyle := ControlStyle - [csDoubleClicks]; Width := 121; PrepareEditValue(Integer(cbsUnchecked), FEditValue, False); end; function TcxCustomCheckBox.InternalGetNotPublishedStyleValues: TcxEditStyleValues; begin Result := inherited InternalGetNotPublishedStyleValues; Include(Result, svEdges); end; procedure TcxCustomCheckBox.InternalSetEditValue(const Value: TcxEditValue; AValidateEditValue: Boolean); var APrevState: TcxCheckBoxState; begin APrevState := State; inherited InternalSetEditValue(Value, AValidateEditValue); if APrevState <> State then begin ViewInfo.State := State; Click; DoChange; end; ShortRefreshContainer(False); end; function TcxCustomCheckBox.IsClickEnabledDuringLoading: Boolean; begin Result := IsDBEdit; end; function TcxCustomCheckBox.IsNativeBackground: Boolean; begin Result := IsNativeStyle and ParentBackground and not IsInplace and not Transparent; end; procedure TcxCustomCheckBox.Loaded; begin FIsLoaded := True; LockChangeEvents(True); LockClick(True); try inherited Loaded; if FIsLoadingStateAssigned then State := FLoadingState else if not IsDBEdit then State := cbsUnchecked; finally LockClick(False); LockChangeEvents(False, False); FIsLoaded := False; end; end; procedure TcxCustomCheckBox.ProcessViewInfoChanges(APrevViewInfo: TcxCustomEditViewInfo; AIsMouseDownUpEvent: Boolean); begin if (TcxCustomCheckBoxViewInfo(APrevViewInfo).CheckBoxState = ecsPressed) and (ViewInfo.CheckBoxState = ecsHot) then Toggle; end; procedure TcxCustomCheckBox.PropertiesChanged(Sender: TObject); begin if ActiveProperties.FIsCaptionAssigned then begin Caption := ActiveProperties.Caption; ActiveProperties.FIsCaptionAssigned := False; end; if ViewInfo.State <> State then begin ViewInfo.State := State; InvalidateCheckRect; if not AreChangeEventsLocked then begin Click; DoChange; end; end; inherited PropertiesChanged(Sender); end; procedure TcxCustomCheckBox.TextChanged; begin inherited TextChanged; ViewInfo.Text := Caption; Invalidate; end; procedure TcxCustomCheckBox.InvalidateCheckRect; begin InvalidateRect(ViewInfo.CheckBoxRect, False); end; procedure TcxCustomCheckBox.Toggle; begin LockChangeEvents(True); try KeyboardAction := True; try begin case State of cbsUnchecked: if ActiveProperties.AllowGrayed then State := cbsGrayed else State := cbsChecked; cbsChecked: State := cbsUnchecked; cbsGrayed: State := cbsChecked; end; end; finally KeyboardAction := False; end; if ActiveProperties.ImmediatePost and CanPostEditValue and ValidateEdit(True) then InternalPostEditValue; finally LockChangeEvents(False); end; end; function TcxCustomCheckBox.GetChecked: Boolean; begin Result := State = cbsChecked; end; function TcxCustomCheckBox.GetProperties: TcxCustomCheckBoxProperties; begin Result := TcxCustomCheckBoxProperties(FProperties); end; function TcxCustomCheckBox.GetActiveProperties: TcxCustomCheckBoxProperties; begin Result := TcxCustomCheckBoxProperties(InternalGetActiveProperties); end; function TcxCustomCheckBox.GetState: TcxCheckBoxState; begin Result := ActiveProperties.GetState(EditValue); end; function TcxCustomCheckBox.GetStyle: TcxCheckBoxStyle; begin Result := TcxCheckBoxStyle(FStyles.Style); end; function TcxCustomCheckBox.GetViewInfo: TcxCustomCheckBoxViewInfo; begin Result := TcxCustomCheckBoxViewInfo(FViewInfo); end; function TcxCustomCheckBox.IsStateStored: Boolean; const AStates: array[Boolean] of TcxCheckBoxState = (cbsUnchecked, cbsChecked); begin Result := not (Action is TCustomAction) or (State <> AStates[TCustomAction(Action).Checked]); end; procedure TcxCustomCheckBox.SetChecked(Value: Boolean); begin if Value then State := cbsChecked else State := cbsUnchecked; end; procedure TcxCustomCheckBox.SetProperties(Value: TcxCustomCheckBoxProperties); begin FProperties.Assign(Value); end; procedure TcxCustomCheckBox.SetState(Value: TcxCheckBoxState); var AEditValue: TcxEditValue; begin if IsLoading then begin FLoadingState := Value; FIsLoadingStateAssigned := True; end else if Value <> State then begin PrepareEditValue(Integer(Value), AEditValue, InternalFocused); InternalEditValue := AEditValue; end; end; procedure TcxCustomCheckBox.SetStyle(Value: TcxCheckBoxStyle); begin FStyles.Style := Value; end; procedure TcxCustomCheckBox.WMLButtonUp(var Message: TWMLButtonUp); begin ControlState := ControlState - [csClicked]; inherited; end; procedure TcxCustomCheckBox.CMDialogChar(var Message: TCMDialogChar); begin with Message do if IsAccel(CharCode, Caption) {D3 - bug "&&"} and CanFocus then begin SetFocus; if Focused then Toggle; Result := 1; end else inherited; end; procedure TcxCustomCheckBox.CMParentColorChanged(var Message: TMessage); begin inherited; if ViewInfo.NativeStyle and ParentBackground then Invalidate; end; { TcxCheckBox } class function TcxCheckBox.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxCheckBoxProperties; end; function TcxCheckBox.GetActiveProperties: TcxCheckBoxProperties; begin Result := TcxCheckBoxProperties(InternalGetActiveProperties); end; function TcxCheckBox.GetProperties: TcxCheckBoxProperties; begin Result := TcxCheckBoxProperties(FProperties); end; procedure TcxCheckBox.SetProperties(Value: TcxCheckBoxProperties); begin FProperties.Assign(Value); end; { TcxFilterCheckBoxHelper } class procedure TcxFilterCheckBoxHelper.GetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; var V: Variant; var S: TCaption); begin with TcxComboBox(AEdit) do begin case ItemIndex of -1: V := Null; 0: V := TcxCustomCheckBoxProperties(AEditProperties).ValueChecked; 1: V := TcxCustomCheckBoxProperties(AEditProperties).ValueUnchecked; end; if ItemIndex = -1 then S := '' else S := TcxCustomCheckBoxProperties(AEditProperties).GetDisplayText(V); end; end; class function TcxFilterCheckBoxHelper.GetSupportedFilterOperators( AProperties: TcxCustomEditProperties; AValueTypeClass: TcxValueTypeClass; AExtendedSet: Boolean = False): TcxFilterControlOperators; begin Result := [fcoEqual, fcoNotEqual, fcoBlanks, fcoNonBlanks]; end; class procedure TcxFilterCheckBoxHelper.InitializeProperties(AProperties, AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); var ACheckBoxProperties: TcxCustomCheckBoxProperties; begin ACheckBoxProperties := TcxCustomCheckBoxProperties(AEditProperties); with TcxComboBoxProperties(AProperties).Items do begin Clear; Add(ACheckBoxProperties.GetDisplayText(ACheckBoxProperties.ValueChecked)); Add(ACheckBoxProperties.GetDisplayText(ACheckBoxProperties.ValueUnchecked)); end; TcxComboBoxProperties(AProperties).DropDownListStyle := lsFixedList; TcxComboBoxProperties(AProperties).IDefaultValuesProvider := nil; ClearPropertiesEvents(AProperties); end; class procedure TcxFilterCheckBoxHelper.SetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; AValue: Variant); const AItemIndexMap: array [TcxCheckBoxState] of Integer = (1, 0, -1); var V: TcxEditValue; begin AEditProperties.PrepareDisplayValue(AValue, V, AEdit.Focused); TcxComboBox(AEdit).ItemIndex := AItemIndexMap[TcxCheckBoxState((V))]; end; class function TcxFilterCheckBoxHelper.UseDisplayValue: Boolean; begin Result := True; end; { TcxCheckBoxActionLink } procedure TcxCheckBoxActionLink.AssignClient(AClient: TObject); begin inherited AssignClient(AClient); FClient := AClient as TcxCustomCheckBox; end; function TcxCheckBoxActionLink.IsCheckedLinked: Boolean; begin Result := inherited IsCheckedLinked and (FClient.State <> cbsGrayed) and (FClient.Checked = TCustomAction(Action).Checked); end; procedure TcxCheckBoxActionLink.SetChecked(Value: Boolean); begin if IsCheckedLinked then InternalSetChecked(Value); end; procedure TcxCheckBoxActionLink.InternalSetChecked(Value: Boolean); begin FClient.LockClick(True); FClient.LockChangeEvents(True); try FClient.Checked := Value; finally FClient.LockChangeEvents(False, False); FClient.LockClick(False); end; end; initialization GetRegisteredEditProperties.Register(TcxCheckBoxProperties, scxSEditRepositoryCheckBoxItem); FilterEditsController.Register(TcxCheckBoxProperties, TcxFilterCheckBoxHelper); PrepareCheckMask; finalization FilterEditsController.Unregister(TcxCheckBoxProperties, TcxFilterCheckBoxHelper); FreeAndNil(FCheckMask); end.