diff --git a/Lib/D2006/placeholder.txt b/Lib/D2006/placeholder.txt new file mode 100644 index 0000000..e69de29 diff --git a/Lib/D7/placeholder.txt b/Lib/D7/placeholder.txt new file mode 100644 index 0000000..e69de29 diff --git a/Packages/X2CLGLReg.pas b/Packages/X2CLGLReg.pas index 2c1300e..f3aa4f0 100644 --- a/Packages/X2CLGLReg.pas +++ b/Packages/X2CLGLReg.pas @@ -21,7 +21,8 @@ uses procedure Register; begin - RegisterComponents('X²Software', [TX2GraphicContainer, TX2GraphicList]); + RegisterComponents('X2Software', [TX2GraphicContainer, TX2GraphicList]); + RegisterPropertyEditor(TypeInfo(TX2GraphicCollection), TX2GraphicContainer, 'Graphics', TX2GraphicsProperty); RegisterComponentEditor(TX2GraphicContainer, TX2GraphicContainerEditor); RegisterComponentEditor(TX2GraphicList, TX2GraphicListEditor); diff --git a/Packages/X2CLMBReg.pas b/Packages/X2CLMBReg.pas new file mode 100644 index 0000000..688cc06 --- /dev/null +++ b/Packages/X2CLMBReg.pas @@ -0,0 +1,29 @@ +{ + :: Registers the MenuBar components + :: + :: Last changed: $Date$ + :: Revision: $Rev$ + :: Author: $Author$ +} +unit X2CLMBReg; + +interface + procedure Register; + +implementation +uses + Classes, + DesignIntf, + X2CLMenuBar, + X2CLmusikCubePainter; + +{.$R ..\Resources\MenuBar.dcr} + +procedure Register; +begin + RegisterComponents('X2Software', [TX2MenuBar, + TX2MenuBarmusikCubePainter]); +end; + +end. + diff --git a/Source/X2CLMenuBar.pas b/Source/X2CLMenuBar.pas new file mode 100644 index 0000000..38ce87e --- /dev/null +++ b/Source/X2CLMenuBar.pas @@ -0,0 +1,1306 @@ +{ + :: X2CLMenuBar is a generic group/items menu. Through the various painters, + :: it can resemble styles such as the musikCube or BBox/Uname-IT menu bars. + :: + :: Last changed: $Date$ + :: Revision: $Rev$ + :: Author: $Author$ +} +unit X2CLMenuBar; + +interface +uses + Classes, + Contnrs, + Controls, + Forms, + Graphics, + ImgList, + Messages, + Windows; + +type + // #ToDo1 (MvR) 19-3-2006: implement collection Update mechanisms + // #ToDo1 (MvR) 19-3-2006: group ImageIndex + // #ToDo1 (MvR) 19-3-2006: OnCollapsing/OnCollapse/expand events + // #ToDo1 (MvR) 19-3-2006: AutoCollapse property + // #ToDo1 (MvR) 19-3-2006: AutoSelectItem property or something + // #ToDo1 (MvR) 19-3-2006: find a way to remember the selected item per + // group, required for when AutoCollapse = True and + // AutoSelectItem = True + TX2MenuBarPainterClass = class of TX2MenuBarPainter; + TX2MenuBarPainter = class; + TX2MenuBarItem = class; + TX2MenuBarGroup = class; + TX2CustomMenuBar = class; + + IX2MenuBarPainterObserver = interface + ['{22DE60C9-49A1-4E7D-B547-901BEDCC0FB7}'] + procedure PainterUpdate(Sender: TX2MenuBarPainter); + end; + + TX2MenuBarHitTest = record + HitTestCode: Integer; + Item: TObject; + end; + + TX2MenuBarDrawState = (mdsHot, mdsSelected); + TX2MenuBarDrawStates = set of TX2MenuBarDrawState; + + TX2MenuBarAnimationStyle = (asNone, asSlide); + + { + :$ Abstract animation class + + :: Descendants implement the animation-specific drawing code. + } + TX2MenuBarAnimator = class(TObject) + private + FAnimationTime: Cardinal; + FExpanding: Boolean; + FGroup: TX2MenuBarGroup; + FMenuBar: TX2CustomMenuBar; + FStartTime: Cardinal; + FItemsBuffer: Graphics.TBitmap; + FTerminated: Boolean; + + function GetTimeElapsed(): Cardinal; + protected + procedure Terminate(); virtual; + + property ItemsBuffer: Graphics.TBitmap read FItemsBuffer; + property MenuBar: TX2CustomMenuBar read FMenuBar write FMenuBar; + property TimeElapsed: Cardinal read GetTimeElapsed; + public + constructor Create(AItemsBuffer: Graphics.TBitmap); virtual; + destructor Destroy(); override; + + function PrepareHitPoint(APoint: TPoint): TPoint; virtual; + function Draw(ACanvas: TCanvas; const ABounds: TRect): Integer; virtual; abstract; + + property AnimationTime: Cardinal read FAnimationTime write FAnimationTime; + property Expanding: Boolean read FExpanding write FExpanding; + property Group: TX2MenuBarGroup read FGroup write FGroup; + property Terminated: Boolean read FTerminated; + end; + + { + :$ Implements a sliding animation + } + TX2MenuBarSlideAnimator = class(TX2MenuBarAnimator) + private + FSlidePos: Integer; + FSlideHeight: Integer; + public + function PrepareHitPoint(APoint: TPoint): TPoint; override; + function Draw(ACanvas: TCanvas; const ABounds: TRect): Integer; override; + end; + + { + :$ Abstract painter class. + + :: Descendants must implement the actual drawing code. + } + TX2MenuBarPainter = class(TComponent) + private + FAnimationStyle: TX2MenuBarAnimationStyle; + FAnimationTime: Cardinal; + FMenuBar: TX2CustomMenuBar; + FObservers: TInterfaceList; + + function GetMenuBar(): TX2CustomMenuBar; + protected + procedure BeginPaint(const AMenuBar: TX2CustomMenuBar); + procedure EndPaint(); + + function GetGroupHeaderHeight(AGroup: TX2MenuBarGroup): Integer; virtual; abstract; + function GetGroupHeight(AGroup: TX2MenuBarGroup): Integer; virtual; + function GetItemHeight(AItem: TX2MenuBarItem): Integer; virtual; abstract; + + procedure DrawBackground(ACanvas: TCanvas; const ABounds: TRect); virtual; abstract; + procedure DrawGroupHeader(ACanvas: TCanvas; AGroup: TX2MenuBarGroup; const ABounds: TRect; AState: TX2MenuBarDrawStates); virtual; abstract; + procedure DrawItem(ACanvas: TCanvas; AItem: TX2MenuBarItem; const ABounds: TRect; AState: TX2MenuBarDrawStates); virtual; abstract; + + function CreateAnimator(AItemsBuffer: Graphics.TBitmap): TX2MenuBarAnimator; virtual; + + procedure NotifyObservers(); + + property MenuBar: TX2CustomMenuBar read GetMenuBar; + protected + property AnimationStyle: TX2MenuBarAnimationStyle read FAnimationStyle write FAnimationStyle; + property AnimationTime: Cardinal read FAnimationTime write FAnimationTime; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy(); override; + + function HitTest(APoint: TPoint): TX2MenuBarHitTest; overload; virtual; + function HitTest(AX, AY: Integer): TX2MenuBarHitTest; overload; + + procedure AttachObserver(AObserver: IX2MenuBarPainterObserver); + procedure DetachObserver(AObserver: IX2MenuBarPainterObserver); + end; + + { + :$ Contains a single menu item. + } + TX2MenuBarItem = class(TCollectionItem) + private + FCaption: String; + FData: TObject; + FOwnsData: Boolean; + FImageIndex: TImageIndex; + + function GetGroup(): TX2MenuBarGroup; + function GetMenuBar(): TX2CustomMenuBar; + procedure SetCaption(const Value: String); + procedure SetData(const Value: TObject); + procedure SetImageIndex(const Value: TImageIndex); + public + constructor Create(Collection: TCollection); override; + destructor Destroy(); override; + + procedure Assign(Source: TPersistent); override; + + property Data: TObject read FData write SetData; + property Group: TX2MenuBarGroup read GetGroup; + property MenuBar: TX2CustomMenuBar read GetMenuBar; + property OwnsData: Boolean read FOwnsData write FOwnsData; + published + property Caption: String read FCaption write SetCaption; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + end; + + { + :$ Manages a collection of menu items. + } + TX2MenuBarItems = class(TOwnedCollection) + private + function GetItem(Index: Integer): TX2MenuBarItem; + procedure SetItem(Index: Integer; const Value: TX2MenuBarItem); + public + constructor Create(AOwner: TPersistent); + + function Add(const ACaption: TCaption = ''): TX2MenuBarItem; + + property Items[Index: Integer]: TX2MenuBarItem read GetItem write SetItem; default; + end; + + { + :$ Contains a single menu group. + } + TX2MenuBarGroup = class(TCollectionItem) + private + FCaption: String; + FExpanded: Boolean; + FItems: TX2MenuBarItems; + FData: TObject; + FOwnsData: Boolean; + + function GetMenuBar(): TX2CustomMenuBar; + procedure SetCaption(const Value: String); + procedure SetExpanded(const Value: Boolean); + procedure SetItems(const Value: TX2MenuBarItems); + procedure SetData(const Value: TObject); + public + constructor Create(Collection: TCollection); override; + destructor Destroy(); override; + + procedure Assign(Source: TPersistent); override; + + property Data: TObject read FData write SetData; + property MenuBar: TX2CustomMenuBar read GetMenuBar; + property OwnsData: Boolean read FOwnsData write FOwnsData; + published + property Caption: String read FCaption write SetCaption; + property Expanded: Boolean read FExpanded write SetExpanded; + property Items: TX2MenuBarItems read FItems write SetItems; + end; + + { + :$ Manages a collection of menu groups. + } + TX2MenuBarGroups = class(TOwnedCollection) + private + function GetItem(Index: Integer): TX2MenuBarGroup; + procedure SetItem(Index: Integer; const Value: TX2MenuBarGroup); + public + constructor Create(AOwner: TPersistent); + + function Add(const ACaption: TCaption = ''): TX2MenuBarGroup; + + property Items[Index: Integer]: TX2MenuBarGroup read GetItem write SetItem; default; + end; + + { + :$ Implements the menu bar. + + :: The menu bar is the visual container for the menu. It manages the groups + :: and items, and implements the switching between menu items. It does not + :: paint itself, instead it delegates this to it's linked Painter. + } + TX2CustomMenuBar = class(TCustomControl, IX2MenuBarPainterObserver) + private + FBorderStyle: TBorderStyle; + FGroups: TX2MenuBarGroups; + FPainter: TX2MenuBarPainter; + FHotItem: TObject; + FSelectedItem: TObject; + FImageList: TCustomImageList; + FAnimator: TX2MenuBarAnimator; + FLastMousePos: TPoint; + + procedure SetBorderStyle(const Value: TBorderStyle); + procedure SetGroups(const Value: TX2MenuBarGroups); + procedure SetImageList(const Value: TCustomImageList); + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure PainterUpdate(Sender: TX2MenuBarPainter); + + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; +// procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + + procedure TestMousePos(); virtual; + protected + procedure SetPainter(const Value: TX2MenuBarPainter); virtual; + + procedure WMEraseBkgnd(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure Paint(); override; + + function GetDrawState(AItem: TObject): TX2MenuBarDrawStates; + function DrawMenu(ACanvas: TCanvas; const ABounds: TRect): Integer; virtual; + function DrawMenuItems(ACanvas: TCanvas; AGroup: TX2MenuBarGroup; const ABounds: TRect): Integer; virtual; + procedure DrawNoPainter(ACanvas: TCanvas; const ABounds: TRect); virtual; + + function AllowInteraction(): Boolean; virtual; + procedure AnimateExpand(AGroup: TX2MenuBarGroup; AExpanding: Boolean); + + property Animator: TX2MenuBarAnimator read FAnimator write FAnimator; + property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone; + protected + function ExpandedChanging(AGroup: TX2MenuBarGroup; AExpanding: Boolean): Boolean; virtual; + procedure ExpandedChanged(AGroup: TX2MenuBarGroup); virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy(); override; + + function HitTest(APoint: TPoint): TX2MenuBarHitTest; overload; + function HitTest(AX, AY: Integer): TX2MenuBarHitTest; overload; + + property Groups: TX2MenuBarGroups read FGroups write SetGroups; + property ImageList: TCustomImageList read FImageList write SetImageList; + property Painter: TX2MenuBarPainter read FPainter write SetPainter; + end; + + { + :$ Exposes the menu bar's published properties. + } + TX2MenuBar = class(TX2CustomMenuBar) + published + property Align; + property BevelEdges; + property BevelInner; + property BevelKind; + property BevelOuter; + property BorderStyle; + property BorderWidth; + property Groups; + property ImageList; + property OnClick; + property OnDblClick; + property OnEnter; + property OnExit; + property OnMouseActivate; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnResize; + property Painter; + end; + + { + :$ Provides a wrapper for the DrawText API. + } + TDrawTextClipStyle = (csNone, csEllipsis, csPathEllipsis); + + procedure DrawText(ACanvas: TCanvas; const AText: String; + const ABounds: TRect; + AHorzAlignment: TAlignment = taLeftJustify; + AVertAlignment: TVerticalAlignment = taVerticalCenter; + AMultiLine: Boolean = False; + AClipStyle: TDrawTextClipStyle = csNone); + + +const + { HitTest Codes } + htUnknown = 0; + htBackground = 1; + htGroup = 2; + htItem = 3; + +implementation +uses + SysUtils; + +const + DefaultAnimationStyle = asSlide; + DefaultAnimationTime = 250; + SDefaultItemCaption = 'Menu Item'; + SDefaultGroupCaption = 'Group'; + SNoPainter = 'Painter property not set'; + + +{ DrawText wrapper } +procedure DrawText(ACanvas: TCanvas; const AText: String; + const ABounds: TRect; AHorzAlignment: TAlignment; + AVertAlignment: TVerticalAlignment; + AMultiLine: Boolean; AClipStyle: TDrawTextClipStyle); +const + HorzAlignmentFlags: array[TAlignment] of Cardinal = + (DT_LEFT, DT_RIGHT, DT_CENTER); + VertAlignmentFlags: array[TVerticalAlignment] of Cardinal = + (DT_TOP, DT_BOTTOM, DT_VCENTER); + MultiLineFlags: array[Boolean] of Cardinal = + (DT_SINGLELINE, 0); + ClipStyleFlags: array[TDrawTextClipStyle] of Cardinal = + (0, DT_END_ELLIPSIS, DT_PATH_ELLIPSIS); + +var + flags: Cardinal; + bounds: TRect; + +begin + flags := HorzAlignmentFlags[AHorzAlignment] or + VertAlignmentFlags[AVertAlignment] or + MultiLineFlags[AMultiLine] or + ClipStyleFlags[AClipStyle]; + + if AMultiLine and (AClipStyle <> csNone) then + flags := flags or DT_EDITCONTROL; + + bounds := ABounds; + Windows.DrawText(ACanvas.Handle, PChar(AText), Length(AText), bounds, flags); +end; + + +{ TX2MenuBarPainter } +constructor TX2MenuBarPainter.Create(AOwner: TComponent); +begin + inherited; + + FAnimationStyle := DefaultAnimationStyle; + FAnimationTime := DefaultAnimationTime; + + if AOwner is TX2CustomMenuBar then + FMenuBar := TX2CustomMenuBar(AOwner); +end; + +destructor TX2MenuBarPainter.Destroy(); +begin + FreeAndNil(FObservers); + inherited; +end; + + +procedure TX2MenuBarPainter.AttachObserver(AObserver: IX2MenuBarPainterObserver); +begin + if not Assigned(FObservers) then + FObservers := TInterfaceList.Create(); + + if FObservers.IndexOf(AObserver) = -1 then + FObservers.Add(AObserver); +end; + +procedure TX2MenuBarPainter.DetachObserver(AObserver: IX2MenuBarPainterObserver); +begin + if Assigned(FObservers) then + FObservers.Remove(AObserver); +end; + + +procedure TX2MenuBarPainter.BeginPaint(const AMenuBar: TX2CustomMenuBar); +begin + Assert(not Assigned(FMenuBar), 'BeginPaint already called'); + FMenuBar := AMenuBar; +end; + +procedure TX2MenuBarPainter.EndPaint(); +begin + Assert(Assigned(FMenuBar), 'EndPaint without BeginPaint'); + FMenuBar := nil; +end; + +procedure TX2MenuBarPainter.NotifyObservers(); +var + observerIndex: Integer; + +begin + if Assigned(FObservers) then + for observerIndex := 0 to Pred(FObservers.Count) do + (FObservers[observerIndex] as IX2MenuBarPainterObserver).PainterUpdate(Self); +end; + + +function TX2MenuBarPainter.GetGroupHeight(AGroup: TX2MenuBarGroup): Integer; +var + itemIndex: Integer; + +begin + Result := 0; + for itemIndex := 0 to Pred(AGroup.Items.Count) do + Inc(Result, GetItemHeight(AGroup.Items[itemIndex])); +end; + + +function TX2MenuBarPainter.CreateAnimator(AItemsBuffer: Graphics.TBitmap): TX2MenuBarAnimator; +begin + Result := nil; + + case AnimationStyle of + asSlide: Result := TX2MenuBarSlideAnimator.Create(AItemsBuffer); + end; + + if Assigned(Result) then + Result.AnimationTime := AnimationTime; +end; + + +function TX2MenuBarPainter.HitTest(APoint: TPoint): TX2MenuBarHitTest; +var + hitRect: TRect; + groupIndex: Integer; + group: TX2MenuBarGroup; + itemIndex: Integer; + item: TX2MenuBarItem; + +begin + Result.HitTestCode := htUnknown; + Result.Item := nil; + hitRect := Rect(0, 0, MenuBar.ClientWidth, 0); + + for groupIndex := 0 to Pred(MenuBar.Groups.Count) do + begin + group := MenuBar.Groups[groupIndex]; + hitRect.Bottom := hitRect.Top + GetGroupHeaderHeight(group); + + if PtInRect(hitRect, APoint) then + begin + Result.HitTestCode := htGroup; + Result.Item := group; + break; + end; + + hitRect.Top := hitRect.Bottom; + if group.Expanded then + begin + for itemIndex := 0 to Pred(group.Items.Count) do + begin + item := group.Items[itemIndex]; + hitRect.Bottom := hitRect.Top + GetItemHeight(item); + + if PtInRect(hitRect, APoint) then + begin + Result.HitTestCode := htItem; + Result.Item := item; + break; + end; + + hitRect.Top := hitRect.Bottom; + end; + + if Result.HitTestCode <> htUnknown then + break; + end; + end; +end; + +function TX2MenuBarPainter.HitTest(AX, AY: Integer): TX2MenuBarHitTest; +begin + Result := HitTest(Point(AX, AY)); +end; + + +function TX2MenuBarPainter.GetMenuBar(): TX2CustomMenuBar; +begin + Assert(Assigned(FMenuBar), 'BeginPaint not called'); + Result := FMenuBar; +end; + + +{ TX2MenuBarAnimator } +constructor TX2MenuBarAnimator.Create(AItemsBuffer: Graphics.TBitmap); +begin + inherited Create(); + + FStartTime := GetTickCount(); + FItemsBuffer := Graphics.TBitmap.Create(); + FItemsBuffer.Assign(AItemsBuffer); +end; + +destructor TX2MenuBarAnimator.Destroy(); +begin + FreeAndNil(FItemsBuffer); + + inherited; +end; + + +function TX2MenuBarAnimator.GetTimeElapsed(): Cardinal; +var + currentTime: Cardinal; + +begin + currentTime := GetTickCount(); + Result := currentTime - FStartTime; + + if currentTime < FStartTime then + Inc(Result, High(Cardinal)); +end; + +procedure TX2MenuBarAnimator.Terminate(); +begin + FTerminated := True; +end; + + +function TX2MenuBarAnimator.PrepareHitPoint(APoint: TPoint): TPoint; +begin + Result := APoint; +end; + +{ TX2MenuBarSlideAnimator } +function TX2MenuBarSlideAnimator.PrepareHitPoint(APoint: TPoint): TPoint; +begin + Result := inherited PrepareHitPoint(APoint); + + { While expanding / collapsing, Group.Expanded has already changed. HitTest + uses this data to determine if items should be taken into account. We must + compensate for that while sliding. } + if Expanding then + begin + if Result.Y > (FSlidePos + FSlideHeight) then + Inc(Result.Y, ItemsBuffer.Height - FSlideHeight); + end + else + if Result.Y >= FSlidePos then + if Result.Y <= FSlidePos + FSlideHeight then + Result.Y := -1 + else + Dec(Result.Y, FSlideHeight); +end; + +function TX2MenuBarSlideAnimator.Draw(ACanvas: TCanvas; const ABounds: TRect): Integer; +var + elapsed: Cardinal; + sourceRect: TRect; + destRect: TRect; + +begin + elapsed := TimeElapsed; + FSlidePos := ABounds.Top; + FSlideHeight := Trunc((elapsed / AnimationTime) * ItemsBuffer.Height); + if not Expanding then + FSlideHeight := ItemsBuffer.Height - FSlideHeight; + + Result := FSlideHeight; + + sourceRect := Rect(0, 0, ItemsBuffer.Width, FSlideHeight); + destRect := ABounds; + destRect.Bottom := destRect.Top + FSlideHeight; + ACanvas.CopyRect(destRect, ItemsBuffer.Canvas, sourceRect); + + if elapsed >= AnimationTime then + Terminate(); +end; + + +{ TX2MenuBarItem } +constructor TX2MenuBarItem.Create(Collection: TCollection); +begin + inherited; + + FCaption := SDefaultItemCaption; +end; + +destructor TX2MenuBarItem.Destroy(); +begin + if OwnsData then + FreeAndNil(FData); + + inherited; +end; + + +function TX2MenuBarItem.GetGroup(): TX2MenuBarGroup; +begin + Result := nil; + + if Assigned(Collection) and (Collection.Owner <> nil) and + (Collection.Owner is TX2MenuBarGroup) then + Result := TX2MenuBarGroup(Collection.Owner); +end; + +function TX2MenuBarItem.GetMenuBar(): TX2CustomMenuBar; +var + group: TX2MenuBarGroup; + +begin + Result := nil; + group := GetGroup(); + if Assigned(group) then + Result := group.MenuBar; +end; + +procedure TX2MenuBarItem.Assign(Source: TPersistent); +begin + if Source is TX2MenuBarItem then + with TX2MenuBarItem(Source) do + begin + Self.Caption := Caption; + Self.Data := Data; + Self.OwnsData := OwnsData; + end + else + inherited; +end; + + +procedure TX2MenuBarItem.SetCaption(const Value: String); +begin + if Value <> FCaption then + begin + FCaption := Value; + Changed(False); + end; +end; + +procedure TX2MenuBarItem.SetData(const Value: TObject); +begin + if Value <> FData then + begin + if FOwnsData then + FreeAndNil(FData); + + FData := Value; + end; +end; + +procedure TX2MenuBarItem.SetImageIndex(const Value: TImageIndex); +begin + if Value <> FImageIndex then + begin + FImageIndex := Value; + Changed(False); + end; +end; + + +{ TX2MenuBarItems } +constructor TX2MenuBarItems.Create(AOwner: TPersistent); +begin + inherited Create(AOwner, TX2MenuBarItem); +end; + + +function TX2MenuBarItems.Add(const ACaption: TCaption): TX2MenuBarItem; +begin + Result := TX2MenuBarItem(inherited Add()); + Result.Caption := ACaption; +end; + + +function TX2MenuBarItems.GetItem(Index: Integer): TX2MenuBarItem; +begin + Result := TX2MenuBarItem(inherited GetItem(Index)); +end; + +procedure TX2MenuBarItems.SetItem(Index: Integer; const Value: TX2MenuBarItem); +begin + inherited SetItem(Index, Value); +end; + + +{ TX2MenuBarGroup } +constructor TX2MenuBarGroup.Create(Collection: TCollection); +begin + inherited; + + FCaption := SDefaultGroupCaption; + FItems := TX2MenuBarItems.Create(Self); +end; + +destructor TX2MenuBarGroup.Destroy(); +begin + FreeAndNil(FItems); + + if OwnsData then + FreeAndNil(FData); + + inherited; +end; + + +procedure TX2MenuBarGroup.Assign(Source: TPersistent); +begin + if Source is TX2MenuBarGroup then + with TX2MenuBarGroup(Source) do + begin + Self.Caption := Caption; + Self.Items.Assign(Items); + end + else + inherited; +end; + + +function TX2MenuBarGroup.GetMenuBar(): TX2CustomMenuBar; +begin + Result := nil; + + if Assigned(Collection) and (Collection.Owner <> nil) and + (Collection.Owner is TX2CustomMenuBar) then + Result := TX2CustomMenuBar(Collection.Owner); +end; + +procedure TX2MenuBarGroup.SetCaption(const Value: String); +begin + if Value <> FCaption then + begin + FCaption := Value; + Changed(False); + end; +end; + +procedure TX2MenuBarGroup.SetData(const Value: TObject); +begin + if Value <> FData then + begin + if FOwnsData then + FreeAndNil(FData); + + FData := Value; + end; +end; + +procedure TX2MenuBarGroup.SetExpanded(const Value: Boolean); +var + menu: TX2CustomMenuBar; + +begin + if Value <> FExpanded then + begin + menu := MenuBar; + if Assigned(menu) then + menu.ExpandedChanging(Self, Value); + + FExpanded := Value; + Changed(False); + + if Assigned(menu) then + menu.ExpandedChanged(Self); + end; +end; + +procedure TX2MenuBarGroup.SetItems(const Value: TX2MenuBarItems); +begin + if Value <> FItems then + begin + FItems.Assign(Value); + Changed(False); + end; +end; + + +{ TX2MenuBarGroups } +constructor TX2MenuBarGroups.Create(AOwner: TPersistent); +begin + inherited Create(AOwner, TX2MenuBarGroup); +end; + + +function TX2MenuBarGroups.Add(const ACaption: TCaption): TX2MenuBarGroup; +begin + Result := TX2MenuBarGroup(inherited Add()); + if Length(ACaption) > 0 then + Result.Caption := ACaption; +end; + + +function TX2MenuBarGroups.GetItem(Index: Integer): TX2MenuBarGroup; +begin + Result := TX2MenuBarGroup(inherited GetItem(Index)); +end; + +procedure TX2MenuBarGroups.SetItem(Index: Integer; const Value: TX2MenuBarGroup); +begin + inherited SetItem(Index, Value); +end; + +{ TX2CustomMenuBar } +constructor TX2CustomMenuBar.Create(AOwner: TComponent); +begin + inherited; + + FBorderStyle := bsNone; + FGroups := TX2MenuBarGroups.Create(Self); +end; + +procedure TX2CustomMenuBar.CreateParams(var Params: TCreateParams); +const + BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER); + +begin + inherited; + + { Source: TScrollBox.CreateParams } + with Params do + begin + Style := Style or BorderStyles[FBorderStyle]; + + if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then + begin + Style := Style and not WS_BORDER; + ExStyle := ExStyle or WS_EX_CLIENTEDGE; + end; + end; +end; + +destructor TX2CustomMenuBar.Destroy(); +begin + FreeAndNil(FGroups); + + inherited; +end; + +procedure TX2CustomMenuBar.WMEraseBkgnd(var Msg: TWMEraseBkgnd); +begin + Msg.Result := 0; +end; + +procedure TX2CustomMenuBar.Paint(); +var + buffer: Graphics.TBitmap; + +begin + if Assigned(Painter) then + begin + buffer := Graphics.TBitmap.Create(); + try + buffer.PixelFormat := pf24bit; + buffer.Width := Self.ClientWidth; + buffer.Height := Self.ClientHeight; + + Painter.BeginPaint(Self); + try + Painter.DrawBackground(buffer.Canvas, Self.ClientRect); + DrawMenu(buffer.Canvas, Self.ClientRect); + finally + Painter.EndPaint(); + end; + finally + Self.Canvas.Draw(0, 0, buffer); + FreeAndNil(buffer); + end; + + if Assigned(Animator) then + begin + if Animator.Terminated then + FreeAndNil(FAnimator); + + TestMousePos(); + Invalidate(); + end; + end + else + DrawNoPainter(Self.Canvas, Self.ClientRect); +end; + + +function TX2CustomMenuBar.GetDrawState(AItem: TObject): TX2MenuBarDrawStates; +begin + Result := []; + + if AItem = FHotItem then + Include(Result, mdsHot); + + if AItem = FSelectedItem then + Include(Result, mdsSelected); +end; + +function TX2CustomMenuBar.DrawMenu(ACanvas: TCanvas; const ABounds: TRect): Integer; +var + groupIndex: Integer; + group: TX2MenuBarGroup; + groupBounds: TRect; + drawState: TX2MenuBarDrawStates; + +begin + groupBounds := ABounds; + + for groupIndex := 0 to Pred(Groups.Count) do + begin + { Group header } + group := Groups[groupIndex]; + groupBounds.Bottom := groupBounds.Top + + Painter.GetGroupHeaderHeight(group); + + if groupBounds.Bottom > ABounds.Bottom then + break; + + drawState := GetDrawState(group); + Painter.DrawGroupHeader(ACanvas, group, groupBounds, drawState); + groupBounds.Top := groupBounds.Bottom; + + if Assigned(Animator) and (Animator.Group = group) then + begin + { Animated group } + groupBounds.Bottom := ABounds.Bottom; + Inc(groupBounds.Top, Animator.Draw(ACanvas, groupBounds)); + end else + begin + { Items } + if group.Expanded and (groupBounds.Top <= ABounds.Bottom) then + begin + groupBounds.Bottom := ABounds.Bottom; + Inc(groupBounds.Top, DrawMenuItems(ACanvas, group, groupBounds)); + end; + end; + end; + + Result := groupBounds.Top - ABounds.Top; +end; + +function TX2CustomMenuBar.DrawMenuItems(ACanvas: TCanvas; + AGroup: TX2MenuBarGroup; + const ABounds: TRect): Integer; +var + itemIndex: Integer; + item: TX2MenuBarItem; + itemBounds: TRect; + drawState: TX2MenuBarDrawStates; + +begin + itemBounds := ABounds; + + for itemIndex := 0 to Pred(AGroup.Items.Count) do + begin + item := AGroup.Items[itemIndex]; + itemBounds.Bottom := itemBounds.Top + Painter.GetItemHeight(item); + + if itemBounds.Bottom <= ABounds.Bottom then + begin + drawState := GetDrawState(item); + Painter.DrawItem(ACanvas, item, itemBounds, drawState); + end; + + itemBounds.Top := itemBounds.Bottom; + end; + + Result := itemBounds.Top - ABounds.Top; +end; + +procedure TX2CustomMenuBar.DrawNoPainter(ACanvas: TCanvas; const ABounds: TRect); +const + XorColor = $00FFD8CE; // RGB(206, 216, 255) + +begin + with ACanvas do + begin + Brush.Color := clBtnFace; + FillRect(ABounds); + + Pen.Style := psDot; + Pen.Mode := pmXor; + Pen.Color := XorColor; + Brush.Style := bsClear; + Rectangle(ABounds); + + DrawText(ACanvas, SNoPainter, ABounds, taCenter); + end; +end; + + +function TX2CustomMenuBar.ExpandedChanging(AGroup: TX2MenuBarGroup; + AExpanding: Boolean): Boolean; +begin + // #ToDo1 (MvR) 20-3-2006: raise event + + AnimateExpand(AGroup, AExpanding); + + Result := True; +end; + +procedure TX2CustomMenuBar.ExpandedChanged(AGroup: TX2MenuBarGroup); +begin + // #ToDo1 (MvR) 20-3-2006: raise event +end; + + +function TX2CustomMenuBar.AllowInteraction(): Boolean; +begin + Result := not Assigned(Animator); +end; + + +procedure TX2CustomMenuBar.AnimateExpand(AGroup: TX2MenuBarGroup; AExpanding: Boolean); +var + itemsBuffer: Graphics.TBitmap; + itemsBounds: TRect; + +begin + Assert(not Assigned(Animator), 'Already animating'); + if not Assigned(Painter) then + exit; + + Painter.BeginPaint(Self); + try + itemsBuffer := Graphics.TBitmap.Create(); + try + itemsBuffer.PixelFormat := pf24bit; + itemsBuffer.Width := Self.ClientWidth; + itemsBuffer.Height := Painter.GetGroupHeight(AGroup); + itemsBounds := Rect(0, 0, itemsBuffer.Width, itemsBuffer.Height); + + // #ToDo3 (MvR) 23-3-2006: this will probably cause problems if we ever + // want a bitmapped/customdrawn background. + // Maybe we can trick around a bit with the + // canvas offset? think about it later. + Painter.DrawBackground(itemsBuffer.Canvas, itemsBounds); + DrawMenuItems(itemsBuffer.Canvas, AGroup, itemsBounds); + + Animator := Painter.CreateAnimator(itemsBuffer); + if Assigned(Animator) then + begin + Animator.Group := AGroup; + Animator.Expanding := AExpanding; + end; + finally + FreeAndNil(itemsBuffer); + end; + finally + Painter.EndPaint(); + Invalidate(); + end; + +// Painter.BeginPaint(Self); +// try +// groupBounds := Painter.GetGroupBounds(AGroup, ClientRect); +// menuBitmap.Width := Self.ClientWidth; +// menuBitmap.Height := Self.ClientHeight; +// Painter.DrawBackground(menuBitmap.Canvas, ClientRect); +// DrawMenu(menuBitmap.Canvas, ClientRect); +// finally +// Painter.EndPaint(); +// end; +// + { Pre-paint the parts which will be animated } +// Animator.Top.Width := Self.ClientWidth; +// Animator.Top.Height := groupBounds.Top; +// Animator.Top.Canvas.Draw(0, 0, menuBitmap); +// +// Animator.Group.Width := Self.ClientWidth; +// Animator.Group.Height := groupBounds.Bottom - groupBounds.Top; +// Animator.Group.Canvas.Draw(0, -groupBounds.Top, menuBitmap); +// +// Animator.Bottom.Width := Self.ClientWidth; +// Animator.Bottom.Height := Self.ClientHeight - groupBounds.Bottom; +// Animator.Bottom.Canvas.Draw(0, -groupBounds.Bottom, menuBitmap); +// finally +// FreeAndNil(menuBitmap); +// end; + +// Animator.Expanding := AExpanding; +// Animator.Max := 250; +// timeStart := GetTickCount(); +// repeat +// timeNow := GetTickCount(); +// Animator.Position := timeNow - timeStart; +// +// Invalidate(); +// Application.ProcessMessages(); +// // #ToDo1 (MvR) 20-3-2006: wait for paint cycle (event)? +// Sleep(0); +// until (timeNow > timeStart + 250) or (timeNow < timeStart); +// finally +// EndAnimate(); +// end; +end; + + +function TX2CustomMenuBar.HitTest(APoint: TPoint): TX2MenuBarHitTest; +var + hitPoint: TPoint; + +begin + Result.HitTestCode := htUnknown; + Result.Item := nil; + hitPoint := APoint; + + { Sliding animations alter the position of the underlying groups } + if Assigned(Animator) then + hitPoint := Animator.PrepareHitPoint(hitPoint); + + if PtInRect(Self.ClientRect, APoint) then + begin + Painter.BeginPaint(Self); + try + Result := Painter.HitTest(hitPoint); + finally + Painter.EndPaint(); + end; + end; +end; + +function TX2CustomMenuBar.HitTest(AX, AY: Integer): TX2MenuBarHitTest; +begin + Result := HitTest(Point(AX, AY)); +end; + + +procedure TX2CustomMenuBar.Notification(AComponent: TComponent; Operation: TOperation); +begin + if Operation = opRemove then + if AComponent = FPainter then + begin + FPainter := nil; + Invalidate(); + end else if AComponent = FImageList then + begin + FImageList := nil; + Invalidate(); + end; + + inherited; +end; + +procedure TX2CustomMenuBar.PainterUpdate(Sender: TX2MenuBarPainter); +begin + Invalidate(); +end; + + +procedure TX2CustomMenuBar.MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); +var + hitTest: TX2MenuBarHitTest; + group: TX2MenuBarGroup; + +begin + if AllowInteraction then + begin + hitTest := Self.HitTest(X, Y); + + if hitTest.HitTestCode = htGroup then + begin + group := TX2MenuBarGroup(hitTest.Item); + if group.Items.Count > 0 then + begin + hitTest.Item := FSelectedItem; + group.Expanded := not group.Expanded; + Invalidate(); + end; + end; + + if hitTest.Item <> FSelectedItem then + begin + FSelectedItem := hitTest.Item; + Invalidate(); + end; + end; + + inherited; +end; + +procedure TX2CustomMenuBar.MouseMove(Shift: TShiftState; X, Y: Integer); +begin + FLastMousePos := Point(X, Y); + TestMousePos(); + + inherited; +end; + +//procedure TX2CustomMenuBar.MouseUp(Button: TMouseButton; Shift: TShiftState; +// X, Y: Integer); +//begin +// inherited; +//end; + +procedure TX2CustomMenuBar.CMMouseLeave(var Message: TMessage); +begin + FLastMousePos := Point(-1, -1); + FHotItem := nil; + Invalidate(); +end; + +procedure TX2CustomMenuBar.TestMousePos(); +var + hitTest: TX2MenuBarHitTest; + +begin + hitTest := Self.HitTest(FLastMousePos.X, FLastMousePos.Y); + if hitTest.Item <> FHotItem then + begin + FHotItem := hitTest.Item; + Invalidate(); + end; +end; + + +procedure TX2CustomMenuBar.SetBorderStyle(const Value: TBorderStyle); +begin + if Value <> FBorderStyle then + begin + FBorderStyle := Value; + RecreateWnd(); + end; +end; + +procedure TX2CustomMenuBar.SetGroups(const Value: TX2MenuBarGroups); +begin + if Value <> FGroups then + FGroups.Assign(Value); +end; + +procedure TX2CustomMenuBar.SetImageList(const Value: TCustomImageList); +begin + if Value <> FImageList then + begin + if Assigned(FImageList) then + FImageList.RemoveFreeNotification(Self); + + FImageList := Value; + + if Assigned(FImageList) then + FImageList.FreeNotification(Self); + + Invalidate(); + end; +end; + +procedure TX2CustomMenuBar.SetPainter(const Value: TX2MenuBarPainter); +begin + if FPainter <> Value then + begin + if Assigned(FPainter) then + begin + FPainter.DetachObserver(Self); + FPainter.RemoveFreeNotification(Self); + end; + + FPainter := Value; + + if Assigned(FPainter) then + begin + FPainter.FreeNotification(Self); + FPainter.AttachObserver(Self); + end; + + Invalidate; + end; +end; + +end. diff --git a/Source/X2CLmusikCubePainter.pas b/Source/X2CLmusikCubePainter.pas new file mode 100644 index 0000000..c489ff6 --- /dev/null +++ b/Source/X2CLmusikCubePainter.pas @@ -0,0 +1,627 @@ +{ + :: Implements a musikCube-style painter for the X2MenuBar. + :: + :: Last changed: $Date$ + :: Revision: $Rev$ + :: Author: $Author$ +} +unit X2CLmusikCubePainter; + +interface +uses + Classes, + Graphics, + ImgList, + Windows, + + X2CLMenuBar; + +type + // #ToDo1 (MvR) 19-3-2006: IsStored implementations + // #ToDo1 (MvR) 19-3-2006: cache positions + TX2MenuBarmCColor = class(TPersistent) + private + FBorderAlpha: Byte; + FBorderColor: TColor; + FFillAlpha: Byte; + FFillColor: TColor; + FOnChange: TNotifyEvent; + + procedure SetBorderAlpha(const Value: Byte); + procedure SetBorderColor(const Value: TColor); + procedure SetFillAlpha(const Value: Byte); + procedure SetFillColor(const Value: TColor); + protected + procedure DoChange(); + + function MixColors(ABackColor, AForeColor: TColor; AAlpha: Byte): TColor; + + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(); + + function MixBorder(AColor: TColor): TColor; + function MixFill(AColor: TColor): TColor; + published + property BorderColor: TColor read FBorderColor write SetBorderColor; + property BorderAlpha: Byte read FBorderAlpha write SetBorderAlpha; + property FillColor: TColor read FFillColor write SetFillColor; + property FillAlpha: Byte read FFillAlpha write SetFillAlpha; + end; + + TX2MenuBarmCColors = class(TPersistent) + private + FHot: TX2MenuBarmCColor; + FNormal: TX2MenuBarmCColor; + FSelected: TX2MenuBarmCColor; + FOnChange: TNotifyEvent; + + procedure SetHot(const Value: TX2MenuBarmCColor); + procedure SetNormal(const Value: TX2MenuBarmCColor); + procedure SetSelected(const Value: TX2MenuBarmCColor); + protected + procedure DoChange(); + procedure ColorChange(Sender: TObject); + + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(); + destructor Destroy(); override; + published + property Hot: TX2MenuBarmCColor read FHot write SetHot; + property Normal: TX2MenuBarmCColor read FNormal write SetNormal; + property Selected: TX2MenuBarmCColor read FSelected write SetSelected; + end; + + // #ToDo1 (MvR) 19-3-2006: Custom base class + TX2MenuBarmusikCubePainter = class(TX2MenuBarPainter) + private + FColor: TColor; + FGroupColors: TX2MenuBarmCColors; + FGroupHeight: Integer; + FIndicatorColors: TX2MenuBarmCColors; + FItemColors: TX2MenuBarmCColors; + FItemHeight: Integer; + + procedure SetColor(const Value: TColor); + procedure SetGroupColors(const Value: TX2MenuBarmCColors); + procedure SetGroupHeight(const Value: Integer); + procedure SetIndicatorColors(const Value: TX2MenuBarmCColors); + procedure SetItemColors(const Value: TX2MenuBarmCColors); + procedure SetItemHeight(const Value: Integer); + protected + procedure ColorChange(Sender: TObject); + + function GetColor(AColors: TX2MenuBarmCColors; AState: TX2MenuBarDrawStates): TX2MenuBarmCColor; + procedure DrawBlended(ACanvas: TCanvas; AImageList: TCustomImageList; AX, AY, AImageIndex: Integer; AAlpha: Byte); + + function GetGroupHeaderHeight(AGroup: TX2MenuBarGroup): Integer; override; + function GetGroupHeight(AGroup: TX2MenuBarGroup): Integer; override; + function GetItemHeight(AItem: TX2MenuBarItem): Integer; override; + + procedure DrawBackground(ACanvas: TCanvas; const ABounds: TRect); override; + procedure DrawGroupHeader(ACanvas: TCanvas; AGroup: TX2MenuBarGroup; const ABounds: TRect; AState: TX2MenuBarDrawStates); override; + procedure DrawItem(ACanvas: TCanvas; AItem: TX2MenuBarItem; const ABounds: TRect; AState: TX2MenuBarDrawStates); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy(); override; + + procedure ResetColors(); + published + property AnimationStyle; + property AnimationTime; + property Color: TColor read FColor write SetColor stored False; + property GroupColors: TX2MenuBarmCColors read FGroupColors write SetGroupColors stored False; + property GroupHeight: Integer read FGroupHeight write SetGroupHeight stored False; + property IndicatorColors: TX2MenuBarmCColors read FIndicatorColors write SetIndicatorColors stored False; + property ItemColors: TX2MenuBarmCColors read FItemColors write SetItemColors stored False; + property ItemHeight: Integer read FItemHeight write SetItemHeight stored False; + end; + +implementation +uses + SysUtils; + +type + PRGBArray = ^TRGBArray; + TRGBArray = array[Word] of TRGBTriple; + + +{ TX2MenuBarmusikCubePainter } +constructor TX2MenuBarmusikCubePainter.Create(AOwner: TComponent); +begin + inherited; + + FColor := clBtnFace; + FGroupColors := TX2MenuBarmCColors.Create(); + FGroupHeight := 22; + FIndicatorColors := TX2MenuBarmCColors.Create(); + FItemColors := TX2MenuBarmCColors.Create(); + FItemHeight := 22; + + FGroupColors.OnChange := ColorChange; + FIndicatorColors.OnChange := ColorChange; + FItemColors.OnChange := ColorChange; + + ResetColors(); +end; + +destructor TX2MenuBarmusikCubePainter.Destroy(); +begin + FreeAndNil(FItemColors); + FreeAndNil(FIndicatorColors); + FreeAndNil(FGroupColors); + + inherited; +end; + + +procedure TX2MenuBarmusikCubePainter.ResetColors(); +begin + { Group buttons } + with GroupColors.Hot do + begin + BorderColor := clBtnShadow; + FillAlpha := 128; + FillColor := clBtnShadow; + end; + + with GroupColors.Normal do + begin + BorderAlpha := 64; + BorderColor := clBtnShadow; + FillAlpha := 64; + FillColor := clBtnShadow; + end; + + with GroupColors.Selected do + begin + BorderColor := clBtnShadow; + FillColor := clBtnHighlight; + end; + + { Indicator } + with IndicatorColors.Selected do + begin + BorderAlpha := 252; + BorderColor := clHighlight; + FillAlpha := 252; + FillColor := clHighlight; + end; + + { Item buttons } + with ItemColors.Hot do + begin + BorderColor := clBtnShadow; + FillAlpha := 114; + FillColor := clBtnHighlight; + end; + + with ItemColors.Normal do + begin + BorderAlpha := 50; + BorderColor := clBtnHighlight; + FillAlpha := 50; + FillColor := clBtnHighlight; + end; + + with ItemColors.Selected do + begin + BorderColor := clBtnShadow; + FillColor := clBtnHighlight; + end; +end; + + +function TX2MenuBarmusikCubePainter.GetColor(AColors: TX2MenuBarmCColors; + AState: TX2MenuBarDrawStates): TX2MenuBarmCColor; +begin + if mdsSelected in AState then + Result := AColors.Selected + else if mdsHot in AState then + Result := AColors.Hot + else + Result := AColors.Normal; +end; + +procedure TX2MenuBarmusikCubePainter.DrawBlended(ACanvas: TCanvas; + AImageList: TCustomImageList; + AX, AY, AImageIndex: Integer; + AAlpha: Byte); +var + backBuffer: Graphics.TBitmap; + iconBuffer: Graphics.TBitmap; + sourceRect: TRect; + destRect: TRect; + sourceRow: PRGBArray; + destRow: PRGBArray; + xPos: Integer; + yPos: Integer; + backAlpha: Integer; + iconAlpha: Integer; + +begin + backBuffer := Graphics.TBitmap.Create(); + try + backBuffer.PixelFormat := pf24bit; + backBuffer.Width := AImageList.Width; + backBuffer.Height := AImageList.Height; + + destRect := Rect(0, 0, backBuffer.Width, backBuffer.Height); + sourceRect := destRect; + OffsetRect(sourceRect, AX, AY); + backBuffer.Canvas.CopyRect(destRect, ACanvas, sourceRect); + + iconBuffer := Graphics.TBitmap.Create(); + try + iconBuffer.Assign(backBuffer); + AImageList.Draw(iconBuffer.Canvas, 0, 0, AImageIndex); + + backAlpha := AAlpha; + iconAlpha := 256 - AAlpha; + + for yPos := 0 to Pred(iconBuffer.Height) do + begin + sourceRow := iconBuffer.ScanLine[yPos]; + destRow := backBuffer.ScanLine[yPos]; + + for xPos := 0 to Pred(iconBuffer.Width) do + with destRow^[xPos] do + begin + rgbtRed := ((rgbtRed * backAlpha) + + (sourceRow^[xPos].rgbtRed * iconAlpha)) shr 8; + rgbtGreen := ((rgbtGreen * backAlpha) + + (sourceRow^[xPos].rgbtGreen * iconAlpha)) shr 8; + rgbtBlue := ((rgbtBlue * backAlpha) + + (sourceRow^[xPos].rgbtBlue * iconAlpha)) shr 8; + end; + end; + finally + FreeAndNil(iconBuffer); + end; + + ACanvas.Draw(AX, AY, backBuffer); + finally + FreeAndNil(backBuffer); + end; +end; + + +function TX2MenuBarmusikCubePainter.GetGroupHeaderHeight(AGroup: TX2MenuBarGroup): Integer; +begin + Result := FGroupHeight; +end; + +function TX2MenuBarmusikCubePainter.GetGroupHeight(AGroup: TX2MenuBarGroup): Integer; +begin + Result := (AGroup.Items.Count * FGroupHeight); +end; + +function TX2MenuBarmusikCubePainter.GetItemHeight(AItem: TX2MenuBarItem): Integer; +begin + Result := FItemHeight; +end; + + +procedure TX2MenuBarmusikCubePainter.DrawBackground(ACanvas: TCanvas; + const ABounds: TRect); +begin + with ACanvas do + begin + Brush.Color := FColor; + FillRect(ABounds); + end; +end; + +procedure TX2MenuBarmusikCubePainter.DrawGroupHeader(ACanvas: TCanvas; + AGroup: TX2MenuBarGroup; + const ABounds: TRect; + AState: TX2MenuBarDrawStates); +var + groupColor: TX2MenuBarmCColor; + textBounds: TRect; + +begin + with ACanvas do + begin + groupColor := GetColor(GroupColors, AState); + + Brush.Color := groupColor.MixFill(Color); + Brush.Style := bsSolid; + Pen.Color := groupColor.MixBorder(Color); + Pen.Style := psSolid; + Rectangle(ABounds); + + textBounds := ABounds; + Inc(textBounds.Left, 12); // #ToDo3 (MvR) 19-3-2006: GroupIndent property? + + ACanvas.Font.Style := [fsBold]; + DrawText(ACanvas, AGroup.Caption, textBounds); + end; +end; + + +procedure TX2MenuBarmusikCubePainter.DrawItem(ACanvas: TCanvas; + AItem: TX2MenuBarItem; + const ABounds: TRect; + AState: TX2MenuBarDrawStates); +var + itemColor: TX2MenuBarmCColor; + itemBounds: TRect; + indicatorBounds: TRect; + indicatorColor: TX2MenuBarmCColor; + textBounds: TRect; + imageList: TCustomImageList; + imgY: Integer; + +begin + with ACanvas do + begin + itemColor := GetColor(ItemColors, AState); + indicatorColor := GetColor(IndicatorColors, AState); + + itemBounds := ABounds; + indicatorBounds := itemBounds; + indicatorBounds.Right := indicatorBounds.Left + 6; + Brush.Color := indicatorColor.MixFill(Color); + Brush.Style := bsSolid; + Pen.Color := indicatorColor.MixBorder(Color); + Pen.Style := psSolid; + Rectangle(itemBounds); + + itemBounds.Left := indicatorBounds.Right; + Brush.Color := itemColor.MixFill(Color); + Brush.Style := bsSolid; + Pen.Color := itemColor.MixBorder(Color); + Pen.Style := psSolid; + Rectangle(itemBounds); + + textBounds := itemBounds; + Inc(textBounds.Left, 4); + + imageList := MenuBar.ImageList; + if Assigned(imageList) then + begin + if AItem.ImageIndex > -1 then + begin + imgY := textBounds.Top + ((textBounds.Bottom - textBounds.Top - + imageList.Height) div 2); + + if (mdsHot in AState) or (mdsSelected in AState) then + imageList.Draw(ACanvas, textBounds.Left, imgY, AItem.ImageIndex) + else + DrawBlended(ACanvas, imageList, textBounds.Left, imgY, + AItem.ImageIndex, 128); + end; + + Inc(textBounds.Left, imageList.Width + 4); + end; + + if mdsSelected in AState then + ACanvas.Font.Style := [fsBold] + else + ACanvas.Font.Style := []; + + DrawText(ACanvas, AItem.Caption, textBounds); + end; +end; + +procedure TX2MenuBarmusikCubePainter.ColorChange(Sender: TObject); +begin + NotifyObservers(); +end; + + +procedure TX2MenuBarmusikCubePainter.SetIndicatorColors(const Value: TX2MenuBarmCColors); +begin + if Value <> FIndicatorColors then + begin + FIndicatorColors.Assign(Value); + NotifyObservers(); + end; +end; + +procedure TX2MenuBarmusikCubePainter.SetItemColors(const Value: TX2MenuBarmCColors); +begin + if Value <> FItemColors then + begin + FItemColors.Assign(Value); + NotifyObservers(); + end; +end; + +procedure TX2MenuBarmusikCubePainter.SetItemHeight(const Value: Integer); +begin + if Value <> FItemHeight then + begin + FItemHeight := Value; + NotifyObservers(); + end; +end; + +procedure TX2MenuBarmusikCubePainter.SetColor(const Value: TColor); +begin + if Value <> FColor then + begin + FColor := Value; + NotifyObservers(); + end; +end; + +procedure TX2MenuBarmusikCubePainter.SetGroupColors(const Value: TX2MenuBarmCColors); +begin + if Value <> FGroupColors then + begin + FGroupColors.Assign(Value); + NotifyObservers(); + end; +end; + +procedure TX2MenuBarmusikCubePainter.SetGroupHeight(const Value: Integer); +begin + if Value <> FGroupHeight then + begin + FGroupHeight := Value; + NotifyObservers(); + end; +end; + + +{ TX2MenuBarmCColor } +constructor TX2MenuBarmCColor.Create(); +begin + inherited; + + FBorderAlpha := 255; + FBorderColor := clNone; + FFillAlpha := 255; + FFillColor := clNone; +end; + + +procedure TX2MenuBarmCColor.DoChange(); +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + + +function TX2MenuBarmCColor.MixColors(ABackColor, AForeColor: TColor; + AAlpha: Byte): TColor; +var + cBack: Cardinal; + cFore: Cardinal; + bBack: Byte; + +begin + { Source: X2UtGraphics.BlendColors } + cBack := ColorToRGB(ABackColor); + cFore := ColorToRGB(AForeColor); + bBack := 255 - AAlpha; + + Result := RGB(((GetRValue(cBack) * bBack) + + (GetRValue(cFore) * AAlpha)) shr 8, + ((GetGValue(cBack) * bBack) + + (GetGValue(cFore) * AAlpha)) shr 8, + ((GetBValue(cBack) * bBack) + + (GetBValue(cFore) * AAlpha)) shr 8); +end; + +function TX2MenuBarmCColor.MixBorder(AColor: TColor): TColor; +begin + if BorderColor = clNone then + Result := AColor + else + Result := MixColors(AColor, BorderColor, BorderAlpha); +end; + +function TX2MenuBarmCColor.MixFill(AColor: TColor): TColor; +begin + if FillColor = clNone then + Result := AColor + else + Result := MixColors(AColor, FillColor, FillAlpha); +end; + + +procedure TX2MenuBarmCColor.SetBorderAlpha(const Value: Byte); +begin + if Value <> FBorderAlpha then + begin + FBorderAlpha := Value; + DoChange(); + end; +end; + +procedure TX2MenuBarmCColor.SetBorderColor(const Value: TColor); +begin + if Value <> FBorderColor then + begin + FBorderColor := Value; + DoChange(); + end; +end; + +procedure TX2MenuBarmCColor.SetFillAlpha(const Value: Byte); +begin + if Value <> FFillAlpha then + begin + FFillAlpha := Value; + DoChange(); + end; +end; + +procedure TX2MenuBarmCColor.SetFillColor(const Value: TColor); +begin + if Value <> FFillColor then + begin + FFillColor := Value; + DoChange(); + end; +end; + + +{ TX2MenuBarmCColors } +constructor TX2MenuBarmCColors.Create(); +begin + inherited; + + FHot := TX2MenuBarmCColor.Create(); + FNormal := TX2MenuBarmCColor.Create(); + FSelected := TX2MenuBarmCColor.Create(); + + FHot.OnChange := ColorChange; + FNormal.OnChange := ColorChange; + FSelected.OnChange := ColorChange; +end; + +destructor TX2MenuBarmCColors.Destroy(); +begin + FreeAndNil(FSelected); + FreeAndNil(FNormal); + FreeAndNil(FHot); + + inherited; +end; + + +procedure TX2MenuBarmCColors.DoChange(); +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TX2MenuBarmCColors.ColorChange(Sender: TObject); +begin + DoChange(); +end; + + +procedure TX2MenuBarmCColors.SetHot(const Value: TX2MenuBarmCColor); +begin + if FHot <> Value then + begin + FHot.Assign(Value); + DoChange(); + end; +end; + +procedure TX2MenuBarmCColors.SetNormal(const Value: TX2MenuBarmCColor); +begin + if FNormal <> Value then + begin + FNormal.Assign(Value); + DoChange(); + end; +end; + +procedure TX2MenuBarmCColors.SetSelected(const Value: TX2MenuBarmCColor); +begin + if FNormal <> Value then + begin + FSelected.Assign(Value); + DoChange(); + end; +end; + +end. diff --git a/Test/MenuBar/MainForm.dfm b/Test/MenuBar/MainForm.dfm new file mode 100644 index 0000000..4f56e3b --- /dev/null +++ b/Test/MenuBar/MainForm.dfm @@ -0,0 +1,278 @@ +object frmMain: TfrmMain + Left = 300 + Top = 219 + Caption = 'X2MenuBar Test' + ClientHeight = 360 + ClientWidth = 550 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + PixelsPerInch = 96 + TextHeight = 13 + object bvlMenu: TBevel + Left = 137 + Top = 0 + Width = 8 + Height = 360 + Align = alLeft + Shape = bsLeftLine + ExplicitLeft = 141 + end + object lblAnimationTime: TLabel + Left = 364 + Top = 32 + Width = 98 + Height = 13 + Caption = 'Animation time (ms):' + end + object mbTest: TX2MenuBar + Left = 0 + Top = 0 + Width = 137 + Height = 360 + Align = alLeft + Groups = < + item + Caption = 'Share' + Expanded = True + Items = < + item + Caption = 'File' + ImageIndex = 0 + end + item + Caption = 'Folder' + ImageIndex = 1 + end + item + Caption = 'Photo' + ImageIndex = 2 + end + item + Caption = 'Video' + ImageIndex = 3 + end> + end + item + Caption = 'Group' + Expanded = False + Items = < + item + Caption = 'Menu Item' + ImageIndex = -1 + end + item + Caption = 'Menu Item' + ImageIndex = -1 + end + item + Caption = 'Menu Item' + ImageIndex = -1 + end> + end + item + Caption = 'Group without items' + Expanded = False + Items = <> + end> + ImageList = glMenu + Painter = mbPainter + end + object seAnimationTime: TJvSpinEdit + Left = 364 + Top = 48 + Width = 81 + Height = 21 + CheckMinValue = True + ButtonKind = bkStandard + Value = 250.000000000000000000 + TabOrder = 1 + OnChange = seAnimationTimeChange + end + object Panel1: TPanel + Left = 220 + Top = 80 + Width = 133 + Height = 153 + BevelOuter = bvNone + TabOrder = 2 + object rbmusikCube: TRadioButton + Left = 0 + Top = 0 + Width = 113 + Height = 17 + Caption = 'musikCube style' + Checked = True + TabOrder = 0 + TabStop = True + end + object rbUnameIT: TRadioButton + Left = 0 + Top = 20 + Width = 113 + Height = 17 + Caption = 'Uname-IT style' + Enabled = False + TabOrder = 1 + end + end + object Panel2: TPanel + Left = 364 + Top = 80 + Width = 129 + Height = 153 + BevelOuter = bvNone + TabOrder = 3 + object rbSliding: TRadioButton + Left = 0 + Top = 20 + Width = 113 + Height = 17 + Caption = 'Sliding animation' + Checked = True + TabOrder = 0 + TabStop = True + OnClick = AnimationClick + end + object rbNoAnimation: TRadioButton + Left = 0 + Top = 0 + Width = 113 + Height = 17 + Caption = 'No animation' + TabOrder = 1 + OnClick = AnimationClick + end + object rbFade: TRadioButton + Left = 0 + Top = 40 + Width = 113 + Height = 17 + Caption = 'Fading animation' + Enabled = False + TabOrder = 2 + end + end + object gcMenu: TX2GraphicContainer + Graphics = < + item + Name = 'ShareFile' + Picture.Data = { + 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000001000 + 00001008060000001FF3FF61000001844944415478DAA5D2CD4B02411400F0B7 + DB2DA27FAB4EE22102A1A0C0FCA0837A4989683734C7A072A12C45502902FB00 + E95487FEA20E1D24337777E635B33BBB389B5E6A60F6ED1EDE6FDE9BB71AFC73 + 69C14BADF98A223A8EEB7DDB41B4FD38B11D1112D661A23F1728A657E69E5428 + F761796911869F5F0A32174044102551E6BF17C90364B76270F7F4A6202140AE + 5FB09459554E1589942B8CF9C0F4E280A600A6F58C462E3613A01C70F9B61DCA + 4F1F83D51CA0656EEB2A501FA0918FAB2D88646FA3D74A108D6A0F2E2A496D26 + 20127D80972E93998208A00B97951D1530CE076816E2E052FFF238E125B228C4 + 1F06E941230AEC9F3CE2F1DE1A7CBB2CAC00652B4CB6C2E49D1C912E07522A50 + 22F7484AEB30B2250018224C2607509974A0719C5681BC798B75630386131AA9 + 80274B2C68A5C22BB8AA46809C71C347B3091F631ACC414564152E8FD55A079A + 24A302A9621B5BB524BC8F9CA951AA80F72FF07D76DA8516C9AAC0EE411B755D + 0790339045841719DC8BA86241D37F4FE1AFEB07F8392D2050E7313500000000 + 49454E44AE426082} + end + item + Name = 'ShareFolder' + Picture.Data = { + 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000001000 + 00001008060000001FF3FF610000025B4944415478DAAD936D48535118C7FF77 + 775BEAD8ACA123CB2834EC9B2DB2B0328CCC284B461192146A48040505D36A05 + 154826A64D53A490303F6510C528421B6B2CC4C0E5170317ABA859099ACEBBF7 + B6BBFBD2F172433F680875E0CF797BFE3FCE79CE7928FC63A3961B38D201BB3F + 82524100E6140AA0A7D28ADA65039C2D88159DF3A7AA52F5D2FCF90D0AA60650 + 4B02BCBDD8C504512288284CB23088EA0C63F18569FACFFE92007727BCB47E4B + 9E5A9385F4753B9091530EB5D6009AD690DD28519C2813B66B5A1CB9B908C075 + 0762B139042EEE412CF01D51BF0789F04F4064C1712C36EEAE275119787A350B + C79A64C0609B2209958E5E633C4FF9DE36A0B07610D1D97EA8523448D56AB122 + 2D8D642E8EC98FA3D0E79442AD31E289250F15CD32C0D942058ACE0EA7ABD236 + C1D19C8E7D973F93D521804B4A4649624292CFF3151B0AEAF1F8E26654B6CA00 + C76DA53BFF68DFB6CCDC9DB037ADC5FE2BA3C4F41AE009804BCC03F8047E787D + C8DE5E8547751538619501F62674AF5A5F525350D9AD1A68CCC5018B8BE4AA5F + 324060E57EEE041CC4A40026A6C3CBAE07A8BA2B03061A5141F1F4BDBD752FF4 + AF5ACB70E8928D24FC1931B20B00736312ACA010F42760EB79839ACE05AF3070 + 2BC5A6CBDA6A9AF10DA1DCFC1008F649999704228508669605331E86776C06D3 + 939189EA0E6453F31F0367D49AD55DF1F0246D32B713402F3125C04C45C8BD43 + 98188F89D15032405E72F8781B0E2E5A0BCEAE7C8E99784F97551FC627B70BDF + BEFCE2E3117E4AE031625809CB9EEBF8F0D7627A77BFE0D4D8D88855A9440022 + 1C27DB71FABF55E352ED373075032024CD24170000000049454E44AE426082} + end + item + Name = 'ShareWebcam' + Picture.Data = { + 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000001000 + 00001008060000001FF3FF61000002C14944415478DABD935D48935118C7FF9B + DB9CD38913155CB586D008C30F9A95A8217927A14157DE441FE88521A4828108 + 0A8992621745A80C477AB3A048D44A08A18589BA959AE0D4A09CBAE936F7E55E + 759B7BDFB91EDF20E82E283A70381CCE797EFFE739E7FF08F09743F04F00D5D5 + BA94C4C4E47A954AA171BB0F6452292B92CB25C24824088E63A32C1BE658F630 + B2BFBF175E5B5B5B0F0643AF8DC6E79F7F011A1B87DE3435555C0D8582181F37 + 637BFB3BEAEA6ED28918BBBB3EC4C589F8AB1C071C1C846136CFC52626DE0D8D + 8E0EDEE6011D1D2F772A2B0BD2392E0A936915878711C46231088502582C6FB1 + B4B44CC0079899998048C48132A1A8D42D9DAEEB240F686919F017179F4D6118 + 8ED4BD9048E22016FF9C16CB14525353A056E7C26AB5109C4166A692A0566F6F + EFC3341ED0DDFDC25759A9552C2CAC8061F6715C7B2C968868D405AD36076EB7 + 874A0990BA020A453A8145181B1BF1F7F575A7F280F6F621574D4D4586DDEE81 + D7CBC066B3D2EA446E6E16BABA9E906A0C39392AE4E79F874A758E32946078F8 + 95BBBFBF278307B4B50D6CD6D65E3FB5B9E982CFC7606BCB4EEA3EACAE2E2110 + 5042A3C9C6E4A40EA5A525042A444282140683C1A6D33D56F180E6E6A75F1B1A + 6E683636B649790F3B3B0E04832EACAF7F83D13887B4B44CC8E52C0A0B8B9097 + 7701F1F1F1D0EBF52B7A7D6F360FA8AFEFFAD4DA7AB7C06ADD86C7B34BC10C1C + 0E3BA4D2E35F311F7B014AE50994945C21F544242727D1BB3D9A32189E5DE601 + 55558D239D9DF7AE310C4BEA7EAA5100A7D3857098A1E010EDC5C8CA3A43CA32 + BACD61717131363030747F76F6430F0F282FBF73A9ACACE47D51915666B3B9C8 + 386421B11432593C418294CD163DAC2DE2743AE697972DC66834326A327D34FD + D60BE5E5B72EAAD5A7079392E41AB2AE9BCC6275B91CCB3E5FE08B40C0CE1F1D + F917A6A767427FD24C429A47FFAD1B7F00ED1B51200D4AE2740000000049454E + 44AE426082} + end + item + Name = 'ShareWebcamVideo' + Picture.Data = { + 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000001000 + 00001008060000001FF3FF61000002EA4944415478DAA5935D48935118C7FFF3 + DDAB6BCEF9FDED44DC4CA15E8761412A1296A121285ED595DD7521298C125341 + E9622B584CE6BCF122454891AE9424432B3FC8A4FC203F32D1E9FCAA95D36DCD + B5BDAF7BB78E2B040BA2E8DC9CAFE7FC9EE7FCCFF90BF09F4DF0EB82CFE713E8 + F5FA149AA6198FC7C3884422262C2C8C118BC5A91CC7EDBBDDAE75ABD5BAC4B2 + 9C4EA5524D1E03747777574B2492A688888830D2432A952238580C9AA6C82E8F + 830316DBDB7632077A7B7B5FD7D737E41C017A7A7A8A939393FB188611DA6C36 + 2426268265DDB05A2D9899716373D30BA39187CD7608FA86ADCD06D7E0D0A0D8 + 0F50ABD585342D7CEA703828A55289E8E818242424203C5C82AE2E0789909183 + FB70BB59389D2E02F66274F4BA6361615CEA075455DD1C11894EE43FEC7C8C2B + C59791794A8EA2A26212ECC4F47436380EE430878D8D31D8ED6FC93A199BDEAC + 4FCD0CA4F801776A6B9D731F56C553CB1C3EED72A82C4FC2A5C2622814C99898 + 9061656519F3F3F7B1B7B785A8A818040444212DEDCCAC56AB52FA013535B7ED + E65D56FA688405EF0DC5D59CAF60329290937B0E7373720C0CA840511C76763E + FB01F1F1371014343B6B3034FE005456560E9D4C935FACD6AF03541CCAB35791 + 9A1082D34C3A9697F33035A5267A444128CC464848162C163BD1A97FB2B5557D + F667053525F0F17D2C1527E81B36212B6E1D79F917E0724988FAB9100804F078 + 78A2C5A1802EA2831B1919CFFB753A6DC9D133D6D5D5DD22719AF434B9D0E9E2 + 488981E4B942313C1C47EECCC3EBF591B9070E871B4AA58FC09E7536371B2A8E + 7DA4F6F6F677A5A5A59966B39964B1C164B2A0A34388C04090CC3C2223BD2828 + A0C978D16B327D2CD56A1F3C3906D0E974E3656565E7799EF7976DB57E415BDB + 26C46211C94A932A8CBEA5A5B5171415D8A8D1685EFDE605F2A1AE51146590C9 + 64110A8582F8C2EBBFF7E2E27B9FD1B8F6322040D8A4D1DC1BFBA39988418288 + 894A481515B1B1B185168BE51531D8DD969696D1BF72E3BFB6EF2C065120000A + A5C30000000049454E44AE426082} + end> + Left = 180 + Top = 8 + end + object glMenu: TX2GraphicList + Container = gcMenu + Left = 208 + Top = 8 + end + object mbPainter: TX2MenuBarmusikCubePainter + Left = 152 + Top = 8 + end +end diff --git a/Test/MenuBar/MainForm.pas b/Test/MenuBar/MainForm.pas new file mode 100644 index 0000000..8f34385 --- /dev/null +++ b/Test/MenuBar/MainForm.pas @@ -0,0 +1,52 @@ +unit MainForm; + +interface +uses + Classes, + Controls, + Forms, + ImgList, + + PNGImage, + X2CLGraphicList, + X2CLMenuBar, + X2CLmusikCubePainter, StdCtrls, ExtCtrls, Mask, JvExMask, JvSpin; + +type + TfrmMain = class(TForm) + mbTest: TX2MenuBar; + mbPainter: TX2MenuBarmusikCubePainter; + gcMenu: TX2GraphicContainer; + glMenu: TX2GraphicList; + bvlMenu: TBevel; + rbmusikCube: TRadioButton; + rbSliding: TRadioButton; + lblAnimationTime: TLabel; + seAnimationTime: TJvSpinEdit; + Panel1: TPanel; + Panel2: TPanel; + rbNoAnimation: TRadioButton; + rbFade: TRadioButton; + rbUnameIT: TRadioButton; + procedure AnimationClick(Sender: TObject); + procedure seAnimationTimeChange(Sender: TObject); + end; + +implementation + +{$R *.dfm} + +procedure TfrmMain.AnimationClick(Sender: TObject); +begin + if rbSliding.Checked then + mbPainter.AnimationStyle := asSlide + else + mbPainter.AnimationStyle := asNone; +end; + +procedure TfrmMain.seAnimationTimeChange(Sender: TObject); +begin + mbPainter.AnimationTime := seAnimationTime.AsInteger; +end; + +end. diff --git a/Test/MenuBar/MenuBarGroup.bdsgroup b/Test/MenuBar/MenuBarGroup.bdsgroup new file mode 100644 index 0000000..6ac8695 --- /dev/null +++ b/Test/MenuBar/MenuBarGroup.bdsgroup @@ -0,0 +1,20 @@ + + + + + + + + + + + MenuBarTest.bdsproj + ..\..\Packages\D2006\X2CLMB.bdsproj + ..\..\Packages\D2006\X2CLMBD.bdsproj + ..\..\..\..\Archive\Tests\2006\ColorBlender\ColorBlender.bdsproj + MenuBarTest.exe X2CLMB.bpl X2CLMBD.bpl ColorBlender.exe + + + + diff --git a/Test/MenuBar/MenuBarTest.bdsproj b/Test/MenuBar/MenuBarTest.bdsproj new file mode 100644 index 0000000..41f7d5d --- /dev/null +++ b/Test/MenuBar/MenuBarTest.bdsproj @@ -0,0 +1,172 @@ + + + + + + + + + + + + MenuBarTest.dpr + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 4194304 + + + + + + + + ..\..\Source + + + + False + + + + + + False + + + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1043 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + + diff --git a/Test/MenuBar/MenuBarTest.cfg b/Test/MenuBar/MenuBarTest.cfg new file mode 100644 index 0000000..30e5130 --- /dev/null +++ b/Test/MenuBar/MenuBarTest.cfg @@ -0,0 +1,42 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-LE"C:\Documents and Settings\PsychoMark\My Documents\Borland Studio Projects\Bpl" +-LN"C:\Documents and Settings\PsychoMark\My Documents\Borland Studio Projects\Bpl" +-U"..\..\Source" +-O"..\..\Source" +-I"..\..\Source" +-R"..\..\Source" +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/Test/MenuBar/MenuBarTest.dpr b/Test/MenuBar/MenuBarTest.dpr new file mode 100644 index 0000000..1c023f5 --- /dev/null +++ b/Test/MenuBar/MenuBarTest.dpr @@ -0,0 +1,16 @@ +program MenuBarTest; + +uses + Forms, + MainForm in 'MainForm.pas' {frmMain}; + +{$R *.res} + +var + frmMain: TfrmMain; + +begin + Application.Initialize; + Application.CreateForm(TfrmMain, frmMain); + Application.Run; +end. diff --git a/Test/MenuBar/MenuBarTest.res b/Test/MenuBar/MenuBarTest.res new file mode 100644 index 0000000..ba1ed6e Binary files /dev/null and b/Test/MenuBar/MenuBarTest.res differ