{********************************************************************} { } { Developer Express Visual Component Library } { ExpressEditors } { } { Copyright (c) 1998-2008 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 cxGroupBox; {$I cxVer.inc} interface uses Windows, Messages, SysUtils, Classes, Controls, Graphics, Forms, cxControls, cxGraphics, cxLookAndFeels, cxContainer, cxEditPaintUtils, cxEdit, cxTextEdit, cxClasses, cxCheckBox, cxLookAndFeelPainters; const cxGroupBox_SupportNonClientArea: Boolean = True; type TcxCaptionAlignment = (alTopLeft, alTopCenter, alTopRight, alBottomLeft, alBottomCenter, alBottomRight, alLeftTop, alLeftCenter, alLeftBottom, alRightTop, alRightCenter, alRightBottom, alCenterCenter); TcxPanelOffice11BackgroundKind = (pobkGradient, pobkOffice11Color, pobkStyleColor); { TcxGroupBoxButtonViewInfo } TcxGroupBoxButtonViewInfo = class(TcxEditButtonViewInfo) public Caption: string; Column, Row: Integer; function GetGlyphRect(ACanvas: TcxCanvas; AGlyphSize: TSize; AAlignment: TLeftRight; AIsPaintCopy: Boolean): TRect; virtual; end; { TcxGroupBoxViewInfo } TcxCustomGroupBox = class; TcxGroupBoxViewInfo = class(TcxCustomTextEditViewInfo) private function GetCaptionRectIndent: TRect; function GetControlRect: TRect; function GetEdit: TcxCustomGroupBox; function CalcOffsetBoundsForPanel: TRect; procedure CalcBoundsForPanel; function GetFrameBounds: TRect; procedure CalcTextBoundsForPanel; function CalcCorrectionBoundsForPanel: TRect; procedure AdjustTextBoundsForPanel; procedure AdjustCaptionBoundsForPanel; procedure DrawHorizontalTextCaption(ACanvas: TcxCanvas); procedure DrawVerticalTextCaption(ACanvas: TcxCanvas); procedure DrawFrame(ACanvas: TcxCanvas; R: TRect); function GetThemeBackgroundRect(ACanvas: TcxCanvas): TRect; function GetBoundsForPanel: TRect; procedure DrawUsualBackground(ACanvas: TcxCanvas); procedure DrawNativeBackground(ACanvas: TcxCanvas; const ACaptionRect: TRect); procedure DrawNativeGroupBoxBackground(ACanvas: TcxCanvas); procedure DrawNativePanelBackground(ACanvas: TcxCanvas; const ACaptionRect: TRect); procedure DrawOffice11PanelBackground(ACanvas: TcxCanvas; const R: TRect); procedure InternalDrawBackground(ACanvas: TcxCanvas); protected procedure AdjustCaptionRect(ACaptionPosition: TcxGroupBoxCaptionPosition); virtual; procedure DrawCaption(ACanvas: TcxCanvas); virtual; function GetButtonViewInfoClass: TcxEditButtonViewInfoClass; override; procedure InternalPaint(ACanvas: TcxCanvas); override; property ControlRect: TRect read GetControlRect; public Alignment: TLeftRight; CaptionRect: TRect; IsDesigning: Boolean; TextRect: TRect; constructor Create; override; destructor Destroy; override; property Edit: TcxCustomGroupBox read GetEdit; end; { TcxGroupBoxViewData } TcxGroupBoxViewData = class(TcxCustomEditViewData) private function GetCaptionRect(ACanvas: TcxCanvas): TRect; function GetShadowWidth: Integer; function HasNonClientArea: Boolean; procedure AdjustHorizontalCaptionRect(var R: TRect); procedure AdjustVerticalCaptionRect(var R: TRect); function GetEdit: TcxCustomGroupBox; procedure CalcRects(ACanvas: TcxCanvas; AEditViewInfo: TcxGroupBoxViewInfo); protected function GetBorderExtentBySkinPainter: TRect; virtual; function GetContainerState(const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AIsMouseEvent: Boolean): TcxContainerState; override; public procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override; function GetBorderColor: TColor; override; function GetBorderExtent: TRect; override; function GetClientExtent(ACanvas: TcxCanvas; AViewInfo: TcxCustomEditViewInfo): TRect; override; function HasShadow: Boolean; override; class function IsNativeStyle(ALookAndFeel: TcxLookAndFeel): Boolean; override; property Edit: TcxCustomGroupBox read GetEdit; end; { TcxButtonGroupViewData } TcxCustomButtonGroupProperties = class; TcxEditMetrics = record AutoHeightColumnWidthCorrection, AutoHeightWidthCorrection, ColumnWidthCorrection, WidthCorrection: Integer; ClientLeftBoundCorrection, ClientWidthCorrection, ColumnOffset: Integer; ButtonSize: TSize; end; { TcxButtonGroupViewInfo } TcxButtonGroupViewInfo = class(TcxGroupBoxViewInfo) protected procedure DrawEditButton(ACanvas: TcxCanvas; AButtonVisibleIndex: Integer); override; procedure DrawButtonCaption(ACanvas: TcxCanvas; AButtonViewInfo: TcxGroupBoxButtonViewInfo; const AGlyphRect: TRect); virtual; abstract; procedure DrawButtonGlyph(ACanvas: TcxCanvas; AButtonViewInfo: TcxGroupBoxButtonViewInfo; const AGlyphRect: TRect); virtual; abstract; function GetGlyphSize: TSize; virtual; function IsButtonGlypthTransparent(AButtonViewInfo: TcxGroupBoxButtonViewInfo): Boolean; virtual; abstract; public CaptionExtent: TRect; GlyphSize: TSize; end; TcxButtonGroupViewData = class(TcxGroupBoxViewData) private function GetProperties: TcxCustomButtonGroupProperties; protected procedure CalculateButtonPositions(ACanvas: TcxCanvas; AViewInfo: TcxCustomEditViewInfo); virtual; procedure CalculateButtonViewInfos(AViewInfo: TcxCustomEditViewInfo); virtual; function GetDrawTextFlags: Integer; virtual; procedure GetEditMetrics(AAutoHeight: Boolean; ACanvas: TcxCanvas; out AMetrics: TcxEditMetrics); virtual; abstract; function GetCaptionRectExtent: TRect; virtual; procedure CalculateButtonNativeState(AViewInfo: TcxCustomEditViewInfo; AButtonViewInfo: TcxGroupBoxButtonViewInfo); virtual; abstract; public procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override; procedure CalculateButtonsViewInfo(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override; function GetEditConstantPartSize(ACanvas: TcxCanvas; const AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo = nil): TSize; override; class function IsButtonNativeStyle(ALookAndFeel: TcxLookAndFeel): Boolean; virtual; property Properties: TcxCustomButtonGroupProperties read GetProperties; end; TcxButtonGroupViewDataClass = class of TcxButtonGroupViewData; { TcxCustomGroupBoxProperties } TcxCustomGroupBoxProperties = class(TcxCustomEditProperties) protected class function GetViewDataClass: TcxCustomEditViewDataClass; override; public class function GetContainerClass: TcxContainerClass; override; class function GetViewInfoClass: TcxContainerViewInfoClass; override; end; { TcxButtonGroupItem } TcxButtonGroupItem = class(TCollectionItem) private FCaption: TCaption; FEnabled: Boolean; FTag: TcxTag; function GetIsCollectionDestroying: Boolean; function IsTagStored: Boolean; procedure SetCaption(const Value: TCaption); procedure SetEnabled(Value: Boolean); protected procedure DoChanged(ACollection: TCollection; ACollectionOperation: TcxCollectionOperation; AIndex: Integer = -1); property Caption: TCaption read FCaption write SetCaption; property Enabled: Boolean read FEnabled write SetEnabled default True; property IsCollectionDestroying: Boolean read GetIsCollectionDestroying; property Tag: TcxTag read FTag write FTag stored IsTagStored; public constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function GetCaption: TCaption; end; { TcxButtonGroupItems } TcxButtonGroupItems = class(TOwnedCollection, IUnknown, IcxCheckItems) private FChangedItemIndex: Integer; FChangedItemOperation: TcxCollectionOperation; FIsDestroying: Boolean; FItemChanged: Boolean; function GetItem(Index: Integer): TcxButtonGroupItem; procedure SetItem(Index: Integer; Value: TcxButtonGroupItem); { IUnknown } function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; { IcxCheckItems } function IcxCheckItems.GetCaption = CheckItemsGetCaption; function IcxCheckItems.GetCount = CheckItemsGetCount; function CheckItemsGetCaption(Index: Integer): string; function CheckItemsGetCount: Integer; protected procedure Update(Item: TCollectionItem); override; property ChangedItemIndex: Integer read FChangedItemIndex; property ChangedItemOperation: TcxCollectionOperation read FChangedItemOperation; property IsDestroying: Boolean read FIsDestroying; property ItemChanged: Boolean read FItemChanged; public destructor Destroy; override; procedure InternalNotify(AItem: TcxButtonGroupItem; AItemIndex: Integer; AItemOperation: TcxCollectionOperation); property Items[Index: Integer]: TcxButtonGroupItem read GetItem write SetItem; default; end; TcxButtonGroupItemsClass = class of TcxButtonGroupItems; { TcxCustomButtonGroupProperties } TcxCustomButtonGroupProperties = class(TcxCustomGroupBoxProperties) private FColumns: Integer; FItems: TcxButtonGroupItems; FWordWrap: Boolean; procedure SetColumns(Value: Integer); procedure SetItems(Value: TcxButtonGroupItems); procedure SetWordWrap(Value: Boolean); protected class function GetViewDataClass: TcxCustomEditViewDataClass; override; function CreateItems: TcxButtonGroupItems; virtual; function GetButtonsPerColumn: Integer; function GetColumnCount: Integer; virtual; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function CreatePreviewProperties: TcxCustomEditProperties; override; class function GetContainerClass: TcxContainerClass; override; function GetSpecialFeatures: TcxEditSpecialFeatures; override; function GetSupportedOperations: TcxEditSupportedOperations; override; class function GetViewInfoClass: TcxContainerViewInfoClass; override; // !!! property Columns: Integer read FColumns write SetColumns default 1; property Items: TcxButtonGroupItems read FItems write SetItems; property WordWrap: Boolean read FWordWrap write SetWordWrap default False; end; { TcxPanelStyle } TcxPanelStyle = class(TPersistent) private FActive: Boolean; FCaptionIndent: Integer; FEdit: TcxCustomGroupBox; FOfficeBackgroundKind: TcxPanelOffice11BackgroundKind; FWordWrap: Boolean; procedure SetActive(AValue: Boolean); procedure SetCaptionIndent(AValue: Integer); procedure SetOfficeBackgroundKind(AValue: TcxPanelOffice11BackgroundKind); procedure SetWordWrap(AValue: Boolean); protected procedure Update; property Edit: TcxCustomGroupBox read FEdit; public constructor Create(AOwner: TcxCustomGroupBox); virtual; procedure Assign(ASource: TPersistent); override; published property Active: Boolean read FActive write SetActive default False; property CaptionIndent: Integer read FCaptionIndent write SetCaptionIndent default 2; property OfficeBackgroundKind: TcxPanelOffice11BackgroundKind read FOfficeBackgroundKind write SetOfficeBackgroundKind default pobkOffice11Color; property WordWrap: Boolean read FWordWrap write SetWordWrap default False; end; { TcxCustomGroupBox } TcxGroupBoxCustomDrawEvent = procedure (Sender: TcxCustomGroupBox; var ADone: Boolean) of object; TcxGroupBoxMeasureCaptionHeightEvent = procedure (Sender: TcxCustomGroupBox; const APainter: TcxCustomLookAndFeelPainterClass; var ACaptionHeight: Integer) of object; TcxGroupBoxCustomDrawElementEvent = procedure (Sender: TcxCustomGroupBox; ACanvas: TCanvas; const ABounds: TRect; const APainter: TcxCustomLookAndFeelPainterClass; var ADone: Boolean) of object; TcxCustomGroupBox = class(TcxCustomEdit) private FAlignment: TcxCaptionAlignment; FCaptionBkColor: TColor; // deprecated FCaptionFont: TFont; FIsAccelCharHandling: Boolean; FPanelStyle: TcxPanelStyle; FVisibleCaption: string; FOnCustomDraw: TcxGroupBoxCustomDrawEvent; {$IFDEF DELPHI7} FOnCustomDrawCaption: TcxGroupBoxCustomDrawElementEvent; FOnCustomDrawContentBackground: TcxGroupBoxCustomDrawElementEvent; FOnMeasureCaptionHeight: TcxGroupBoxMeasureCaptionHeightEvent; {$ENDIF} procedure CalculateVisibleCaption; function GetCaptionBkColor: TColor; // deprecated function GetColor: TColor; // deprecated function GetFont: TFont; // deprecated function IsSkinAvailable: Boolean; procedure UpdateCaption; procedure UpdateNonClientArea; function GetPanelStyleCaptionDrawingFlags: Cardinal; function GetHorizontalCaptionIndent: Integer; function GetVerticalCaptionIndent: Integer; function GetVisibleCaption: string; procedure SetAlignment(Value: TcxCaptionAlignment); procedure SetCaptionBkColor(Value: TColor); // deprecated procedure SetColor(Value: TColor); // deprecated procedure SetFont(Value: TFont); // deprecated procedure SetPanelStyle(AValue: TcxPanelStyle); procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; procedure WMNCPaint(var Message: TWMNCPaint); {$IFNDEF DELPHI7} procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; {$ENDIF} protected procedure AdjustClientRect(var Rect: TRect); override; function CanAutoSize: Boolean; override; function CanFocusOnClick: Boolean; override; function CanHaveTransparentBorder: Boolean; override; procedure ContainerStyleChanged(Sender: TObject); override; function CreatePanelStyle: TcxPanelStyle; virtual; function DefaultParentColor: Boolean; override; procedure FontChanged; override; function GetShadowBounds: TRect; override; procedure Initialize; override; function InternalGetActiveStyle: TcxContainerStyle; override; function InternalGetNotPublishedStyleValues: TcxEditStyleValues; override; function IsContainerClass: Boolean; override; function IsNativeBackground: Boolean; override; function IsPanelStyle: Boolean; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override; procedure Paint; override; procedure TextChanged; override; function HasShadow: Boolean; override; procedure AdjustCanvasFontSettings(ACanvas: TcxCanvas); function DoCustomDraw: Boolean; {$IFDEF DELPHI7} function DoCustomDrawCaption(ACanvas: TcxCanvas; const ABounds: TRect; const APainter: TcxCustomLookAndFeelPainterClass): Boolean; virtual; function DoCustomDrawContentBackground(ACanvas: TcxCanvas; const ABounds: TRect; const APainter: TcxCustomLookAndFeelPainterClass): Boolean; virtual; procedure DoMeasureCaptionHeight(const APainter: TcxCustomLookAndFeelPainterClass; var ACaptionHeight: Integer); {$ENDIF} function GetCaptionDrawingFlags: Cardinal; function HasNonClientArea: Boolean; virtual; function IsNonClientAreaSupported: Boolean; virtual; function IsVerticalText: Boolean; procedure CalculateCaptionFont; procedure WndProc(var Message: TMessage); override; property CaptionBkColor: TColor read GetCaptionBkColor write SetCaptionBkColor stored False; // deprecated property Color: TColor read GetColor write SetColor stored False; // deprecated property Ctl3D; property Font: TFont read GetFont write SetFont stored False; // deprecated property PanelStyle: TcxPanelStyle read FPanelStyle write SetPanelStyle; property ParentBackground; property TabStop default False; property OnCustomDraw: TcxGroupBoxCustomDrawEvent read FOnCustomDraw write FOnCustomDraw; {$IFDEF DELPHI7} property OnCustomDrawCaption: TcxGroupBoxCustomDrawElementEvent read FOnCustomDrawCaption write FOnCustomDrawCaption; property OnCustomDrawContentBackground: TcxGroupBoxCustomDrawElementEvent read FOnCustomDrawContentBackground write FOnCustomDrawContentBackground; property OnMeasureCaptionHeight: TcxGroupBoxMeasureCaptionHeightEvent read FOnMeasureCaptionHeight write FOnMeasureCaptionHeight; {$ENDIF} public constructor Create(AOwner: TComponent); override; destructor Destroy; override; class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; property Alignment: TcxCaptionAlignment read FAlignment write SetAlignment default alTopLeft; property Transparent; end; { TcxGroupBox } TcxGroupBox = class(TcxCustomGroupBox) published property Align; property Alignment; property Anchors; property BiDiMode; property Caption; property CaptionBkColor; // deprecated property Color; // deprecated property Constraints; property Ctl3D; property DockSite; property DragCursor; property DragKind; property DragMode; property Enabled; property Font; // deprecated property LookAndFeel; // deprecated property ParentBackground; property ParentBiDiMode; property ParentColor; property ParentCtl3D; property ParentFont; property PanelStyle; property ParentShowHint; property PopupMenu; property ShowHint; property Style; property StyleDisabled; property StyleFocused; property StyleHot; property TabOrder; property TabStop; property Transparent; property Visible; property OnClick; property OnContextPopup; property OnCustomDraw; {$IFDEF DELPHI7} property OnCustomDrawCaption; property OnCustomDrawContentBackground; {$ENDIF} property OnDblClick; property OnDockDrop; property OnDockOver; property OnDragDrop; property OnDragOver; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnGetSiteInfo; {$IFDEF DELPHI7} property OnMeasureCaptionHeight; {$ENDIF} property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnStartDock; property OnStartDrag; property OnUnDock; end; { TcxCustomButtonGroup } TcxCustomButtonGroup = class(TcxCustomGroupBox) private FButtons: TList; procedure DoButtonDragDrop(Sender, Source: TObject; X, Y: Integer); procedure DoButtonDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure DoButtonKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure DoButtonKeyPress(Sender: TObject; var Key: Char); procedure DoButtonKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure DoButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure DoButtonMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure DoButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure DoButtonMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); function GetProperties: TcxCustomButtonGroupProperties; function GetActiveProperties: TcxCustomButtonGroupProperties; procedure SetProperties(Value: TcxCustomButtonGroupProperties); procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; protected function CanAutoSize: Boolean; override; procedure ContainerStyleChanged(Sender: TObject); override; procedure CursorChanged; override; procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override; procedure EnabledChanged; override; procedure Initialize; override; function IsButtonDC(ADC: THandle): Boolean; override; function IsContainerClass: Boolean; override; procedure PropertiesChanged(Sender: TObject); override; procedure ReadState(Reader: TReader); override; function RefreshContainer(const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AIsMouseEvent: Boolean): Boolean; override; procedure CreateHandle; override; procedure ArrangeButtons; virtual; function GetButtonDC(AButtonIndex: Integer): THandle; virtual; abstract; function GetButtonIndexAt(const P: TPoint): Integer; function GetButtonInstance: TWinControl; virtual; abstract; function GetFocusedButtonIndex: Integer; procedure InitButtonInstance(AButton: TWinControl); virtual; function IsNonClientAreaSupported: Boolean; override; procedure SetButtonCount(Value: Integer); virtual; procedure SynchronizeButtonsStyle; virtual; procedure UpdateButtons; virtual; property InternalButtons: TList read FButtons; property TabStop default True; public destructor Destroy; override; procedure ActivateByMouse(Shift: TShiftState; X, Y: Integer; var AEditData: TcxCustomEditData); override; function Focused: Boolean; override; class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; procedure GetTabOrderList(List: TList); override; function IsButtonNativeStyle: Boolean; property AutoSize default False; property ActiveProperties: TcxCustomButtonGroupProperties read GetActiveProperties; property Properties: TcxCustomButtonGroupProperties read GetProperties write SetProperties; end; implementation uses {$IFDEF DELPHI6} Variants, {$ENDIF} dxThemeConsts, cxEditUtils, Math, Types, dxOffice11, TypInfo, dxThemeManager, dxUxTheme, cxDrawTextUtils, cxGeometry; const cxCaptionRectLeftBound = 8; cxNativeState: array[Boolean] of Integer = (GBS_DISABLED, GBS_NORMAL); WM_DXUPDATENONCLIENTAREA: Cardinal = WM_DX + $10; type TControlAccess = class(TControl); TWinControlAccess = class(TWinControl); function cxGroupBoxAlignment2GroupBoxCaption(AAlignment: TcxCaptionAlignment): TcxGroupBoxCaptionPosition; begin if AAlignment in [alTopLeft, alTopCenter, alTopRight] then Result := cxgpTop else if AAlignment in [alBottomLeft, alBottomCenter, alBottomRight] then Result := cxgpBottom else if AAlignment in [alLeftTop, alLeftCenter, alLeftBottom] then Result := cxgpLeft else if AAlignment in [alRightTop, alRightCenter, alRightBottom] then Result := cxgpRight else Result := cxgpCenter; end; { TcxGroupBoxButtonViewInfo } function TcxGroupBoxButtonViewInfo.GetGlyphRect(ACanvas: TcxCanvas; AGlyphSize: TSize; AAlignment: TLeftRight; AIsPaintCopy: Boolean): TRect; begin Result.Top := Bounds.Top + (Bounds.Bottom - Bounds.Top - AGlyphSize.cy) div 2; Result.Bottom := Result.Top + AGlyphSize.cy; if AAlignment = taRightJustify then begin Result.Left := Bounds.Left; Result.Right := Result.Left + AGlyphSize.cx; end else begin Result.Right := Bounds.Right; Result.Left := Result.Right - AGlyphSize.cx; end; end; { TcxGroupBoxViewInfo } constructor TcxGroupBoxViewInfo.Create; begin inherited Create; end; destructor TcxGroupBoxViewInfo.Destroy; begin inherited Destroy; end; procedure TcxGroupBoxViewInfo.AdjustCaptionRect(ACaptionPosition: TcxGroupBoxCaptionPosition); var ACaptionHeight: Integer; begin if not Edit.IsVerticalText then ACaptionHeight := cxRectHeight(CaptionRect) else ACaptionHeight := cxRectWidth(CaptionRect); {$IFDEF DELPHI7} Edit.DoMeasureCaptionHeight(Painter, ACaptionHeight); {$ENDIF} case Edit.Alignment of alTopLeft, alTopCenter, alTopRight: CaptionRect.Bottom := CaptionRect.Top + ACaptionHeight; alBottomLeft, alBottomCenter, alBottomRight: CaptionRect.Top := CaptionRect.Bottom - ACaptionHeight; alLeftTop, alLeftCenter, alLeftBottom: CaptionRect.Right := CaptionRect.Left + ACaptionHeight; alRightTop, alRightCenter, alRightBottom: CaptionRect.Left := CaptionRect.Right - ACaptionHeight; end; end; procedure TcxGroupBoxViewInfo.DrawCaption(ACanvas: TcxCanvas); procedure AdjustRectForBordersNone(var R: TRect); var ACaptionPos: TcxGroupBoxCaptionPosition; ARect: TRect; begin if (BorderStyle = ebsNone) then begin ACaptionPos := cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment); case ACaptionPos of cxgpTop: ACaptionPos := cxgpBottom; cxgpBottom: ACaptionPos := cxgpTop; cxgpLeft: ACaptionPos := cxgpRight; cxgpRight: ACaptionPos := cxgpLeft; end; ARect := Painter.GroupBoxBorderSize(False, ACaptionPos); R := Rect(R.Left - ARect.Left, R.Top - ARect.Top, R.Right + ARect.Right, R.Bottom + ARect.Bottom); end; end; var ACaptionPos: TcxGroupBoxCaptionPosition; ACaptionRect: TRect; begin ACanvas.SaveClipRegion; try ACanvas.SetClipRegion(TcxRegion.Create(CaptionRect), roIntersect); if (Edit.FVisibleCaption = '') {$IFDEF DELPHI7}or Edit.DoCustomDrawCaption(ACanvas, CaptionRect, Painter){$ENDIF} then Exit; Edit.AdjustCanvasFontSettings(ACanvas); if Assigned(Painter) then begin ACaptionPos := cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment); if not Edit.IsPanelStyle then begin ACaptionRect := CaptionRect; AdjustRectForBordersNone(ACaptionRect); Painter.DrawGroupBoxCaption(ACanvas, ACaptionRect, ACaptionPos); end; end; ACanvas.Brush.Style := bsClear; if not Edit.IsVerticalText then DrawHorizontalTextCaption(ACanvas) else DrawVerticalTextCaption(ACanvas); finally ACanvas.RestoreClipRegion; end; end; function TcxGroupBoxViewInfo.GetButtonViewInfoClass: TcxEditButtonViewInfoClass; begin Result := TcxGroupBoxButtonViewInfo; end; procedure TcxGroupBoxViewInfo.InternalPaint(ACanvas: TcxCanvas); begin if IsInplace then begin if Edit = nil then inherited InternalPaint(ACanvas) else if IsCustomBackground then DrawBackground(ACanvas) else cxEditFillRect(ACanvas, Bounds, BackgroundColor); Exit; end; InternalDrawBackground(ACanvas); DrawCaption(ACanvas); if not Edit.IsPanelStyle then ACanvas.ExcludeClipRect(CaptionRect); DrawFrame(ACanvas, GetFrameBounds); if Edit.IsDBEditPaintCopyDrawing then DrawButtons(ACanvas); end; function TcxGroupBoxViewInfo.GetCaptionRectIndent: TRect; var ACaptionPosition: TcxGroupBoxCaptionPosition; R1: TRect; begin Result := cxNullRect; if Assigned(Edit) and Assigned(Edit.Style.LookAndFeel.SkinPainter) and not Edit.IsPanelStyle then begin ACaptionPosition := cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment); R1 := Edit.Style.LookAndFeel.SkinPainter.GroupBoxBorderSize(True, ACaptionPosition); case ACaptionPosition of cxgpTop: Result.Top := R1.Top + R1.Bottom; cxgpBottom: Result.Bottom := R1.Top + R1.Bottom; cxgpLeft: Result.Left := R1.Right + R1.Left; cxgpRight: Result.Right := R1.Right + R1.Left; end; end; end; function TcxGroupBoxViewInfo.GetControlRect: TRect; begin Result := cxContainer.GetControlRect(Edit); end; function TcxGroupBoxViewInfo.GetEdit: TcxCustomGroupBox; begin Result := TcxCustomGroupBox(FEdit); end; function TcxGroupBoxViewInfo.CalcOffsetBoundsForPanel: TRect; var ABorderSize: TRect; ACaptionIndentRect: TRect; ABorderWidth: Integer; begin ABorderWidth := GetContainerBorderWidth(TcxContainerBorderStyle(BorderStyle)); ABorderSize := Rect(ABorderWidth, ABorderWidth, ABorderWidth, ABorderWidth); ACaptionIndentRect := cxEmptyRect; case Edit.Alignment of alTopLeft, alLeftTop, alLeftCenter, alLeftBottom, alBottomLeft: ACaptionIndentRect.Left := Edit.GetHorizontalCaptionIndent; alTopRight, alRightTop, alRightCenter, alRightBottom, alBottomRight: ACaptionIndentRect.Right := Edit.GetHorizontalCaptionIndent; end; case Edit.Alignment of alLeftTop, alTopLeft, alTopCenter, alTopRight, alRightTop: ACaptionIndentRect.Top := Edit.GetVerticalCaptionIndent; alLeftBottom, alBottomLeft, alBottomCenter, alBottomRight, alRightBottom: ACaptionIndentRect.Bottom := Edit.GetVerticalCaptionIndent; end; Result.Left := ABorderSize.Left + ACaptionIndentRect.Left; Result.Top := ABorderSize.Top + ACaptionIndentRect.Top; Result.Right := ABorderSize.Right + ACaptionIndentRect.Right; Result.Bottom := ABorderSize.Bottom + ACaptionIndentRect.Bottom; end; procedure TcxGroupBoxViewInfo.CalcBoundsForPanel; begin if Edit.IsPanelStyle then begin CalcTextBoundsForPanel; AdjustTextBoundsForPanel; CaptionRect := TextRect; AdjustCaptionBoundsForPanel; end; end; function TcxGroupBoxViewInfo.GetFrameBounds: TRect; var ABorderWidth: Integer; begin ABorderWidth := GetContainerBorderWidth(TcxContainerBorderStyle(BorderStyle)); if Edit.IsPanelStyle then Result := GetBoundsForPanel else begin Result := BorderRect; ExtendRectByBorders(Result, ABorderWidth, Edges); end; end; procedure TcxGroupBoxViewInfo.CalcTextBoundsForPanel; var AFlag: Cardinal; ACanvas: TcxCanvas; begin AFlag := CXTO_CALCRECT; if Edit.PanelStyle.WordWrap then AFlag := AFlag or CXTO_WORDBREAK; TextRect := CalcCorrectionBoundsForPanel; ACanvas := TcxCanvas.Create(Edit.Canvas.Canvas); try Edit.AdjustCanvasFontSettings(ACanvas); cxTextOut(ACanvas.Handle, PChar(Edit.FVisibleCaption), TextRect, AFlag); finally FreeAndNil(ACanvas); end; end; function TcxGroupBoxViewInfo.CalcCorrectionBoundsForPanel: TRect; var AOffsetRect: TRect; begin AOffsetRect := CalcOffsetBoundsForPanel; Result := GetBoundsForPanel; with AOffsetRect do begin Inc(Result.Left, Left); Inc(Result.Top, Top); Dec(Result.Right, Right); Dec(Result.Bottom, Bottom); end; end; procedure TcxGroupBoxViewInfo.AdjustTextBoundsForPanel; var ATextWidth, ATextHeight: Integer; R: TRect; begin with TextRect do begin ATextWidth := Right - Left; ATextHeight := Bottom - Top; end; R := CalcCorrectionBoundsForPanel; OffsetRect(TextRect, R.Left - TextRect.Left, R.Top - TextRect.Top); case Edit.Alignment of alTopCenter, alBottomCenter, alCenterCenter: OffsetRect(TextRect, (R.Right - R.Left - ATextWidth - TextRect.Left) div 2, 0); alTopRight, alRightTop, alRightCenter, alRightBottom, alBottomRight: OffsetRect(TextRect, R.Right - ATextWidth - TextRect.Left, 0); end; case Edit.Alignment of alLeftCenter, alRightCenter, alCenterCenter: OffsetRect(TextRect, 0, (R.Bottom - R.Top - ATextHeight - TextRect.Top) div 2); alLeftBottom, alBottomLeft, alBottomCenter, alBottomRight, alRightBottom: OffsetRect(TextRect, 0, R.Bottom - ATextHeight - TextRect.Top); end; end; procedure TcxGroupBoxViewInfo.AdjustCaptionBoundsForPanel; procedure ChangeIfLess(var AInValue, AChangeValue: Integer); begin AInValue := Max(AChangeValue, AInValue); end; procedure ChangeIfGreat(var AInValue, AChangeValue: Integer); begin AInValue := Min(AChangeValue, AInValue); end; var R: TRect; begin R := CalcCorrectionBoundsForPanel; ChangeIfGreat(CaptionRect.Right, R.Right); ChangeIfGreat(CaptionRect.Bottom, R.Bottom); ChangeIfLess(CaptionRect.Left, R.Left); ChangeIfLess(CaptionRect.Top, R.Top); end; procedure TcxGroupBoxViewInfo.DrawHorizontalTextCaption(ACanvas: TcxCanvas); begin cxDrawText(ACanvas.Handle, Edit.FVisibleCaption, TextRect, Edit.GetCaptionDrawingFlags); end; procedure TcxGroupBoxViewInfo.DrawVerticalTextCaption(ACanvas: TcxCanvas); var AFlags, X, Y: Integer; begin AFlags := ETO_CLIPPED; if Edit.FAlignment in [alLeftTop, alLeftCenter, alLeftBottom] then begin X := TextRect.Left; Y := TextRect.Bottom - 1; end else begin X := TextRect.Right; Y := TextRect.Top + 1; end; cxExtTextOut(ACanvas.Handle, Edit.FVisibleCaption, Point(X, Y), TextRect, AFlags); end; procedure TcxGroupBoxViewInfo.DrawFrame(ACanvas: TcxCanvas; R: TRect); var ABackgroundRect: TRect; ANativeState: Integer; ATheme: TdxTheme; begin if NativeStyle then begin if Edit.IsPanelStyle then begin if BorderStyle <> ebsNone then Edit.LookAndFeelPainter.DrawBorder(ACanvas, GetBoundsForPanel); end else begin if BorderStyle <> ebsNone then begin ATheme := OpenTheme(totButton); ANativeState := cxNativeState[Enabled]; ABackgroundRect := GetThemeBackgroundRect(ACanvas); DrawThemeBackground(ATheme, ACanvas.Handle, BP_GROUPBOX, ANativeState, ABackgroundRect); end; end; end else begin if not Assigned(Painter) then begin case BorderStyle of ebsSingle: ACanvas.FrameRect(R, BorderColor, 1, Edit.ActiveStyle.Edges, True); ebsThick: ACanvas.FrameRect(R, BorderColor, 2, Edit.ActiveStyle.Edges, True); ebsFlat: begin ACanvas.FrameRect(R, clBtnShadow, 1, Edit.ActiveStyle.Edges, True); InflateRect(R, -1, -1); ACanvas.FrameRect(R, clBtnHighlight, 1, Edit.ActiveStyle.Edges, True); end; ebs3D: if Edit.Ctl3D then begin Dec(R.Right); Dec(R.Bottom); ACanvas.FrameRect(R, clBtnShadow, 1, Edit.ActiveStyle.Edges, True); OffsetRect(R, 1, 1); ACanvas.FrameRect(R, clBtnHighlight, 1, Edit.ActiveStyle.Edges, True); end else begin ACanvas.FrameRect(R, clWindowFrame, 1, Edit.ActiveStyle.Edges, True); InflateRect(R, -1, -1); ACanvas.FrameRect(R, BackgroundColor, 1, Edit.ActiveStyle.Edges, True); end; end; end; end; end; function TcxGroupBoxViewInfo.GetThemeBackgroundRect( ACanvas: TcxCanvas): TRect; begin Result := ControlRect; if not Edit.IsPanelStyle then case Edit.FAlignment of alTopLeft, alTopCenter, alTopRight: Result.Top := ACanvas.TextHeight('Qq') div 2; alBottomLeft, alBottomCenter, alBottomRight: Dec(Result.Bottom, ACanvas.TextHeight('Qq') div 2); alLeftTop, alLeftCenter, alLeftBottom: Result.Left := ACanvas.TextHeight('Qq') div 2; alRightTop, alRightCenter, alRightBottom: Dec(Result.Right, ACanvas.TextHeight('Qq') div 2); end; end; function TcxGroupBoxViewInfo.GetBoundsForPanel: TRect; begin Result := Bounds; if not NativeStyle and (Painter = nil) then if Edit.HasShadow then begin Dec(Result.Right, cxContainerShadowWidth); Dec(Result.Bottom, cxContainerShadowWidth); end; end; procedure TcxGroupBoxViewInfo.DrawUsualBackground(ACanvas: TcxCanvas); begin if Edit.HasShadow then DrawContainerShadow(ACanvas, GetFrameBounds); if not Transparent then begin if Edit.IsTransparent then cxDrawTransparentControlBackground(Edit, ACanvas, ControlRect) else cxEditFillRect(ACanvas, ControlRect, BackgroundColor); end; end; procedure TcxGroupBoxViewInfo.DrawNativeBackground(ACanvas: TcxCanvas; const ACaptionRect: TRect); begin if Edit.IsPanelStyle then DrawNativePanelBackground(ACanvas, ACaptionRect) else DrawNativeGroupBoxBackground(ACanvas); end; procedure TcxGroupBoxViewInfo.DrawNativeGroupBoxBackground( ACanvas: TcxCanvas); var AClipRgn: TcxRegion; ANativeState: Integer; ATheme: TdxTheme; begin AClipRgn := ACanvas.GetClipRegion; try ATheme := OpenTheme(totButton); ANativeState := cxNativeState[Enabled]; if Edit.IsTransparent then cxDrawTransparentControlBackground(Edit, ACanvas, Bounds) else if Edit.IsNativeBackground and IsThemeBackgroundPartiallyTransparent(ATheme, BP_GROUPBOX, ANativeState) then begin cxDrawThemeParentBackground(Edit, ACanvas, Bounds); ACanvas.Canvas.Refresh; // SC-B31215 end else cxEditFillRect(ACanvas.Handle, Bounds, GetSolidBrush(ACanvas, BackgroundColor)); finally ACanvas.SetClipRegion(AClipRgn, roSet); end; end; procedure TcxGroupBoxViewInfo.DrawNativePanelBackground( ACanvas: TcxCanvas; const ACaptionRect: TRect); var ABackgroundRect: TRect; begin ABackgroundRect := GetBoundsForPanel; if BorderStyle <> ebsNone then InflateRect(ABackgroundRect, -Edit.LookAndFeelPainter.BorderSize, -Edit.LookAndFeelPainter.BorderSize); if Edit.IsTransparent then begin ACanvas.SaveClipRegion; try ACanvas.SetClipRegion(TcxRegion.Create(ABackgroundRect), roIntersect); Edit.LookAndFeelPainter.DrawPanelBackground(ACanvas, Edit, GetBoundsForPanel); finally ACanvas.RestoreClipRegion; end; end else if Edit.LookAndFeel.NativeStyle then if Edit.IsNativeBackground then cxDrawThemeParentBackground(Edit, ACanvas, ABackgroundRect) else Edit.LookAndFeelPainter.DrawPanelBackground(ACanvas, Edit, ABackgroundRect, BackgroundColor) else if Edit.LookAndFeel.Kind = lfOffice11 then DrawOffice11PanelBackground(ACanvas, ABackgroundRect); end; procedure TcxGroupBoxViewInfo.DrawOffice11PanelBackground(ACanvas: TcxCanvas; const R: TRect); begin with Edit.LookAndFeelPainter do case Edit.PanelStyle.OfficeBackgroundKind of pobkGradient: DrawPanelBackground(ACanvas, Edit, R, dxOffice11ToolbarsColor1, dxOffice11ToolbarsColor2); pobkOffice11Color: DrawPanelBackground(ACanvas, Edit, R, GetMiddleRGB(dxOffice11ToolbarsColor1, dxOffice11ToolbarsColor2, 50)); pobkStyleColor: DrawPanelBackground(ACanvas, Edit, R, BackgroundColor); end; end; procedure TcxGroupBoxViewInfo.InternalDrawBackground(ACanvas: TcxCanvas); var ABounds: TRect; begin if NativeStyle then DrawNativeBackground(ACanvas, CaptionRect) else begin ACanvas.SaveClipRegion; try if Assigned(Painter) then begin if Edit.IsPanelStyle then ABounds := GetBoundsForPanel else if BorderStyle = ebsNone then ABounds := Bounds else ABounds := BorderRect; {$IFDEF DELPHI7} if not Edit.DoCustomDrawContentBackground(ACanvas, ABounds, Painter) then begin {$ENDIF} if Edit.IsPanelStyle then Painter.DrawPanelContent(ACanvas, ABounds, BorderStyle <> ebsNone) else begin if BorderStyle = ebsNone then Painter.DrawGroupBoxBackground(ACanvas, ABounds, ABounds) else begin cxDrawTransparentControlBackground(Edit, ACanvas, ControlRect); Painter.DrawGroupBoxContent(ACanvas, ABounds, cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment)); end; end; {$IFDEF DELPHI7} end; {$ENDIF} end else DrawUsualBackground(ACanvas); finally ACanvas.RestoreClipRegion; end; end; end; { TcxGroupBoxViewData } procedure TcxGroupBoxViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); var AEditViewInfo: TcxGroupBoxViewInfo; begin AEditViewInfo := TcxGroupBoxViewInfo(AViewInfo); AEditViewInfo.IsDesigning := IsDesigning; inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent); if not IsInplace then begin Edit.CalculateCaptionFont; Edit.CalculateVisibleCaption; CalcRects(ACanvas, AEditViewInfo); end; end; function TcxGroupBoxViewData.GetBorderColor: TColor; begin if Style.BorderStyle in [ebsUltraFlat, ebsOffice11] then begin if Enabled then Result := GetEditBorderHighlightColor(Style.BorderStyle = ebsOffice11) else Result := clBtnShadow; end else Result := Style.BorderColor; end; function TcxGroupBoxViewData.GetBorderExtentBySkinPainter: TRect; begin Result := cxEmptyRect; if bLeft in Style.Edges then Result.Left := 1; if bTop in Style.Edges then Result.Top := 1; if bRight in Style.Edges then Result.Right := 1; if bBottom in Style.Edges then Result.Bottom := 1; end; function TcxGroupBoxViewData.GetBorderExtent: TRect; var AHeaderSideBorderOffset: Integer; begin if Style.LookAndFeel.SkinPainter = nil then Result := inherited GetBorderExtent else Result := GetBorderExtentBySkinPainter; if not IsInplace and (Edit.FAlignment <> alCenterCenter) and not Edit.IsPanelStyle then begin cxScreenCanvas.Font := Edit.FCaptionFont; AHeaderSideBorderOffset := cxScreenCanvas.TextHeight('Qq') div 2 - 1 + cxEditMaxBorderWidth; case Edit.FAlignment of alTopLeft, alTopCenter, alTopRight: Result.Top := AHeaderSideBorderOffset; alBottomLeft, alBottomCenter, alBottomRight: Result.Bottom := AHeaderSideBorderOffset; alLeftTop, alLeftCenter, alLeftBottom: Result.Left := AHeaderSideBorderOffset - 1; alRightTop, alRightCenter, alRightBottom: Result.Right := AHeaderSideBorderOffset - 1; end; end; end; function TcxGroupBoxViewData.GetClientExtent(ACanvas: TcxCanvas; AViewInfo: TcxCustomEditViewInfo): TRect; var AHeaderSideClientExtent: Integer; ABorderWidth: Integer; begin if IsInplace or (Style.LookAndFeel.SkinPainter = nil) then Result := inherited GetBorderExtent else begin if Edit.IsPanelStyle then Result := Style.LookAndFeel.SkinPainter.PanelBorderSize else Result := Style.LookAndFeel.SkinPainter.GroupBoxBorderSize(False, cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment)); ABorderWidth := Edit.LookAndFeelPainter.BorderSize; OffsetRect(Result, ABorderWidth, ABorderWidth); if HasShadow then begin Result.Right := Result.Right + cxEditShadowWidth; Result.Bottom := Result.Bottom + cxEditShadowWidth; end; if HasNonClientArea then with TcxGroupBoxViewInfo(AViewInfo) do begin case cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment) of cxgpTop: Inc(Result.Bottom, GetCaptionRectIndent.Top); cxgpLeft: Inc(Result.Right, GetCaptionRectIndent.Left); end; end; end; if not IsInplace and not Edit.IsPanelStyle then if Edit.FAlignment <> alCenterCenter then begin cxScreenCanvas.Font := Edit.FCaptionFont; AHeaderSideClientExtent := cxScreenCanvas.TextHeight('Qq') + Result.Top + cxEditMaxBorderWidth + 1; case Edit.FAlignment of alTopLeft, alTopCenter, alTopRight: Result.Top := AHeaderSideClientExtent; alBottomLeft, alBottomCenter, alBottomRight: Result.Bottom := AHeaderSideClientExtent; alLeftTop, alLeftCenter, alLeftBottom: Result.Left := AHeaderSideClientExtent; alRightTop, alRightCenter, alRightBottom: Result.Right := AHeaderSideClientExtent; end; end; end; function TcxGroupBoxViewData.HasShadow: Boolean; begin Result := Edit.HasShadow and inherited HasShadow; end; class function TcxGroupBoxViewData.IsNativeStyle(ALookAndFeel: TcxLookAndFeel): Boolean; begin Result := AreVisualStylesMustBeUsed( ALookAndFeel.NativeStyle or (ALookAndFeel.Kind = lfOffice11), totEdit) and (ALookAndFeel.SkinPainter = nil); end; function TcxGroupBoxViewData.GetContainerState(const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AIsMouseEvent: Boolean): TcxContainerState; begin if Enabled then Result := [csNormal] else Result := [csDisabled]; end; function TcxGroupBoxViewData.HasNonClientArea: Boolean; begin Result := not IsInplace and Edit.HasNonClientArea; end; function TcxGroupBoxViewData.GetShadowWidth: Integer; begin Result := 0; if HasShadow then Result := cxContainerShadowWidth; end; function TcxGroupBoxViewData.GetCaptionRect(ACanvas: TcxCanvas): TRect; var ACaptionSize: TSize; begin if Edit.FVisibleCaption = '' then begin Result := cxEmptyRect; Exit; end; Edit.AdjustCanvasFontSettings(ACanvas); with ACanvas do begin ACaptionSize := cxTextExtent(Font, Edit.FVisibleCaption, Font.Size); Result := Rect(0, 0, ACaptionSize.cx, ACaptionSize.cy); OffsetRect(Result, cxCaptionRectLeftBound, 0); if not Edit.IsVerticalText then AdjustHorizontalCaptionRect(Result) else AdjustVerticalCaptionRect(Result); //B93506 //InflateRect(Result, 1, 1); end; end; procedure TcxGroupBoxViewData.AdjustHorizontalCaptionRect(var R: TRect); var AShadowWidth: Integer; begin AShadowWidth := GetShadowWidth; case Edit.FAlignment of alTopCenter, alBottomCenter, alCenterCenter: OffsetRect(R, -R.Left + (Edit.Width - AShadowWidth - (R.Right - R.Left)) div 2, 0); alTopRight, alRightTop, alRightCenter, alRightBottom, alBottomRight: OffsetRect(R, Edit.Width - R.Right - R.Left - AShadowWidth, 0); end; case Edit.FAlignment of alLeftCenter, alRightCenter, alCenterCenter: OffsetRect(R, 0, -R.Top + (Edit.Height - AShadowWidth - (R.Bottom - R.Top)) div 2); alLeftBottom, alBottomLeft, alBottomCenter, alBottomRight, alRightBottom: R := Rect(R.Left, Edit.Height - R.Top - (R.Bottom - R.Top), R.Right, Edit.Height - R.Top); end end; procedure TcxGroupBoxViewData.AdjustVerticalCaptionRect(var R: TRect); var AShadowWidth, ATextWidth: Integer; begin AShadowWidth := GetShadowWidth; ATextWidth := R.Right - R.Left; case Edit.FAlignment of alLeftTop: begin R := Rect(R.Top, R.Left, R.Bottom, 0); R.Bottom := R.Top + ATextWidth + 1; end; alLeftCenter: begin R := Rect(R.Top, 0, R.Bottom, Edit.Height - AShadowWidth - (Edit.Height - AShadowWidth - ATextWidth) div 2); R.Top := R.Bottom - ATextWidth - 1; end; alLeftBottom: begin R := Rect(R.Top, 0, R.Bottom, Edit.Height - AShadowWidth - R.Left); R.Top := R.Bottom - ATextWidth - 1; end; alRightTop: R := Rect(Edit.Width - R.Bottom, R.Left, Edit.Width - R.Top, R.Left + ATextWidth); alRightCenter: begin R := Rect(Edit.Width - R.Bottom, (Edit.Height - ATextWidth) div 2, Edit.Width - R.Top, 0); R.Bottom := R.Top + ATextWidth; end; alRightBottom: R := Rect(Edit.Width - R.Bottom, Edit.Height - R.Left - ATextWidth, Edit.Width - R.Top, Edit.Height - R.Left); end; end; function TcxGroupBoxViewData.GetEdit: TcxCustomGroupBox; begin Result := TcxCustomGroupBox(FEdit); end; procedure TcxGroupBoxViewData.CalcRects(ACanvas: TcxCanvas; AEditViewInfo: TcxGroupBoxViewInfo); procedure CalculateBorderRect(var R: TRect; const AIndent: TRect; ACaptionPosition: TcxGroupBoxCaptionPosition); begin if HasNonClientArea then case ACaptionPosition of cxgpTop: Dec(R.Bottom, AIndent.Top); cxgpLeft: Dec(R.Right, AIndent.Left); end; end; procedure CalculateCaptionRect(var R: TRect; const AIndent: TRect; const ATextSize: TSize; ACaptionPosition: TcxGroupBoxCaptionPosition); begin case ACaptionPosition of cxgpBottom: R.Top := R.Bottom - ATextSize.cy - AIndent.Bottom; cxgpRight: R.Left := R.Right - ATextSize.cy - AIndent.Right; cxgpCenter: R := cxRectCenter(R, ATextSize); cxgpLeft: begin R.Right := R.Left + ATextSize.cy; if HasNonClientArea then Dec(R.Left, AIndent.Left) else Inc(R.Right, AIndent.Left); end; cxgpTop: begin R.Bottom := R.Top + ATextSize.cy; if HasNonClientArea then Dec(R.Top, AIndent.Top) else Inc(R.Bottom, AIndent.Top); end; end; end; procedure CalculateTextRect(const ABorderSize: TRect; ATextWidth: Integer); begin with AEditViewInfo do begin TextRect := cxRectContent(CaptionRect, ABorderSize); if Edit.Alignment in [alTopRight, alBottomRight] then TextRect.Left := TextRect.Right - ATextWidth; if Edit.Alignment in [alTopCenter, alBottomCenter] then TextRect.Left := (TextRect.Left + TextRect.Right - ATextWidth) div 2; if Edit.Alignment in [alLeftTop, alRightTop] then TextRect.Bottom := TextRect.Top + ATextWidth; if Edit.Alignment in [alLeftBottom, alRightBottom] then TextRect.Top := TextRect.Bottom - ATextWidth; if Edit.Alignment in [alLeftCenter, alRightCenter] then begin TextRect.Top := (TextRect.Bottom + TextRect.Top - ATextWidth) div 2; TextRect.Bottom := TextRect.Top + ATextWidth; end; end; end; var ACaptionPos: TcxGroupBoxCaptionPosition; ARect: TRect; ATextSize: TSize; begin if Edit.IsPanelStyle then begin AEditViewInfo.CalcBoundsForPanel; Exit; end; if Style.LookAndFeel.SkinPainter = nil then begin AEditViewInfo.CaptionRect := GetCaptionRect(ACanvas); AEditViewInfo.TextRect := AEditViewInfo.CaptionRect; end else with AEditViewInfo do begin ARect := GetCaptionRectIndent; BorderRect := ControlRect; CaptionRect := BorderRect; Edit.AdjustCanvasFontSettings(ACanvas); ATextSize := ACanvas.TextExtent(Edit.FVisibleCaption); ATextSize.cy := Max(ATextSize.cy, ACanvas.TextHeight('Qq')); ACaptionPos := cxGroupBoxAlignment2GroupBoxCaption(Edit.Alignment); CalculateCaptionRect(CaptionRect, ARect, ATextSize, ACaptionPos); CalculateBorderRect(BorderRect, ARect, ACaptionPos); CalculateTextRect(Style.LookAndFeel.SkinPainter.GroupBoxBorderSize(True, ACaptionPos), ATextSize.cx); AdjustCaptionRect(ACaptionPos); end; end; { TcxButtonGroupViewInfo } procedure TcxButtonGroupViewInfo.DrawEditButton(ACanvas: TcxCanvas; AButtonVisibleIndex: Integer); var AButtonViewInfo: TcxGroupBoxButtonViewInfo; AGlyphRect: TRect; begin AButtonViewInfo := TcxGroupBoxButtonViewInfo(ButtonsInfo[AButtonVisibleIndex]); AGlyphRect := AButtonViewInfo.GetGlyphRect(ACanvas, GetGlyphSize, Alignment, IsDBEditPaintCopyDrawing); if not IsDBEditPaintCopyDrawing then DrawEditBackground(ACanvas, AButtonViewInfo.Bounds, AGlyphRect, IsButtonGlypthTransparent(AButtonViewInfo)); DrawButtonGlyph(ACanvas, AButtonViewInfo, AGlyphRect); DrawButtonCaption(ACanvas, AButtonViewInfo, AGlyphRect); end; function TcxButtonGroupViewInfo.GetGlyphSize: TSize; begin Result := GlyphSize; end; { TcxButtonGroupViewData } procedure TcxButtonGroupViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); begin inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent); with TcxButtonGroupViewInfo(AViewInfo) do begin DrawTextFlags := GetDrawTextFlags; CaptionExtent := GetCaptionRectExtent; end; end; procedure TcxButtonGroupViewData.CalculateButtonsViewInfo(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); procedure CalculateButtonStates; var AButtonsCount, APrevPressedButton, I: Integer; AButtonViewInfo: TcxGroupBoxButtonViewInfo; ACapturePressing, AHoldPressing, AIsButtonPressed, AMouseButtonPressing: Boolean; begin AButtonsCount := Properties.Items.Count; AViewInfo.IsButtonReallyPressed := False; if AIsMouseEvent then APrevPressedButton := AViewInfo.PressedButton else APrevPressedButton := -1; AViewInfo.PressedButton := -1; AViewInfo.SelectedButton := -1; for I := 0 to AButtonsCount - 1 do begin AButtonViewInfo := TcxGroupBoxButtonViewInfo(AViewInfo.ButtonsInfo[I]); AButtonViewInfo.Index := I; AButtonViewInfo.Data.NativeStyle := IsButtonNativeStyle(Style.LookAndFeel); AButtonViewInfo.Data.Transparent := (Self.Style.ButtonTransparency = ebtAlways) or (Self.Style.ButtonTransparency = ebtInactive) and not Selected; AButtonViewInfo.Data.BackgroundColor := AViewInfo.BackgroundColor; AIsButtonPressed := IsButtonPressed(AViewInfo, I); with AButtonViewInfo do begin if not Enabled then Data.State := ebsDisabled else if AIsButtonPressed or (not IsDesigning and PtInRect(AButtonViewInfo.Bounds, P)) then begin ACapturePressing := (Button = cxmbNone) and (ButtonToShift(mbLeft) * Shift <> []) and (Data.State = ebsNormal) and (GetCaptureButtonVisibleIndex = I); AMouseButtonPressing := (Button = ButtonTocxButton(mbLeft)) and ((Shift = ButtonToShift(mbLeft)) or (Shift = ButtonToShift(mbLeft) + [ssDouble])); AHoldPressing := (Data.State = ebsPressed) and (Shift * ButtonToShift(mbLeft) <> []); if AIsButtonPressed or AMouseButtonPressing or AHoldPressing or ACapturePressing then AViewInfo.IsButtonReallyPressed := True; if not AIsButtonPressed and (Shift = []) and not ACapturePressing then begin Data.State := ebsSelected; AViewInfo.SelectedButton := I; end else if (AIsButtonPressed or ACapturePressing and CanPressButton(AViewInfo, I) or ((Shift = [ssLeft]) or (Shift = [ssLeft, ssDouble])) and ((Button = cxmbLeft) and CanPressButton(AViewInfo, I) or (APrevPressedButton = I))) or AHoldPressing then begin Data.State := ebsPressed; AViewInfo.PressedButton := I; end else Data.State := ebsNormal; end else Data.State := ebsNormal; CalculateButtonNativeState(AViewInfo, AButtonViewInfo); end; end; end; var AButtonsCount: Integer; begin AButtonsCount := Properties.Items.Count; TcxGroupBoxViewInfo(AViewInfo).SetButtonCount(AButtonsCount); if AButtonsCount = 0 then Exit; CalculateButtonViewInfos(AViewInfo); CalculateButtonPositions(ACanvas, AViewInfo); CalculateButtonStates; end; function TcxButtonGroupViewData.GetEditConstantPartSize(ACanvas: TcxCanvas; const AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo = nil): TSize; var AButtonsCount, AButtonsPerColumn, AColumnsCount: Integer; ACaption: string; AColumnWidth, AMaxButtonHeight: Integer; ADefaultButtonHeight, AButtonHeight: Integer; AFlags: Integer; AMaxColumnWidth: Integer; ASizeCorrection: TSize; ATextWidth: Integer; I: Integer; R: TRect; AEditMetrics: TcxEditMetrics; begin MinContentSize := cxNullSize; ACanvas.Font := Style.GetVisibleFont; ASizeCorrection := Self.GetEditContentSizeCorrection; AButtonsCount := Properties.Items.Count; AColumnsCount := Properties.GetColumnCount; GetEditMetrics(AEditSizeProperties.Width >= 0, ACanvas, AEditMetrics); ADefaultButtonHeight := ACanvas.TextHeight('Zg') + ASizeCorrection.cy; if AEditSizeProperties.Width >= 0 then begin Result.cx := AEditSizeProperties.Width; if AButtonsCount = 0 then Result.cy := ADefaultButtonHeight else begin Result.cy := 0; AButtonsPerColumn := Properties.GetButtonsPerColumn; AColumnWidth := AEditSizeProperties.Width - ContentOffset.Left - ContentOffset.Right + AEditMetrics.AutoHeightWidthCorrection - AEditMetrics.ColumnOffset * (AColumnsCount - 1); AColumnWidth := AColumnWidth div AColumnsCount - AEditMetrics.ButtonSize.cx - AEditMetrics.AutoHeightColumnWidthCorrection; if AColumnWidth <= 0 then AColumnWidth := 1; AMaxButtonHeight := ADefaultButtonHeight; Include(PaintOptions, epoAutoHeight); AFlags := GetDrawTextFlags and not cxAlignVCenter or cxAlignTop; for I := 0 to AButtonsCount - 1 do begin R := Rect(0, 0, AColumnWidth, MaxInt); ACaption := Properties.Items[I].Caption; if Properties.WordWrap and (ACaption <> '') then begin ACanvas.TextExtent(ACaption, R, AFlags); AButtonHeight := R.Bottom - R.Top + ASizeCorrection.cy; if AMaxButtonHeight < AButtonHeight then AMaxButtonHeight := AButtonHeight; end; end; Result.cy := AMaxButtonHeight * AButtonsPerColumn; if not IsInplace then begin R := GetClientExtent(ACanvas, nil); Result.cy := Result.cy + R.Top + R.Bottom; end; end; end else begin if AButtonsCount = 0 then begin Result.cx := 0; Result.cy := ACanvas.TextHeight('Zg') + ASizeCorrection.cy; end else begin AMaxColumnWidth := 0; AButtonsPerColumn := Properties.GetButtonsPerColumn; for I := 0 to AButtonsCount - 1 do begin ATextWidth := ACanvas.TextWidth(Properties.Items[I].Caption); if ATextWidth > AMaxColumnWidth then AMaxColumnWidth := ATextWidth; end; Result.cx := (AMaxColumnWidth + AEditMetrics.ColumnWidthCorrection + AEditMetrics.ButtonSize.cx) * AColumnsCount + AEditMetrics.ColumnOffset * (AColumnsCount - 1) + AEditMetrics.WidthCorrection; if ADefaultButtonHeight > AEditMetrics.ButtonSize.cy then Result.cy := ADefaultButtonHeight else Result.cy := AEditMetrics.ButtonSize.cy; Result.cy := Result.cy * AButtonsPerColumn; end; end; end; class function TcxButtonGroupViewData.IsButtonNativeStyle( ALookAndFeel: TcxLookAndFeel): Boolean; begin Result := AreVisualStylesMustBeUsed(ALookAndFeel.NativeStyle, totButton); end; procedure TcxButtonGroupViewData.CalculateButtonPositions(ACanvas: TcxCanvas; AViewInfo: TcxCustomEditViewInfo); var AButtonsCount, AButtonsPerColumn, AButtonHeight, AButtonWidth, AClientHeight, AColumnsCount, ATopOffset, I: Integer; AButtonViewInfo: TcxGroupBoxButtonViewInfo; AClientExtent: TRect; AEditMetrics: TcxEditMetrics; begin AButtonsCount := Properties.Items.Count; AColumnsCount := Properties.GetColumnCount; AButtonsPerColumn := Properties.GetButtonsPerColumn; AClientExtent := GetClientExtent(ACanvas, AViewInfo); GetEditMetrics(False, nil, AEditMetrics); AButtonWidth := (Bounds.Right - Bounds.Left - (AClientExtent.Left + AClientExtent.Right) + AEditMetrics.ClientWidthCorrection - AEditMetrics.ColumnOffset * (AColumnsCount - 1)) div AColumnsCount; AClientHeight := Bounds.Bottom - Bounds.Top - AClientExtent.Top - AClientExtent.Bottom; ATopOffset := Bounds.Top + AClientExtent.Top + (AClientHeight mod AButtonsPerColumn) div 2; AButtonHeight := AClientHeight div AButtonsPerColumn; for I := 0 to AButtonsCount - 1 do begin AButtonViewInfo := TcxGroupBoxButtonViewInfo(AViewInfo.ButtonsInfo[I]); AButtonViewInfo.Bounds.Left := Bounds.Left + AClientExtent.Left + AButtonViewInfo.Column * (AButtonWidth + AEditMetrics.ColumnOffset) + AEditMetrics.ClientLeftBoundCorrection; AButtonViewInfo.Bounds.Top := ATopOffset + AButtonViewInfo.Row * AButtonHeight; AButtonViewInfo.Bounds.Right := AButtonViewInfo.Bounds.Left + AButtonWidth; AButtonViewInfo.Bounds.Bottom := AButtonViewInfo.Bounds.Top + AButtonHeight; AButtonViewInfo.VisibleBounds := AButtonViewInfo.Bounds; end; end; procedure TcxButtonGroupViewData.CalculateButtonViewInfos(AViewInfo: TcxCustomEditViewInfo); function GetButtonStyle: TcxEditButtonStyle; const AButtonInplaceStyleMap: array[TcxLookAndFeelKind] of TcxEditButtonStyle = (btsFlat, bts3D, btsUltraFlat, btsOffice11); AButtonStyleMap: array [TcxEditBorderStyle] of TcxEditButtonStyle = (bts3D, btsFlat, btsFlat, btsFlat, bts3D, btsUltraFlat, btsOffice11); begin if IsInplace then Result := AButtonInplaceStyleMap[Style.LookAndFeel.Kind] else case Style.BorderStyle of ebsUltraFlat: Result := btsUltraFlat; ebsOffice11: Result := btsOffice11; else Result := AButtonStyleMap[AViewInfo.BorderStyle]; end; end; var AButtonsCount, AButtonsPerColumn, I: Integer; AButtonStyle: TcxEditButtonStyle; AButtonViewInfo: TcxGroupBoxButtonViewInfo; begin AButtonStyle := GetButtonStyle; AButtonsCount := Properties.Items.Count; AButtonsPerColumn := Properties.GetButtonsPerColumn; for I := 0 to AButtonsCount - 1 do begin AButtonViewInfo := TcxGroupBoxButtonViewInfo(AViewInfo.ButtonsInfo[I]); with AButtonViewInfo do begin HasBackground := AViewInfo.HasBackground; Data.Style := AButtonStyle; Caption := Properties.FItems[I].Caption; Column := I div AButtonsPerColumn; Row := I mod AButtonsPerColumn; end; end; end; function TcxButtonGroupViewData.GetDrawTextFlags: Integer; begin Result := cxAlignLeft or cxAlignVCenter or cxShowPrefix; if (epoAutoHeight in PaintOptions) and Properties.WordWrap then begin Result := Result or cxDontClip; Result := Result or cxWordBreak; end else Result := Result or cxSingleLine; end; function TcxButtonGroupViewData.GetCaptionRectExtent: TRect; begin Result := cxEmptyRect; end; function TcxButtonGroupViewData.GetProperties: TcxCustomButtonGroupProperties; begin Result := TcxCustomButtonGroupProperties(FProperties); end; { TcxCustomGroupBoxProperties } class function TcxCustomGroupBoxProperties.GetContainerClass: TcxContainerClass; begin Result := TcxCustomGroupBox; end; class function TcxCustomGroupBoxProperties.GetViewInfoClass: TcxContainerViewInfoClass; begin Result := TcxGroupBoxViewInfo; end; class function TcxCustomGroupBoxProperties.GetViewDataClass: TcxCustomEditViewDataClass; begin Result := TcxGroupBoxViewData; end; { TcxButtonGroupItem } constructor TcxButtonGroupItem.Create(Collection: TCollection); begin if Assigned(Collection) then Collection.BeginUpdate; try inherited Create(Collection); FEnabled := True; DoChanged(Collection, copAdd); finally if Assigned(Collection) then Collection.EndUpdate; end; end; destructor TcxButtonGroupItem.Destroy; var ACollection: TCollection; AIndex: Integer; begin ACollection := Collection; if not IsCollectionDestroying then AIndex := Index else AIndex := -1; if Assigned(ACollection) then ACollection.BeginUpdate; try inherited Destroy; DoChanged(ACollection, copDelete, AIndex); finally if Assigned(ACollection) then ACollection.EndUpdate; end; end; procedure TcxButtonGroupItem.Assign(Source: TPersistent); begin if Source is TcxButtonGroupItem then with TcxButtonGroupItem(Source) do begin Self.Caption := Caption; Self.Enabled := Enabled; Self.Tag := Tag; end else inherited Assign(Source); end; function TcxButtonGroupItem.GetCaption: TCaption; begin Result := FCaption; end; procedure TcxButtonGroupItem.DoChanged(ACollection: TCollection; ACollectionOperation: TcxCollectionOperation; AIndex: Integer = -1); begin if Assigned(ACollection) then if AIndex = -1 then TcxButtonGroupItems(ACollection).InternalNotify(Self, AIndex, ACollectionOperation) else TcxButtonGroupItems(ACollection).InternalNotify(nil, AIndex, ACollectionOperation); end; function TcxButtonGroupItem.GetIsCollectionDestroying: Boolean; begin Result := (Collection <> nil) and TcxButtonGroupItems(Collection).IsDestroying; end; function TcxButtonGroupItem.IsTagStored: Boolean; begin Result := FTag <> 0; end; procedure TcxButtonGroupItem.SetCaption(const Value: TCaption); begin if Value <> FCaption then begin FCaption := Value; DoChanged(Collection, copChanged); end; end; procedure TcxButtonGroupItem.SetEnabled(Value: Boolean); begin if Value <> FEnabled then begin FEnabled := Value; DoChanged(Collection, copChanged); end; end; { TcxButtonGroupItems } destructor TcxButtonGroupItems.Destroy; begin FIsDestroying := True; inherited Destroy; end; procedure TcxButtonGroupItems.InternalNotify(AItem: TcxButtonGroupItem; AItemIndex: Integer; AItemOperation: TcxCollectionOperation); begin if TcxCustomEditProperties(GetOwner).ChangedLocked or IsDestroying then Exit; if AItem <> nil then FChangedItemIndex := AItem.Index else FChangedItemIndex := AItemIndex; FChangedItemOperation := AItemOperation; FItemChanged := True; try TcxCustomEditProperties(GetOwner).Changed; finally FItemChanged := False; end; end; procedure TcxButtonGroupItems.Update(Item: TCollectionItem); begin TcxCustomEditProperties(GetOwner).Changed; end; function TcxButtonGroupItems.GetItem(Index: Integer): TcxButtonGroupItem; begin Result := TcxButtonGroupItem(inherited Items[Index]); end; procedure TcxButtonGroupItems.SetItem(Index: Integer; Value: TcxButtonGroupItem); begin inherited Items[Index] := Value; end; function TcxButtonGroupItems.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := S_OK else Result := E_NOINTERFACE; end; function TcxButtonGroupItems._AddRef: Integer; begin Result := -1; end; function TcxButtonGroupItems._Release: Integer; begin Result := -1; end; function TcxButtonGroupItems.CheckItemsGetCaption(Index: Integer): string; begin Result := TcxButtonGroupItem(Items[Index]).Caption; end; function TcxButtonGroupItems.CheckItemsGetCount: Integer; begin Result := Count; end; { TcxCustomButtonGroupProperties } constructor TcxCustomButtonGroupProperties.Create(AOwner: TPersistent); begin inherited Create(AOwner); FColumns := 1; FItems := CreateItems; end; destructor TcxCustomButtonGroupProperties.Destroy; begin BeginUpdate; try FreeAndNil(FItems); finally EndUpdate(False); end; inherited Destroy; end; procedure TcxCustomButtonGroupProperties.Assign(Source: TPersistent); begin if Source is TcxCustomButtonGroupProperties then begin BeginUpdate; try inherited Assign(Source); with Source as TcxCustomButtonGroupProperties do begin Self.Columns := Columns; Self.Items := Items; Self.WordWrap := WordWrap; end; finally EndUpdate; end end else inherited Assign(Source); end; function TcxCustomButtonGroupProperties.CreatePreviewProperties: TcxCustomEditProperties; const AItemCaptions: array [0..2] of string = ('A', 'B', 'C'); var I: Integer; begin Result := inherited CreatePreviewProperties; for I := 0 to High(AItemCaptions) do TcxButtonGroupItem(TcxCustomButtonGroupProperties(Result).Items.Add).Caption := AItemCaptions[I]; TcxCustomButtonGroupProperties(Result).Columns := 3; end; class function TcxCustomButtonGroupProperties.GetContainerClass: TcxContainerClass; begin Result := TcxCustomButtonGroup; end; function TcxCustomButtonGroupProperties.GetSpecialFeatures: TcxEditSpecialFeatures; begin Result := inherited GetSpecialFeatures + [esfMinSize]; end; function TcxCustomButtonGroupProperties.GetSupportedOperations: TcxEditSupportedOperations; begin Result := [esoAlwaysHotTrack, esoAutoHeight, esoEditing, esoFiltering, esoShowingCaption, esoSorting, esoTransparency]; if Items.Count > 0 then Include(Result, esoHotTrack); end; class function TcxCustomButtonGroupProperties.GetViewInfoClass: TcxContainerViewInfoClass; begin Result := TcxButtonGroupViewInfo; end; class function TcxCustomButtonGroupProperties.GetViewDataClass: TcxCustomEditViewDataClass; begin Result := TcxButtonGroupViewData; end; function TcxCustomButtonGroupProperties.GetColumnCount: Integer; var AButtonCount, AButtonsPerColumn: Integer; begin Result := Columns; AButtonCount := Items.Count; if Result > AButtonCount then Result := AButtonCount; if AButtonCount > 0 then begin if Result = 0 then Result := 1; AButtonsPerColumn := (AButtonCount + Result - 1) div Result; Result := (AButtonCount + AButtonsPerColumn - 1) div AButtonsPerColumn; end; end; function TcxCustomButtonGroupProperties.CreateItems: TcxButtonGroupItems; begin Result := TcxButtonGroupItems.Create(Self, TcxButtonGroupItem); end; function TcxCustomButtonGroupProperties.GetButtonsPerColumn: Integer; var AColumnsCount: Integer; begin AColumnsCount := GetColumnCount; Result := (Items.Count + AColumnsCount - 1) div AColumnsCount; end; procedure TcxCustomButtonGroupProperties.SetColumns(Value: Integer); begin if Value < 1 then Value := 1; if Value <> FColumns then begin FColumns := Value; Changed; end; end; procedure TcxCustomButtonGroupProperties.SetItems(Value: TcxButtonGroupItems); begin FItems.Assign(Value); end; procedure TcxCustomButtonGroupProperties.SetWordWrap(Value: Boolean); begin if Value <> FWordWrap then begin FWordWrap := Value; Changed; end; end; { TcxPanelStyle } constructor TcxPanelStyle.Create(AOwner: TcxCustomGroupBox); begin inherited Create; FEdit := AOwner; FCaptionIndent := 2; FActive := False; FOfficeBackgroundKind := pobkOffice11Color; FWordWrap := False; end; procedure TcxPanelStyle.Assign(ASource: TPersistent); begin if ASource is TcxPanelStyle then begin Active := TcxPanelStyle(ASource).Active; CaptionIndent := TcxPanelStyle(ASource).CaptionIndent; WordWrap := TcxPanelStyle(ASource).WordWrap; OfficeBackgroundKind := TcxPanelStyle(ASource).OfficeBackgroundKind; end else inherited Assign(ASource); end; procedure TcxPanelStyle.SetActive(AValue: Boolean); begin if AValue <> FActive then begin FActive := AValue; Update; end; end; procedure TcxPanelStyle.SetCaptionIndent(AValue: Integer); begin AValue := Max(2, AValue); if AValue <> FCaptionIndent then begin FCaptionIndent := AValue; if FActive then Update; end; end; procedure TcxPanelStyle.SetOfficeBackgroundKind( AValue: TcxPanelOffice11BackgroundKind); begin if FOfficeBackgroundKind <> AValue then begin FOfficeBackgroundKind := AValue; if FActive and (Edit.LookAndFeel.Kind = lfOffice11) then Update; end; end; procedure TcxPanelStyle.SetWordWrap(AValue: Boolean); begin if AValue <> FWordWrap then begin FWordWrap := AValue; if FActive then Update; end; end; procedure TcxPanelStyle.Update; begin Edit.UpdateCaption; end; { TcxCustomGroupBox } constructor TcxCustomGroupBox.Create(AOwner: TComponent); begin inherited Create(AOwner); end; destructor TcxCustomGroupBox.Destroy; begin FreeAndNil(FCaptionFont); FreeAndNil(FPanelStyle); inherited Destroy; end; class function TcxCustomGroupBox.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxCustomGroupBoxProperties; end; procedure TcxCustomGroupBox.CalculateVisibleCaption; begin if not SameText(GetVisibleCaption, FVisibleCaption) then begin FVisibleCaption := GetVisibleCaption; UpdateNonClientArea; end; end; function TcxCustomGroupBox.GetCaptionBkColor: TColor; begin Result := FCaptionBkColor; // for CBuilder 10 end; function TcxCustomGroupBox.GetColor: TColor; begin Result := Style.Color; end; function TcxCustomGroupBox.GetFont: TFont; begin Result := Style.GetVisibleFont; end; function TcxCustomGroupBox.IsSkinAvailable: Boolean; begin Result := (LookAndFeel <> nil) and (LookAndFeel.SkinPainter <> nil); end; procedure TcxCustomGroupBox.UpdateCaption; begin CalculateCaptionFont; CalculateVisibleCaption; ShortRefreshContainer(False); UpdateNonClientArea; Realign; end; procedure TcxCustomGroupBox.UpdateNonClientArea; begin if HandleAllocated and IsNonClientAreaSupported then PostMessage(Handle, WM_DXUPDATENONCLIENTAREA, 0, 0); end; procedure TcxCustomGroupBox.SetPanelStyle(AValue: TcxPanelStyle); begin if AValue <> FPanelStyle then begin FPanelStyle.Assign(AValue); UpdateCaption; end; end; function TcxCustomGroupBox.GetHorizontalCaptionIndent: Integer; begin Result := 0; if IsPanelStyle Then begin Result := 2; if not (Alignment in [alTopCenter, alCenterCenter, alBottomCenter]) then Result := PanelStyle.CaptionIndent; end; end; function TcxCustomGroupBox.GetVerticalCaptionIndent: Integer; begin Result := 0; if IsPanelStyle Then begin Result := 2; if not (FAlignment in [alLeftCenter, alCenterCenter, alRightCenter]) then Result := PanelStyle.CaptionIndent; end; end; function TcxCustomGroupBox.GetVisibleCaption: string; begin if IsVerticalText then Result := RemoveAccelChars(Caption) else Result := Caption; end; function TcxCustomGroupBox.GetPanelStyleCaptionDrawingFlags: Cardinal; begin Result := 0; case Alignment of alTopLeft, alLeftTop, alLeftCenter, alLeftBottom, alBottomLeft: Result := Result or DT_LEFT; alTopCenter, alCenterCenter, alBottomCenter: Result := Result or DT_CENTER; alTopRight, alRightTop, alRightCenter, alRightBottom, alBottomRight: Result := Result or DT_RIGHT; end; case Alignment of alLeftTop, alTopLeft, alTopCenter, alTopRight, alRightTop: Result := Result or DT_TOP; alLeftCenter, alCenterCenter, alRightCenter: Result := Result or DT_VCENTER; alLeftBottom, alBottomLeft, alBottomCenter, alBottomRight, alRightBottom: Result := Result or DT_BOTTOM; end; end; procedure TcxCustomGroupBox.SetAlignment(Value: TcxCaptionAlignment); begin if FAlignment <> Value then begin FAlignment := Value; UpdateCaption; end; end; procedure TcxCustomGroupBox.SetCaptionBkColor(Value: TColor); begin FCaptionBkColor := Value; // for CBuilder 10 end; procedure TcxCustomGroupBox.SetColor(Value: TColor); begin Style.Color := Value; end; procedure TcxCustomGroupBox.SetFont(Value: TFont); begin Style.Font := Value; end; {$IFNDEF DELPHI7} procedure TcxCustomGroupBox.WMPrintClient(var Message: TMessage); begin if (Message.Result <> 1) and ((Message.LParam and PRF_CHECKVISIBLE = 0) or Visible) then PaintHandler(TWMPaint(Message)) else inherited; end; {$ENDIF} procedure TcxCustomGroupBox.CMDialogChar(var Message: TCMDialogChar); begin with Message do if IsAccel(CharCode, Caption) and CanFocus then begin FIsAccelCharHandling := True; try SelectFirst; Result := 1; finally FIsAccelCharHandling := False; end; end else inherited; end; procedure TcxCustomGroupBox.WMNCPaint(var Message: TWMNCPaint); procedure DrawCaption(const ACanvas: TcxCanvas); var AViewInfo: TcxGroupBoxViewInfo; R, R1: TRect; begin ACanvas.SaveClipRegion; try AViewInfo := TcxGroupBoxViewInfo(ViewInfo); R := AViewInfo.GetCaptionRectIndent; R1 := AViewInfo.CaptionRect; case cxGroupBoxAlignment2GroupBoxCaption(Alignment) of cxgpLeft: R1.Right := R1.Left + R.Left; cxgpRight: R1.Left := R1.Right - R.Right; cxgpTop: R1.Bottom := R1.Top + R.Top; cxgpBottom: R1.Top := R1.Bottom - R.Bottom; end; SetWindowOrgEx(ACanvas.Handle, -R.Left, -R.Top, nil); ACanvas.SetClipRegion(TcxRegion.Create(R1), roSet); AViewInfo.DrawCaption(ACanvas); finally ACanvas.RestoreClipRegion; end; end; var ACanvas: TCanvas; AcxCanvas: TcxCanvas; DC: HDC; begin if IsNonClientAreaSupported and IsSkinAvailable then begin DC := GetWindowDC(Handle); ACanvas := TCanvas.Create; AcxCanvas := TcxCanvas.Create(ACanvas); try ACanvas.Handle := DC; DrawCaption(AcxCanvas); ACanvas.Handle := 0; finally AcxCanvas.Free; ACanvas.Free; end; ReleaseDC(Handle, DC); end; end; function TcxCustomGroupBox.IsNonClientAreaSupported: Boolean; begin Result := cxGroupBox_SupportNonClientArea; end; procedure TcxCustomGroupBox.WndProc(var Message: TMessage); const RedrawWindowFlags = RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ALLCHILDREN; SetWindowPosFlags = SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER; begin case Message.Msg of WM_NCPAINT: WMNCPaint(TWMNCPaint(Message)); WM_NCCALCSIZE: if HasNonClientArea then begin TWMNCCalcSize(Message).CalcSize_Params^.rgrc[0] := cxRectContent(BoundsRect, TcxGroupBoxViewInfo(ViewInfo).GetCaptionRectIndent); end; else if (Message.Msg = WM_DXUPDATENONCLIENTAREA) and IsNonClientAreaSupported then begin SetWindowPos(Handle, 0, 0, 0, 0, 0, SetWindowPosFlags); RedrawWindow(Handle, nil, 0, RedrawWindowFlags); end; end; inherited WndProc(Message); end; procedure TcxCustomGroupBox.LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin inherited LookAndFeelChanged(Sender, AChangedValues); UpdateNonClientArea; Invalidate; end; procedure TcxCustomGroupBox.AdjustClientRect(var Rect: TRect); var AViewData: TcxCustomEditViewData; begin if IsDestroying then Exit; AViewData := TcxCustomEditViewData(CreateViewData); try InitializeViewData(AViewData); Rect := GetControlRect(Self); ExtendRect(Rect, AViewData.GetClientExtent(Canvas, ViewInfo)); finally FreeAndNil(AViewData); end; end; function TcxCustomGroupBox.CanAutoSize: Boolean; begin Result := False; end; function TcxCustomGroupBox.CanFocusOnClick: Boolean; begin Result := False; end; function TcxCustomGroupBox.CanHaveTransparentBorder: Boolean; begin Result := Style.TransparentBorder and not IsPanelStyle and inherited CanHaveTransparentBorder; end; procedure TcxCustomGroupBox.ContainerStyleChanged(Sender: TObject); begin CalculateCaptionFont; inherited ContainerStyleChanged(Sender); end; function TcxCustomGroupBox.CreatePanelStyle: TcxPanelStyle; begin Result := TcxPanelStyle.Create(Self); end; function TcxCustomGroupBox.DefaultParentColor: Boolean; begin Result := True; end; procedure TcxCustomGroupBox.FontChanged; begin inherited FontChanged; Realign; end; function TcxCustomGroupBox.GetShadowBounds: TRect; begin Result := inherited GetShadowBounds; case Alignment of alTopLeft, alTopCenter, alTopRight: Result.Top := 0; alBottomLeft, alBottomCenter, alBottomRight: Result.Bottom := Height; alLeftTop, alLeftCenter, alLeftBottom: Result.Left := 0; alRightTop, alRightCenter, alRightBottom: Result.Right := Width; end; end; procedure TcxCustomGroupBox.Initialize; begin inherited Initialize; ControlStyle := ControlStyle + [csAcceptsControls, csCaptureMouse, csClickEvents]; SetBounds(Left, Top, 185, 105); FCaptionFont := TFont.Create; CalculateCaptionFont; TabStop := False; FPanelStyle := CreatePanelStyle; end; function TcxCustomGroupBox.InternalGetActiveStyle: TcxContainerStyle; begin if csDisabled in ViewInfo.ContainerState then Result := FStyles.StyleDisabled else Result := FStyles.Style; end; function TcxCustomGroupBox.InternalGetNotPublishedStyleValues: TcxEditStyleValues; begin Result := inherited InternalGetNotPublishedStyleValues; Include(Result, svHotTrack); end; function TcxCustomGroupBox.IsContainerClass: Boolean; begin Result := True; end; function TcxCustomGroupBox.IsNativeBackground: Boolean; begin Result := IsNativeStyle and ParentBackground and not IsInplace and not Transparent; end; function TcxCustomGroupBox.IsPanelStyle: Boolean; begin Result := PanelStyle.Active; end; procedure TcxCustomGroupBox.Paint; begin if not DoCustomDraw then inherited Paint; end; procedure TcxCustomGroupBox.TextChanged; begin inherited TextChanged; CalculateVisibleCaption; ShortRefreshContainer(False); end; function TcxCustomGroupBox.HasShadow: Boolean; begin Result := (((Alignment in [alLeftTop, alLeftCenter, alLeftBottom, alTopLeft, alTopCenter, alTopRight]) and not IsPanelStyle) or IsPanelStyle) and not ViewInfo.NativeStyle and not IsSkinAvailable and inherited HasShadow; end; procedure TcxCustomGroupBox.AdjustCanvasFontSettings(ACanvas: TcxCanvas); var AColor: TColorRef; ATextColor: TColor; ATheme: TdxTheme; begin with ACanvas do begin Font := FCaptionFont; if IsNativeStyle then begin ATheme := OpenTheme(totButton); GetThemeColor(ATheme, BP_GROUPBOX, cxNativeState[Enabled], TMT_TEXTCOLOR, AColor); Font.Color := AColor; end; if ViewInfo.Painter <> nil then begin ATextColor := ViewInfo.Painter.GroupBoxTextColor( cxGroupBoxAlignment2GroupBoxCaption(Alignment)); if ATextColor <> clDefault then Font.Color := ATextColor; end; end; end; procedure TcxCustomGroupBox.CalculateCaptionFont; var AFontEscapement: Longint; ALogFont: TLogFont; ATextMetric : TTextMetric; begin if IsInplace then Exit; FCaptionFont.Assign(ActiveStyle.GetVisibleFont); if IsVerticalText then begin cxScreenCanvas.Font := FCaptionFont; GetTextMetrics(cxScreenCanvas.Handle, ATextMetric); if ATextMetric.tmPitchAndFamily and TMPF_TRUETYPE = 0 then FCaptionFont.Name := 'Arial'; if FAlignment in [alLeftTop, alLeftCenter, alLeftBottom] then AFontEscapement := 900 else AFontEscapement := 2700; cxGetFontData(FCaptionFont.Handle, ALogFont); if AFontEscapement <> ALogFont.lfEscapement then begin ALogFont.lfEscapement := AFontEscapement; ALogFont.lfOrientation := AFontEscapement; ALogFont.lfOutPrecision := OUT_TT_ONLY_PRECIS; FCaptionFont.Handle := CreateFontIndirect(ALogFont); end; end; end; function TcxCustomGroupBox.DoCustomDraw: Boolean; begin Result := False; if Assigned(FOnCustomDraw) then FOnCustomDraw(Self, Result); end; {$IFDEF DELPHI7} function TcxCustomGroupBox.DoCustomDrawCaption(ACanvas: TcxCanvas; const ABounds: TRect; const APainter: TcxCustomLookAndFeelPainterClass): Boolean; begin Result := False; if Assigned(FOnCustomDrawCaption) then FOnCustomDrawCaption(Self, ACanvas.Canvas, ABounds, APainter, Result); end; function TcxCustomGroupBox.DoCustomDrawContentBackground(ACanvas: TcxCanvas; const ABounds: TRect; const APainter: TcxCustomLookAndFeelPainterClass): Boolean; begin Result := False; if Assigned(FOnCustomDrawContentBackground) then FOnCustomDrawContentBackground(Self, ACanvas.Canvas, ABounds, APainter, Result); end; procedure TcxCustomGroupBox.DoMeasureCaptionHeight(const APainter: TcxCustomLookAndFeelPainterClass; var ACaptionHeight: Integer); begin if Assigned(FOnMeasureCaptionHeight) then FOnMeasureCaptionHeight(Self, APainter, ACaptionHeight); end; {$ENDIF} function TcxCustomGroupBox.GetCaptionDrawingFlags: Cardinal; begin if IsPanelStyle then begin if PanelStyle.WordWrap then Result := DT_WORDBREAK else Result := DT_SINGLELINE; Result := Result or GetPanelStyleCaptionDrawingFlags; end else Result := DT_SINGLELINE; end; function TcxCustomGroupBox.HasNonClientArea: Boolean; begin Result := not IsPanelStyle and IsNonClientAreaSupported and IsSkinAvailable and (Caption <> ''); end; function TcxCustomGroupBox.IsVerticalText: Boolean; begin Result := (FAlignment in [alLeftTop, alLeftCenter, alLeftBottom, alRightTop, alRightCenter, alRightBottom]) and not IsPanelStyle; end; { TcxCustomButtonGroup } destructor TcxCustomButtonGroup.Destroy; begin SetButtonCount(0); FreeAndNil(FButtons); inherited Destroy; end; procedure TcxCustomButtonGroup.ActivateByMouse(Shift: TShiftState; X, Y: Integer; var AEditData: TcxCustomEditData); var P: TPoint; AButtonIndex: Integer; begin Activate(AEditData); P := Parent.ClientToScreen(Point(X, Y)); P := ScreenToClient(P); AButtonIndex := GetButtonIndexAt(P); if AButtonIndex <> -1 then begin with ViewInfo.ButtonsInfo[AButtonIndex].Bounds do begin P.X := (Right - Left) div 2; P.Y := (Bottom - Top) div 2; end; if ssLeft in Shift then SendMessage(TWinControl(FButtons[AButtonIndex]).Handle, WM_LBUTTONDOWN, ShiftStateToKeys(Shift), P.Y shl 16 + P.X) else SendMessage(TWinControl(FButtons[AButtonIndex]).Handle, WM_LBUTTONUP, ShiftStateToKeys(Shift), P.Y shl 16 + P.X); end; end; function TcxCustomButtonGroup.Focused: Boolean; var I: Integer; begin Result := inherited Focused; if not Result and not FIsCreating then for I := 0 to FButtons.Count - 1 do if TWinControl(FButtons[I]).Focused then begin Result := True; Break; end; end; class function TcxCustomButtonGroup.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxCustomButtonGroupProperties; end; procedure TcxCustomButtonGroup.GetTabOrderList(List: TList); begin if IsInplace and Visible then List.Remove(Parent); end; function TcxCustomButtonGroup.IsButtonNativeStyle: Boolean; begin Result := TcxButtonGroupViewDataClass(Properties.GetViewDataClass).IsButtonNativeStyle(Style.LookAndFeel); end; procedure TcxCustomButtonGroup.PropertiesChanged(Sender: TObject); begin if not (csReading in ComponentState) then UpdateButtons; inherited PropertiesChanged(Sender); end; procedure TcxCustomButtonGroup.ReadState(Reader: TReader); begin inherited ReadState(Reader); UpdateButtons; SynchronizeDisplayValue; end; function TcxCustomButtonGroup.CanAutoSize: Boolean; begin Result := not IsInplace and AutoSize; end; procedure TcxCustomButtonGroup.ContainerStyleChanged(Sender: TObject); begin inherited ContainerStyleChanged(Sender); if not FIsCreating then UpdateButtons; end; procedure TcxCustomButtonGroup.CursorChanged; begin UpdateButtons; end; procedure TcxCustomButtonGroup.DoEditKeyDown(var Key: Word; Shift: TShiftState); var AButtonsInColumn, AButtonsPerColumn: Integer; AFocusedButtonIndex: Integer; AColumn, ARow: Integer; begin AFocusedButtonIndex := GetFocusedButtonIndex; if AFocusedButtonIndex = -1 then Exit; AButtonsPerColumn := ActiveProperties.GetButtonsPerColumn; AButtonsInColumn := AButtonsPerColumn; with TcxGroupBoxButtonViewInfo(ViewInfo.ButtonsInfo[AFocusedButtonIndex]) do begin AColumn := Column; ARow := Row; end; if AFocusedButtonIndex - ARow + AButtonsInColumn - 1 >= ActiveProperties.Items.Count then AButtonsInColumn := ActiveProperties.Items.Count - (AFocusedButtonIndex - ARow); case Key of VK_DOWN: if ARow < AButtonsInColumn - 1 then begin TWinControl(FButtons[AFocusedButtonIndex + 1]).SetFocus; Key := 0; end; VK_LEFT: if AColumn > 0 then begin TWinControl(FButtons[AFocusedButtonIndex - AButtonsPerColumn]).SetFocus; Key := 0; end; VK_RIGHT: if AFocusedButtonIndex + AButtonsPerColumn < FButtons.Count then begin TWinControl(FButtons[AFocusedButtonIndex + AButtonsPerColumn]).SetFocus; Key := 0; end; VK_UP: if ARow > 0 then begin TWinControl(FButtons[AFocusedButtonIndex - 1]).SetFocus; Key := 0; end end; inherited DoEditKeyDown(Key, Shift); end; procedure TcxCustomButtonGroup.EnabledChanged; begin inherited EnabledChanged; UpdateButtons; end; procedure TcxCustomButtonGroup.Initialize; begin inherited Initialize; FButtons := TList.Create; AutoSize := False; TabStop := True; end; function TcxCustomButtonGroup.IsButtonDC(ADC: THandle): Boolean; var I: Integer; begin Result := False; for I := 0 to InternalButtons.Count - 1 do if GetButtonDC(I) = ADC then begin Result := True; Break; end; end; function TcxCustomButtonGroup.IsContainerClass: Boolean; begin Result := FIsAccelCharHandling; end; function TcxCustomButtonGroup.RefreshContainer(const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AIsMouseEvent: Boolean): Boolean; begin Result := inherited RefreshContainer(P, Button, Shift, AIsMouseEvent); ArrangeButtons; end; procedure TcxCustomButtonGroup.CreateHandle; begin inherited CreateHandle; UpdateButtons; SynchronizeDisplayValue; end; procedure TcxCustomButtonGroup.ArrangeButtons; var AButtonViewInfo: TcxGroupBoxButtonViewInfo; I: Integer; R: TRect; begin for I := 0 to FButtons.Count - 1 do with TWinControl(FButtons[I]) do begin AButtonViewInfo := TcxGroupBoxButtonViewInfo(ViewInfo.ButtonsInfo[I]); R := AButtonViewInfo.Bounds; SetBounds(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top); end; end; function TcxCustomButtonGroup.GetButtonIndexAt(const P: TPoint): Integer; var I: Integer; begin Result := -1; for I := 0 to ActiveProperties.Items.Count - 1 do if PtInRect(ViewInfo.ButtonsInfo[I].Bounds, P) then begin Result := I; Break; end; end; function TcxCustomButtonGroup.GetFocusedButtonIndex: Integer; var I: Integer; begin Result := -1; for I := 0 to ActiveProperties.Items.Count - 1 do if TWinControl(FButtons[I]).Focused then begin Result := I; Break; end; end; procedure TcxCustomButtonGroup.InitButtonInstance(AButton: TWinControl); begin TControlAccess(AButton).ParentShowHint := False; AButton.Parent := Self; TControlAccess(AButton).OnDragDrop := DoButtonDragDrop; TControlAccess(AButton).OnDragOver := DoButtonDragOver; TWinControlAccess(AButton).OnKeyDown := DoButtonKeyDown; TWinControlAccess(AButton).OnKeyPress := DoButtonKeyPress; TWinControlAccess(AButton).OnKeyUp := DoButtonKeyUp; TControlAccess(AButton).OnMouseDown := DoButtonMouseDown; TControlAccess(AButton).OnMouseMove := DoButtonMouseMove; TControlAccess(AButton).OnMouseUp := DoButtonMouseUp; {$IFDEF DELPHI6} TControlAccess(AButton).OnMouseWheel := DoButtonMouseWheel; {$ELSE} TWinControlAccess(AButton).OnMouseWheel := DoButtonMouseWheel; {$ENDIF} end; procedure TcxCustomButtonGroup.SetButtonCount(Value: Integer); begin with ActiveProperties.Items do if ItemChanged then begin if ChangedItemOperation = copAdd then InitButtonInstance(GetButtonInstance) else if ChangedItemOperation = copDelete then TWinControl(FButtons[ChangedItemIndex]).Free; end else if Value <> FButtons.Count then begin DisableAlign; try if Value < FButtons.Count then while FButtons.Count > Value do TWinControl(FButtons.Last).Free else while FButtons.Count < Value do InitButtonInstance(GetButtonInstance); finally EnableAlign; end; end; end; function TcxCustomButtonGroup.IsNonClientAreaSupported: Boolean; begin Result := False; end; procedure TcxCustomButtonGroup.SynchronizeButtonsStyle; var AButton: TWinControlAccess; ATempFont: TFont; I: Integer; begin ATempFont := TFont.Create; try for I := 0 to FButtons.Count - 1 do begin AButton := TWinControlAccess(FButtons[I]); AButton.Color := ActiveStyle.Color; ATempFont.Assign(Style.GetVisibleFont); ATempFont.Color := ActiveStyle.GetVisibleFont.Color; AssignFonts(AButton.Font, ATempFont); end; finally ATempFont.Free; end; end; procedure TcxCustomButtonGroup.UpdateButtons; var AButton: TWinControl; I: Integer; begin SetButtonCount(ActiveProperties.Items.Count); ShortRefreshContainer(False); for I := 0 to FButtons.Count - 1 do begin AButton := TWinControl(FButtons[I]); AButton.Enabled := Enabled and ActiveProperties.Items[I].Enabled; end; SynchronizeButtonsStyle; for I := 0 to FButtons.Count - 1 do begin AButton := TWinControl(FButtons[I]); AButton.Cursor := Cursor; end; end; procedure TcxCustomButtonGroup.DoButtonDragDrop(Sender, Source: TObject; X, Y: Integer); begin with TWinControl(Sender) do Self.DragDrop(Source, Left + X, Top + Y); end; procedure TcxCustomButtonGroup.DoButtonDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin with TWinControl(Sender) do Self.DragOver(Source, Left + X, Top + Y, State, Accept); end; procedure TcxCustomButtonGroup.DoButtonKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin KeyDown(Key, Shift); end; procedure TcxCustomButtonGroup.DoButtonKeyPress(Sender: TObject; var Key: Char); begin KeyPress(Key); end; procedure TcxCustomButtonGroup.DoButtonKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin KeyUp(Key, Shift); end; procedure TcxCustomButtonGroup.DoButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin InnerControlMouseDown := True; try with TWinControl(Sender) do Self.MouseDown(Button, Shift, X + Left, Y + Top); finally InnerControlMouseDown := False; end; end; procedure TcxCustomButtonGroup.DoButtonMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin with TWinControl(Sender) do Self.MouseMove(Shift, X + Left, Y + Top); end; procedure TcxCustomButtonGroup.DoButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin with TWinControl(Sender) do Self.MouseUp(Button, Shift, X + Left, Y + Top); end; procedure TcxCustomButtonGroup.DoButtonMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); begin Handled := False; end; function TcxCustomButtonGroup.GetProperties: TcxCustomButtonGroupProperties; begin Result := TcxCustomButtonGroupProperties(FProperties); end; function TcxCustomButtonGroup.GetActiveProperties: TcxCustomButtonGroupProperties; begin Result := TcxCustomButtonGroupProperties(InternalGetActiveProperties); end; procedure TcxCustomButtonGroup.SetProperties(Value: TcxCustomButtonGroupProperties); begin FProperties.Assign(Value); end; procedure TcxCustomButtonGroup.WMWindowPosChanged(var Message: TWMWindowPosChanged); begin inherited; if not IsDestroying and IsTransparentBackground then RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN); end; initialization WM_DXUPDATENONCLIENTAREA := RegisterWindowMessage('WM_DXUPDATENONCLIENTAREA'); end.