Componentes.Terceros.DevExp.../official/x.35/ExpressSkins Library/Sources/dxSkinsForm.pas
2008-05-12 15:08:14 +00:00

3360 lines
104 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressSkins Library }
{ }
{ Copyright (c) 2006-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 EXPRESSSKINS 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 dxSkinsForm;
interface
{$I cxVer.inc}
uses
Types, Windows, Classes, SysUtils, Messages, Forms, Graphics, Controls, cxScrollBar,
MultiMon, cxDWMAPI, ShellApi, cxLookAndFeelPainters, cxClasses, StdCtrls,
cxGraphics, cxControls, cxGeometry, dxSkinsLookAndFeelPainter, dxSkinsCore, Math,
ExtCtrls, FlatSB, cxLookAndFeels, dxUxTheme, dxSkinInfo;
const
dxSkinFormTextOffset = 5;
dxSkinIconSpacing = 2;
WM_POSTREDRAW: Cardinal = WM_DX + 1;
WM_CHILDCHANGED: Cardinal = WM_DX + 2;
WM_POSTCREATE: Cardinal = WM_DX + 3;
WM_POSTCHECKRGN: Cardinal = WM_DX + 4;
IsDesigning: Boolean = False;
type
TdxSkinFormPainter = class;
TdxSkinFormNonClientAreaInfo = class;
TdxSkinFormCorner = (sfcLeftTop, sfcRightTop, sfcLeftBottom, sfcRightBottom);
TdxScrollAreaElement = (saeHorzScroll, saeVertScroll, saeSizeGrip);
TdxScrollAreaElements = set of TdxScrollAreaElement;
TdxSkinFormScrollBar = saeHorzScroll..saeVertScroll;
TdxSkinFormEvent = procedure(Sender: TObject; AForm: TCustomForm;
var ASkinName: string; var UseSkin: Boolean) of object;
TdxSkinControlEvent = procedure(Sender: TObject; AControl: TWinControl;
var UseSkin: Boolean) of object;
{ TdxSkinController }
TdxSkinController = class(TcxLookAndFeelController)
private
FOnSkinControl: TdxSkinControlEvent;
FOnSkinForm: TdxSkinFormEvent;
function GetUseSkins: Boolean;
procedure SetUseSkins(Value: Boolean);
protected
procedure Changed;
function DoSkinControl(AControl: TWinControl): Boolean; virtual;
function DoSkinForm(AForm: TCustomForm): TdxSkinLookAndFeelPainterClass; virtual;
function DoSkinFormEx(AForm: TCustomForm;
var ASkinName: string; var AUseSkin: Boolean): TdxSkinLookAndFeelPainterClass; virtual;
procedure Loaded; override;
procedure MasterLookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override;
procedure MasterLookAndFeelDestroying(Sender: TcxLookAndFeel); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Refresh;
class function GetFormSkin(AForm: TCustomForm; var ASkinName: string): Boolean;
published
property Kind;
property NativeStyle;
property SkinName;
property UseSkins: Boolean read GetUseSkins write SetUseSkins default True;
property OnSkinForm: TdxSkinFormEvent read FOnSkinForm write FOnSkinForm;
property OnSkinControl: TdxSkinControlEvent read FOnSkinControl write FOnSkinControl;
end;
{ TdxSkinWinController }
TdxSkinWinController = class(TcxIUnknownObject, IcxMouseTrackingCaller)
private
FHandle: HWND;
FLookAndFeelPainter: TdxSkinLookAndFeelPainterClass;
FMaster: TdxSkinWinController;
FProcInstance: Pointer;
FSavedWndProc: TWndMethod;
FSavedWndProcPtr: Pointer;
FWinControl: TWinControl;
function GetHasVirtualChilds: Boolean;
function GetIsHooked: Boolean;
function GetIsMDIClient: Boolean;
function GetLookAndFeelPainter: TdxSkinLookAndFeelPainterClass;
procedure SetHandle(AHandle: HWND);
protected
function GetIsSkinUsed: Boolean; virtual;
function GetMaster(AHandle: HWND): TdxSkinWinController; virtual;
function GetUseSkinForControl: Boolean; virtual;
procedure DefWndProc(var AMessage);
procedure HookWndProc; virtual;
procedure InitializePainter; virtual;
procedure RedrawWindow(AUpdateNow: Boolean);
procedure UnHookWndProc; virtual;
procedure WndProc(var AMessage: TMessage); virtual;
{ IcxMouseTrackingCaller }
procedure MouseLeave; virtual;
public
constructor Create(AHandle: HWND); virtual;
destructor Destroy; override;
class function IsMDIChildWindow(AHandle: HWND): Boolean; virtual;
class function IsMDIClientWindow(AHandle: HWND): Boolean; virtual;
class function IsMessageDlgWindow(AHandle: HWND): Boolean; virtual;
class function IsSkinActive(AHandle: HWND): Boolean;
class procedure FinalizeEngine(AHandle: HWND);
class procedure InitializeEngine(AHandle: HWND);
function GetSkinName(var ASkinName: string): Boolean;
procedure Refresh; virtual;
procedure Update; virtual;
property Handle: HWND read FHandle write SetHandle;
property HasVirtualChilds: Boolean read GetHasVirtualChilds;
property IsHooked: Boolean read GetIsHooked;
property IsMDIClient: Boolean read GetIsMDIClient;
property IsSkinUsed: Boolean read GetIsSkinUsed;
property LookAndFeelPainter: TdxSkinLookAndFeelPainterClass read GetLookAndFeelPainter;
property Master: TdxSkinWinController read FMaster;
property ProcInstance: Pointer read FProcInstance;
property WinControl: TWinControl read FWinControl;
end;
TdxSkinWinControllerClass = class of TdxSkinWinController;
TdxSkinGetControllerClassForWindowProc = function (AWnd: HWND): TdxSkinWinControllerClass;
{ TdxSkinFormController }
TdxSkinFormController = class(TdxSkinWinController)
private
FForceRedraw: Boolean;
FHasRegion: Boolean;
FLockRedrawCount: Integer;
FMaster: TdxSkinFormController;
FPainter: TdxSkinFormPainter;
FSizingInProcess: Boolean;
FViewInfo: TdxSkinFormNonClientAreaInfo;
function GetForm: TCustomForm;
function GetIsMDIMain: Boolean;
protected
function GetIsSkinUsed: Boolean; override;
function NeedForceRgnUpdate(ASizeType: Integer): Boolean;
procedure CalculateViewInfo; virtual;
procedure CheckWindowRgn(AForceRgn: Boolean);
procedure DrawWindowBackground(DC: HDC); virtual;
procedure DrawWindowBorder; virtual;
procedure InitializeMessageForm; virtual;
procedure InitializePainter; override;
function HandleWindowMessage(var AMessage: TMessage): Boolean; virtual;
procedure LockRedraw;
procedure MouseLeave; override;
function RefreshOnMouseEvent(AForceRefresh: Boolean = False): Boolean;
procedure UnlockRedraw;
procedure UpdateMDIClientEdge;
procedure UpdateScrollTrackPos(AKind: TdxSkinFormScrollBar; APos: Integer);
procedure WMDestroy(var Message: TWMDestroy); virtual;
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); virtual;
procedure WMNCActivate(var Message: TWMNCActivate); virtual;
procedure WMNCButtonDown(var Message: TWMNCHitMessage); virtual;
procedure WMNCCalcSize(var Message: TWMNCCALCSIZE); virtual;
procedure WMNCHitTest(var Message: TWMNCHitTest); virtual;
procedure WMNCLButtonUp(var Message: TWMNCHitMessage); virtual;
procedure WMNCMouseMove(var Message: TWMNCHitMessage);
procedure WMNCPaint(var Message: TWMNCPaint); virtual;
procedure WMScroll(var Message: TWMScroll); virtual;
procedure WMSetText(var Message: TWMSetText); virtual;
procedure WMSize(var Message: TWMSize); virtual;
procedure WMSizing(var Message: TWMSize); virtual;
procedure WMSysCommand(var Message: TWMSysCommand); virtual;
procedure WndProc(var AMessage: TMessage); override;
public
constructor Create(AHandle: HWND); override;
destructor Destroy; override;
procedure Update; override;
property ForceRedraw: Boolean read FForceRedraw write FForceRedraw;
property Form: TCustomForm read GetForm;
property HasRegion: Boolean read FHasRegion write FHasRegion;
property IsMDIMain: Boolean read GetIsMDIMain;
property Painter: TdxSkinFormPainter read FPainter;
property SizingInProcess: Boolean read FSizingInProcess write FSizingInProcess;
property ViewInfo: TdxSkinFormNonClientAreaInfo read FViewInfo;
end;
{ TdxSkinFormNonClientAreaInfo }
TdxSkinFormNonClientAreaInfo = class
private
FController: TdxSkinFormController;
FThemeActive: Boolean;
FThemeActiveAssigned: Boolean;
function GetBorderBounds(ASide: TcxBorder): TRect;
function GetButtonPressed: Boolean;
function GetCaptionBounds: TRect;
function GetCaptionButtonRect(const ACaptionRect: TRect): TRect;
function GetCaptionContentOffset: TRect;
function GetCaptionIconSize: Integer;
function GetCaptionTextColor: TColor;
function GetClientRect: TRect;
function GetClientRectOnClient: TRect;
function GetExStyle: Integer;
function GetHandle: HWND;
function GetHasBorder: Boolean;
function GetHasCaption: Boolean;
function GetHasMenu: Boolean;
function GetIconBounds(AIcon: TdxSkinFormIcon): TRect;
function GetIconState(AIcon: TdxSkinFormIcon): TdxSkinElementState;
function GetIsAlphaBlendUsed: Boolean;
function GetIsDialog: Boolean;
function GetIsIconic: Boolean;
function GetIsSizeBox: Boolean;
function GetIsZoomed: Boolean;
function GetNativeBorderWidth: Boolean;
function GetNeedCheckNonClientSize: Boolean;
function GetScrollAreaBounds(AItem: TdxScrollAreaElement): TRect;
function GetScrollBarInfo(AScrollBar: TdxSkinFormScrollBar): TScrollBarInfo;
function GetScrollBarPartBounds(AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart): TRect;
function GetScrollBarPartState(AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart): TcxButtonState;
function GetSizeArea(ASide: TcxBorder): TRect;
function GetSizeCorners(ACorner: TdxSkinFormCorner): TRect;
function GetSkinBorderWidth(ASide: TcxBorder): Integer;
function GetStyle: Integer;
function GetThemeActive: Boolean;
function GetToolWindow: Boolean;
function GetWindowRect: TRect;
procedure SetActive(AActive: Boolean);
procedure SetUpdateRgn(ARgn: HRGN);
procedure SetWindowRgn(ARgn: HRGN);
protected
FActive: Boolean;
FBorderBounds: array[TcxBorder] of TRect;
FBorderWidths: TRect;
FBoundsNoBorders: TRect;
FCaption: string;
FCaptionBounds: TRect;
FCaptionFont: TFont;
FCaptionSufix: string;
FCaptionTextColor: array[Boolean] of TColor;
FCaptionTextShadowColor: TColor;
FHasMenu: Boolean;
FIconBounds: array[TdxSkinFormIcon] of TRect;
FIconPressed: TdxSkinFormIcon;
FIcons: TdxSkinFormIcons;
FIconState: array[TdxSkinFormIcon] of TdxSkinElementState;
FIsMDIClient: Boolean;
FIsSimpleForm: Boolean;
FMenuBounds: TRect;
FPainter: TcxCustomLookAndFeelPainterClass;
FPainterInfo: TdxSkinLookAndFeelPainterInfo;
FScrollAreaBounds: array[TdxScrollAreaElement] of TRect;
FScrollAreaElements: TdxScrollAreaElements;
FScrollBarPartBounds: array[TdxSkinFormScrollBar, TcxScrollBarPart] of TRect;
FScrollBarPartState: array[TdxSkinFormScrollBar, TcxScrollBarPart] of TcxButtonState;
FScrollBarsInfo: array[TdxSkinFormScrollBar] of TScrollBarInfo;
FSizeFrame: TSize;
FSysMenuIcon: HICON;
FTrackedScrollBar: TdxScrollAreaElement;
FTrackIcon: TdxSkinFormIcon;
FUpdateRgn: HRGN;
FWindowBounds: TRect;
FWindowRgn: HRGN;
WindowInfo: TWindowInfo;
procedure CalculateBordersInfo; virtual;
procedure CalculateBorderWidths; virtual;
procedure CalculateCaptionIconsInfo; virtual;
procedure CalculateFontInfo;
procedure CalculateScrollArea; virtual;
procedure CalculateScrollBarPartInfo(AScrollBar: TdxSkinFormScrollBar;
Pos1, Pos2: Integer; APart: TcxScrollBarPart);
procedure CalculateScrollBarPartsInfo; virtual;
function GetActiveMDIChild: TCustomForm;
function GetBorderRect(ASide: TcxBorder; const ABounds, AWidths: TRect): TRect;
function GetCaption: string;
function GetIcons: TdxSkinFormIcons; virtual;
function GetMaximizedMDIChild: TCustomForm;
function GetSysMenuIcon: HICON; virtual;
function GetSystemSizeFrame: TSize;
function IsMDIMainAlphaBlendUsed: Boolean;
procedure UpdateCaption(const ANewText: string);
function UpdateCaptionIconStates: Boolean;
function UpdateCaptionSufix: Boolean;
function UpdateIconPressed(AReset: Boolean = False): TdxSkinFormIcon;
property ThemeActiveAssigned: Boolean read FThemeActiveAssigned write FThemeActiveAssigned;
public
constructor Create(AController: TdxSkinFormController); virtual;
destructor Destroy; override;
procedure Calculate(AUpdateRgn: HRGN); virtual;
function ClientToScreen(const P: TPoint): TPoint; overload;
function ClientToScreen(const R: TRect): TRect; overload;
function CreateDrawRgn: HRGN; virtual;
function GetHitTest(AHitPoint: TPoint; AHitTest: Integer = 0): Integer;
function GetIconHitTest: TdxSkinFormIcon;
function GetIconHitTestFromHitTest(AHitTest: Integer): TdxSkinFormIcon;
function GetScrollBarHitTest(var AScrollBar: TdxSkinFormScrollBar; var APart: TcxScrollBarPart): Boolean;
function ScreenToClient(const P: TSmallPoint): TPoint; overload;
function ScreenToClient(const P: TPoint): TPoint; overload;
function ScreenToClient(const R: TRect): TRect; overload;
property Active: Boolean read FActive write SetActive;
property BorderBounds[ASide: TcxBorder]: TRect read GetBorderBounds;
property BorderWidths: TRect read FBorderWidths;
property BoundsNoBorders: TRect read FBoundsNoBorders;
property ButtonPressed: Boolean read GetButtonPressed;
property Caption: string read GetCaption;
property CaptionBounds: TRect read FCaptionBounds;
property CaptionFont: TFont read FCaptionFont;
property CaptionTextColor: TColor read GetCaptionTextColor;
property CaptionTextShadowColor: TColor read FCaptionTextShadowColor write FCaptionTextShadowColor;
property ClientRect: TRect read GetClientRect;
property ClientRectOnClient: TRect read GetClientRectOnClient;
property Controller: TdxSkinFormController read FController;
property ExStyle: Integer read GetExStyle;
property Handle: HWND read GetHandle;
property HasBorder: Boolean read GetHasBorder;
property HasCaption: Boolean read GetHasCaption;
property HasMenu: Boolean read GetHasMenu;
property IconBounds[AIcon: TdxSkinFormIcon]: TRect read GetIconBounds;
property IconPressed: TdxSkinFormIcon read FIconPressed write FIconPressed;
property Icons: TdxSkinFormIcons read FIcons;
property IconState[AIcon: TdxSkinFormIcon]: TdxSkinElementState read GetIconState;
property IsAlphaBlendUsed: Boolean read GetIsAlphaBlendUsed;
property IsDialog: Boolean read GetIsDialog;
property IsIconic: Boolean read GetIsIconic;
property IsMDIClient: Boolean read FIsMDIClient;
property IsSizebox: Boolean read GetIsSizeBox;
property IsZoomed: Boolean read GetIsZoomed;
property MenuBounds: TRect read FMenuBounds;
property NativeBorderWidth: Boolean read GetNativeBorderWidth;
property NeedCheckNonClientSize: Boolean read GetNeedCheckNonClientSize;
property Painter: TcxCustomLookAndFeelPainterClass read FPainter;
property PainterInfo: TdxSkinLookAndFeelPainterInfo read FPainterInfo;
property ScrollAreaBounds[AItem: TdxScrollAreaElement]: TRect read GetScrollAreaBounds;
property ScrollAreaElements: TdxScrollAreaElements read FScrollAreaElements;
property ScrollBarInfo[AScrollBar: TdxSkinFormScrollBar]: TScrollBarInfo read GetScrollBarInfo;
property ScrollBarPartBounds[AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart]: TRect read GetScrollBarPartBounds;
property ScrollBarPartState[AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart]: TcxButtonState read GetScrollBarPartState;
property SimpleForm: Boolean read FIsSimpleForm;
property SizeArea[ASide: TcxBorder]: TRect read GetSizeArea;
property SizeCorners[ACorner: TdxSkinFormCorner]: TRect read GetSizeCorners;
property SizeFrame: TSize read FSizeFrame;
property SkinBorderWidth[ASide: TcxBorder]: Integer read GetSkinBorderWidth;
property Style: Integer read GetStyle;
property SysMenuIcon: HICON read FSysMenuIcon;
property SystemSizeFrame: TSize read GetSystemSizeFrame;
property ThemeActive: Boolean read GetThemeActive;
property ToolWindow: Boolean read GetToolWindow;
property TrackedScrollBar: TdxScrollAreaElement read FTrackedScrollBar write FTrackedScrollBar;
property TrackIcon: TdxSkinFormIcon read FTrackIcon write FTrackIcon;
property UpdateRgn: HRGN read FUpdateRgn write SetUpdateRgn;
property WindowBounds: TRect read FWindowBounds;
property WindowRect: TRect read GetWindowRect;
property WindowRgn: HRGN read FWindowRgn write SetWindowRgn;
end;
{ TdxSkinFormPainter }
TdxSkinFormPainter = class
private
FBaseCanvas: TCanvas;
FBordersCache: array[TcxBorder] of TdxSkinElementCache;
FCanvas: TcxCanvas;
FDC: HDC;
FIconsCache: array[TdxSkinFormIcon] of TdxSkinElementCache;
FNeedRelease: Boolean;
FPainter: TcxCustomLookAndFeelPainterClass;
FPainterInfo: TdxSkinLookAndFeelPainterInfo;
FViewInfo: TdxSkinFormNonClientAreaInfo;
function GetActive: Boolean;
function GetIconElement(AIcon: TdxSkinFormIcon): TdxSkinElement;
function GetIsBordersThin: Boolean;
protected
procedure CreateCacheInfos;
procedure DrawBackground(DC: HDC; const R: TRect); virtual;
procedure DrawScrollAreaElements(DC: HDC); virtual;
procedure DrawScrollBar(DC: HDC;
AScrollBar: TdxSkinFormScrollBar; const R: TRect); virtual;
procedure DrawSizeGrip(DC: HDC; const R: TRect);
procedure DrawWindowCaption(DC: HDC;
const R: TRect; AElement: TdxSkinElement); virtual;
procedure DrawWindowIcon(DC: HDC; const R: TRect;
AIcon: TdxSkinFormIcon; AElement: TdxSkinElement); virtual;
procedure FreeCacheInfos;
procedure InternalDrawBorder(const R: TRect; ASide: TcxBorder;
AFillBackground: Boolean);
procedure InternalDrawBorders;
procedure InternalDrawCaption(const R: TRect; AElement: TdxSkinElement);
procedure InternalDrawThinBorders;
public
constructor Create(AViewInfo: TdxSkinFormNonClientAreaInfo); virtual;
destructor Destroy; override;
procedure BeginPaint(ADestDC: HDC = 0);
procedure DrawWindowBackground; virtual;
procedure DrawWindowBorder; virtual;
procedure EndPaint;
function IsRectVisible(const R: TRect): Boolean;
function SelectDC(DC: HDC): Integer;
property Active: Boolean read GetActive;
property Canvas: TcxCanvas read FCanvas;
property IconElements[AIcon: TdxSkinFormIcon]: TdxSkinElement read GetIconElement;
property IsBordersThin: Boolean read GetIsBordersThin;
property Painter: TcxCustomLookAndFeelPainterClass read FPainter;
property PainterInfo: TdxSkinLookAndFeelPainterInfo read FPainterInfo;
property ViewInfo: TdxSkinFormNonClientAreaInfo read FViewInfo;
end;
{ TdxSkinCustomControlViewInfo }
TdxSkinCustomControlViewInfo = class
private
FController: TdxSkinWinController;
function GetClientRect: TRect;
function GetIsEnabled: Boolean;
function GetIsFocused: Boolean;
function GetIsMouseAtControl: Boolean;
public
constructor Create(AController: TdxSkinWinController); virtual;
property ClientRect: TRect read GetClientRect;
property Controller: TdxSkinWinController read FController;
property IsEnabled: Boolean read GetIsEnabled;
property IsFocused: Boolean read GetIsFocused;
property IsMouseAtControl: Boolean read GetIsMouseAtControl;
end;
TdxSkinCustomControlViewInfoClass = class of TdxSkinCustomControlViewInfo;
{ TdxSkinButtonViewInfo }
TdxSkinButtonViewInfo = class(TdxSkinCustomControlViewInfo)
private
FCaption: string;
FPressed: Boolean;
FState: TcxButtonState;
procedure SetState(AState: TcxButtonState);
protected
procedure UpdateEnabledState;
public
constructor Create(AController: TdxSkinWinController); override;
property Caption: string read FCaption;
procedure MouseClickEvent(ADown: Boolean); virtual;
procedure MouseHoverEvent(AEnter: Boolean); virtual;
property Pressed: Boolean read FPressed;
property State: TcxButtonState read FState write SetState;
end;
{ TdxSkinCustomPainter }
TdxSkinCustomControlPainter = class(TObject)
private
FCanvas: TCanvas;
FcxCanvas: TcxCanvas;
FDC: HDC;
FNeedRelease: Boolean;
FViewInfo: TdxSkinCustomControlViewInfo;
function GetController: TdxSkinWinController;
function GetPainter: TcxCustomLookAndFeelPainterClass;
protected
procedure BeginPaint(DC: HDC = 0);
procedure EndPaint;
property NeedRelease: Boolean read FNeedRelease;
public
constructor Create(AViewInfo: TdxSkinCustomControlViewInfo);
destructor Destroy; override;
procedure DrawBackground;
procedure DrawButton(const ACaption: string; const R: TRect; AState: TcxButtonState);
procedure DrawFocus(const R: TRect);
property Canvas: TcxCanvas read FcxCanvas;
property Controller: TdxSkinWinController read GetController;
property Painter: TcxCustomLookAndFeelPainterClass read GetPainter;
property ViewInfo: TdxSkinCustomControlViewInfo read FViewInfo;
end;
{ TdxSkinCustomController }
TdxSkinCustomController = class(TdxSkinWinController)
private
FPainter: TdxSkinCustomControlPainter;
FViewInfo: TdxSkinCustomControlViewInfo;
protected
class function GetViewInfoClass: TdxSkinCustomControlViewInfoClass; virtual;
function GetMaster(AHandle: HWND): TdxSkinWinController; override;
procedure InitializePainter; override;
procedure WndProc(var AMessage: TMessage); override;
// Messages
function WMEraseBk(var AMessage: TWMEraseBkgnd): Boolean; virtual;
function WMPaint(var AMessage: TWMPaint): Boolean; virtual;
public
constructor Create(AHandle: HWND); override;
destructor Destroy; override;
procedure DrawBackground(DC: HDC = 0);
procedure DrawContent(DC: HDC = 0); virtual;
property Painter: TdxSkinCustomControlPainter read FPainter;
property ViewInfo: TdxSkinCustomControlViewInfo read FViewInfo;
end;
{ TdxSkinButtonController }
TdxSkinButtonController = class(TdxSkinCustomController)
protected
function GetViewInfo: TdxSkinButtonViewInfo;
class function GetViewInfoClass: TdxSkinCustomControlViewInfoClass; override;
procedure MouseLeave; override;
procedure WndProc(var AMessage: TMessage); override;
public
procedure DrawContent(DC: HDC = 0); override;
property ViewInfo: TdxSkinButtonViewInfo read GetViewInfo;
end;
{ TdxSkinPanelController }
TdxSkinPanelController = class(TdxSkinCustomController)
private
FPainting: Boolean;
protected
function WMEraseBk(var AMessage: TWMEraseBkgnd): Boolean; override;
function WMPaint(var AMessage: TWMPaint): Boolean; override;
procedure InternalDrawBackground(APanel: TCustomPanel; const R: TRect);
procedure WndProc(var AMessage: TMessage); override;
public
procedure DrawContent(DC: HDC = 0); override;
end;
{ TdxSkinFrameController }
TdxSkinFrameController = class(TdxSkinCustomController)
protected
function WMPrintClient(var AMessage: TWMPrintClient): Boolean;
procedure WndProc(var AMessage: TMessage); override;
public
procedure DrawContent(DC: HDC = 0); override;
end;
var
dxSkinGetControllerClassForWindowProc: TdxSkinGetControllerClassForWindowProc;
function dxSkinGetControllerClassForWindow(AWnd: HWND): TdxSkinWinControllerClass;
implementation
const
SC_TITLEDBLCLICK = 61490;
{$IFNDEF DELPHI7}
ICON_SMALL2 = 2;
WM_NCMOUSELEAVE = $02A2;
WM_NCMOUSEHOVER = $02A0;
{$ENDIF}
WM_NCUAHDRAWCAPTION = $00AE;
WM_NCUAHDRAWFRAME = $00AF;
WM_SYNCPAINT = $0088;
// hittests
CornerHitTests: array[TdxSkinFormCorner] of DWORD =
(HTTOPLEFT, HTTOPRIGHT, HTBOTTOMLEFT, HTBOTTOMRIGHT);
ResizeHitTests: array[TcxBorder] of DWORD =
(HTLEFT, HTTOP, HTRIGHT, HTBOTTOM);
IconsHitTest: array[TdxSkinFormIcon] of DWORD =
(HTSYSMENU, HTHELP, HTMINBUTTON, HTMAXBUTTON, HTMAXBUTTON, HTCLOSE);
IconCommand: array[TdxSkinFormIcon] of Integer =
(SC_DEFAULT, SC_CONTEXTHELP, SC_MINIMIZE, SC_MAXIMIZE, SC_RESTORE, SC_CLOSE);
sdxMDICaptionFormat = '%s - [%s]';
const
CaptionFlags = DT_VCENTER or DT_SINGLELINE or DT_EDITCONTROL or DT_END_ELLIPSIS;
FrameStates: array[Boolean] of TdxSkinElementState = (esActiveDisabled, esActive);
type
{ TdxSkinWinControllerHelper }
TdxSkinWinControllerHelper = class(TObject)
private
FHandle: HWND;
protected
procedure WndProc(var AMsg: TMessage);
public
constructor Create;
destructor Destroy; override;
property Handle: HWND read FHandle;
end;
var
FormControllers: TcxObjectList;
SkinControllersList: TList;
SkinHelper: TdxSkinWinControllerHelper;
WndProcHookHandle: HHOOK;
type
TCustomFormAccess = class(TCustomForm);
TCustomFrameAccess = class(TCustomFrame);
TCustomLabelAccess = class(TCustomLabel);
TCustomPanelAccess = class(TCustomPanel);
TcxLookAndFeelAccess = class(TcxLookAndFeel);
function GetControllerByControl(AControl: TWinControl): TdxSkinWinController;
var
I: Integer;
begin
Result := nil;
if AControl = nil then Exit;
for I := 0 to FormControllers.Count - 1 do
if TdxSkinWinController(FormControllers.Items[I]).WinControl = AControl then
begin
Result := TdxSkinWinController(FormControllers.Items[I]);
Break;
end;
end;
function GetControllerByHandle(AHandle: HWND): TdxSkinWinController;
var
I: Integer;
begin
Result := nil;
for I := 0 to FormControllers.Count - 1 do
if TdxSkinWinController(FormControllers.Items[I]).Handle = AHandle then
begin
Result := TdxSkinWinController(FormControllers.Items[I]);
Break;
end;
end;
function GetWindowCaption(AWnd: HWND): string;
var
L: Integer;
begin
L := SendMessage(AWnd, WM_GETTEXTLENGTH, 0, 0);
SetLength(Result, L);
if L > 0 then
SendMessage(AWnd, WM_GETTEXT, L + 1, Integer(@Result[1]));
end;
function GetWindowClass(AWnd: HWND): string;
var
AClassName: array[Byte] of Char;
begin
if GetClassName(AWnd, @AClassName[0], 256) > 0 then
Result := AClassName
else
Result := '';
end;
procedure RefreshController(AController: TdxSkinFormController);
var
AIndex: Integer;
ASkinController: TdxSkinController;
ASkinName: string;
AUseSkin: Boolean;
begin
with AController do
for AIndex := SkinControllersList.Count - 1 downto 0 do
begin
ASkinController := TdxSkinController(SkinControllersList[AIndex]);
if (csDestroying in ASkinController.ComponentState) then
Continue;
if FLookAndFeelPainter = nil then
FLookAndFeelPainter := ASkinController.DoSkinForm(Form)
else
begin
AUseSkin := SendMessage(Form.Handle, dxWMGetSkinnedMessage, 0, 0) <> 1;
if AUseSkin then
begin
AUseSkin := GetSkinName(ASkinName);
FLookAndFeelPainter := ASkinController.DoSkinFormEx(Form, ASkinName, AUseSkin);
end
else
FLookAndFeelPainter := nil;
end;
end;
end;
procedure RefreshControllers;
var
AIndex: Integer;
begin
for AIndex := 0 to FormControllers.Count - 1 do
with TdxSkinWinController(FormControllers[AIndex]) do
begin
FLookAndFeelPainter := nil;
if IsMDIClient then
Continue;
if FormControllers[AIndex] is TdxSkinFormController then
RefreshController(TdxSkinFormController(FormControllers[AIndex]));
end;
for AIndex := 0 to FormControllers.Count - 1 do
TdxSkinWinController(FormControllers[AIndex]).Update;
end;
{ TdxSkinWinController }
constructor TdxSkinWinController.Create(AHandle: HWND);
begin
FProcInstance := Classes.MakeObjectInstance(WndProc);
Handle := AHandle;
end;
destructor TdxSkinWinController.Destroy;
begin
EndMouseTracking(Self);
Handle := 0;
{$IFDEF DELPHI6}Classes.{$ENDIF}FreeObjectInstance(FProcInstance);
inherited Destroy;
end;
class procedure TdxSkinWinController.InitializeEngine(AHandle: HWND);
var
ANewController: TdxSkinWinController;
begin
ANewController := GetControllerByHandle(AHandle);
if ANewController = nil then
begin
ANewController := GetControllerByControl(FindControl(AHandle));
if ANewController = nil then
begin
ANewController := Self.Create(AHandle);
ANewController.FMaster := ANewController.GetMaster(AHandle);
FormControllers.Add(ANewController);
end
else
ANewController.Handle := AHandle;
ANewController.InitializePainter;
ANewController.Update;
end;
end;
class procedure TdxSkinWinController.FinalizeEngine(AHandle: HWND);
var
AController: TdxSkinWinController;
begin
AController := GetControllerByHandle(AHandle);
if Assigned(AController) then
begin
FormControllers.Remove(AController);
AController.Free;
end;
end;
class function TdxSkinWinController.IsMDIChildWindow(AHandle: HWND): Boolean;
var
AControl: TWinControl;
begin
AControl := FindControl(AHandle);
Result := (AControl is TCustomForm) and
(TCustomFormAccess(AControl).FormStyle = fsMDIChild);
end;
class function TdxSkinWinController.IsMDIClientWindow(AHandle: HWND): Boolean;
begin
Result := AnsiSameText(GetWindowClass(AHandle), 'MDICLIENT');
end;
class function TdxSkinWinController.IsSkinActive(AHandle: HWND): Boolean;
var
AController: TdxSkinWinController;
begin
AController := GetControllerByHandle(AHandle);
Result := Assigned(AController) and AController.IsSkinUsed;
end;
class function TdxSkinWinController.IsMessageDlgWindow(AHandle: HWND): Boolean;
begin
Result := AnsiSameText(GetWindowClass(AHandle), 'TMessageForm');
end;
function TdxSkinWinController.GetHasVirtualChilds: Boolean;
var
AControl: TWinControl;
I: Integer;
begin
AControl := WinControl;
Result := False;
if Assigned(AControl) then
for I := 0 to AControl.ControlCount - 1 do
begin
Result := not (AControl.Controls[I] is TWinControl);
if Result then
Break;
end;
end;
function TdxSkinWinController.GetIsHooked: Boolean;
begin
Result := (Handle <> 0) and ((FSavedWndProcPtr <> nil) or Assigned(FSavedWndProc));
end;
function TdxSkinWinController.GetIsMDIClient: Boolean;
begin
Result := Assigned(FMaster);
end;
function TdxSkinWinController.GetLookAndFeelPainter: TdxSkinLookAndFeelPainterClass;
begin
Result := FLookAndFeelPainter;
if Master <> nil then
Result := Master.LookAndFeelPainter;
end;
procedure TdxSkinWinController.SetHandle(AHandle: HWND);
begin
UnHookWndProc;
FHandle := AHandle;
FWinControl := FindControl(Handle);
Update;
end;
function TdxSkinWinController.GetIsSkinUsed: Boolean;
begin
Result := LookAndFeelPainter <> nil;
end;
function TdxSkinWinController.GetMaster(AHandle: HWND): TdxSkinWinController;
begin
Result := nil;
if IsMDIClientWindow(AHandle) then
Result := GetControllerByHandle(GetParent(AHandle));
end;
function TdxSkinWinController.GetUseSkinForControl: Boolean;
var
AControl: TWinControl;
AIndex: Integer;
ASkinController: TdxSkinController;
AUseSkin: Boolean;
begin
AControl := WinControl;
AUseSkin := cxUseSkins and (AControl <> nil);
if Assigned(AControl) then
for AIndex := SkinControllersList.Count - 1 downto 0 do
begin
ASkinController := TdxSkinController(SkinControllersList[AIndex]);
if (csDestroying in ASkinController.ComponentState) then
Continue;
AUseSkin := ASkinController.DoSkinControl(AControl);
if AUseSkin then
Break;
end;
Result := AUseSkin;
end;
procedure TdxSkinWinController.DefWndProc(var AMessage);
begin
if FSavedWndProcPtr <> nil then
with TMessage(AMessage) do
Result := CallWindowProc(FSavedWndProcPtr, Handle, Msg, wParam, lParam)
else
if Assigned(FSavedWndProc) then
FSavedWndProc(TMessage(AMessage));
end;
procedure TdxSkinWinController.HookWndProc;
begin
if Handle = 0 then Exit;
UnHookWndProc;
if WinControl <> nil then
begin
FSavedWndProc := WinControl.WindowProc;
WinControl.WindowProc := WndProc;
end
else
begin
FSavedWndProcPtr := Pointer(GetWindowLong(Handle, GWL_WNDPROC));
SetWindowLong(Handle, GWL_WNDPROC, Integer(FProcInstance));
end;
end;
procedure TdxSkinWinController.InitializePainter;
begin
// nothing todo
end;
procedure TdxSkinWinController.RedrawWindow(AUpdateNow: Boolean);
var
AFlags: Integer;
const
DefaultFlags = RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ALLCHILDREN;
begin
if Handle = 0 then Exit;
AFlags := DefaultFlags;
if AUpdateNow then
AFlags := AFlags or RDW_UPDATENOW;
Windows.RedrawWindow(Handle, nil, 0, AFlags);
end;
procedure TdxSkinWinController.UnHookWndProc;
begin
if IsHooked then
begin
if WinControl <> nil then
WinControl.WindowProc := FSavedWndProc
else
SetWindowLong(Handle, GWL_WNDPROC, Integer(FSavedWndProcPtr));
FSavedWndProcPtr := nil;
FSavedWndProc := nil;
end;
end;
function TdxSkinWinController.GetSkinName(var ASkinName: string): Boolean;
begin
Result := GetExtendedStylePainters.GetNameByPainter(FLookAndFeelPainter, ASkinName);
end;
procedure TdxSkinWinController.Refresh;
const
Flags = SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
SWP_NOZORDER;
begin
if Handle <> 0 then
SetWindowPos(Handle, 0, 0, 0, 0, 0, Flags);
end;
procedure TdxSkinWinController.Update;
begin
HookWndProc;
Refresh;
RedrawWindow(HasVirtualChilds);
end;
procedure TdxSkinWinController.WndProc(var AMessage: TMessage);
begin
DefWndProc(AMessage);
end;
procedure TdxSkinWinController.MouseLeave;
begin
end;
{ TdxSkinController }
constructor TdxSkinController.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if SkinControllersList <> nil then
SkinControllersList.Add(Self);
Changed;
end;
destructor TdxSkinController.Destroy;
begin
Changed;
if SkinControllersList <> nil then
SkinControllersList.Remove(Self);
inherited Destroy;
end;
procedure TdxSkinController.Refresh;
begin
Changed;
end;
class function TdxSkinController.GetFormSkin(AForm: TCustomForm; var ASkinName: string): Boolean;
var
AController: TdxSkinWinController;
begin
AController := GetControllerByHandle(AForm.Handle);
Result := Assigned(AController) and AController.GetSkinName(ASkinName);
end;
procedure TdxSkinController.Changed;
begin
RefreshControllers;
end;
function TdxSkinController.DoSkinControl(AControl: TWinControl): Boolean;
var
AUseSkin: Boolean;
begin
Result := AControl <> nil;
if Result then
begin
AUseSkin := True;
if Assigned(OnSkinControl) then
OnSkinControl(Self, AControl, AUseSkin);
Result := AUseSkin
end
end;
function TdxSkinController.DoSkinForm(
AForm: TCustomForm): TdxSkinLookAndFeelPainterClass;
var
ASkinName: string;
AUseSkin: Boolean;
begin
if (AForm <> nil) and (SendMessage(AForm.Handle, dxWMGetSkinnedMessage, 0, 0) = 1) then
begin
ASkinName := '';
AUseSkin := False;
end
else
begin
ASkinName := SkinName;
AUseSkin := UseSkins;
end;
Result := DoSkinFormEx(AForm, ASkinName, AUseSkin);
end;
function TdxSkinController.DoSkinFormEx(AForm: TCustomForm;
var ASkinName: string; var AUseSkin: Boolean): TdxSkinLookAndFeelPainterClass;
var
APainter: TcxCustomLookAndFeelPainterClass;
begin
Result := nil;
if AForm = nil then Exit;
if Assigned(OnSkinForm) then
OnSkinForm(Self, AForm, ASkinName, AUseSkin);
if AUseSkin and (ASkinName <> '') and GetExtendedStylePainters.GetPainterByName(
ASkinName, APainter) and (APainter.InheritsFrom(TdxSkinLookAndFeelPainter)) then
Result := TdxSkinLookAndFeelPainterClass(APainter);
end;
procedure TdxSkinController.Loaded;
begin
inherited Loaded;
Changed;
end;
procedure TdxSkinController.MasterLookAndFeelChanged(
Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
begin
inherited MasterLookAndFeelChanged(Sender, AChangedValues);
Changed;
end;
procedure TdxSkinController.MasterLookAndFeelDestroying(
Sender: TcxLookAndFeel);
begin
inherited MasterLookAndFeelDestroying(Sender);
Changed;
end;
function TdxSkinController.GetUseSkins: Boolean;
begin
Result := cxUseSkins;
end;
procedure TdxSkinController.SetUseSkins(Value: Boolean);
begin
if Value <> UseSkins then
begin
cxLookAndFeels.cxUseSkins := Value;
TcxLookAndFeelAccess(RootLookAndFeel).Changed([lfvKind..lfvSkinName]);
Changed;
end;
end;
{ TdxSkinFormController }
constructor TdxSkinFormController.Create(AHandle: HWND);
begin
inherited Create(AHandle);
FViewInfo := TdxSkinFormNonClientAreaInfo.Create(Self);
FPainter := TdxSkinFormPainter.Create(FViewInfo);
if IsMessageDlgWindow(AHandle) then
InitializeMessageForm;
end;
destructor TdxSkinFormController.Destroy;
var
I: Integer;
begin
cxClearObjectLinks(Self);
for I := 0 to SkinControllersList.Count - 1 do
with TdxSkinFormController(SkinControllersList[I]) do
if FMaster = Self then FMaster := nil;
FreeAndNil(FPainter);
FreeAndNil(FViewInfo);
inherited Destroy;
end;
procedure TdxSkinFormController.Update;
begin
inherited Update;
if HasRegion and not IsSkinUsed and (Handle <> 0) and (Form <> nil) then
begin
HasRegion := False;
SetWindowRgn(Handle, 0, False);
end;
UpdateMDIClientEdge;
end;
procedure TdxSkinFormController.DrawWindowBackground(DC: HDC);
begin
Painter.BeginPaint(DC);
try
Painter.DrawWindowBackground;
finally
Painter.EndPaint;
end;
end;
procedure TdxSkinFormController.DrawWindowBorder;
begin
Painter.BeginPaint;
try
Painter.DrawWindowBorder;
finally
Painter.EndPaint;
end;
end;
procedure TdxSkinFormController.CalculateViewInfo;
begin
ViewInfo.Calculate(0);
end;
procedure TdxSkinFormController.CheckWindowRgn(AForceRgn: Boolean);
var
R: TRect;
begin
if AForceRgn then
begin
HasRegion := True;
GetWindowRect(Handle, R);
OffsetRect(R, -R.Left, -R.Top);
SetWindowRgn(Handle, CreateRectRgnIndirect(R), True);
end
else
if IsZoomed(Handle) and HasRegion then
begin
HasRegion := False;
LockRedraw;
SetWindowRgn(Handle, 0, False);
UnlockRedraw;
PostMessage(Handle, WM_POSTREDRAW, 0, 0);
end;
end;
procedure TdxSkinFormController.InitializeMessageForm;
var
I: Integer;
AForm: TCustomForm;
begin
AForm := Form;
for I := AForm.ControlCount - 1 downto 0 do
begin
if AForm.Controls[I] is TCustomLabel then
TCustomLabelAccess(AForm.Controls[I]).Transparent := True;
end;
end;
procedure TdxSkinFormController.InitializePainter;
var
ASkinName: string;
AUseSkin: Boolean;
I: Integer;
begin
if Form <> nil then
for I := 0 to SkinControllersList.Count - 1 do
with TdxSkinController(SkinControllersList[I]) do
begin
if I = 0 then
begin
FLookAndFeelPainter := DoSkinForm(Form);
AUseSkin := FLookAndFeelPainter <> nil;
end
else
begin
AUseSkin := GetFormSkin(Form, ASkinName);
FLookAndFeelPainter := DoSkinFormEx(Form, ASkinName, AUseSkin);
end;
if FLookAndFeelPainter <> nil then Break;
end;
end;
function TdxSkinFormController.HandleWindowMessage(
var AMessage: TMessage): Boolean;
const
WindowState: array[Boolean] of Integer = (0, SIZE_MAXIMIZED);
begin
Result := IsSkinUsed;
if not Result then Exit;
CheckWindowRgn(False);
if ForceRedraw then
begin
DrawWindowBorder;
ForceRedraw := False;
end;
case AMessage.Msg of
$3F:
UpdateMDIClientEdge;
WM_DESTROY, WM_MDIDESTROY:
if AMessage.WParam = 0 then
WMDestroy(TWMDestroy(AMessage))
else
DefWndProc(AMessage);
WM_NCCALCSIZE:
WMNCCalcSize(TWMNCCalcSize(AMessage));
WM_NCMOUSEMOVE:
WMNCMouseMove(TWMNCHitMessage(AMessage));
WM_NCACTIVATE:
WMNCActivate(TWMNCActivate(AMessage));
WM_ACTIVATE:
begin
DefWndProc(AMessage);
DrawWindowBorder;
end;
WM_NCUAHDRAWFRAME, WM_NCUAHDRAWCAPTION, WM_SYNCPAINT:
DrawWindowBorder;
WM_NCLBUTTONDOWN, WM_NCLBUTTONDBLCLK:
WMNCButtonDown(TWMNCHitMessage(AMessage));
WM_NCLBUTTONUP:
WMNCLButtonUp(TWMNCHitMessage(AMessage));
WM_NCPAINT:
WMNCPaint(TWMNCPaint(AMessage));
WM_NCHITTEST:
WMNCHitTest(TWMNCHitTest(AMessage));
WM_ERASEBKGND:
WMEraseBkgnd(TWMEraseBkgnd(AMessage));
WM_SIZING:
WMSizing(TWMSize(AMessage));
WM_SIZE:
WMSize(TWMSize(AMessage));
WM_SYSCOMMAND:
WMSysCommand(TWMSysCommand(AMessage));
WM_VSCROLL, WM_HSCROLL:
WMScroll(TWMScroll(AMessage));
WM_THEMECHANGED:
begin
ViewInfo.ThemeActiveAssigned := False;
Result := False;
end;
else
if AMessage.Msg = WM_CHILDCHANGED then
begin
if ViewInfo.UpdateCaptionSufix then
DrawWindowBorder;
end
else
if (dxWMSetSkinnedMessage > 0) and (AMessage.Msg = dxWMSetSkinnedMessage) then
RefreshController(ViewInfo.Controller)
else
if AMessage.Msg = WM_POSTREDRAW then
RedrawWindow(False)
else
if AMessage.Msg = WM_POSTCHECKRGN then
CheckWindowRgn(NeedForceRgnUpdate(WindowState[IsZoomed(Handle)]))
else
Result := False;
end;
end;
procedure TdxSkinFormController.LockRedraw;
begin
Inc(FLockRedrawCount);
if FLockRedrawCount = 1 then
DefWindowProc(Handle, WM_SETREDRAW, 0, 0);
end;
procedure TdxSkinFormController.UpdateMDIClientEdge;
var
AStyle: Integer;
begin
if IsMDIClient then
begin
AStyle := GetWindowLong(Handle, GWL_EXSTYLE);
if AStyle and WS_EX_CLIENTEDGE <> 0 then
AStyle := AStyle and not WS_EX_CLIENTEDGE
else
Exit;
SetWindowLong(Handle, GWL_EXSTYLE, AStyle);
Refresh;
end;
end;
function TdxSkinFormController.RefreshOnMouseEvent(
AForceRefresh: Boolean = False): Boolean;
var
APart: TcxScrollBarPart;
AScrollBar: TdxSkinFormScrollBar;
begin
with ViewInfo do
begin
Result := UpdateCaptionIconStates;
if TrackIcon <> sfiMenu then
BeginMouseTracking(nil, ClientToScreen(IconBounds[TrackIcon]), Self)
else
if GetScrollBarHitTest(AScrollBar, APart) then
begin
Result := not IsMouseTracking(Self);
BeginMouseTracking(nil, ClientToScreen(ScrollBarPartBounds[AScrollBar, APart]), Self)
end
else
begin
Result := Result or IsMouseTracking(Self);
EndMouseTracking(Self);
end;
end;
if Result or AForceRefresh then
Refresh;
end;
procedure TdxSkinFormController.UnlockRedraw;
begin
Dec(FLockRedrawCount);
if FLockRedrawCount = 0 then
DefWindowProc(Handle, WM_SETREDRAW, 1, 0);
end;
procedure TdxSkinFormController.UpdateScrollTrackPos(
AKind: TdxSkinFormScrollBar; APos: Integer);
var
Info: TScrollInfo;
begin
Info.cbSize := SizeOf(TScrollInfo);
Info.fMask := SIF_TRACKPOS;
if FlatSB_GetScrollInfo(Handle, Byte(AKind), Info) then
APos := Info.nTrackPos;
FlatSB_SetScrollPos(Handle, Byte(AKind), APos, False);
end;
procedure TdxSkinFormController.WMDestroy(var Message: TWMDestroy);
begin
FLookAndFeelPainter := nil;
DefWndProc(Message);
UnHookWndProc;
end;
procedure TdxSkinFormController.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
DrawWindowBackground(Message.DC);
Message.Result := 1;
end;
procedure TdxSkinFormController.WMNCActivate(var Message: TWMNCActivate);
var
AFlags: DWORD;
AMDIChild: TCustomForm;
begin
ViewInfo.Active := Message.Active;
AMDIChild := ViewInfo.GetActiveMDIChild;
if Assigned(AMDIChild) then
AMDIChild.Perform(WM_NCACTIVATE, TMessage(Message).WParam, 0);
if IsMDIChildWindow(Handle) then
begin
AFlags := GetWindowLong(Handle, GWL_STYLE);
SetWindowLong(Handle, GWL_STYLE, AFlags and not WS_VISIBLE);
Message.Result := DefWindowProc(Handle, WM_NCACTIVATE, TMessage(Message).WParam, 0);
SetWindowLong(Handle, GWL_STYLE, AFlags);
end
else
Message.Result := 1;
DrawWindowBorder;
end;
procedure TdxSkinFormController.WMNCButtonDown(var Message: TWMNCHitMessage);
var
ALink: TcxObjectLink;
ALocked: Boolean;
begin
ALink := cxAddObjectLink(Self);
try
ForceRedraw := True;
ViewInfo.UpdateIconPressed;
ViewInfo.UpdateCaptionIconStates;
ALocked := Message.HitTest in [HTHSCROLL, HTVSCROLL];
if ALocked then
LockRedraw;
if ViewInfo.GetIconHitTest in [sfiMenu, sfiHelp] then
DefWndProc(Message);
if Assigned(ALink.Ref) then
begin
if ALocked then
UnlockRedraw;
RefreshOnMouseEvent(True);
DrawWindowBorder;
end;
finally
cxRemoveObjectLink(ALink);
end;
Message.Result := 0;
end;
procedure TdxSkinFormController.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R, Margins: TRect;
begin
R := Message.CalcSize_Params^.rgrc[0];
DefWndProc(Message);
CalculateViewInfo;
if Message.CalcValidRects and ViewInfo.NeedCheckNonClientSize then
begin
Margins := ViewInfo.BorderWidths;
if saeVertScroll in ViewInfo.ScrollAreaElements then
Inc(Margins.Right, GetSystemMetrics(SM_CXVSCROLL));
if saeHorzScroll in ViewInfo.ScrollAreaElements then
Inc(Margins.Bottom, GetSystemMetrics(SM_CYHSCROLL));
with ViewInfo do
if IsZoomed and IsSizebox then
begin
Inc(Margins.Left, SystemSizeFrame.cx - SizeFrame.cx);
Inc(Margins.Right, SystemSizeFrame.cx - SizeFrame.cx);
Inc(Margins.Top, SystemSizeFrame.cy - SizeFrame.cy);
if saeVertScroll in ScrollAreaElements then
Inc(Margins.Right, SizeFrame.cx - BorderWidths.Right);
if saeHorzScroll in ScrollAreaElements then
Inc(Margins.Bottom, SizeFrame.cy - BorderWidths.Bottom);
end;
Message.CalcSize_Params^.rgrc[0] := cxRectContent(R, Margins);
end;
end;
procedure TdxSkinFormController.WMNCHitTest(var Message: TWMNCHitTest);
begin
with Message do
Result := ViewInfo.GetHitTest(SmallPointToPoint(Pos), Result);
if (Message.Result = HTNOWHERE) or (Message.Result = HTSYSMENU) then
DefWndProc(Message);
end;
procedure TdxSkinFormController.WMNCLButtonUp(var Message: TWMNCHitMessage);
var
ADefaultCall: Boolean;
ADownIcon: TdxSkinFormIcon;
begin
ADownIcon := ViewInfo.UpdateIconPressed(True);
ADefaultCall := ADownIcon in [sfiMenu, sfiHelp];
if ADefaultCall then
DefWndProc(Message);
RefreshOnMouseEvent(True);
if not ADefaultCall then
SendMessage(Handle, WM_SYSCOMMAND, IconCommand[ADownIcon], 0);
end;
procedure TdxSkinFormController.WMNCMouseMove(var Message: TWMNCHitMessage);
begin
if not RefreshOnMouseEvent then
begin
Message.HitTest := 0;
DefWndProc(Message);
DrawWindowBorder;
end;
end;
procedure TdxSkinFormController.WMNCPaint(var Message: TWMNCPaint);
var
AFrameRgn, AWindowRgn: HRgn;
begin
CalculateViewInfo;
DrawWindowBorder;
AFrameRgn := ViewInfo.CreateDrawRgn;
AWindowRgn := CreateRectRgnIndirect(ViewInfo.WindowRect);
CombineRgn(AWindowRgn, AWindowRgn, AFrameRgn, RGN_XOR);
DeleteObject(AFrameRgn);
if ViewInfo.HasMenu or IsMDIClientWindow(Handle) then
begin
if Message.RGN <> 1 then
begin
CombineRgn(AWindowRgn, AWindowRgn, Message.RGN, RGN_AND);
DeleteObject(Message.RGN);
end;
Message.RGN := AWindowRgn;
DefWndProc(Message);
end;
DeleteObject(AWindowRgn);
Message.RGN := 1;
Message.Result := 0;
end;
procedure TdxSkinFormController.WMScroll(var Message: TWMScroll);
begin
ViewInfo.TrackedScrollBar := TdxScrollAreaElement(Message.Msg - WM_HSCROLL);
if TWMScroll(Message).ScrollCode = SB_THUMBTRACK then
UpdateScrollTrackPos(ViewInfo.TrackedScrollBar, TWMScroll(Message).Pos)
else
ViewInfo.TrackedScrollBar := saeSizeGrip;
LockRedraw;
DefWndProc(Message);
UnlockRedraw;
UnlockRedraw;
try
RedrawWindow(True);
finally
LockRedraw;
end;
end;
procedure TdxSkinFormController.WMSetText(var Message: TWMSetText);
begin
DefWndProc(Message);
if IsWindowUnicode(Handle) then
ViewInfo.UpdateCaption(PWideChar(Message.Text))
else
ViewInfo.UpdateCaption(Message.Text);
Refresh;
end;
procedure TdxSkinFormController.WMSizing(var Message: TWMSize);
begin
FSizingInProcess := True;
DefWndProc(Message);
end;
procedure TdxSkinFormController.WMSize(var Message: TWMSize);
begin
FSizingInProcess := False;
DefWndProc(Message);
CheckWindowRgn(NeedForceRgnUpdate(Message.SizeType));
end;
procedure TdxSkinFormController.WMSysCommand(var Message: TWMSysCommand);
var
ALink: TcxObjectLink;
begin
ALink := cxAddObjectLink(Self);
try
DefWndProc(Message);
if Assigned(ALink.Ref) then
DrawWindowBorder;
finally
cxRemoveObjectLink(ALink);
end;
end;
procedure TdxSkinFormController.MouseLeave;
begin
UnlockRedraw;
RefreshOnMouseEvent(True);
UpdateWindow(Handle);
LockRedraw;
end;
function TdxSkinFormController.GetForm: TCustomForm;
var
AControl: TWinControl;
begin
AControl := FindControl(Handle);
if AControl is TCustomForm then
Result := AControl as TCustomForm
else
Result := nil;
end;
function TdxSkinFormController.GetIsMDIMain: Boolean;
begin
Result := (Form <> nil) and (TCustomFormAccess(Form).FormStyle = fsMDIForm);
end;
function TdxSkinFormController.GetIsSkinUsed: Boolean;
begin
Result := inherited GetIsSkinUsed and (ViewInfo <> nil);
end;
function TdxSkinFormController.NeedForceRgnUpdate(ASizeType: Integer): Boolean;
var
AForm: TCustomForm;
begin
AForm := Form;
if Assigned(AForm) then
begin
Result := AForm.BorderStyle <> bsNone;
if Result then
Result := (ASizeType <> SIZE_MAXIMIZED) or Assigned(AForm.Parent)
end
else
Result := ASizeType <> SIZE_MAXIMIZED;
end;
procedure TdxSkinFormController.WndProc(var AMessage: TMessage);
begin
if AMessage.Msg = WM_SETTEXT then
WMSetText(TWMSetText(AMessage))
else
if not (IsSkinUsed and HandleWindowMessage(AMessage)) then
DefWndProc(AMessage);
end;
{ TdxSkinFormNonClientAreaInfo }
constructor TdxSkinFormNonClientAreaInfo.Create(AController: TdxSkinFormController);
begin
FController := AController;
FCaptionFont := TFont.Create;
FTrackedScrollBar := saeSizeGrip;
FCaption := GetWindowCaption(Handle);
FActive := True;
end;
destructor TdxSkinFormNonClientAreaInfo.Destroy;
begin
UpdateRgn := 0;
WindowRgn := 0;
FreeAndNil(FCaptionFont);
inherited Destroy;
end;
procedure TdxSkinFormNonClientAreaInfo.Calculate(
AUpdateRgn: HRGN);
begin
FHasMenu := IsMenu(GetMenu(Handle)) and not TdxSkinFormController.IsMDIChildWindow(Handle);
FIsMDIClient := TdxSkinFormController.IsMDIClientWindow(Handle);
FIsSimpleForm := (Controller.Form <> nil) and not
(TCustomFormAccess(Controller.Form).FormStyle in [fsMDIChild, fsMDIForm]);
FPainter := Controller.LookAndFeelPainter;
GetExtendedStylePainters.GetPainterData(Painter, FPainterInfo);
WindowInfo.cbSize := SizeOf(WindowInfo);
GetWindowInfo(Handle, WindowInfo);
if NativeBorderWidth then
FSizeFrame := GetSystemSizeFrame
else
FSizeFrame := Size(4, 4);
FWindowBounds := cxRectOffset(WindowRect, -WindowRect.Left, -WindowRect.Top);
FBoundsNOBorders := cxRectOffset(ClientRect, cxPointInvert(WindowRect.TopLeft));
WindowRgn := CreateRectRgnIndirect(WindowBounds);
FIcons := GetIcons;
FSysMenuIcon := GetSysMenuIcon;
CalculateFontInfo;
CalculateBorderWidths;
FMenuBounds := cxRectSetBottom(FBoundsNOBorders, FBoundsNOBorders.Top,
FBoundsNOBorders.Top - BorderWidths.Top);
CalculateBordersInfo;
CalculateCaptionIconsInfo;
CalculateScrollArea;
end;
function TdxSkinFormNonClientAreaInfo.ClientToScreen(const P: TPoint): TPoint;
begin
Result := cxPointOffset(P, WindowRect.TopLeft);
end;
function TdxSkinFormNonClientAreaInfo.ClientToScreen(const R: TRect): TRect;
begin
Result := cxRectOffset(R, WindowRect.TopLeft);
end;
function TdxSkinFormNonClientAreaInfo.CreateDrawRgn: HRGN;
var
ARgn: HRgn;
ASide: TcxBorder;
AItem: TdxScrollAreaElement;
begin
Result := CreateRectRgnIndirect(cxNullRect);
for ASide := bLeft to bBottom do
begin
if cxRectIsEmpty(BorderBounds[ASide]) then Continue;
ARgn := CreateRectRgnIndirect(
ClientToScreen(BorderBounds[ASide]));
CombineRgn(Result, Result, ARgn, RGN_OR);
DeleteObject(ARgn);
end;
if HasMenu then
begin
ARgn := CreateRectRgnIndirect(ClientToScreen(
cxRectSetBottom(MenuBounds, MenuBounds.Bottom, 1)));
CombineRgn(Result, Result, ARgn, RGN_OR);
DeleteObject(ARgn);
end;
for AItem := saeHorzScroll to saeSizeGrip do
if AItem in FScrollAreaElements then
begin
ARgn := CreateRectRgnIndirect(ClientToScreen(ScrollAreaBounds[AItem]));
CombineRgn(Result, Result, ARgn, RGN_OR);
DeleteObject(ARgn);
end;
end;
function TdxSkinFormNonClientAreaInfo.GetHitTest(AHitPoint: TPoint; AHitTest: Integer = 0): Integer;
var
ASide: TcxBorder;
AIcon: TdxSkinFormIcon;
ACorner: TdxSkinFormCorner;
begin
Result := AHitTest;
AHitPoint := ScreenToClient(AHitPoint);
if IsSizebox and not IsZoomed then
begin
for ACorner := sfcLeftTop to sfcRightBottom do
if (Result = HTNOWHERE) and PtInRect(SizeCorners[ACorner], AHitPoint) then
Result := CornerHitTests[ACorner];
for ASide := bLeft to bBottom do
if (Result = HTNOWHERE) and PtInRect(SizeArea[ASide], AHitPoint) then
Result := ResizeHitTests[ASide];
end;
if (Result = HTNOWHERE) and PtInRect(BorderBounds[bTop], AHitPoint) then
begin
Result := HTCAPTION;
// correct 'restore' hittest
IconsHitTest[sfiRestore] := HTMAXBUTTON;
if IsIconic then
IconsHitTest[sfiRestore] := HTMINBUTTON;
//
for AIcon := sfiMenu to sfiClose do
begin
if PtInRect(IconBounds[AIcon], AHitPoint) then
Result := IconsHitTest[AIcon];
end;
end;
end;
function TdxSkinFormNonClientAreaInfo.GetIconHitTest: TdxSkinFormIcon;
begin
Result := GetIconHitTestFromHitTest(GetHitTest(GetMouseCursorPos));
end;
function TdxSkinFormNonClientAreaInfo.GetIconHitTestFromHitTest(
AHitTest: Integer): TdxSkinFormIcon;
begin
Result := sfiMenu;
case AHitTest of
HTHELP:
Result := sfiHelp;
HTMINBUTTON:
if IsIconic then
Result := sfiRestore
else
Result := sfiMinimize;
HTMAXBUTTON:
if IsZoomed then
Result := sfiRestore
else
Result := sfiMaximize;
HTCLOSE:
Result := sfiClose;
end;
end;
function TdxSkinFormNonClientAreaInfo.GetScrollBarHitTest(
var AScrollBar: TdxSkinFormScrollBar; var APart: TcxScrollBarPart): Boolean;
var
APoint: TPoint;
AItem: TdxSkinFormScrollBar;
APartItem: TcxScrollBarPart;
begin
Result := False;
APoint := ScreenToClient(GetMouseCursorPos);
for AItem := saeHorzScroll to saeVertScroll do
begin
if not (AItem in ScrollAreaElements) or
not PtInRect(ScrollAreaBounds[AItem], APoint) then Continue;
AScrollBar := AItem;
for APartItem := sbpLineUp to sbpPageDown do
begin
Result := (ScrollBarPartState[AItem, APartItem] <> cxbsDefault) and
PtInRect(ScrollBarPartBounds[AItem, APartItem], APoint);
if Result then
begin
APart := APartItem;
Exit;
end;
end;
end;
end;
function TdxSkinFormNonClientAreaInfo.ScreenToClient(const P: TSmallPoint): TPoint;
begin
Result := ScreenToClient(SmallPointToPoint(P));
end;
function TdxSkinFormNonClientAreaInfo.ScreenToClient(const P: TPoint): TPoint;
begin
Result := cxPointOffset(P, cxPointInvert(WindowRect.TopLeft));
end;
function TdxSkinFormNonClientAreaInfo.ScreenToClient(const R: TRect): TRect;
begin
Result := cxRectOffset(R, cxPointInvert(WindowRect.TopLeft));
end;
procedure TdxSkinFormNonClientAreaInfo.UpdateCaption(const ANewText: string);
begin
FCaption := ANewText;
UpdateCaptionSufix;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateBordersInfo;
var
ASide: TcxBorder;
begin
for ASide := bLeft to bBottom do
FBorderBounds[ASide] := GetBorderRect(ASide, WindowBounds, BorderWidths);
if IsZoomed and not NativeBorderWidth and IsSizeBox then
OffsetRect(FBorderBounds[bTop], 0, SystemSizeFrame.cy - SizeFrame.cy);
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateBorderWidths;
const
CaptionMetric: array[Boolean] of Integer = (SM_CYCAPTION, SM_CYSMCAPTION);
begin
FBorderWidths := cxNullRect;
if not NativeBorderWidth and HasBorder then
begin
FBorderWidths := PainterInfo.FormBorderWidths[not ToolWindow];
if ToolWindow then
Inc(FBorderWidths.Top, SizeFrame.cy);
end;
if HasCaption then
if NativeBorderWidth or ToolWindow then
Inc(FBorderWidths.Top, GetSystemMetrics(CaptionMetric[ToolWindow]))
else
Inc(FBorderWidths.Top, SizeFrame.cy + 2 * GetSystemMetrics(SM_CYEDGE) +
Max(GetSystemMetrics(SM_CYSMICON), cxScreenCanvas.FontHeight(FCaptionFont)));
if NativeBorderWidth and HasBorder then
begin
Inc(FBorderWidths.Left, WindowInfo.cxWindowBorders);
Inc(FBorderWidths.Right, WindowInfo.cxWindowBorders);
Inc(FBorderWidths.Top, WindowInfo.cyWindowBorders);
Inc(FBorderWidths.Bottom, WindowInfo.cyWindowBorders);
end;
end;
function TdxSkinFormNonClientAreaInfo.GetCaptionButtonRect(
const ACaptionRect: TRect): TRect;
begin
Result := BorderBounds[bTop];
with GetCaptionContentOffset do
begin
if NativeBorderWidth and IsSizeBox then
Inc(Result.Top, SystemSizeFrame.cy)
else
Inc(Result.Top, Top);
Dec(Result.Bottom, Bottom);
Result.Right := ACaptionRect.Right;
Result.Left := Result.Right - (Result.Bottom - Result.Top);
end;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateCaptionIconsInfo;
const
RestoreAndMaximize = [sfiRestore, sfiMaximize];
var
AIcon: TdxSkinFormIcon;
AIconSize: Integer;
ARealIcons: TdxSkinFormIcons;
R: TRect;
begin
FillChar(FIconBounds, SizeOf(FIconBounds), 0);
AIconSize := GetCaptionIconSize;
FCaptionBounds := GetCaptionBounds;
R := FCaptionBounds;
R.Top := (R.Top + R.Bottom - AIconSize) div 2;
R.Bottom := R.Top + AIconSize;
if sfiMenu in Icons then
begin
FIconBounds[sfiMenu] := cxRectCenter(cxRectSetWidth(R, AIconSize),
AIconSize, AIconSize);
FCaptionBounds.Left := FIconBounds[sfiMenu].Right + dxSkinFormTextOffset;
end
else
FCaptionBounds.Left := cxTextOffset + dxSkinFormTextOffset;
R := GetCaptionButtonRect(FCaptionBounds);
ARealIcons := Icons;
if RestoreAndMaximize * Icons = RestoreAndMaximize then
ARealIcons := ARealIcons - [sfiRestore] + [sfiMinimize];
for AIcon := sfiClose downto sfiHelp do
begin
if not (AIcon in ARealIcons) then Continue;
FIconBounds[AIcon] := R;
OffsetRect(R, -(R.Right - R.Left + dxSkinIconSpacing), 0);
FCaptionBounds.Right := FIconBounds[AIcon].Left - dxSkinFormTextOffset;
end;
if RestoreAndMaximize * Icons = RestoreAndMaximize then
FIconBounds[sfiRestore] := FIconBounds[sfiMinimize];
UpdateCaptionIconStates;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateFontInfo;
var
AMetrics: TNonClientMetrics;
begin
AMetrics.cbSize := SizeOf(AMetrics);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @AMetrics, 0);
if ToolWindow then
FCaptionFont.Handle := CreateFontIndirect(AMetrics.lfSmCaptionFont)
else
begin
FCaptionFont.Handle := CreateFontIndirect(AMetrics.lfCaptionFont);
if PainterInfo <> nil then
FCaptionFont.Size := FCaptionFont.Size + (PainterInfo.FormCaptionDelta - 1);
end;
FCaptionTextShadowColor := clBtnShadow;
FCaptionTextColor[True] := GetSysColor(COLOR_CAPTIONTEXT);
FCaptionTextColor[False] := GetSysColor(COLOR_INACTIVECAPTIONTEXT);
if PainterInfo <> nil then
begin
FCaptionTextColor[True] := PainterInfo.FormFrames[True, bTop].TextColor;
if PainterInfo.FormInactiveColor <> nil then
FCaptionTextColor[False] := PainterInfo.FormInactiveColor.Value;
if PainterInfo.FormTextShadowColor <> nil then
FCaptionTextShadowColor := PainterInfo.FormTextShadowColor.Value;
end;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateScrollArea;
const
BothScrollBars = [saeHorzScroll, saeVertScroll];
begin
FScrollAreaElements := [];
FillChar(FScrollAreaBounds, SizeOf(FScrollAreaBounds), 0);
FillChar(FScrollBarsInfo[saeHorzScroll], SizeOf(TScrollBarInfo), 0);
FScrollBarsInfo[saeHorzScroll].cbSize := SizeOf(TScrollBarInfo);
FScrollBarsInfo[saeVertScroll] := FScrollBarsInfo[saeHorzScroll];
Windows.GetScrollBarInfo(Handle, Integer(OBJID_VSCROLL), FScrollBarsInfo[saeVertScroll]);
Windows.GetScrollBarInfo(Handle, Integer(OBJID_HSCROLL), FScrollBarsInfo[saeHorzScroll]);
if Style and WS_HSCROLL = WS_HSCROLL then
begin
Include(FScrollAreaElements, saeHorzScroll);
FScrollAreaBounds[saeHorzScroll] := cxRectSetTop(BoundsNOBorders,
BoundsNOBorders.Bottom, GetSystemMetrics(SM_CYHSCROLL));
end;
if Style and WS_VSCROLL = WS_VSCROLL then
begin
Include(FScrollAreaElements, saeVertScroll);
FScrollAreaBounds[saeVertScroll] := cxRectSetLeft(BoundsNOBorders,
BoundsNOBorders.Right, GetSystemMetrics(SM_CXVSCROLL));
end;
if BothScrollBars * ScrollAreaElements = BothScrollBars then
begin
Include(FScrollAreaElements, saeSizeGrip);
FScrollAreaBounds[saeHorzScroll].Right := FScrollAreaBounds[saeVertScroll].Left;
FScrollAreaBounds[saeVertScroll].Bottom := FScrollAreaBounds[saeHorzScroll].Top;
FScrollAreaBounds[saeSizeGrip] := cxRect(BoundsNOBorders.BottomRight,
Point(FScrollAreaBounds[saeVertScroll].Right, FScrollAreaBounds[saeHorzScroll].Bottom));
end;
CalculateScrollBarPartsInfo;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateScrollBarPartInfo(
AScrollBar: TdxSkinFormScrollBar; Pos1, Pos2: Integer; APart: TcxScrollBarPart);
var
P: TPoint;
AState: Integer;
const
Part2StateIndex: array[TcxScrollBarPart] of Integer = (0, 1, 5, 3, 2, 4);
begin
AState := ScrollBarInfo[AScrollBar].rgState[Part2StateIndex[APart]];
FScrollBarPartState[AScrollBar, APart] := cxbsDefault;
if AState and STATE_SYSTEM_INVISIBLE = STATE_SYSTEM_INVISIBLE then Exit;
FScrollBarPartState[AScrollBar, APart] := cxbsNormal;
FScrollBarPartBounds[AScrollBar, APart] := ScrollAreaBounds[AScrollBar];
P := ScreenToClient(GetMouseCursorPos);
if (Pos1 <> Pos2) and (Pos1 <> -1) then
begin
if AScrollBar = saeHorzScroll then
FScrollBarPartBounds[AScrollBar, APart] :=
cxRectSetXPos(FScrollBarPartBounds[AScrollBar, APart], Pos1, Pos2)
else
FScrollBarPartBounds[AScrollBar, APart] :=
cxRectSetYPos(FScrollBarPartBounds[AScrollBar, APart], Pos1, Pos2);
end;
if ((APart = sbpThumbnail) and (AScrollBar = TrackedScrollBar)) or
(AState and STATE_SYSTEM_PRESSED = STATE_SYSTEM_PRESSED) then
FScrollBarPartState[AScrollBar, APart] := cxbsPressed
else
if AState and STATE_SYSTEM_UNAVAILABLE = STATE_SYSTEM_UNAVAILABLE then
FScrollBarPartState[AScrollBar, APart] := cxbsDisabled
else
if (AState and STATE_SYSTEM_HOTTRACKED = STATE_SYSTEM_HOTTRACKED) or
PtInRect(FScrollBarPartBounds[AScrollBar, APart], P) then
begin
FScrollBarPartState[AScrollBar, APart] := cxbsHot;
if ButtonPressed and PtInRect(FScrollBarPartBounds[AScrollBar, APart], P) then
FScrollBarPartState[AScrollBar, APart] := cxbsPressed;
end;
end;
procedure TdxSkinFormNonClientAreaInfo.CalculateScrollBarPartsInfo;
var
R: TRect;
AScrollBar: TdxSkinFormScrollBar;
begin
for AScrollBar := saeHorzScroll to saeVertScroll do
begin
if not (AScrollBar in ScrollAreaElements) then Continue;
R := ScrollAreaBounds[AScrollBar];
if AScrollBar = saeVertScroll then
R := cxRectSetXPos(R, R.Top, R.Bottom);
with ScrollBarInfo[AScrollBar] do
begin
CalculateScrollBarPartInfo(AScrollBar, R.Left,
R.Left + dxyLineButton, sbpLineUp);
CalculateScrollBarPartInfo(AScrollBar, R.Right - dxyLineButton,
R.Right, sbpLineDown);
CalculateScrollBarPartInfo(AScrollBar, R.Left + xyThumbTop,
R.Left + xyThumbBottom, sbpThumbnail);
CalculateScrollBarPartInfo(AScrollBar, R.Left + dxyLineButton,
R.Left + xyThumbTop, sbpPageUp);
CalculateScrollBarPartInfo(AScrollBar, R.Left + xyThumbBottom,
R.Right - dxyLineButton, sbpPageDown);
end
end;
end;
function TdxSkinFormNonClientAreaInfo.GetActiveMDIChild: TCustomForm;
var
AActiveChild: TCustomForm;
begin
Result := nil;
if Assigned(Controller.Form) then
if TCustomFormAccess(Controller.Form).FormStyle = fsMDIForm then
begin
AActiveChild := TCustomFormAccess(Controller.Form).ActiveMDIChild;
if Assigned(AActiveChild) then
Result := AActiveChild;
end;
end;
function TdxSkinFormNonClientAreaInfo.GetBorderRect(
ASide: TcxBorder; const ABounds, AWidths: TRect): TRect;
begin
Result := ABounds;
case ASide of
bLeft:
Result.Right := Result.Left + AWidths.Left;
bTop:
Result.Bottom := Result.Top + AWidths.Top;
bRight:
Result.Left := Result.Right - AWidths.Right;
bBottom:
Result.Top := Result.Bottom - AWidths.Bottom;
end;
end;
function TdxSkinFormNonClientAreaInfo.GetCaption: string;
begin
if FCaptionSufix = '' then
Result := FCaption
else
Result := Format(sdxMDICaptionFormat, [FCaption, FCaptionSufix]);
end;
function TdxSkinFormNonClientAreaInfo.GetIcons: TdxSkinFormIcons;
const
SysMenuIcons: array[Boolean] of TdxSkinFormIcons =
([sfiMenu, sfiClose], [sfiClose]);
begin
Result := [];
if Style and WS_SYSMENU = WS_SYSMENU then
Result := SysMenuIcons[ToolWindow or IsDialog];
if Style and WS_MINIMIZEBOX = WS_MINIMIZEBOX then
begin
if IsIconic then
Include(Result, sfiRestore)
else
Include(Result, sfiMinimize);
end;
if Style and WS_MAXIMIZEBOX = WS_MAXIMIZEBOX then
begin
if IsZoomed then
Include(Result, sfiRestore)
else
Include(Result, sfiMaximize);
end;
if ExStyle and WS_EX_CONTEXTHELP = WS_EX_CONTEXTHELP then
Include(Result, sfiHelp);
end;
function TdxSkinFormNonClientAreaInfo.GetMaximizedMDIChild: TCustomForm;
var
AActiveMDI: TCustomForm;
begin
AActiveMDI := GetActiveMDIChild;
if Assigned(AActiveMDI) and Windows.IsZoomed(AActiveMDI.Handle) then
Result := AActiveMDI
else
Result := nil;
end;
function TdxSkinFormNonClientAreaInfo.GetSysMenuIcon: HIcon;
var
wParam: Integer;
begin
wParam := Byte(not ToolWindow);
if IsWinXP then
wParam := ICON_SMALL2;
Result := DefWindowProc(Handle, WM_GETICON, wParam, 0);
end;
function TdxSkinFormNonClientAreaInfo.GetSystemSizeFrame: TSize;
begin
Result := Size(GetSystemMetrics(SM_CXSIZEFRAME), GetSystemMetrics(SM_CYSIZEFRAME));
end;
function TdxSkinFormNonClientAreaInfo.IsMDIMainAlphaBlendUsed: Boolean;
var
AMainForm: TWinControl;
begin
AMainForm := FindControl(GetParent(GetParent(Handle)));
Result := (AMainForm <> nil) and (AMainForm is TCustomForm) and
TCustomFormAccess(AMainForm).AlphaBlend;
end;
function TdxSkinFormNonClientAreaInfo.UpdateCaptionIconStates: Boolean;
var
AHitTest, AIcon: TdxSkinFormIcon;
APrevStates: array[TdxSkinFormIcon] of TdxSkinElementState;
begin
Result := False;
Move(FIconState, APrevStates, SizeOf(FIconState));
FillChar(FIconState, SizeOf(FIconState), 0);
AHitTest := GetIconHitTest;
TrackIcon := IconPressed;
for AIcon := sfiMenu to sfiClose do
begin
if not Active then
FIconState[AIcon] := esActiveDisabled
else
if ((AIcon = sfiMinimize) and (Style and WS_MINIMIZEBOX <> WS_MINIMIZEBOX)) or
((AIcon = sfiMaximize) and (Style and WS_MAXIMIZEBOX <> WS_MAXIMIZEBOX)) then
FIconState[AIcon] := esDisabled;
if (AHitTest <> AIcon) or (FIconState[AIcon] = esDisabled) then Continue;
if ButtonPressed and (IconPressed = AIcon) then
FIconState[AIcon] := esPressed
else
if IconPressed = sfiMenu then
begin
FIconState[AIcon] := esHot;
TrackIcon := AIcon;
end;
end;
for AIcon := sfiMenu to sfiClose do
Result := Result or (FIconState[AIcon] <> APrevStates[AIcon]);
end;
function TdxSkinFormNonClientAreaInfo.UpdateIconPressed(
AReset: Boolean = False): TdxSkinFormIcon;
begin
Result := FIconPressed;
FIconPressed := GetIconHitTest;
if AReset then
begin
if Result <> FIconPressed then
Result := sfiMenu;
FIconPressed := sfiMenu;
end;
end;
function TdxSkinFormNonClientAreaInfo.UpdateCaptionSufix: Boolean;
var
AMDIChild: TCustomForm;
ATempSufix: string;
begin
AMDIChild := GetMaximizedMDIChild;
if Assigned(AMDIChild) then
ATempSufix := AMDIChild.Caption
else
ATempSufix := '';
Result := ATempSufix <> FCaptionSufix;
if Result then
FCaptionSufix := ATempSufix;
end;
function TdxSkinFormNonClientAreaInfo.GetBorderBounds(ASide: TcxBorder): TRect;
begin
Result := FBorderBounds[ASide];
end;
function TdxSkinFormNonClientAreaInfo.GetButtonPressed: Boolean;
begin
Result := GetMouseKeys and MK_LBUTTON = MK_LBUTTON;
end;
function TdxSkinFormNonClientAreaInfo.GetCaptionBounds: TRect;
var
AFrame: TSize;
begin
AFrame := Size(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
Result := BorderBounds[bTop];
Inc(Result.Top, Byte(ToolWindow) + 1);
if IsSizeBox and not NativeBorderWidth and IsZoomed then
InflateRect(Result, -SystemSizeFrame.cx, -AFrame.cy)
else
InflateRect(Result, -SizeFrame.cx, -AFrame.cy);
if IsSizeBox then
begin
if IsZoomed then
Inc(Result.Top, SizeFrame.cy)
else
if NativeBorderWidth then
Inc(Result.Top, SystemSizeFrame.cy - 4);
end;
end;
function TdxSkinFormNonClientAreaInfo.GetCaptionContentOffset: TRect;
begin
if PainterInfo.FormFrames[not ToolWindow, bTop] <> nil then
Result := PainterInfo.FormFrames[not ToolWindow, bTop].ContentOffset.Rect
else
Result := cxNullRect;
end;
function TdxSkinFormNonClientAreaInfo.GetCaptionIconSize: Integer;
begin
if ToolWindow then
Result := GetSystemMetrics(SM_CYSMCAPTION) - 2 * GetSystemMetrics(SM_CYEDGE)
else
Result := GetSystemMetrics(SM_CYSMICON);
end;
function TdxSkinFormNonClientAreaInfo.GetCaptionTextColor: TColor;
begin
Result := FCaptionTextColor[Active];
end;
function TdxSkinFormNonClientAreaInfo.GetClientRect: TRect;
begin
Result := WindowInfo.rcClient;
end;
function TdxSkinFormNonClientAreaInfo.GetExStyle: Integer;
begin
Result := WindowInfo.dwExStyle;
end;
function TdxSkinFormNonClientAreaInfo.GetHandle: HWND;
begin
Result := Controller.Handle;
end;
function TdxSkinFormNonClientAreaInfo.GetClientRectOnClient: TRect;
begin
Result := cxRectOffset(ClientRect, cxPointInvert(ClientRect.TopLeft));
end;
function TdxSkinFormNonClientAreaInfo.GetHasBorder: Boolean;
begin
Result := GetWindowLong(Handle, GWL_STYLE) and WS_BORDER = WS_BORDER;
end;
function TdxSkinFormNonClientAreaInfo.GetHasCaption: Boolean;
begin
Result := GetWindowLong(Handle, GWL_STYLE) and WS_CAPTION = WS_CAPTION;
end;
function TdxSkinFormNonClientAreaInfo.GetHasMenu: Boolean;
begin
Result := FHasMenu;
end;
function TdxSkinFormNonClientAreaInfo.GetIconBounds(
AIcon: TdxSkinFormIcon): TRect;
begin
Result := FIconBounds[AIcon];
end;
function TdxSkinFormNonClientAreaInfo.GetIconState(
AIcon: TdxSkinFormIcon): TdxSkinElementState;
begin
Result := FIconState[AIcon];
end;
function TdxSkinFormNonClientAreaInfo.GetIsAlphaBlendUsed: Boolean;
begin
Result := Controller.Form <> nil;
if Result then
with TCustomFormAccess(Controller.Form) do
Result := AlphaBlend or (FormStyle = fsMDIChild) and IsMDIMainAlphaBlendUsed;
end;
function TdxSkinFormNonClientAreaInfo.GetIsDialog: Boolean;
begin
Result := WindowInfo.dwExStyle and WS_EX_DLGMODALFRAME = WS_EX_DLGMODALFRAME;
end;
function TdxSkinFormNonClientAreaInfo.GetIsIconic: Boolean;
begin
Result := WindowInfo.dwStyle and WS_ICONIC = WS_ICONIC;
end;
function TdxSkinFormNonClientAreaInfo.GetIsSizeBox: Boolean;
begin
Result := WindowInfo.dwStyle and WS_SIZEBOX = WS_SIZEBOX;
end;
function TdxSkinFormNonClientAreaInfo.GetIsZoomed: Boolean;
begin
Result := WindowInfo.dwStyle and WS_MAXIMIZE = WS_MAXIMIZE;
end;
function TdxSkinFormNonClientAreaInfo.GetNativeBorderWidth: Boolean;
begin
Result := FHasMenu or FIsMDIClient or not ThemeActive;
end;
function TdxSkinFormNonClientAreaInfo.GetNeedCheckNonClientSize: Boolean;
begin
Result := HasBorder and not (NativeBorderWidth or
IsZoomed and TdxSkinFormController.IsMDIChildWindow(Handle));
end;
function TdxSkinFormNonClientAreaInfo.GetScrollAreaBounds(
AItem: TdxScrollAreaElement): TRect;
begin
Result := FScrollAreaBounds[AItem];
end;
function TdxSkinFormNonClientAreaInfo.GetScrollBarInfo(
AScrollBar: TdxSkinFormScrollBar): TScrollBarInfo;
begin
Result := FScrollBarsInfo[AScrollBar];
end;
function TdxSkinFormNonClientAreaInfo.GetScrollBarPartBounds(
AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart): TRect;
begin
Result := FScrollBarPartBounds[AScrollBar, APart];
end;
function TdxSkinFormNonClientAreaInfo.GetScrollBarPartState(
AScrollBar: TdxSkinFormScrollBar; APart: TcxScrollBarPart): TcxButtonState;
begin
Result := FScrollBarPartState[AScrollBar, APart];
end;
function TdxSkinFormNonClientAreaInfo.GetSizeArea(
ASide: TcxBorder): TRect;
begin
Result := WindowBounds;
if ASide in [bLeft, bRight] then
Inc(Result.Top, BorderWidths.Top);
if NativeBorderWidth then
with SizeFrame do
Result := GetBorderRect(ASide, Result, Rect(cx, cy, cx, cy))
else
Result := GetBorderRect(ASide, Result, Rect(2, 2, 2, 2))
end;
function TdxSkinFormNonClientAreaInfo.GetSizeCorners(
ACorner: TdxSkinFormCorner): TRect;
var
ASize: TSize;
begin
Result := WindowBounds;
ASize := SizeFrame;
if not NativeBorderWidth then
ASize := Size(2, 2);
if ACorner in [sfcLeftTop, sfcLeftBottom] then
Result.Right := Result.Left + ASize.cx
else
Result.Left := Result.Right - ASize.cx;
if ACorner in [sfcLeftTop, sfcRightTop] then
Result.Bottom := Result.Top + BorderWidths.Top
else
Result.Top := Result.Bottom - ASize.cy;
end;
function TdxSkinFormNonClientAreaInfo.GetSkinBorderWidth(ASide: TcxBorder): Integer;
var
AElement: TdxSkinElement;
begin
Result := 0;
AElement := PainterInfo.FormFrames[not ToolWindow, ASide];
if Assigned(AElement) then
begin
if ASide in [bLeft, bRight] then
Result := AElement.Size.cx
else
Result := AElement.Size.cy;
end;
end;
function TdxSkinFormNonClientAreaInfo.GetStyle: Integer;
begin
Result := WindowInfo.dwStyle;
end;
function TdxSkinFormNonClientAreaInfo.GetThemeActive: Boolean;
begin
if not ThemeActiveAssigned then
begin
FThemeActive := IsThemeActive;
ThemeActiveAssigned := True;
end;
Result := FThemeActive;
end;
function TdxSkinFormNonClientAreaInfo.GetToolWindow: Boolean;
begin
Result := WindowInfo.dwExStyle and WS_EX_TOOLWINDOW = WS_EX_TOOLWINDOW;
end;
function TdxSkinFormNonClientAreaInfo.GetWindowRect: TRect;
begin
Result := WindowInfo.rcWindow;
end;
procedure TdxSkinFormNonClientAreaInfo.SetActive(AActive: Boolean);
begin
if FActive <> AActive then
begin
FActive := AActive;
UpdateCaptionIconStates;
end;
end;
procedure TdxSkinFormNonClientAreaInfo.SetUpdateRgn(ARgn: HRGN);
begin
if FUpdateRgn <> 0 then
DeleteObject(FUpdateRgn);
FUpdateRgn := ARgn;
if FUpdateRgn <> 0 then
OffsetRgn(FUpdateRgn, -WindowRect.Left, -WindowRect.Top);
end;
procedure TdxSkinFormNonClientAreaInfo.SetWindowRgn(ARgn: HRGN);
begin
if FWindowRgn <> 0 then
DeleteObject(FWindowRgn);
FWindowRgn := ARgn;
end;
{ TdxSkinFormPainter }
constructor TdxSkinFormPainter.Create(AViewInfo: TdxSkinFormNonClientAreaInfo);
begin
FViewInfo := AViewInfo;
FBaseCanvas := TCanvas.Create;
FCanvas := TcxCanvas.Create(FBaseCanvas);
CreateCacheInfos;
end;
destructor TdxSkinFormPainter.Destroy;
begin
FreeCacheInfos;
FCanvas.Free;
FBaseCanvas.Free;
inherited Destroy;
end;
procedure TdxSkinFormPainter.CreateCacheInfos;
var
AIcon: TdxSkinFormIcon;
ASide: TcxBorder;
begin
for ASide := Low(TcxBorder) to High(TcxBorder) do
FBordersCache[ASide] := TdxSkinElementCache.Create;
for AIcon := Low(TdxSkinFormIcon) to High(TdxSkinFormIcon) do
FIconsCache[AIcon] := TdxSkinElementCache.Create;
end;
procedure TdxSkinFormPainter.FreeCacheInfos;
var
AIcon: TdxSkinFormIcon;
ASide: TcxBorder;
begin
for ASide := Low(TcxBorder) to High(TcxBorder) do
FBordersCache[ASide].Free;
for AIcon := Low(TdxSkinFormIcon) to High(TdxSkinFormIcon) do
FIconsCache[AIcon].Free;
end;
procedure TdxSkinFormPainter.BeginPaint(ADestDC: HDC = 0);
const
Flags = DCX_CACHE or DCX_CLIPSIBLINGS or DCX_WINDOW or DCX_VALIDATE;
begin
FPainter := ViewInfo.Painter;
FPainterInfo := ViewInfo.PainterInfo;
FDC := ADestDC;
FNeedRelease := ADestDC = 0;
if FNeedRelease then
FDC := GetDCEx(ViewInfo.Handle, 0, Flags);
FBaseCanvas.Handle := FDC;
end;
procedure TdxSkinFormPainter.DrawWindowBackground;
begin
if PainterInfo <> nil then
dxSkinCheckSkinElement(PainterInfo.FormContent).Draw(Canvas.Handle,
ViewInfo.ClientRectOnClient);
end;
procedure TdxSkinFormPainter.DrawWindowBorder;
begin
InternalDrawCaption(ViewInfo.BorderBounds[bTop],
PainterInfo.FormFrames[not ViewInfo.ToolWindow, bTop]);
if IsBordersThin then
InternalDrawThinBorders
else
InternalDrawBorders;
// Draw menu separator
if ViewInfo.HasMenu then
FillRect(Canvas.Handle, cxRectSetBottom(ViewInfo.MenuBounds, ViewInfo.MenuBounds.Bottom, 1),
GetSysColorBrush(COLOR_MENU));
if (ViewInfo.ScrollAreaElements <> []) and not ViewInfo.IsIconic then
DrawScrollAreaElements(Canvas.Handle);
end;
procedure TdxSkinFormPainter.EndPaint;
begin
if FNeedRelease then
ReleaseDC(ViewInfo.Handle, FDC);
FBaseCanvas.Handle := 0;
end;
procedure TdxSkinFormPainter.DrawBackground(DC: HDC; const R: TRect);
begin
dxSkinCheckSkinElement(PainterInfo.FormContent).Draw(DC, R);
end;
procedure TdxSkinFormPainter.DrawScrollAreaElements(DC: HDC);
var
AElement: TdxScrollAreaElement;
CDC: HDC;
MemBMP: HBitmap;
begin
for AElement := saeHorzScroll to saeSizeGrip do
with ViewInfo do
begin
if not (AElement in ViewInfo.ScrollAreaElements) then Continue;
if AElement = saeSizeGrip then
DrawSizeGrip(DC, ScrollAreaBounds[AElement])
else
begin
CDC := CreateCompatibleDC(0);
with ScrollAreaBounds[AElement] do
begin
MemBMP := CreateCompatibleBitmap(DC, Right - Left, Bottom - Top);
SetWindowOrgEx(CDC, Left, Top, nil);
end;
MemBMP := SelectObject(CDC, MemBmp);
DrawBackground(CDC, ScrollAreaBounds[AElement]);
DrawScrollBar(CDC, AElement, ScrollAreaBounds[AElement]);
SetWindowOrgEx(CDC, 0, 0, nil);
with ScrollAreaBounds[AElement] do
BitBlt(DC, Left, Top, Right - Left, Bottom - Top, CDC, 0, 0, SRCCOPY);
MemBMP := SelectObject(CDC, MemBmp);
DeleteObject(MemBMP);
DeleteDC(CDC);
end;
end;
end;
procedure TdxSkinFormPainter.DrawScrollBar(
DC: HDC; AScrollBar: TdxSkinFormScrollBar; const R: TRect);
var
APart: TcxScrollBarPart;
begin
DrawBackground(DC, R);
DC := SelectDC(DC);
for APart := sbpLineUp to sbpPageDown do
with ViewInfo do
begin
if ScrollBarPartState[AScrollBar, APart] = cxbsDefault then Continue;
Painter.DrawScrollBarPart(Canvas, AScrollBar = saeHorzScroll,
ScrollBarPartBounds[AScrollBar, APart], APart, ScrollBarPartState[AScrollBar, APart]);
end;
SelectDC(DC);
end;
procedure TdxSkinFormPainter.DrawSizeGrip(DC: HDC; const R: TRect);
begin
// FillRect(DC, R, CreateSolidBrush(clRed));
DrawBackground(DC, R);
Painter.DrawSizeGrip(Canvas, R, clNone);
end;
procedure TdxSkinFormPainter.DrawWindowCaption(DC: HDC; const R: TRect;
AElement: TdxSkinElement);
var
CR: TRect;
AIcon: TdxSkinFormIcon;
APrevFont: HFONT;
APrevColor: TColor;
APrevTransparent: Integer;
begin
FBordersCache[bTop].CheckCacheState(dxSkinCheckSkinElement(AElement), R,
FrameStates[ViewInfo.Active], 0);
FBordersCache[bTop].Draw(DC, R);
for AIcon := Low(TdxSkinFormIcon) to High(TdxSkinFormIcon) do
if AIcon in ViewInfo.Icons then
begin
DrawWindowIcon(DC, ViewInfo.IconBounds[AIcon], AIcon,
PainterInfo.FormIcons[not ViewInfo.ToolWindow, AIcon]);
end;
if Length(ViewInfo.Caption) > 0 then
begin
APrevFont := SelectObject(DC, ViewInfo.CaptionFont.Handle);
APrevTransparent := SetBkMode(DC, Transparent);
CR := ViewInfo.CaptionBounds;
if ViewInfo.Active and not ViewInfo.ToolWindow then
begin
APrevColor := SetTextColor(DC, ViewInfo.CaptionTextShadowColor);
if ViewInfo.CaptionTextShadowColor <> clDefault then
cxDrawText(DC, ViewInfo.Caption, CR, CaptionFlags);
SetTextColor(DC, APrevColor);
end;
OffsetRect(CR, -1, -1);
APrevColor := SetTextColor(DC, ViewInfo.CaptionTextColor);
cxDrawText(DC, ViewInfo.Caption, CR, CaptionFlags);
SetBkMode(DC, APrevTransparent);
SelectObject(DC, APrevFont);
SetTextColor(DC, APrevColor);
end;
end;
procedure TdxSkinFormPainter.DrawWindowIcon(DC: HDC; const R: TRect;
AIcon: TdxSkinFormIcon; AElement: TdxSkinElement);
begin
if ((AIcon = sfiMenu) and (ViewInfo.SysMenuIcon = 0)) or
((AIcon <> sfiMenu) and (AElement = nil)) then Exit;
if RectVisible(DC, R) then
begin
if AElement = nil then
DrawIconEx(DC, R.Left, R.Top, ViewInfo.SysMenuIcon, R.Right - R.Left,
R.Bottom - R.Top, 0, 0, DI_NORMAL)
else
begin
FIconsCache[AIcon].CheckCacheState(AElement, R, ViewInfo.IconState[AIcon], 0);
FIconsCache[AIcon].Draw(DC, R);
end;
end;
end;
procedure TdxSkinFormPainter.InternalDrawBorder(const R: TRect;
ASide: TcxBorder; AFillBackground: Boolean);
var
ACachedDC: HDC;
AElement: TdxSkinElement;
AMemBmp: HBitmap;
R1: TRect;
begin
AElement := PainterInfo.FormFrames[not ViewInfo.ToolWindow, ASide];
FBordersCache[ASide].CheckCacheState(AElement, R, FrameStates[Active]);
if AFillBackground then
begin
R1 := R;
OffsetRect(R1, -R1.Left, -R1.Top);
ACachedDC := CreateCompatibleDC(Canvas.Handle);
AMemBmp := CreateCompatibleBitmap(Canvas.Handle, R1.Right, R1.Bottom);
AMemBmp := SelectObject(ACachedDC, AMemBmp);
dxSkinCheckSkinElement(PainterInfo.FormContent).Draw(ACachedDC, R1, 0, FrameStates[Active]);
FBordersCache[ASide].Draw(ACachedDC, R1);
BitBlt(Canvas.Handle, R.Left, R.Top, R1.Right, R1.Bottom, ACachedDC, 0, 0, SRCCOPY);
AMemBMP := SelectObject(ACachedDC, AMemBmp);
DeleteObject(AMemBmp);
DeleteDC(ACachedDC);
end
else
FBordersCache[ASide].Draw(Canvas.Handle, R);
end;
procedure TdxSkinFormPainter.InternalDrawBorders;
var
AIsAlphaBlendUsed: Boolean;
ASide: TcxBorder;
R: TRect;
begin
AIsAlphaBlendUsed := ViewInfo.IsAlphaBlendUsed;
for ASide := Low(TcxBorder) to High(TcxBorder) do
begin
R := ViewInfo.BorderBounds[ASide];
if (ASide <> bTop) and IsRectVisible(R) and not cxRectIsEmpty(R) then
begin
if ASide in [bLeft, bRight] then
begin
R.Top := ViewInfo.BorderBounds[bTop].Bottom;
R.Bottom := ViewInfo.BorderBounds[bBottom].Top;
end;
InternalDrawBorder(R, ASide, AIsAlphaBlendUsed);
end;
end;
end;
procedure TdxSkinFormPainter.InternalDrawCaption(const R: TRect;
AElement: TdxSkinElement);
var
ACachedDC: HDC;
AMemBmp: HBitmap;
begin
ACachedDC := CreateCompatibleDC(Canvas.Handle);
AMemBmp := CreateCompatibleBitmap(Canvas.Handle, R.Right, R.Bottom);
AMemBmp := SelectObject(ACachedDC, AMemBmp);
DrawWindowCaption(ACachedDC, R, AElement);
BitBlt(Canvas.Handle, 0, 0, R.Right, R.Bottom, ACachedDC, 0, 0, SRCCOPY);
AMemBMP := SelectObject(ACachedDC, AMemBmp);
DeleteObject(AMemBmp);
DeleteDC(ACachedDC);
end;
procedure TdxSkinFormPainter.InternalDrawThinBorders;
var
ASide: TcxBorder;
R: TRect;
begin
InternalDrawBorder(ViewInfo.BorderBounds[bBottom], bBottom, True);
for ASide := Low(TcxBorder) to High(TcxBorder) do
if ASide in [bLeft, bRight] then
begin
R := ViewInfo.BorderBounds[ASide];
if IsRectVisible(R) and not cxRectIsEmpty(R) then
begin
R.Top := ViewInfo.BorderBounds[bTop].Bottom;
R.Bottom := ViewInfo.WindowBounds.Bottom - ViewInfo.SkinBorderWidth[bBottom];
InternalDrawBorder(R, ASide, True);
end;
end;
end;
function TdxSkinFormPainter.IsRectVisible(const R: TRect): Boolean;
begin
with FViewInfo do
Result := (FUpdateRgn = 0) or RectInRegion(FUpdateRgn, R);
if Result then
Result := Canvas.RectVisible(R);
end;
function TdxSkinFormPainter.SelectDC(DC: HDC): Integer;
begin
Result := Canvas.Handle;
Canvas.Canvas.Handle := DC;
end;
function TdxSkinFormPainter.GetActive: Boolean;
begin
Result := ViewInfo.Active;
end;
function TdxSkinFormPainter.GetIconElement(
AIcon: TdxSkinFormIcon): TdxSkinElement;
begin
Result := FPainterInfo.FormIcons[ViewInfo.ToolWindow, AIcon];
end;
function TdxSkinFormPainter.GetIsBordersThin: Boolean;
begin
Result := (ViewInfo.SkinBorderWidth[bLeft] < ViewInfo.BorderWidths.Left) or
(ViewInfo.SkinBorderWidth[bRight] < ViewInfo.BorderWidths.Right) or
(ViewInfo.SkinBorderWidth[bBottom] < ViewInfo.BorderWidths.Bottom);
end;
{ TdxSkinButtonPainter }
constructor TdxSkinCustomControlPainter.Create(AViewInfo: TdxSkinCustomControlViewInfo);
begin
FViewInfo := AViewInfo;
FCanvas := TCanvas.Create;
FcxCanvas := TcxCanvas.Create(FCanvas);
end;
destructor TdxSkinCustomControlPainter.Destroy;
begin
FViewInfo := nil;
FcxCanvas.Free;
FCanvas.Free;
inherited Destroy;
end;
function TdxSkinCustomControlPainter.GetController: TdxSkinWinController;
begin
Result := ViewInfo.Controller;
end;
function TdxSkinCustomControlPainter.GetPainter: TcxCustomLookAndFeelPainterClass;
begin
Result := Controller.LookAndFeelPainter;
end;
procedure TdxSkinCustomControlPainter.BeginPaint(DC: HDC = 0);
const
Flags = DCX_CACHE or DCX_CLIPSIBLINGS or DCX_WINDOW or DCX_VALIDATE;
begin
FNeedRelease := DC = 0;
if NeedRelease then
DC := GetDCEx(Controller.Handle, 0, Flags);
FDC := DC;
Canvas.Canvas.Handle := FDC;
end;
procedure TdxSkinCustomControlPainter.EndPaint;
begin
Canvas.Canvas.Handle := 0;
if NeedRelease then
ReleaseDC(Controller.Handle, FDC);
end;
procedure TdxSkinCustomControlPainter.DrawBackground;
var
AControl: TWinControl;
begin
AControl := Controller.WinControl;
if AControl <> nil then
cxDrawTransparentControlBackground(AControl, Canvas, ViewInfo.ClientRect);
end;
procedure TdxSkinCustomControlPainter.DrawButton(const ACaption: string;
const R: TRect; AState: TcxButtonState);
var
AFlags: Integer;
begin
Painter.DrawButton(Canvas, R, '', AState, False, clDefault, clDefault, False);
if Length(ACaption) > 0 then
begin
Canvas.Brush.Style := bsClear;
AFlags := cxAlignVCenter or cxShowPrefix or cxAlignHCenter;
if GetWindowLong(Controller.Handle, GWL_STYLE) and BS_MULTILINE <> 0 then
AFlags := AFlags or cxWordBreak
else
AFlags := AFlags or cxSingleLine;
if AState = cxbsDisabled then
begin
Canvas.Font.Color := clBtnHighlight;
Canvas.DrawText(ACaption, cxRectOffset(R, 1, 1), AFlags, True);
end;
Canvas.Font.Color := Painter.ButtonSymbolColor(AState);
Canvas.DrawText(ACaption, R, AFlags, True);
end;
end;
procedure TdxSkinCustomControlPainter.DrawFocus(const R: TRect);
begin
DrawFocusRect(Canvas.Handle, R);
end;
{ TdxSkinCustomControlViewInfo }
constructor TdxSkinCustomControlViewInfo.Create(AController: TdxSkinWinController);
begin
FController := AController;
end;
function TdxSkinCustomControlViewInfo.GetClientRect: TRect;
begin
GetWindowRect(Controller.Handle, Result);
OffsetRect(Result, -Result.Left, -Result.Top);
end;
function TdxSkinCustomControlViewInfo.GetIsEnabled: Boolean;
begin
Result := IsWindowEnabled(Controller.Handle);
end;
function TdxSkinCustomControlViewInfo.GetIsFocused: Boolean;
begin
Result := GetFocus = Controller.Handle;
end;
function TdxSkinCustomControlViewInfo.GetIsMouseAtControl: Boolean;
begin
Result := WindowFromPoint(Mouse.CursorPos) = FController.Handle;
end;
{ TdxSkinButtonViewInfo }
constructor TdxSkinButtonViewInfo.Create(AController: TdxSkinWinController);
begin
inherited Create(AController);
FCaption := GetWindowCaption(Controller.Handle);
UpdateEnabledState;
end;
procedure TdxSkinButtonViewInfo.MouseClickEvent(ADown: Boolean);
const
AStates: array[Boolean] of TcxButtonState = (cxbsNormal, cxbsPressed);
begin
State := AStates[ADown];
end;
procedure TdxSkinButtonViewInfo.MouseHoverEvent(AEnter: Boolean);
const
AStates: array[Boolean, Boolean] of TcxButtonState =
((cxbsNormal, cxbsNormal), (cxbsHot, cxbsPressed));
begin
State := AStates[AEnter, Pressed];
end;
procedure TdxSkinButtonViewInfo.SetState(AState: TcxButtonState);
var
ANewState: TcxButtonState;
begin
if IsEnabled then
ANewState := AState
else
ANewState := cxbsDisabled;
if ANewState <> FState then
begin
FState := ANewState;
FPressed := FState = cxbsPressed;
Controller.RedrawWindow(True);
end;
end;
procedure TdxSkinButtonViewInfo.UpdateEnabledState;
const
AStates: array[Boolean] of TcxButtonState = (cxbsDisabled, cxbsNormal);
begin
State := AStates[IsEnabled];
end;
{ TdxSkinButtonController }
function TdxSkinButtonController.GetViewInfo: TdxSkinButtonViewInfo;
begin
Result := TdxSkinButtonViewInfo(inherited ViewInfo);
end;
class function TdxSkinButtonController.GetViewInfoClass: TdxSkinCustomControlViewInfoClass;
begin
Result := TdxSkinButtonViewInfo;
end;
procedure TdxSkinButtonController.DrawContent(DC: HDC = 0);
begin
Painter.BeginPaint(DC);
try
Painter.DrawBackground;
with TdxSkinButtonViewInfo(ViewInfo) do
begin
Painter.DrawButton(Caption, ClientRect, State);
if IsFocused then
Painter.DrawFocus(cxRectInflate(ClientRect, -4, -4));
end;
finally
Painter.EndPaint;
end;
end;
procedure TdxSkinButtonController.MouseLeave;
begin
inherited MouseLeave;
ViewInfo.MouseHoverEvent(False)
end;
procedure TdxSkinButtonController.WndProc(var AMessage: TMessage);
const
AStates: array[Boolean] of TcxButtonState = (cxbsDisabled, cxbsNormal);
begin
if AMessage.Msg = WM_SETTEXT then
ViewInfo.FCaption := TWMSetText(AMessage).Text;
inherited WndProc(AMessage);
if IsSkinUsed then
case AMessage.Msg of
WM_ENABLE:
ViewInfo.UpdateEnabledState;
WM_UPDATEUISTATE:
if AMessage.WParamLo in [UIS_SET, UIS_CLEAR] then
DrawContent;
BM_SETSTATE:
ViewInfo.MouseClickEvent(AMessage.WParam <> 0);
WM_MOUSELEAVE, CM_MOUSELEAVE:
ViewInfo.MouseHoverEvent(False);
WM_MOUSEMOVE, WM_MOUSEHOVER:
if ViewInfo.IsMouseAtControl then
ViewInfo.MouseHoverEvent(True);
end;
end;
{ TdxSkinCustomController }
constructor TdxSkinCustomController.Create(AHandle: HWND);
begin
inherited Create(AHandle);
FViewInfo := GetViewInfoClass.Create(Self);
FPainter := TdxSkinCustomControlPainter.Create(FViewInfo);
end;
destructor TdxSkinCustomController.Destroy;
begin
FViewInfo.Free;
FPainter.Free;
inherited Destroy;
end;
procedure TdxSkinCustomController.DrawBackground(DC: HDC = 0);
begin
Painter.BeginPaint(DC);
try
Painter.DrawBackground;
finally
Painter.EndPaint;
end;
end;
procedure TdxSkinCustomController.DrawContent(DC: HDC = 0);
begin
end;
class function TdxSkinCustomController.GetViewInfoClass: TdxSkinCustomControlViewInfoClass;
begin
Result := TdxSkinCustomControlViewInfo;
end;
function TdxSkinCustomController.GetMaster(AHandle: HWND): TdxSkinWinController;
var
AParent: TCustomForm;
begin
Result := nil;
if Assigned(WinControl) then
begin
AParent := GetParentForm(WinControl);
if Assigned(AParent) and GetUseSkinForControl then
Result := GetControllerByHandle(AParent.Handle)
end;
end;
procedure TdxSkinCustomController.InitializePainter;
begin
// nothing todo
end;
function TdxSkinCustomController.WMEraseBk(var AMessage: TWMEraseBkgnd): Boolean;
begin
AMessage.Result := 1;
Result := True;
end;
function TdxSkinCustomController.WMPaint(var AMessage: TWMPaint): Boolean;
var
APaintStruct: TPaintStruct;
ADC: HDC;
begin
Result := True;
if AMessage.DC <> 0 then
DrawContent(AMessage.DC)
else
begin
ADC := BeginPaint(Handle, APaintStruct);
try
DrawContent(ADC);
finally
EndPaint(Handle, APaintStruct);
end;
end;
end;
procedure TdxSkinCustomController.WndProc(var AMessage: TMessage);
var
AHandled: Boolean;
begin
AHandled := False;
if IsSkinUsed then
case AMessage.Msg of
WM_ERASEBKGND:
AHandled := WMEraseBk(TWMEraseBkgnd(AMessage));
WM_PAINT:
AHandled := WMPaint(TWMPaint(AMessage));
end;
if not AHandled then
inherited WndProc(AMessage);
end;
{ TdxSkinPanelController }
procedure TdxSkinPanelController.DrawContent(DC: HDC = 0);
const
Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
AControl: TControl;
R: TRect;
begin
AControl := WinControl;
if Assigned(AControl) and (AControl is TCustomPanel) then
begin
Painter.BeginPaint(DC);
try
R := ViewInfo.ClientRect;
InternalDrawBackground(TCustomPanel(AControl), R);
with TCustomPanelAccess(AControl) do
begin
Painter.Canvas.Brush.Style := bsClear;
Painter.Canvas.Font := Font;
DrawText(Painter.Canvas.Handle, PChar(Caption), -1, R,
DrawTextBiDiModeFlags(DT_EXPANDTABS or DT_SINGLELINE or DT_VCENTER or
Alignments[Alignment]));
PaintControls(Painter.Canvas.Handle, nil);
end;
finally
Painter.EndPaint;
end;
end;
end;
procedure TdxSkinPanelController.InternalDrawBackground(APanel: TCustomPanel;
const R: TRect);
var
ABGColor: TColor;
begin
with TCustomPanelAccess(APanel) do
begin
if (csParentBackground in ControlStyle) or (Color = clBtnFace) then
ABGColor := clDefault
else
ABGColor := Color;
Painter.Painter.DrawPanelBackground(Painter.Canvas, APanel, R, ABGColor);
if not (csParentBackground in ControlStyle) and (ABGColor = clDefault) then
Painter.Painter.DrawPanelContent(Painter.Canvas, R, False);
if (BevelOuter <> bvNone) or (BevelInner <> bvNone) then
Painter.Painter.DrawPanelBorders(Painter.Canvas, R);
end;
end;
function TdxSkinPanelController.WMEraseBk(var AMessage: TWMEraseBkgnd): Boolean;
begin
Result := WMPaint(TWMPaint(AMessage));
if not Result then
Result := inherited WMEraseBk(AMessage);
end;
function TdxSkinPanelController.WMPaint(var AMessage: TWMPaint): Boolean;
begin
Result := False;
if not FPainting then
begin
FPainting := True;
try
Result := inherited WMPaint(AMessage);
finally
FPainting := False;
end;
end;
end;
procedure TdxSkinPanelController.WndProc(var AMessage: TMessage);
var
AHandled: Boolean;
begin
AHandled := False;
if (AMessage.Msg = WM_PRINTCLIENT) and IsSkinUsed then
with TWMPrintClient(AMessage) do
begin
AHandled := (Result <> 1) and ((Flags and PRF_CHECKVISIBLE = 0) or IsWindowVisible(Handle));
if AHandled then
WMPaint(TWMPaint(AMessage));
end;
if not AHandled then
inherited WndProc(AMessage);
end;
{ TdxSkinFrameController }
procedure TdxSkinFrameController.DrawContent(DC: HDC = 0);
var
AControl: TWinControl;
begin
Painter.BeginPaint(DC);
try
AControl := WinControl;
if (AControl <> nil) and (AControl is TCustomFrame) then
with TCustomFrameAccess(AControl) do
begin
if csParentBackground in ControlStyle then
cxDrawTransparentControlBackground(AControl, Painter.Canvas,
ViewInfo.ClientRect, False)
else
(Master as TdxSkinFormController).DrawWindowBackground(Painter.Canvas.Handle);
PaintControls(Painter.Canvas.Handle, nil);
end;
finally
Painter.EndPaint;
end;
end;
function TdxSkinFrameController.WMPrintClient(var AMessage: TWMPrintClient): Boolean;
begin
Result := (AMessage.Result <> 1) and ((AMessage.Flags and PRF_CHECKVISIBLE = 0) or
IsWindowVisible(Handle));
if Result then
Result := WMPaint(TWMPaint(AMessage));
end;
procedure TdxSkinFrameController.WndProc(var AMessage: TMessage);
begin
if not IsSkinUsed or (AMessage.Msg <> WM_PRINTCLIENT) or not
WMPrintClient(TWMPrintClient(AMessage))
then
inherited WndProc(AMessage);
end;
{ TdxSkinWinControllerHelper }
constructor TdxSkinWinControllerHelper.Create;
begin
FHandle := {$IFDEF DELPHI6}Classes.{$ENDIF}AllocateHWnd(WndProc);
end;
destructor TdxSkinWinControllerHelper.Destroy;
begin
{$IFDEF DELPHI6}Classes.{$ENDIF}DeallocateHWnd(FHandle);
inherited Destroy;
end;
procedure TdxSkinWinControllerHelper.WndProc(var AMsg: TMessage);
function IsAnotherApplicatonWindow(AWnd: HWND): Boolean;
var
AProcessId: Cardinal;
begin
GetWindowThreadProcessId(AWnd, @AProcessId);
Result := (AWnd = 0) or (AProcessId <> GetCurrentProcessId);
end;
function GetSkinClassForWindow(AWnd: HWND): TdxSkinWinControllerClass;
begin
Result := nil;
if not IsAnotherApplicatonWindow(AWnd) then
Result := dxSkinGetControllerClassForWindowProc(AWnd);
end;
var
ASkinClass: TdxSkinWinControllerClass;
begin
if AMsg.Msg = WM_POSTCREATE then
begin
ASkinClass := GetSkinClassForWindow(AMsg.LParam);
if ASkinClass <> nil then
begin
GetSystemMenu(AMsg.LParam, True); // W2k redrawing bug
ASkinClass.InitializeEngine(AMsg.LParam);
PostMessage(AMsg.LParam, WM_POSTCHECKRGN, 0, 0);
end;
end
else
AMsg.Result := DefWindowProc(Handle, AMsg.Msg, AMsg.WParam, AMsg.LParam);
end;
//
function dxSkinGetControllerClassForWindow(AWnd: HWND): TdxSkinWinControllerClass;
var
AControl: TControl;
begin
Result := nil;
if TdxSkinWinController.IsMDIClientWindow(AWnd) then
Result := TdxSkinFormController
else
begin
AControl := FindControl(AWnd);
if AControl <> nil then
begin
if AControl is TCustomForm then
Result := TdxSkinFormController;
if AControl is TCustomFrame then
Result := TdxSkinFrameController;
if SameText(AControl.ClassName, 'TButton') then
Result := TdxSkinButtonController;
if SameText(AControl.ClassName, 'TPanel') then
Result := TdxSkinPanelController;
end;
end;
end;
function dxSkinsWndProcHook(Code: Integer; wParam: WParam; lParam: LParam): LRESULT; stdcall;
var
AMsg: PCWPStruct;
procedure ChildChanged(AHandle: HWND);
begin
if AHandle <> 0 then
if AnsiSameText(GetWindowClass(AHandle), 'MDICLIENT') then
begin
AHandle := GetParent(AHandle);
if AHandle <> 0 then
SendMessage(AHandle, WM_CHILDCHANGED, 0, 0);
end;
end;
begin
AMsg := PCWPStruct(lParam);
Result := CallNextHookEx(WndProcHookHandle, Code, wParam, lParam);
if IsDesigning then Exit;
case AMsg.message of
WM_CHILDACTIVATE, WM_MDIACTIVATE:
ChildChanged(GetParent(AMsg.hwnd));
WM_CREATE, WM_MDICREATE:
PostMessage(SkinHelper.Handle, WM_POSTCREATE, 0, AMsg.hwnd);
WM_DESTROY, WM_MDIDESTROY:
if AMsg.wParam = 0 then
begin
TdxSkinWinController.FinalizeEngine(AMsg.hwnd);
ChildChanged(GetParent(AMsg.hwnd));
end;
end;
end;
var
SetScrollInfo: function(hWnd: HWND; BarFlag: Integer;
const ScrollInfo: TScrollInfo; Redraw: BOOL): Integer; stdcall;
SetScrollPos: function (hWnd: HWND; nBar, nPos: Integer;
bRedraw: BOOL): Integer stdcall;
function My_SetScrollPos(hWnd: HWND; nBar, nPos: Integer;
bRedraw: BOOL): Integer; stdcall;
begin
bRedraw := bRedraw and not TdxSkinFormController.IsSkinActive(hWnd);
Result := SetScrollPos(hWnd, nBar, nPos, bRedraw);
end;
function My_SetScrollInfo(hWnd: HWND; BarFlag: Integer;
const ScrollInfo: TScrollInfo; Redraw: BOOL): Integer; stdcall;
begin
Redraw := Redraw and not TdxSkinFormController.IsSkinActive(hWnd);
Result := SetScrollInfo(hWnd, BarFlag, ScrollInfo, Redraw);
end;
procedure RegisterAssistants;
begin
SetScrollPos := FlatSB_SetScrollPos;
SetScrollInfo := FlatSB_SetScrollInfo;
FlatSB_SetScrollPos := My_SetScrollPos;
FlatSB_SetScrollInfo := My_SetScrollInfo;
SkinControllersList := TList.Create;
SkinHelper := TdxSkinWinControllerHelper.Create;
WndProcHookHandle := SetWindowsHookEx(WH_CALLWNDPROC, dxSkinsWndProcHook, 0, GetCurrentThreadId);
WM_POSTREDRAW := RegisterWindowMessage('WM_POSTREDRAW');
WM_CHILDCHANGED := RegisterWindowMessage('WM_CHILDCHANGED');
WM_POSTCREATE := RegisterWindowMessage('WM_POSTCREATE');
WM_POSTCHECKRGN := RegisterWindowMessage('WM_POSTCHECKRGN');
FormControllers := TcxObjectList.Create;
end;
procedure UnregisterAssistants;
begin
FlatSB_SetScrollPos := SetScrollPos;
FlatSB_SetScrollInfo := SetScrollInfo;
UnhookWindowsHookEx(WndProcHookHandle);
FormControllers.Clear; // destroy all active controllers
SkinControllersList.Free;
FormControllers.Free;
SkinHelper.Free;
end;
initialization
dxSkinGetControllerClassForWindowProc := dxSkinGetControllerClassForWindow;
RegisterAssistants;
finalization
UnregisterAssistants;
end.