git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@55 05c56307-c608-d34a-929d-697000501d7a
509 lines
17 KiB
ObjectPascal
509 lines
17 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressQuantumGrid Utils }
|
|
{ }
|
|
{ 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 EXPRESSQUANTUMGRID 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 cxGridStdPopupMenu;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFNDEF DELPHI5}
|
|
cxClasses,
|
|
{$ENDIF}
|
|
Windows, Classes, Menus, cxGridMenuOperations, cxGridCustomPopupMenu,
|
|
cxGridFooterPopupMenuItems, cxGridHeaderPopupMenuItems, cxGridCustomView,
|
|
Graphics, ImgList;
|
|
|
|
type
|
|
TPopupMenuClass = class of TPopupMenu;
|
|
|
|
{ TcxMenuItem }
|
|
|
|
TcxMenuItem = class(TMenuItem)
|
|
end;
|
|
|
|
TStdGridPopupMenu = class(TPopupMenu, IDoPopup)
|
|
private
|
|
procedure InitItems(AItems: TMenuItem);
|
|
protected
|
|
{$IFDEF DELPHI7}
|
|
procedure AdvancedDrawItemD7(Sender: TObject; ACanvas: TCanvas;
|
|
ARect: TRect; State: TOwnerDrawState); virtual;
|
|
{$ENDIF}
|
|
procedure ClearOperations;
|
|
procedure CreateMenuItems; virtual;
|
|
{$IFDEF DELPHI5}
|
|
procedure DoPopup(Sender: TObject); override;
|
|
{$ENDIF}
|
|
procedure GridMenuPopup(ASenderMenu: TComponent;
|
|
AHitTest: TcxCustomGridHitTest; X,Y: Integer); virtual;
|
|
function GetPopupHandler: TcxGridOnPopupProc; virtual;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
{$IFNDEF DELPHI5}
|
|
procedure Popup(X, Y: Integer); override;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
TcxGridStdHeaderMenu = class(TStdGridPopupMenu);
|
|
|
|
TcxGridStdFooterMenu = class(TStdGridPopupMenu);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Dialogs, SysUtils, cxGridTableView;
|
|
|
|
{ TStdGridPopupMenu }
|
|
|
|
constructor TStdGridPopupMenu.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Images := cxGridPopupMenuImages;
|
|
CreateMenuItems;
|
|
end;
|
|
|
|
destructor TStdGridPopupMenu.Destroy;
|
|
begin
|
|
ClearOperations;
|
|
{$IFDEF DELPHI5}
|
|
Items.Clear;
|
|
{$ELSE}
|
|
while Items.Count > 0 do
|
|
Items[0].Free;
|
|
{$ENDIF}
|
|
inherited;
|
|
end;
|
|
|
|
{$IFDEF DELPHI7}
|
|
procedure TStdGridPopupMenu.AdvancedDrawItemD7(Sender: TObject;
|
|
ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState);
|
|
const
|
|
Alignments: array[TPopupAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
|
|
EdgeStyle: array[Boolean] of Longint = (BDR_RAISEDINNER, BDR_SUNKENOUTER);
|
|
var
|
|
ImageList: TCustomImageList;
|
|
ParentMenu: TMenu;
|
|
Alignment: TPopupAlignment;
|
|
DrawImage, DrawGlyph: Boolean;
|
|
GlyphRect, SaveRect: TRect;
|
|
DrawStyle: Longint;
|
|
OldBrushColor: TColor;
|
|
Selected: Boolean;
|
|
|
|
procedure NormalDraw;
|
|
var
|
|
AMenuItem: TcxMenuItem;
|
|
begin
|
|
AMenuItem := TcxMenuItem(Sender);
|
|
with ACanvas do
|
|
begin
|
|
if (odSelected in State) or (odHotLight in State) then
|
|
begin
|
|
Brush.Color := clMenuHighlight;
|
|
Font.Color := clHighlightText;
|
|
end;
|
|
{ With XP, we need to always fill in the rect, even when selected }
|
|
FillRect(ARect);
|
|
if ParentMenu is TMenu then
|
|
Alignment := paLeft
|
|
else if ParentMenu is TPopupMenu then
|
|
Alignment := TPopupMenu(ParentMenu).Alignment
|
|
else
|
|
Alignment := paLeft;
|
|
GlyphRect.Left := ARect.Left + 1;
|
|
GlyphRect.Top := ARect.Top + 1;
|
|
if AMenuItem.Caption = cLineCaption then
|
|
begin
|
|
FillRect(ARect);
|
|
GlyphRect.Left := 0;
|
|
GlyphRect.Right := -4;
|
|
DrawGlyph := False;
|
|
end
|
|
else
|
|
begin
|
|
DrawImage := (ImageList <> nil) and ((AMenuItem.ImageIndex > -1) and
|
|
(AMenuItem.ImageIndex < ImageList.Count));
|
|
if DrawImage then
|
|
begin
|
|
DrawGlyph := True;
|
|
GlyphRect.Right := GlyphRect.Left + ImageList.Width;
|
|
GlyphRect.Bottom := GlyphRect.Top + ImageList.Height;
|
|
|
|
{ Draw background pattern brush if selected }
|
|
if AMenuItem.Checked then
|
|
begin
|
|
Inc(GlyphRect.Right);
|
|
Inc(GlyphRect.Bottom);
|
|
OldBrushColor := Brush.Color;
|
|
if not (odSelected in State) then
|
|
begin
|
|
OldBrushColor := Brush.Color;
|
|
Brush.Bitmap := AllocPatternBitmap(clBtnFace, clBtnHighlight);
|
|
FillRect(GlyphRect);
|
|
end
|
|
else
|
|
begin
|
|
Brush.Color := clBtnFace;
|
|
FillRect(GlyphRect);
|
|
end;
|
|
Brush.Color := OldBrushColor;
|
|
Inc(GlyphRect.Left);
|
|
Inc(GlyphRect.Top);
|
|
end;
|
|
ImageList.Draw(ACanvas, GlyphRect.Left, GlyphRect.Top,
|
|
AMenuItem.ImageIndex, AMenuItem.Enabled);
|
|
if AMenuItem.Checked then
|
|
begin
|
|
Dec(GlyphRect.Right);
|
|
Dec(GlyphRect.Bottom);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (ImageList <> nil) then
|
|
begin
|
|
GlyphRect.Right := GlyphRect.Left + ImageList.Width;
|
|
GlyphRect.Bottom := GlyphRect.Top + ImageList.Height;
|
|
end;
|
|
DrawGlyph := False;
|
|
end;
|
|
end;
|
|
with GlyphRect do
|
|
begin
|
|
Dec(Left);
|
|
Dec(Top);
|
|
Inc(Right, 2);
|
|
Inc(Bottom, 2);
|
|
end;
|
|
if AMenuItem.Checked and DrawGlyph then
|
|
DrawEdge(ACanvas.Handle, GlyphRect, EdgeStyle[AMenuItem.Checked], BF_RECT);
|
|
if Selected then
|
|
begin
|
|
if DrawGlyph then ARect.Left := GlyphRect.Right + 1;
|
|
Brush.Color := clHighlight;
|
|
FillRect(ARect);
|
|
end;
|
|
if not (Selected and DrawGlyph) then
|
|
ARect.Left := GlyphRect.Right + 1;
|
|
Inc(ARect.Left, 2);
|
|
Dec(ARect.Right, 1);
|
|
DrawStyle := DT_EXPANDTABS or DT_SINGLELINE or Alignments[Alignment];
|
|
{ Calculate vertical layout }
|
|
SaveRect := ARect;
|
|
if odDefault in State then
|
|
Font.Style := [fsBold];
|
|
AMenuItem.DoDrawText(ACanvas, AMenuItem.Caption, ARect,
|
|
Selected, DrawStyle or DT_CALCRECT or DT_NOCLIP);
|
|
OffsetRect(ARect, 0, ((SaveRect.Bottom - SaveRect.Top) - (ARect.Bottom - ARect.Top)) div 2);
|
|
AMenuItem.DoDrawText(ACanvas, AMenuItem.Caption, ARect, Selected, DrawStyle);
|
|
if AMenuItem.ShortCut <> 0 then
|
|
begin
|
|
ARect.Left := ARect.Right;
|
|
ARect.Right := SaveRect.Right - 10;
|
|
AMenuItem.DoDrawText(ACanvas, ShortCutToText(AMenuItem.ShortCut), ARect, Selected, DT_RIGHT);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure BiDiDraw;
|
|
var
|
|
AMenuItem: TcxMenuItem;
|
|
S: string;
|
|
begin
|
|
AMenuItem := TcxMenuItem(Sender);
|
|
with ACanvas do
|
|
begin
|
|
if (odSelected in State) or (odHotLight in State) then
|
|
begin
|
|
Brush.Color := clMenuHighlight;
|
|
Font.Color := clHighlightText;
|
|
end;
|
|
FillRect(ARect);
|
|
if ParentMenu is TMenu then
|
|
Alignment := paLeft
|
|
else if ParentMenu is TPopupMenu then
|
|
Alignment := TPopupMenu(ParentMenu).Alignment
|
|
else
|
|
Alignment := paLeft;
|
|
GlyphRect.Right := ARect.Right - 1;
|
|
GlyphRect.Top := ARect.Top + 1;
|
|
if AMenuItem.Caption = cLineCaption then
|
|
begin
|
|
FillRect(ARect);
|
|
GlyphRect.Left := GlyphRect.Right + 2;
|
|
GlyphRect.Right := 0;
|
|
DrawGlyph := False;
|
|
end
|
|
else
|
|
begin
|
|
DrawImage := (ImageList <> nil) and ((AMenuItem.ImageIndex > -1) and
|
|
(AMenuItem.ImageIndex < ImageList.Count));
|
|
if DrawImage then
|
|
begin
|
|
DrawGlyph := True;
|
|
GlyphRect.Left := GlyphRect.Right - ImageList.Width;
|
|
GlyphRect.Bottom := GlyphRect.Top + ImageList.Height;
|
|
{ Draw background pattern brush if selected }
|
|
if AMenuItem.Checked then
|
|
begin
|
|
Dec(GlyphRect.Left);
|
|
Inc(GlyphRect.Bottom);
|
|
OldBrushColor := Brush.Color;
|
|
if not (odSelected in State) then
|
|
begin
|
|
OldBrushColor := Brush.Color;
|
|
Brush.Bitmap := AllocPatternBitmap(clBtnFace, clBtnHighlight);
|
|
FillRect(GlyphRect);
|
|
end
|
|
else
|
|
begin
|
|
Brush.Color := clBtnFace;
|
|
FillRect(GlyphRect);
|
|
end;
|
|
Brush.Color := OldBrushColor;
|
|
Dec(GlyphRect.Right);
|
|
Inc(GlyphRect.Top);
|
|
end;
|
|
ImageList.Draw(ACanvas, GlyphRect.Left, GlyphRect.Top,
|
|
AMenuItem.ImageIndex, AMenuItem.Enabled);
|
|
if AMenuItem.Checked then
|
|
begin
|
|
Dec(GlyphRect.Right);
|
|
Dec(GlyphRect.Bottom);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (ImageList <> nil) then
|
|
begin
|
|
GlyphRect.Left := GlyphRect.Right - ImageList.Width;
|
|
GlyphRect.Bottom := GlyphRect.Top + ImageList.Height;
|
|
end;
|
|
DrawGlyph := False;
|
|
end;
|
|
end;
|
|
with GlyphRect do
|
|
begin
|
|
Dec(Left);
|
|
Dec(Top);
|
|
Inc(Right, 2);
|
|
Inc(Bottom, 2);
|
|
end;
|
|
if AMenuItem.Checked and DrawGlyph then
|
|
DrawEdge(ACanvas.Handle, GlyphRect, EdgeStyle[AMenuItem.Checked], BF_RECT);
|
|
if Selected then
|
|
begin
|
|
if DrawGlyph then ARect.Right := GlyphRect.Left - 1;
|
|
Brush.Color := clHighlight;
|
|
FillRect(ARect);
|
|
end;
|
|
if not (Selected and DrawGlyph) then
|
|
ARect.Right := GlyphRect.Left - 1;
|
|
Inc(ARect.Left, 2);
|
|
Dec(ARect.Right, 1);
|
|
DrawStyle := DT_EXPANDTABS or DT_SINGLELINE or Alignments[Alignment];
|
|
{ Calculate vertical layout }
|
|
SaveRect := ARect;
|
|
if odDefault in State then
|
|
Font.Style := [fsBold];
|
|
AMenuItem.DoDrawText(ACanvas, AMenuItem.Caption, ARect, Selected,
|
|
DrawStyle or DT_CALCRECT or DT_NOCLIP);
|
|
{ the DT_CALCRECT does not take into account alignment }
|
|
ARect.Left := SaveRect.Left;
|
|
ARect.Right := SaveRect.Right;
|
|
OffsetRect(ARect, 0, ((SaveRect.Bottom - SaveRect.Top) - (ARect.Bottom - ARect.Top)) div 2);
|
|
AMenuItem.DoDrawText(ACanvas, AMenuItem.Caption, ARect, Selected, DrawStyle);
|
|
if AMenuItem.ShortCut <> 0 then
|
|
begin
|
|
S := ShortCutToText(AMenuItem.ShortCut);
|
|
ARect.Left := 10;
|
|
ARect.Right := ARect.Left + ACanvas.TextWidth(S);
|
|
AMenuItem.DoDrawText(ACanvas, S, ARect, Selected, DT_RIGHT);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
ParentMenu := TMenuItem(Sender).GetParentMenu;
|
|
ImageList := ParentMenu.Images;
|
|
Selected := odSelected in State;
|
|
if (ParentMenu <> nil) and (not ParentMenu.IsRightToLeft) then
|
|
NormalDraw
|
|
else
|
|
BiDiDraw;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TStdGridPopupMenu.ClearOperations;
|
|
procedure DoClearOperations(AItems: TMenuItem);
|
|
var
|
|
I: Integer;
|
|
AOperation: TcxGridPopupMenuOperation;
|
|
begin
|
|
for I := 0 to AItems.Count - 1 do
|
|
begin
|
|
AOperation := TcxGridPopupMenuOperation(AItems[I].Tag);
|
|
FreeAndNil(AOperation);
|
|
DoClearOperations(AItems[I]);
|
|
end;
|
|
end;
|
|
begin
|
|
DoClearOperations(Items);
|
|
end;
|
|
|
|
procedure TStdGridPopupMenu.CreateMenuItems;
|
|
procedure InsertNewGroup(AItems: TMenuItem);
|
|
var
|
|
AItem: TcxMenuItem;
|
|
begin
|
|
AItem := TcxMenuItem.Create(Self);
|
|
AItem.Caption := '-';
|
|
AItems.Add(AItem);
|
|
end;
|
|
|
|
function GetMenuItemByOperationClass(const AItems: TMenuItem;
|
|
AClass: TcxGridPopupMenuOperationClass): TMenuItem;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to AItems.Count - 1 do
|
|
if (AItems[I].Caption <> '-') and
|
|
Assigned(TcxGridPopupMenuOperation(AItems[I].Tag)) then
|
|
if (TcxGridPopupMenuOperation(AItems[I].Tag).ClassType = AClass) then
|
|
begin
|
|
Result := AItems[I];
|
|
Break;
|
|
end
|
|
else
|
|
begin
|
|
Result := GetMenuItemByOperationClass(AItems[I], AClass);
|
|
If Assigned(Result) then break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
AMenuItem, ASubMenuItem: TMenuItem;
|
|
AOperation: TcxGridPopupMenuOperation;
|
|
AOperationHolder: Integer;
|
|
begin
|
|
if cxGridPopupMenuOperations = nil then exit;
|
|
for I := 0 to cxGridPopupMenuOperations.Count - 1 do
|
|
begin
|
|
if (cxGridPopupMenuOperations[I].OperationClass.GetPopupMenuClass =
|
|
Self.ClassType) or Self.ClassType.InheritsFrom(
|
|
cxGridPopupMenuOperations[I].OperationClass.GetPopupMenuClass) then
|
|
begin
|
|
AMenuItem := TcxMenuItem.Create(Self);
|
|
{$IFDEF DELPHI7}
|
|
if (Win32MajorVersion >= 5) and (Win32MinorVersion >= 1) then
|
|
AMenuItem.OnAdvancedDrawItem := AdvancedDrawItemD7
|
|
else
|
|
AMenuItem.OnAdvancedDrawItem := nil;
|
|
{$ENDIF}
|
|
AOperation := cxGridPopupMenuOperations[I].OperationClass.Create(AMenuItem);
|
|
AOperationHolder := Integer(AOperation);
|
|
AMenuItem.Tag := Variant(AOperationHolder);
|
|
if AOperation.BeginGroup then InsertNewGroup(Items);
|
|
if Assigned(AOperation.Handler) then
|
|
AMenuItem.OnClick := AOperation.DoExecute;
|
|
AMenuItem.ImageIndex := cxGridPopupMenuOperations[I].ImageIndex;
|
|
if AOperation.GetSubOperationClass <> nil then
|
|
begin
|
|
ASubMenuItem := GetMenuItemByOperationClass(Items, AOperation.GetSubOperationClass);
|
|
if Assigned(ASubMenuItem) then ASubMenuItem.Add(TMenuItem(AOperation.MenuItem));
|
|
end
|
|
else
|
|
Items.Add(TMenuItem(AOperation.MenuItem));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TStdGridPopupMenu.InitItems(AItems: TMenuItem);
|
|
var
|
|
I: Integer;
|
|
AOperation: TcxGridPopupMenuOperation;
|
|
begin
|
|
if AItems.Count > 0 then
|
|
for I := 0 to AItems.Count - 1 do
|
|
begin
|
|
if AItems[I].Count > 0 then InitItems(AItems[I]);
|
|
AOperation := TcxGridPopupMenuOperation(AItems[I].Tag);
|
|
if Assigned(AOperation) then
|
|
begin
|
|
AItems[I].Enabled := AOperation.Enabled;
|
|
AItems[I].Checked := AOperation.Down;
|
|
AItems[I].Visible := AOperation.Visible;
|
|
AItems[I].Caption := AOperation.Caption;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF DELPHI5}
|
|
procedure TStdGridPopupMenu.DoPopup(Sender: TObject);
|
|
begin
|
|
InitItems(Items);
|
|
inherited DoPopup(Sender);
|
|
end;
|
|
{$ELSE}
|
|
procedure TStdGridPopupMenu.Popup(X, Y: Integer);
|
|
begin
|
|
InitItems(Items);
|
|
inherited Popup(X, Y);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TStdGridPopupMenu.GetPopupHandler: TcxGridOnPopupProc;
|
|
begin
|
|
Result := GridMenuPopup;
|
|
end;
|
|
|
|
procedure TStdGridPopupMenu.GridMenuPopup(ASenderMenu: TComponent;
|
|
AHitTest: TcxCustomGridHitTest; X, Y: Integer);
|
|
begin
|
|
Popup(X, Y);
|
|
end;
|
|
|
|
initialization
|
|
RegisterPopupMenuClass(TcxGridStdHeaderMenu, [gvhtColumnHeader],
|
|
TcxGridTableView);
|
|
RegisterPopupMenuClass(TcxGridStdFooterMenu,
|
|
[gvhtFooterCell, gvhtGroupFooterCell], TcxGridTableView);
|
|
end.
|
|
|