Componentes.Terceros.DevExp.../internal/x.44/1/ExpressBars 6/Sources/dxRibbonForm.pas
2009-06-29 12:09:02 +00:00

1994 lines
58 KiB
ObjectPascal

{*******************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressBars components }
{ }
{ Copyright (c) 1998-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSBARS 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 dxRibbonForm;
{$I cxVer.inc}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ImgList, cxClasses, cxGraphics, cxControls,
dxRibbonSkins, dxRibbonFormCaptionHelper, cxDWMApi;
type
{ TdxCustomRibbonForm }
TdxCustomRibbonForm = class(TForm)
private
FAdjustLayoutForNonClientDrawing: Boolean;
FAutoScroll: Boolean;
FCaption: TCaption;
FCornerRegions: array[0..3] of HRGN;
FData: TdxRibbonFormData;
FDisableAero: Boolean;
FExtendFrameAtTopHeight: Integer;
FFakeClientHandle: HWND;
FZoomedBoundsOffsets: TRect;
FIsActive: Boolean;
FSizingBorders: TSize;
FSizingLoop: Boolean;
FDelayedActivate: Boolean;
FNeedCallActivate: Boolean;
FRedrawCount: Integer;
FUseSkin: Boolean;
FUseSkinColor: Boolean;
FVisibleChanging: Boolean;
FDefClientProc: TFarProc;
FNewClientInstance: TFarProc;
FOldClientProc: TFarProc;
FPrevActiveControl: TWinControl;
{$IFDEF DELPHI10}
FRibbonAlwaysOnTop: Boolean;
{$ENDIF}
FRibbonNonClientHelper: TdxRibbonFormCaptionHelper;
procedure AfterResize(AIsRibbonVisible: Boolean; ARibbonHeight: Integer; AIsZoomed: Boolean);
procedure BeforeResize(out AIsRibbonVisible: Boolean; out ARibbonHeight: Integer);
procedure CalculateCornerRegions;
procedure CalculateZoomedOffsets;
procedure CheckExtendFrame(AZoomed: Boolean);
procedure CheckResizingNCHitTest(var AHitTest: Integer; const P: TPoint);
procedure CorrectZoomedBounds(var R: TRect);
procedure CreateCornerRegions;
procedure DestroyCornerRegions;
procedure ExcludeRibbonPaintArea(DC: HDC);
procedure ForceUpdateWindowSize;
procedure FullRedrawWithChildren;
function GetCurrentBordersWidth: TRect;
function GetBackgroundColor: TColor;
function GetBorderStyle: TFormBorderStyle;
function GetUseSkin: Boolean;
procedure InvalidateFrame(AWnd: HWND; AUpdate: Boolean = False);
function IsNeedCorrectForAutoHideTaskBar: Boolean;
function IsNormalWindowState: Boolean;
function IsRibbonVisible: Boolean;
procedure NewClientWndProc(var Message: TMessage);
procedure ResetSystemMenu;
procedure SetAutoScroll(const Value: Boolean);
procedure SetBorderStyle(const Value: TFormBorderStyle);
procedure SetDisableAero(const Value: Boolean);
procedure SetPrevActiveControl(AValue: TWinControl);
procedure SetRegion(ARegion: HRGN; ARedraw: Boolean = False);
{$IFDEF DELPHI10}
procedure SetRibbonAlwaysOnTop(const Value: Boolean);
{$ENDIF}
procedure SetRibbonNonClientHelper(const Value: TdxRibbonFormCaptionHelper);
procedure SetUseSkinColor(const Value: Boolean);
procedure ShowSystemMenu(AFromMouse: Boolean);
procedure ResetGlassFrame;
procedure UpdateGlassFrame;
procedure UpdateSystemMenu;
//messages
procedure CMActionUpdate(var Message: TMessage); message CM_ACTIONUPDATE;
procedure CMActivate(var Message: TCMActivate); message CM_ACTIVATE;
procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED;
procedure WMCaptureChanged(var Message: TMessage); message WM_CAPTURECHANGED;
procedure WMDisplayChange(var Message: TMessage); message WM_DISPLAYCHANGE;
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
procedure WMInitMenu(var Message: TWMInitMenu); message WM_INITMENU;
procedure WMNCActivate(var Message: TWMNCActivate); message WM_NCACTIVATE;
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
procedure WMShowWindow(var Message: TMessage); message WM_SHOWWINDOW;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP;
procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
//vista support
procedure WMDWMCompositionChanged(var Message: TMessage); message WM_DWMCOMPOSITIONCHANGED;
//caption
procedure WMGetText(var Message: TWMGetText); message WM_GETTEXT;
procedure WMGetTextLength(var Message: TWMGetTextLength); message WM_GETTEXTLENGTH;
procedure WMSetText(var Message: TWMSetText); message WM_SETTEXT;
protected
procedure AdjustClientRect(var Rect: TRect); override;
procedure AdjustLayout; virtual;
procedure AdjustSize; override;
{$IFDEF DELPHI10}
procedure AlignControls(AControl: TControl; var Rect: TRect); override;
{$ENDIF}
procedure CallDWMWindowProc(var Message);
function CanAdjustLayout: Boolean; virtual;
procedure CaptionChanged;
procedure CreateWnd; override;
procedure DestroyWindowHandle; override;
procedure DoCreate; override;
procedure DrawNonClientArea(ADrawCaption: Boolean; AUpdateRegion: HRGN = 1);
procedure ExtendFrameIntoClientAreaAtTop(AHeight: Integer);
function GetFormBorderIcons: TBorderIcons; virtual;
function HandleWithHelper(ADown: Boolean; AButton: TMouseButton): Boolean; virtual;
procedure InitializeNewForm; {$IFDEF DELPHI12} override; {$ENDIF}
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure ModifySystemMenu(ASysMenu: THandle); virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure Resize; override;
procedure ShiftControlsVertically(ADelta: Integer); virtual;
procedure UpdateNonClientArea;
procedure UpdateWindowRegion(AIsMaximized: Boolean);
procedure UpdateWindowStates;
procedure WndProc(var Message: TMessage); override;
property DisableAero: Boolean read FDisableAero write SetDisableAero default False;
property UseSkin: Boolean read GetUseSkin;
public
constructor Create(AOwner: TComponent); override;
constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
destructor Destroy; override;
procedure FullUpdate;
function GetCaptionHeightDelta(AHasQuickAccessToolbar: Boolean): Integer; virtual;
procedure Invalidate; override;
function IsUseAeroNCPaint: Boolean;
procedure ResetWindowRegion;
procedure SetRedraw(ARedraw: Boolean);
property PrevActiveControl: TWinControl read FPrevActiveControl write SetPrevActiveControl;
{$IFDEF DELPHI10}
property RibbonAlwaysOnTop: Boolean read FRibbonAlwaysOnTop write SetRibbonAlwaysOnTop;
{$ENDIF}
property RibbonNonClientHelper: TdxRibbonFormCaptionHelper
read FRibbonNonClientHelper write SetRibbonNonClientHelper;
property IsActive: Boolean read FIsActive;
published
property AdjustLayoutForNonClientDrawing: Boolean
read FAdjustLayoutForNonClientDrawing write FAdjustLayoutForNonClientDrawing default True;
property AutoScroll: Boolean read FAutoScroll write SetAutoScroll default False;
property BorderStyle: TFormBorderStyle read GetBorderStyle write SetBorderStyle default bsSizeable;
property KeyPreview default True;
property UseSkinColor: Boolean read FUseSkinColor write SetUseSkinColor default True;
end;
{ TdxRibbonForm }
TdxRibbonForm = class(TdxCustomRibbonForm);
procedure SetWindowTextWithoutRedraw(AWnd: HWND; const AText: string);
implementation
uses
Types, dxBar, cxGeometry, Math, dxOffice11, dxUxTheme, MultiMon, ShellAPI,
dxRibbon, dxStatusBar, dxCore;
const
{$IFNDEF DELPHI7}
WM_NCMOUSELEAVE = $02A2;
{$ENDIF}
WM_NCUAHDRAWCAPTION = $00AE;
WM_NCUAHDRAWFRAME = $00AF;
WM_SYNCPAINT = $0088;
WM_SYSMENU = $313;
dxGlassMaximizedNonClientHeight = 4;
dxFullRedrawFlags = RDW_INVALIDATE or RDW_ERASE or RDW_FRAME or RDW_ALLCHILDREN;
function SetWindowInvisibleStyle(AWnd: HWND): Cardinal;
begin
Result := GetWindowLong(AWnd, GWL_STYLE);
SetWindowLong(AWnd, GWL_STYLE, Result and not WS_VISIBLE);
end;
procedure RestoreWindowStyles(AWnd: HWND; AStyles: Cardinal);
begin
SetWindowLong(AWnd, GWL_STYLE, AStyles);
end;
procedure SetWindowTextWithoutRedraw(AWnd: HWND; const AText: string);
var
AStyles: Cardinal;
begin
AStyles := SetWindowInvisibleStyle(AWnd);
DefWindowProc(AWnd, WM_SETTEXT, 0, LongInt(PChar(AText)));
RestoreWindowStyles(AWnd, AStyles);
end;
function GetAnimation: Boolean;
var
AInfo: TAnimationInfo;
begin
AInfo.cbSize := SizeOf(TAnimationInfo);
if SystemParametersInfo(SPI_GETANIMATION, SizeOf(AInfo), @AInfo, 0) then
Result := AInfo.iMinAnimate <> 0
else
Result := False;
end;
procedure SetAnimation(AValue: Boolean);
var
AInfo: TAnimationInfo;
begin
AInfo.cbSize := SizeOf(TAnimationInfo);
BOOL(AInfo.iMinAnimate) := AValue;
SystemParametersInfo(SPI_SETANIMATION, SizeOf(AInfo), @AInfo, 0);
end;
{ TdxCustomRibbonForm }
constructor TdxCustomRibbonForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner); //CBUILDER workaround
end;
constructor TdxCustomRibbonForm.CreateNew(AOwner: TComponent; Dummy: Integer = 0);
begin
inherited CreateNew(AOwner, Dummy);
{$IFNDEF DELPHI12}
InitializeNewForm;
{$ENDIF}
end;
destructor TdxCustomRibbonForm.Destroy;
begin
DestroyCornerRegions;
inherited Destroy;
end;
procedure TdxCustomRibbonForm.FullUpdate;
begin
UpdateGlassFrame;
if HandleAllocated then
begin
UpdateSystemMenu;
SetWindowPos(Handle, 0, 0, 0, Width, Height, SWP_FRAMECHANGED or SWP_NOMOVE or
SWP_NOZORDER or SWP_NOACTIVATE);
FullRedrawWithChildren;
end;
end;
function TdxCustomRibbonForm.GetCaptionHeightDelta(
AHasQuickAccessToolbar: Boolean): Integer;
begin
Result := 0;
end;
procedure TdxCustomRibbonForm.Invalidate;
begin
if HandleAllocated and not IsIconic(Handle) then
CheckExtendFrame(IsZoomed(Handle));
inherited Invalidate;
if ClientHandle <> 0 then
InvalidateRect(ClientHandle, nil, True);
end;
procedure TdxCustomRibbonForm.CreateWnd;
var
ClientCreateStruct: TClientCreateStruct;
begin
FExtendFrameAtTopHeight := -1;
inherited CreateWnd;
if not (csDesigning in ComponentState) and (FormStyle = fsMDIForm) then
begin
with ClientCreateStruct do
begin
idFirstChild := $FF00; //check
hWindowMenu := 0;
end;
FFakeClientHandle := Windows.CreateWindowEx(WS_EX_CLIENTEDGE, 'MDICLIENT',
nil, WS_CHILD or WS_VISIBLE or WS_GROUP or WS_TABSTOP or
WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
MDIS_ALLCHILDSTYLES, 0, 0, ClientWidth, ClientHeight, Handle, 0,
HInstance, @ClientCreateStruct);
SetWindowPos(FFakeClientHandle, 0, -20, -20, 10, 10, SWP_NOACTIVATE or SWP_NOZORDER);
FOldClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
FDefClientProc := Pointer(GetWindowLong(FFakeClientHandle, GWL_WNDPROC));
FNewClientInstance := Classes.MakeObjectInstance(NewClientWndProc);
SetWindowLong(ClientHandle, GWL_WNDPROC, Longint(FNewClientInstance));
if ClientHandle <> 0 then
begin
SetWindowLong(ClientHandle, GWL_EXSTYLE,
GetWindowLong(ClientHandle, GWL_EXSTYLE) and not WS_EX_CLIENTEDGE);
InvalidateFrame(ClientHandle);
end;
end;
UpdateSystemMenu;
end;
procedure TdxCustomRibbonForm.DestroyWindowHandle;
begin
inherited DestroyWindowHandle;
if csDestroying in ComponentState then
RibbonNonClientHelper := nil;
end;
procedure TdxCustomRibbonForm.DoCreate;
begin
inherited DoCreate;
if UseSkin then
AdjustLayout;
end;
procedure TdxCustomRibbonForm.AdjustClientRect(var Rect: TRect);
begin
inherited;
if UseSkin and IsUseAeroNCPaint and IsZoomed(Handle) then
Inc(Rect.Top, dxGlassMaximizedNonClientHeight);
end;
procedure TdxCustomRibbonForm.AdjustLayout;
var
ALoadedHeight, AHeight, ADelta: Integer;
begin
if not CanAdjustLayout then Exit;
RibbonNonClientHelper.GetDesignInfo(ALoadedHeight, AHeight);
ADelta := AHeight - ALoadedHeight;
if WindowState <> wsMaximized then
ClientHeight := ClientHeight + ADelta - (GetSystemMetrics(SM_CYCAPTION) + GetDefaultWindowBordersWidth(Handle).Top);
ShiftControlsVertically(ADelta);
end;
procedure TdxCustomRibbonForm.AdjustSize;
{$IFDEF DELPHI11}
var
AFlags: Cardinal;
{$ENDIF}
begin
{$IFDEF DELPHI11}
if not (csLoading in ComponentState) and HandleAllocated then
begin
AFlags := SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOZORDER;
if IsZoomed(Handle) then
AFlags := AFlags or SWP_NOSIZE;
SetWindowPos(Handle, 0, 0, 0, Width, Height, AFlags);
RequestAlign;
end;
{$ELSE}
inherited AdjustSize;
{$ENDIF}
end;
{$IFDEF DELPHI10}
type
TControlAccess = class(TControl);
procedure TdxCustomRibbonForm.AlignControls(AControl: TControl; var Rect: TRect);
function AlignWork: Boolean;
var
I: Integer;
begin
Result := True;
for I := ControlCount - 1 downto 0 do
if (Controls[I].Align <> alNone) or
(Controls[I].Anchors <> [akLeft, akTop]) then Exit;
Result := False;
end;
procedure UpdateTopmostControlBounds;
var
I: Integer;
AControl: TControl;
begin
for I := ControlCount - 1 downto 0 do
begin
AControl := Controls[I];
if RibbonNonClientHelper.IsTopmostControl(AControl) then
begin
TControlAccess(AControl).UpdateBoundsRect(cxRectSetTop(AControl.BoundsRect, -1));
Break;
end;
end;
end;
begin
if FRibbonAlwaysOnTop and UseSkin and AlignWork then
UpdateTopmostControlBounds;
inherited AlignControls(AControl, Rect);
end;
{$ENDIF}
procedure TdxCustomRibbonForm.CallDWMWindowProc(var Message);
begin
DwmDefWindowProc(Handle, TMessage(Message).Msg, TMessage(Message).WParam,
TMessage(Message).LParam, Integer(@TMessage(Message).Result));
end;
function TdxCustomRibbonForm.CanAdjustLayout: Boolean;
begin
Result := AdjustLayoutForNonClientDrawing and
([csDesigning, csDestroying, csReading, csLoading] * ComponentState = []);
end;
procedure TdxCustomRibbonForm.CaptionChanged;
begin
UpdateWindowStates;
RibbonNonClientHelper.CaptionChanged;
end;
procedure TdxCustomRibbonForm.NewClientWndProc(var Message: TMessage);
procedure Default;
begin
with Message do
Result := CallWindowProc(FDefClientProc, ClientHandle, Msg, wParam, lParam);
end;
procedure OldDefault;
begin
with Message do
Result := CallWindowProc(FOldClientProc, ClientHandle, Msg, wParam, lParam);
end;
function MaximizedChildren: Boolean;
var
I: Integer;
begin
for I := 0 to MDIChildCount - 1 do
if MDIChildren[I].WindowState = wsMaximized then
begin
Result := True;
Exit;
end;
Result := False;
end;
var
DC: HDC;
PS: TPaintStruct;
R: TRect;
// F: TForm;
AColor: TColor;
begin
if not UseSkin then
begin
with Message do
case Msg of
WM_NCHITTEST, WM_PAINT, WM_ERASEBKGND:
OldDefault;
WM_NCCALCSIZE:;
WM_NCPAINT:;
else
Default;
end;
Exit;
end;
with Message do
case Msg of
WM_KEYDOWN:
begin
KeyDown(WParamLo, KeyDataToShiftState(LParam));
if WParamLo = 0 then Exit;
Default;
end;
WM_NCHITTEST:
begin
Default;
if Result = HTCLIENT then Result := HTTRANSPARENT;
end;
WM_ERASEBKGND:
begin
AColor := GetBackgroundColor;
FillRectByColor(TWMEraseBkGnd(Message).DC, ClientRect, AColor);
// Erase the background at the location of an MDI client window
if (FormStyle = fsMDIForm) and (ClientHandle <> 0) then
begin
Windows.GetClientRect(ClientHandle, R);
FillRectByColor(TWMEraseBkGnd(Message).DC, R, AColor);
end;
Result := 1;
end;
WM_NCCALCSIZE:;
WM_NCPAINT:;
WM_MDIREFRESHMENU:
Result := 0;
WM_NCACTIVATE:
Message.Result := 1;
{
$3F://!
begin
Default;
F := ActiveMDIChild;
if (F <> nil) and MaximizedChildren then
begin
//correct maximized bounds
GetWindowRect(ClientHandle, R);
R.Right := R.Right - R.Left + (F.Width - F.ClientWidth);
R.Bottom := R.Bottom - R.Top + (F.Height - F.ClientHeight);
if (F is TdxCustomRibbonForm) and TdxCustomRibbonForm(F).UseSkin then
Inc(R.Bottom, TdxCustomRibbonForm(F).RibbonNonClientHelper.GetWindowCaptionHeight);
SetWindowPos(F.Handle, 0, 0, 0, R.Right, R.Bottom,
SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOZORDER);
end;
end;
}
WM_PAINT:
begin
DC := TWMPaint(Message).DC;
if DC = 0 then
TWMPaint(Message).DC := BeginPaint(ClientHandle, PS);
try
if DC = 0 then
begin
R := cxGetWindowRect(ClientHandle);
R.TopLeft := ScreenToClient(R.TopLeft);
MoveWindowOrg(TWMPaint(Message).DC, -R.Left, -R.Top);
end;
PaintHandler(TWMPaint(Message));
finally
if DC = 0 then
EndPaint(ClientHandle, PS);
end;
end;
else
Default;
end;
end;
procedure TdxCustomRibbonForm.DrawNonClientArea(ADrawCaption: Boolean; AUpdateRegion: HRGN = 1);
var
DC: HDC;
AFlags: Integer;
ARgn: HRGN;
AZoomed: Boolean;
begin
if IsUseAeroNCPaint then Exit;
UpdateWindowStates;
AFlags := DCX_CACHE or DCX_CLIPSIBLINGS or DCX_WINDOW or DCX_VALIDATE;
if AUpdateRegion <> 1 then
begin
ARgn := CreateRectRgnIndirect(cxEmptyRect);
CombineRgn(ARgn, AUpdateRegion, 0, RGN_COPY);
DC := GetDCEx(Handle, ARgn, AFlags or DCX_INTERSECTRGN);
end
else
DC := GetDCEx(Handle, 0, AFlags);
BarCanvas.BeginPaint(DC);
BarCanvas.Canvas.Lock;
try
if IsIconic(Handle) then
RibbonNonClientHelper.DrawWindowCaption(BarCanvas, Caption)
else
begin
AZoomed := IsZoomed(Handle);
if not AZoomed then
RibbonNonClientHelper.DrawWindowBorders(BarCanvas);
if ADrawCaption then
RibbonNonClientHelper.DrawWindowCaption(nil, Caption);
end;
finally
BarCanvas.Canvas.Unlock;
BarCanvas.EndPaint;
ReleaseDC(Handle, DC);
end;
end;
function TdxCustomRibbonForm.HandleWithHelper(ADown: Boolean;
AButton: TMouseButton): Boolean;
var
P: TPoint;
begin
Result := UseSkin;
if Result then
begin
P := GetMouseCursorPos;
if RibbonNonClientHelper.IsInCaptionArea(P.X, P.Y) then
begin
if ADown then
Result := RibbonNonClientHelper.MouseDown(P, AButton)
else
Result := RibbonNonClientHelper.MouseUp(P, AButton);
end
else
Result := False;
end;
end;
procedure TdxCustomRibbonForm.InitializeNewForm;
begin
{$IFDEF DELPHI12}
inherited InitializeNewForm;
{$ENDIF}
FAutoScroll := False;
FUseSkinColor := True;
FAdjustLayoutForNonClientDrawing := True;
AutoScroll := False;
KeyPreview := True;
CreateCornerRegions;
end;
procedure TdxCustomRibbonForm.KeyDown(var Key: Word; Shift: TShiftState);
var
I: Integer;
AIntf: IdxFormKeyPreviewListener;
AForm: TForm;
begin
inherited KeyDown(Key, Shift);
if KeyPreview then
begin
if FormStyle = fsMDIChild then
AForm := Application.MainForm
else
AForm := Self;
for I := 0 to AForm.ControlCount - 1 do
if Supports(TObject(AForm.Controls[I]), IdxFormKeyPreviewListener, AIntf) then
begin
AIntf.FormKeyDown(Key, Shift);
AIntf := nil;
end;
end;
end;
procedure TdxCustomRibbonForm.ModifySystemMenu(ASysMenu: THandle);
procedure UpdateMenuItems(AEnabledItems, ADisabledItems: array of Integer);
var
I: Integer;
begin
for I := 0 to High(AEnabledItems) do
begin
if ((AEnabledItems[I] = SC_MINIMIZE) and not (biMinimize in BorderIcons)) or
((AEnabledItems[I] = SC_MAXIMIZE) and not (biMaximize in BorderIcons)) then
EnableMenuItem(ASysMenu, AEnabledItems[I], MF_BYCOMMAND or MF_GRAYED)
else
EnableMenuItem(ASysMenu, AEnabledItems[I], MF_BYCOMMAND);
end;
for I := 0 to High(ADisabledItems) do
EnableMenuItem(ASysMenu, ADisabledItems[I], MF_BYCOMMAND or MF_GRAYED);
end;
var
AStyles: Cardinal;
begin
if (BorderStyle <> bsNone) and (biSystemMenu in BorderIcons) and (FormStyle <> fsMDIChild) then
begin
AStyles := SetWindowInvisibleStyle(Handle);
if BorderStyle = bsDialog then
begin
DeleteMenu(ASysMenu, SC_TASKLIST, MF_BYCOMMAND);
DeleteMenu(ASysMenu, 7, MF_BYPOSITION);
DeleteMenu(ASysMenu, 5, MF_BYPOSITION);
DeleteMenu(ASysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(ASysMenu, SC_MINIMIZE, MF_BYCOMMAND);
DeleteMenu(ASysMenu, SC_SIZE, MF_BYCOMMAND);
DeleteMenu(ASysMenu, SC_RESTORE, MF_BYCOMMAND);
end
else
case WindowState of
wsNormal:
UpdateMenuItems([SC_MOVE, SC_SIZE, SC_MINIMIZE, SC_MAXIMIZE], [SC_RESTORE]);
wsMaximized:
UpdateMenuItems([SC_MINIMIZE, SC_RESTORE], [SC_MOVE, SC_SIZE, SC_MAXIMIZE]);
wsMinimized:
UpdateMenuItems([SC_MAXIMIZE, SC_RESTORE], [SC_MOVE, SC_SIZE, SC_MINIMIZE]);
end;
SetMenuDefaultItem(ASysMenu, SC_CLOSE, MF_BYCOMMAND);
RestoreWindowStyles(Handle, AStyles);
end;
end;
procedure TdxCustomRibbonForm.Notification(AComponent: TComponent;
Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = FPrevActiveControl) then
FPrevActiveControl := nil;
inherited Notification(AComponent, Operation);
end;
procedure TdxCustomRibbonForm.Resize;
begin
if AlignDisabled then Exit;
inherited Resize;
end;
procedure TdxCustomRibbonForm.ShiftControlsVertically(ADelta: Integer);
var
I: Integer;
R: TRect;
begin
if ADelta = 0 then Exit;
DisableAlign;
try
for I := 0 to ControlCount - 1 do
with Controls[I] do
if Align in [alNone, alCustom] then
begin
if akBottom in Anchors then
begin
if akTop in Anchors then
begin
R := BoundsRect;
Inc(R.Top, ADelta);
BoundsRect := R;
end;
end
else
Top := Top + ADelta;
end;
finally
EnableAlign;
end;
end;
procedure TdxCustomRibbonForm.UpdateNonClientArea;
begin
UpdateWindowStates;
if UseSkin and IsWindowVisible(Handle) then
begin
DrawNonClientArea(False);
RibbonNonClientHelper.UpdateNonClientArea;
end;
end;
procedure TdxCustomRibbonForm.UpdateWindowRegion(AIsMaximized: Boolean);
var
R: TRect;
begin
if IsUseAeroNCPaint then Exit;
if AIsMaximized then
begin
//clip borders
R := cxGetWindowRect(Handle);
OffsetRect(R, -R.Left, -R.Top);
with GetDefaultWindowBordersWidth(Handle) do
R := cxRectInflate(R, -Left, -Top, -Right, -Bottom);
SetRegion(CreateRectRgnIndirect(R), True);
end
else
begin
SetRegion(RibbonNonClientHelper.GetWindowRegion, True);
CalculateCornerRegions;
end;
end;
procedure TdxCustomRibbonForm.UpdateWindowStates;
var
R: TRect;
begin
if UseSkin and not (csDestroying in ComponentState) then
begin
FillChar(FData, SizeOf(TdxRibbonFormData), 0);
if HandleAllocated then
begin
FData.Handle := Handle;
R := cxGetWindowRect(Self);
OffsetRect(R, -R.Left, -R.Top);
FData.Bounds := R;
if IsIconic(Handle) then
FData.State := wsMinimized
else if IsZoomed(Handle) then
FData.State := wsMaximized
else
FData.State := wsNormal;
end;
FData.Active := FIsActive;
FData.Border := BorderStyle;
FData.Style := FormStyle;
FData.DontUseAero := DisableAero or (ParentWindow <> 0);
RibbonNonClientHelper.CheckWindowStates(FData);
end;
end;
procedure TdxCustomRibbonForm.AfterResize(AIsRibbonVisible: Boolean;
ARibbonHeight: Integer; AIsZoomed: Boolean);
procedure CheckGlassFrame;
begin
if IsUseAeroNCPaint then
begin
if AIsZoomed then
SetRegion(0);
CheckExtendFrame(AIsZoomed);
end;
end;
var
ARibbonHandle: THandle;
begin
if AIsRibbonVisible then
begin
ARibbonHandle := RibbonNonClientHelper.Control.Handle;
if IsWindowVisible(ARibbonHandle) then
begin
SendMessage(ARibbonHandle, WM_SETREDRAW, 0, 0);
CheckGlassFrame;
EnableAlign;
if ARibbonHeight <> RibbonNonClientHelper.Control.Height then
begin
UpdateWindow(Handle);
//ensure redraw after restoring minimized ribbon for MDI form
if FormStyle = fsMDIForm then
RedrawWindow(ClientHandle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
SendMessage(ARibbonHandle, WM_SETREDRAW, 1, 0);
RedrawWindow(ARibbonHandle, nil, 0, dxFullRedrawFlags or RDW_UPDATENOW);
end
else
begin
EnableAlign;
CheckGlassFrame;
end;
Resize;
end;
end;
procedure TdxCustomRibbonForm.BeforeResize(out AIsRibbonVisible: Boolean;
out ARibbonHeight: Integer);
begin
AIsRibbonVisible := IsRibbonVisible;
if AIsRibbonVisible then
begin
ARibbonHeight := RibbonNonClientHelper.Control.Height;
DisableAlign;
end
else
ARibbonHeight := -1;
end;
procedure TdxCustomRibbonForm.CalculateCornerRegions;
procedure CalculateRegion(ACornerRgn: HRGN; DX, DY: Integer; const ACornerRect: TRect);
var
R1, R2: HRGN;
begin
R1 := CreateRectRgnIndirect(cxEmptyRect);
GetWindowRgn(Handle, ACornerRgn);
GetWindowRgn(Handle, R1);
OffsetRgn(R1, DX, DY);
CombineRgn(ACornerRgn, ACornerRgn, R1, RGN_DIFF);
R2 := CreateRectRgnIndirect(ACornerRect);
CombineRgn(ACornerRgn, ACornerRgn, R2, RGN_AND);
DeleteObject(R1);
DeleteObject(R2);
end;
var
H: Integer;
begin
H := GetSystemMetrics(SM_CYCAPTION);
CalculateRegion(FCornerRegions[0], FSizingBorders.cx, FSizingBorders.cy,
cxRect(0, 0, H, H));
CalculateRegion(FCornerRegions[1], -FSizingBorders.cx, FSizingBorders.cy,
cxRect(Width - H, 0, Width, H));
CalculateRegion(FCornerRegions[2], -FSizingBorders.cx, -FSizingBorders.cy,
cxRect(Width - H, Height - H, Width, Height));
CalculateRegion(FCornerRegions[3], FSizingBorders.cx, -FSizingBorders.cy,
cxRect(0, Height - H, H, Height));
end;
procedure TdxCustomRibbonForm.CalculateZoomedOffsets;
var
ABData: TAppBarData;
begin
FZoomedBoundsOffsets := cxEmptyRect;
if IsNeedCorrectForAutoHideTaskBar then
begin
FillChar(ABData, sizeof(ABData), 0);
ABData.cbSize := sizeof(ABData);
ABData.hWnd := Handle;
SHAppBarMessage(ABM_GETTASKBARPOS, ABData);
if ABData.uEdge = ABE_LEFT then
FZoomedBoundsOffsets.Left := 1
else if (ABData.uEdge = ABE_TOP) and not IsUseAeroNCPaint then
FZoomedBoundsOffsets.Top := 1
else if ABData.uEdge = ABE_RIGHT then
FZoomedBoundsOffsets.Right := 1 + Ord(IsUseAeroNCPaint)
else if ABData.uEdge = ABE_BOTTOM then
FZoomedBoundsOffsets.Bottom := 1;
end;
end;
procedure TdxCustomRibbonForm.CheckExtendFrame(AZoomed: Boolean);
var
ANonClientHeight: Integer;
begin
if UseSkin and HandleAllocated and IsUseAeroNCPaint then
begin
ANonClientHeight := RibbonNonClientHelper.GetWindowCaptionHeight;
//prevent client area rendering beyond the screen if maximized
if AZoomed and (ANonClientHeight > 0) then
Inc(ANonClientHeight, dxGlassMaximizedNonClientHeight);
ExtendFrameIntoClientAreaAtTop(ANonClientHeight);
end;
end;
function TdxCustomRibbonForm.GetUseSkin: Boolean;
begin
Result := FUseSkin and Assigned(FRibbonNonClientHelper) and
FRibbonNonClientHelper.Control.Visible;
end;
procedure TdxCustomRibbonForm.InvalidateFrame(AWnd: HWND; AUpdate: Boolean = False);
begin
SetWindowPos(AWnd, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or
SWP_NOZORDER or SWP_NOACTIVATE or SWP_DRAWFRAME);
if AUpdate then
UpdateWindow(AWnd);
end;
function TdxCustomRibbonForm.IsNeedCorrectForAutoHideTaskBar: Boolean;
var
ABData : TAppBarData;
begin
FillChar(ABData, sizeof(ABData), 0);
ABData.cbSize := sizeof(ABData);
Result := ((SHAppBarMessage(ABM_GETSTATE, ABData) and ABS_AUTOHIDE) > 0) and
(MonitorFromWindow(FindWindow('Shell_TrayWnd', nil), MONITOR_DEFAULTTONEAREST) = Monitor.Handle);
end;
function TdxCustomRibbonForm.IsNormalWindowState: Boolean;
begin
Result := not (IsIconic(Handle) or IsZoomed(Handle));
end;
function TdxCustomRibbonForm.IsRibbonVisible: Boolean;
begin
Result := UseSkin and RibbonNonClientHelper.Control.HandleAllocated;
end;
procedure TdxCustomRibbonForm.ResetSystemMenu;
begin
if UseSkin and HandleAllocated then
GetSystemMenu(Handle, True);
end;
procedure TdxCustomRibbonForm.ResetWindowRegion;
begin
if not HandleAllocated then Exit;
SetRegion(0);
if IsCompositionEnabled then
begin
FExtendFrameAtTopHeight := -1;
Application.ProcessMessages; //it needs for vista after change window's region
if not UseSkin then
ExtendFrameIntoClientAreaAtTop(0)
else
begin
CheckExtendFrame(WindowState = wsMaximized);
UpdateNonClientArea;
end;
end;
end;
procedure TdxCustomRibbonForm.SetRedraw(ARedraw: Boolean);
begin
if not (HandleAllocated and Visible) then Exit;
if not ARedraw then
begin
Inc(FRedrawCount);
if FRedrawCount = 1 then
SendMessage(Handle, WM_SETREDRAW, 0, 0);
end
else
begin
Dec(FRedrawCount);
if FRedrawCount = 0 then
begin
SendMessage(Handle, WM_SETREDRAW, 1, 0);
FullRedrawWithChildren;
end;
end;
end;
procedure TdxCustomRibbonForm.SetAutoScroll(const Value: Boolean);
begin
//don't change
inherited AutoScroll := False;
end;
procedure TdxCustomRibbonForm.SetBorderStyle(const Value: TFormBorderStyle);
begin
if Value <> BorderStyle then
begin
inherited BorderStyle := Value;
ResetWindowRegion;
ForceUpdateWindowSize;
end;
end;
procedure TdxCustomRibbonForm.SetDisableAero(const Value: Boolean);
begin
if FDisableAero <> Value then
begin
FDisableAero := Value;
ResetGlassFrame;
end;
end;
procedure TdxCustomRibbonForm.SetPrevActiveControl(AValue: TWinControl);
begin
if (AValue <> FPrevActiveControl) then
begin
if Assigned(FPrevActiveControl) then
FPrevActiveControl.RemoveFreeNotification(Self);
FPrevActiveControl := AValue;
if Assigned(FPrevActiveControl) then
FPrevActiveControl.FreeNotification(Self);
end;
end;
procedure TdxCustomRibbonForm.SetRegion(ARegion: HRGN; ARedraw: Boolean = False);
begin
if not HandleAllocated then Exit;
SetWindowRgn(Handle, ARegion, ARedraw and IsWindowVisible(Handle));
end;
{$IFDEF DELPHI10}
procedure TdxCustomRibbonForm.SetRibbonAlwaysOnTop(const Value: Boolean);
begin
if FRibbonAlwaysOnTop <> Value then
begin
FRibbonAlwaysOnTop := Value;
Realign;
end;
end;
{$ENDIF}
procedure TdxCustomRibbonForm.SetRibbonNonClientHelper(const Value: TdxRibbonFormCaptionHelper);
begin
if FRibbonNonClientHelper <> Value then
begin
FRibbonNonClientHelper := Value;
FUseSkin := (Value <> nil) and (FRibbonNonClientHelper <> nil);
FExtendFrameAtTopHeight := -1;
if csDestroying in ComponentState then
FUseSkin := False
else
begin
UpdateWindowStates;
if HandleAllocated then
begin
if dxWMSetSkinnedMessage > 0 then
SendMessage(Handle, dxWMSetSkinnedMessage, Integer(UseSkin), 0);
ResetWindowRegion;
UpdateSystemMenu;
end;
if UseSkin then
RibbonNonClientHelper.CaptionChanged
end;
end;
end;
procedure TdxCustomRibbonForm.SetUseSkinColor(const Value: Boolean);
begin
if FUseSkinColor <> Value then
begin
FUseSkinColor := Value;
if HandleAllocated then
InvalidateRect(Handle, nil, True);
end;
end;
procedure TdxCustomRibbonForm.ShowSystemMenu(AFromMouse: Boolean);
var
P: TPoint;
R: TRect;
begin
if AFromMouse then
P := GetMouseCursorPos
else
begin
R := RibbonNonClientHelper.GetWindowSystemMenuBounds;
P.X := R.Left;
P.Y := R.Bottom;
P := ClientToScreen(P);
end;
RibbonNonClientHelper.ShowSystemMenu(P);
end;
procedure TdxCustomRibbonForm.ResetGlassFrame;
begin
UpdateWindowStates;
if UseSkin and HandleAllocated and IsWindowVisible(Handle) then
begin
SetRedraw(False);
try
ResetWindowRegion;
ForceUpdateWindowSize;
finally
SetRedraw(True);
end;
end;
end;
procedure TdxCustomRibbonForm.UpdateGlassFrame;
begin
UpdateWindowStates;
if UseSkin and HandleAllocated and UseAeroNCPaint(FData) and IsWindowVisible(Handle) then
begin
ResetWindowRegion;
if UseAeroNCPaint(FData) then
begin
FExtendFrameAtTopHeight := -1;
CheckExtendFrame(FData.State = wsMaximized);
RibbonNonClientHelper.CaptionChanged;
end;
end;
end;
procedure TdxCustomRibbonForm.UpdateSystemMenu;
begin
if UseSkin then
begin
RibbonNonClientHelper.InitWindowBorderIcons(GetFormBorderIcons);
ResetSystemMenu;
end;
end;
procedure TdxCustomRibbonForm.CMActionUpdate(var Message: TMessage);
function UpdateControlAction(AControl: TControl): Boolean;
begin
Result := (AControl <> nil) and
AControl.UpdateAction(TBasicAction(Message.LParam));
end;
function ProcessChildren(AContainer: TWinControl): Boolean;
var
I: Integer;
AControl: TControl;
begin
if AContainer.Showing then
for I := 0 to AContainer.ControlCount - 1 do
begin
AControl := AContainer.Controls[I];
if AControl.Visible and UpdateControlAction(AControl) or
(AControl is TWinControl) and ProcessChildren(TWinControl(AControl)) then
begin
Result := True;
Exit;
end;
end;
Result := False;
end;
begin
if (csDesigning in ComponentState) or not Showing then Exit;
if PrevActiveControl is TWinControl then
begin
UpdateControlAction(PrevActiveControl);
Message.Result := 1;
end
else
if UpdateControlAction(ActiveControl) or UpdateControlAction(Self) or ProcessChildren(Self) then
Message.Result := 1;
end;
procedure TdxCustomRibbonForm.CMActivate(var Message: TCMActivate);
begin
FNeedCallActivate := True;
if not FDelayedActivate then
inherited;
end;
procedure TdxCustomRibbonForm.CMColorChanged(var Message: TMessage);
begin
if UseSkin then
begin
if (FormStyle = fsMDIForm) and (ClientHandle <> 0) then
Windows.InvalidateRect(ClientHandle, nil, True);
end;
inherited;
end;
procedure TdxCustomRibbonForm.CMShowingChanged(var Message: TMessage);
function GetNonClientParts: TList;
var
I: Integer;
begin
Result := TList.Create;
for I := 0 to ControlCount - 1 do
if Controls[I].Visible and Supports(TObject(Controls[I]), IdxRibbonFormNonClientPart) then
Result.Add(Controls[I]);
end;
procedure HideRibbonControls(AList: TList);
var
I: Integer;
AControl: TWinControl;
begin
for I := 0 to AList.Count - 1 do
begin
AControl := TWinControl(AList[I]);
if AControl.HandleAllocated then
ShowWindow(AControl.Handle, SW_HIDE);
end;
end;
procedure ShowRibbonControls(AList: TList);
var
I: Integer;
AControl: TWinControl;
begin
for I := 0 to AList.Count - 1 do
begin
AControl := TWinControl(AList[I]);
if AControl.HandleAllocated then
begin
ShowWindow(AControl.Handle, SW_SHOWNA);
UpdateWindow(AControl.Handle);
end;
end;
end;
var
ANonClientParts: TList;
ANeedHideRibbonControls: Boolean;
begin
ANeedHideRibbonControls := Visible and FVisibleChanging;
FDelayedActivate := ANeedHideRibbonControls;
FNeedCallActivate := False;
ANonClientParts := GetNonClientParts;
try
if ANeedHideRibbonControls then
HideRibbonControls(ANonClientParts);
inherited;
finally
UpdateGlassFrame;
if ANeedHideRibbonControls then
ShowRibbonControls(ANonClientParts);
FreeAndNil(ANonClientParts);
FDelayedActivate := False;
if FNeedCallActivate then Perform(CM_ACTIVATE, 0, 0);
end;
end;
procedure TdxCustomRibbonForm.CMVisibleChanged(var Message: TMessage);
var
Animation: Boolean;
begin
FVisibleChanging := True;
try
if UseSkin and Visible and HandleAllocated and (FormStyle = fsMDIChild) then
begin
Animation := GetAnimation;
if Animation then SetAnimation(False);
inherited;
if Animation then SetAnimation(True);
end
else
inherited;
finally
FVisibleChanging := False;
end;
end;
procedure TdxCustomRibbonForm.WMCancelMode(var Message: TWMCancelMode);
begin
if UseSkin then
RibbonNonClientHelper.CancelMode;
inherited;
end;
procedure TdxCustomRibbonForm.WMCaptureChanged(var Message: TMessage);
begin
if UseSkin and (THandle(Message.LParam) <> Handle) then
begin
FSizingLoop := False;
RibbonNonClientHelper.CancelMode;
end;
inherited;
end;
procedure TdxCustomRibbonForm.WMDisplayChange(var Message: TMessage);
var
AWindowPlacement: TWindowPlacement;
AWindowRect, ANormalRect: TRect;
begin
if Useskin and (WindowState = wsMaximized) then
begin
AWindowPlacement.Length := SizeOf(AWindowPlacement);
GetWindowPlacement(Handle, @AWindowPlacement);
GetWindowRect(Handle, AWindowRect);
ANormalRect := AWindowPlacement.rcNormalPosition;
AWindowPlacement.rcNormalPosition := AWindowRect;
SetWindowPlacement(Handle, @AWindowPlacement);
WindowState := wsNormal;
inherited;
WindowState := wsMaximized;
AWindowPlacement.rcNormalPosition := ANormalRect;
SetWindowPlacement(Handle, @AWindowPlacement);
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMEraseBkgnd(var Message: TWMEraseBkgnd);
var
R: TRect;
begin
if UseSkin and (IsUseAeroNCPaint or not DoubleBuffered or (TMessage(Message).wParam = TMessage(Message).lParam)) then
begin
R := ClientRect;
//reduce flickering
if IsUseAeroNCPaint then
Inc(R.Top, FExtendFrameAtTopHeight);
if not cxRectIsEmpty(R) then
FillRectByColor(Message.DC, R, GetBackgroundColor);
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMInitMenu(var Message: TWMInitMenu);
begin
Message.Menu := GetSystemMenu(Handle, False);
inherited;
ModifySystemMenu(Message.Menu);
end;
procedure TdxCustomRibbonForm.WMLButtonDown(var Message: TWMLButtonDown);
begin
if HandleWithHelper(True, mbLeft) then
UpdateNonClientArea
else
inherited;
end;
procedure TdxCustomRibbonForm.WMLButtonUp(var Message: TWMLButtonUp);
begin
if UseSkin then
begin
if HandleWithHelper(False, mbLeft) then
Message.Result := 0
else
begin
RibbonNonClientHelper.CancelMode;
inherited;
end;
end
else inherited
end;
procedure TdxCustomRibbonForm.WMRButtonDown(var Message: TWMRButtonDown);
begin
if HandleWithHelper(True, mbRight) then
Message.Result := 0
else
inherited;
end;
procedure TdxCustomRibbonForm.WMRButtonUp(var Message: TWMRButtonUp);
begin
if HandleWithHelper(False, mbRight) then
Message.Result := 0
else
inherited;
end;
procedure TdxCustomRibbonForm.WMNCRButtonUp(var Message: TWMNCRButtonUp);
begin
if HandleWithHelper(False, mbRight) then
Message.Result := 0
else
inherited;
end;
procedure TdxCustomRibbonForm.WMNCActivate(var Message: TWMNCActivate);
var
AStyles: Cardinal;
begin
FIsActive := Message.Active;
if UseSkin then
begin
UpdateWindowStates;
if (FormStyle = fsMDIChild) or IsUseAeroNCPaint then // AB15017 only on XP
begin // Aero required to call a default method
AStyles := SetWindowInvisibleStyle(Handle);
Message.Result := DefWindowProc(Handle, WM_NCACTIVATE, TMessage(Message).WParam, 0);
RestoreWindowStyles(Handle, AStyles);
end
else
Message.Result := 1; //B20794
if not (csDestroying in ComponentState) then
begin
if not FIsActive then
RibbonNonClientHelper.CancelMode;
UpdateNonClientArea
end;
if (FormStyle = fsMDIForm) and (ActiveMDIChild <> nil) then
ActiveMDIChild.Perform(WM_NCACTIVATE, Ord(IsActive), 0);
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R, SaveR0: TRect;
T: Integer;
AIsZoomed: Boolean;
begin
if not (UseSkin and Visible and not IsIconic(Handle) and not (csReading in ComponentState)) then
inherited
else
begin
if Message.CalcValidRects then
begin
AIsZoomed := IsZoomed(Handle);
if IsUseAeroNCPaint then
begin
T := Message.CalcSize_Params^.rgrc[0].Top;
inherited;
SaveR0 := Message.CalcSize_Params^.rgrc[0];
SaveR0.Top := T;
end
else
begin
R := GetCurrentBordersWidth;
SaveR0 := Message.CalcSize_Params^.rgrc[0];
with Message.CalcSize_Params^.rgrc[0] do
begin
Inc(SaveR0.Top, R.Top);
Dec(SaveR0.Bottom, R.Bottom);
Inc(SaveR0.Left, R.Left);
Dec(SaveR0.Right, R.Right);
end;
end;
if AIsZoomed then
begin
if FormStyle = fsMDIChild then
Inc(SaveR0.Top, GetDefaultWindowNCSize(Handle).Top - RibbonNonClientHelper.GetWindowCaptionHeight)
else
begin
CalculateZoomedOffsets; //check for Taskbar autohide
CorrectZoomedBounds(SaveR0);
end;
end;
Message.CalcSize_Params^.rgrc[0] := SaveR0;
end
else
inherited;
Message.Result := 0;
end;
end;
procedure TdxCustomRibbonForm.WMNCHitTest(var Message: TWMNCHitTest);
var
R: TRect;
P: TPoint;
begin
if UseSkin then
begin
Message.Result := HTNOWHERE;
if IsUseAeroNCPaint then
begin
CallDWMWindowProc(Message);
if Message.Result = HTNOWHERE then
inherited;
if not ((Message.Result = HTCAPTION) or (Message.Result = HTCLIENT)) then
Exit;
Message.Result := HTNOWHERE;
end;
R := cxGetWindowRect(Handle);
P := cxPoint(Message.XPos - R.Left, Message.YPos - R.Top);
if (BorderStyle in [bsSizeable, bsSizeToolWin]) then
CheckResizingNCHitTest(Message.Result, P);
if (Message.Result = HTNOWHERE) and RibbonNonClientHelper.IsInCaptionArea(Message.XPos, Message.YPos) then
RibbonNonClientHelper.GetWindowCaptionHitTest(Message);
if Message.Result = HTNOWHERE then
Message.Result := HTCLIENT;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMShowWindow(var Message: TMessage);
begin
inherited;
if WordBool(Message.WParam) and UseSkin and IsNormalWindowState then
begin
//for a showing MDIChild on vista without DWM
//make sure for WM_SIZE & WM_NCCALCSIZE
SetWindowPos(Handle, 0, 0, 0, Width, Height, SWP_NOZORDER or SWP_NOACTIVATE or
SWP_NOMOVE or SWP_FRAMECHANGED);
RibbonNonClientHelper.InitWindowBorderIcons(GetFormBorderIcons);
CaptionChanged;
end;
end;
procedure TdxCustomRibbonForm.WMNCPaint(var Message: TMessage);
begin
if UseSkin then
begin
if IsUseAeroNCPaint then
inherited;
DrawNonClientArea(False, Message.WParam);
Message.Result := 0;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMPaint(var Message: TWMPaint);
begin
if UseSkin then
begin
UpdateWindowStates;
if IsUseAeroNCPaint then
ExcludeRibbonPaintArea(Message.DC);
inherited;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMSize(var Message: TWMSize);
var
AIsRibbonVisible: Boolean;
ARibbonHeight: Integer;
begin
if UseSkin and not (csReading in ComponentState) then
begin
UpdateWindowStates;
BeforeResize(AIsRibbonVisible, ARibbonHeight);
try
RibbonNonClientHelper.Resize;
inherited;
FSizingBorders.cx := GetSystemMetrics(SM_CXSIZEFRAME);
FSizingBorders.cy := GetSystemMetrics(SM_CYSIZEFRAME);
UpdateWindowRegion(Message.SizeType = SIZE_MAXIMIZED);
finally
AfterResize(AIsRibbonVisible, ARibbonHeight, Message.SizeType = SIZE_MAXIMIZED);
end;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMSysCommand(var Message: TWMSysCommand);
var
ACommand: Word;
Animation: Boolean;
begin
if UseSkin then
begin
ACommand := Message.CmdType and $FFF0;
if (ACommand = SC_KEYMENU) and (Message.Key = $20) then
begin
ShowSystemMenu(False);
Message.Result := 0;
end
else
begin
if (FormStyle = fsMDIChild) and ((ACommand = SC_MAXIMIZE) or
(ACommand = SC_MINIMIZE) or (ACommand = SC_RESTORE))then
begin
Animation := GetAnimation;
if Animation then SetAnimation(False);
inherited;
if Animation then SetAnimation(True);
end
else
inherited;
case ACommand of
SC_MAXIMIZE, SC_RESTORE:
UpdateNonClientArea;
else
UpdateWindowStates;
end;
end;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
UpdateWindowStates;
inherited;
end;
procedure TdxCustomRibbonForm.WMDWMCompositionChanged(var Message: TMessage);
begin
inherited;
if UseSkin then
begin
ResetGlassFrame;
Message.Result := 0;
end;
end;
procedure TdxCustomRibbonForm.WndProc(var Message: TMessage);
begin
if not UseSkin then
inherited WndProc(Message)
else
with Message do
begin
case Msg of
WM_SYSMENU:
begin
if IsWindowEnabled(Handle) then //B136020
ShowSystemMenu(True);
Result := 0;
end;
WM_ENTERSIZEMOVE:
begin
FSizingLoop := True;
inherited WndProc(Message);
end;
WM_EXITSIZEMOVE:
begin
FSizingLoop := False;
inherited WndProc(Message);
UpdateNonClientArea;
end;
WM_NCUAHDRAWCAPTION,
WM_NCUAHDRAWFRAME:
begin
if IsUseAeroNCPaint then
CallDWMWindowProc(Message);
DrawNonClientArea(True);
Message.Result := 0;
end;
WM_QUERYOPEN, WM_EXITMENULOOP: //WM_MENUCHAR
begin
ResetSystemMenu;
inherited WndProc(Message);
end;
WM_MOUSEACTIVATE, WM_SYNCPAINT:
begin
inherited WndProc(Message);
DrawNonClientArea(True);
end;
WM_NCLBUTTONDOWN:
begin
if not IsUseAeroNCPaint then
UpdateWindow(Handle);
inherited WndProc(Message);
if IsIconic(Handle) then
begin
DrawNonClientArea(True);
Result := 0;
end;
end;
WM_NCMOUSELEAVE:
begin
if IsUseAeroNCPaint then
CallDWMWindowProc(Message)
else
inherited;
end;
WM_LBUTTONDOWN:
begin
//dmAutomatic suppress a dispatching
if (DragMode = dmAutomatic) and not IsUseAeroNCPaint then
if HandleWithHelper(True, mbLeft) then
Exit;
inherited;
end;
else
if (dxWMGetSkinnedMessage <> 0) and (Msg = dxWMGetSkinnedMessage) then
begin
Result := Ord(UseSkin);
Exit;
end;
inherited;
end;
end;
end;
function TdxCustomRibbonForm.IsUseAeroNCPaint: Boolean;
begin
Result := UseAeroNCPaint(FData);
end;
procedure TdxCustomRibbonForm.CheckResizingNCHitTest(var AHitTest: Integer; const P: TPoint);
const
CornerHitTests: array[0..3] of DWORD = (HTTOPLEFT, HTTOPRIGHT, HTBOTTOMRIGHT, HTBOTTOMLEFT);
var
I: Integer;
R, RW: TRect;
begin
if not IsNormalWindowState then Exit;
for I := 0 to 3 do
if PtInRegion(FCornerRegions[I], P.X, P.Y) then
begin
AHitTest := CornerHitTests[I];
Break;
end;
if AHitTest = HTNOWHERE then
begin
RW := cxGetWindowRect(Handle);
OffsetRect(RW, -RW.Left, -RW.Top);
R := RW;
R.Bottom := R.Top + FSizingBorders.cy;
if cxRectPtIn(R, P) then
AHitTest := HTTOP
else
if not IsUseAeroNCPaint then
begin
R := RW;
R.Left := R.Right - FSizingBorders.cx;
if cxRectPtIn(R, P) then
AHitTest := HTRIGHT
else
begin
R := RW;
R.Top := R.Bottom - FSizingBorders.cy;
if cxRectPtIn(R, P) then
AHitTest := HTBOTTOM
else
begin
R := RW;
R.Right := R.Left + FSizingBorders.cx;
if cxRectPtIn(R, P) then
AHitTest := HTLEFT;
end;
end;
end;
end;
end;
procedure TdxCustomRibbonForm.CreateCornerRegions;
var
I: Integer;
begin
for I := 0 to 3 do
FCornerRegions[I] := CreateRectRgnIndirect(cxEmptyRect);
end;
procedure TdxCustomRibbonForm.DestroyCornerRegions;
var
I: Integer;
begin
for I := 0 to 3 do
DeleteObject(FCornerRegions[I]);
end;
procedure TdxCustomRibbonForm.ExcludeRibbonPaintArea(DC: HDC);
var
R, CR: HRGN;
ARibbonRect: TRect;
begin
if FExtendFrameAtTopHeight = 0 then Exit;
R := GetClipRegion(DC);
ARibbonRect := cxRect(0, 0, ClientWidth, FExtendFrameAtTopHeight);
CR := CreateRectRgnIndirect(ARibbonRect);
SelectClipRgn(DC, CR);
FillRect(DC, ARibbonRect, GetStockObject(BLACK_BRUSH));
CombineRgn(R, R, CR, RGN_DIFF);
SelectClipRgn(DC, R);
DeleteObject(R);
DeleteObject(CR);
end;
procedure TdxCustomRibbonForm.ForceUpdateWindowSize;
begin
if UseSkin and HandleAllocated then
begin
if not UseAeroNCPaint(FData) and IsNormalWindowState then
begin
SetRegion(RibbonNonClientHelper.GetWindowRegion, True);
CalculateCornerRegions;
end;
RibbonNonClientHelper.CaptionChanged;
end;
end;
procedure TdxCustomRibbonForm.FullRedrawWithChildren;
begin
WinControlFullInvalidate(Self, True, True);
end;
procedure TdxCustomRibbonForm.ExtendFrameIntoClientAreaAtTop(AHeight: Integer);
var
M: TdxMargins;
DC: HDC;
R: TRect;
begin
if HandleAllocated and (FExtendFrameAtTopHeight <> AHeight) then
begin
if AHeight > FExtendFrameAtTopHeight then
begin
R := cxRect(0, FExtendFrameAtTopHeight, Width, AHeight);
if not FVisibleChanging then
Inc(R.Left, 100);
if not cxRectIsEmpty(R) then
begin
DC := GetWindowDC(Handle);
FillRect(DC, R, GetStockObject(BLACK_BRUSH));
ReleaseDC(Handle, DC);
end;
end;
FExtendFrameAtTopHeight := AHeight;
M.cxLeftWidth := 0;
M.cxRightWidth := 0;
M.cyBottomHeight := 0;
M.cyTopHeight := AHeight;
DwmExtendFrameIntoClientArea(Handle, @M);
if IsWindowVisible(Handle) then
RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_UPDATENOW);
end;
end;
function TdxCustomRibbonForm.GetFormBorderIcons: TBorderIcons;
var
ABorderStyle: TFormBorderStyle;
begin
ABorderStyle := BorderStyle;
if (FormStyle = fsMDIChild) and (ABorderStyle in [bsNone, bsDialog]) then
ABorderStyle := bsSizeable;
Result := BorderIcons;
case ABorderStyle of
bsNone: Result := [];
bsDialog: Result := (Result * [biSystemMenu, biHelp]) - [biMaximize];
bsToolWindow,
bsSizeToolWin: Result := Result * [biSystemMenu];
end;
end;
procedure TdxCustomRibbonForm.CorrectZoomedBounds(var R: TRect);
begin
Inc(R.Left, FZoomedBoundsOffsets.Left);
Inc(R.Top, FZoomedBoundsOffsets.Top);
Dec(R.Right, FZoomedBoundsOffsets.Right);
Dec(R.Bottom, FZoomedBoundsOffsets.Bottom);
end;
function TdxCustomRibbonForm.GetCurrentBordersWidth: TRect;
begin
if IsZoomed(Handle) then
begin
Result := GetDefaultWindowBordersWidth(Handle);
if FormStyle = fsMDIChild then
Result.Top := 0;
end
else
Result := RibbonNonClientHelper.GetWindowBordersWidth;
end;
function TdxCustomRibbonForm.GetBorderStyle: TFormBorderStyle;
begin
Result := inherited BorderStyle;
end;
function TdxCustomRibbonForm.GetBackgroundColor: TColor;
begin
if UseSkin and UseSkinColor then
Result := RibbonNonClientHelper.GetWindowColor
else
Result := Color;
end;
procedure TdxCustomRibbonForm.WMGetText(var Message: TWMGetText);
var
L: Integer;
begin
if (csLoading in ComponentState) or UseSkin then
begin
L := Length(FCaption) + 1; //include the terminating null character
if Message.TextMax < L then
L := Message.TextMax;
if L > 1 then
Move(Pointer(FCaption)^, Pointer(Message.Text)^, L * SizeOf(Char));
Message.Result := L - 1;
end
else
inherited;
end;
procedure TdxCustomRibbonForm.WMGetTextLength(var Message: TWMGetTextLength);
begin
if (csLoading in ComponentState) or UseSkin then
Message.Result := Length(FCaption)
else
inherited;
end;
procedure TdxCustomRibbonForm.WMSetText(var Message: TWMSetText);
function IsMaximizedChildForRibbonForm: Boolean;
var
AForm: TdxCustomRibbonForm;
begin
Result := False;
if (FormStyle = fsMDIChild) and IsZoomed(Handle) and
(Application.MainForm is TdxCustomRibbonForm) then
begin
AForm := TdxCustomRibbonForm(Application.MainForm);
Result := AForm.UseSkin;
end;
end;
procedure UpdateMDIForm;
begin
if IsMaximizedChildForRibbonForm then
TdxCustomRibbonForm(Application.MainForm).CaptionChanged;
end;
begin
if (csLoading in ComponentState) or UseSkin then
begin
FCaption := Message.Text;
if UseSkin then
begin
CaptionChanged;
UpdateMDIForm;
Perform(CM_TEXTCHANGED, 0, 0);
if GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_APPWINDOW = WS_EX_APPWINDOW then
SetWindowTextWithoutRedraw(Handle, RibbonNonClientHelper.GetTaskBarCaption);
end
else
begin
inherited;
UpdateMDIForm;
end;
end
else
begin
if not IsThemeActive and IsMaximizedChildForRibbonForm then
begin
Perform(CM_TEXTCHANGED, 0, 0);
SetWindowTextWithoutRedraw(Handle, Message.Text);
end
else
inherited;
UpdateMDIForm;
end;
end;
initialization
if Win32MajorVersion >= 6 then
BufferedPaintInit;
finalization
if Win32MajorVersion >= 6 then
BufferedPaintUnInit;
end.