Revert r62685 #e1838e46a0: LCL: implement MDI for win32. Issue #36582, based on patch by Kostas Michalopoulos

git-svn-id: trunk@62739 -
This commit is contained in:
ondrej 2020-03-11 05:48:36 +00:00
parent cef1d45559
commit 29018d9a1a
14 changed files with 106 additions and 727 deletions

View File

@ -2490,15 +2490,6 @@ tbLeftButton - only left button is used to activate a menu item
<short>
<var>Alignment</var> - determines the position of popup menu relative to the popup coordinate</short>
</element>
<element name="TMenuItem.GetMergedParentMenu">
<short><var>GetMergedParentMenu</var> - returns the parent menu to which this menu item belongs with taking the merged menu into account</short>
</element>
<element name="TMenuItem.MergedItems">
<short>Returns the visible and invisible child items with taking the merged menu into account</short>
</element>
<element name="TMenuItem.MergedParent">
<short>Returns the parent menu item and with taking the merged menu into account</short>
</element>
</module>
<!-- Menus -->
</package>

View File

@ -769,8 +769,6 @@ type
procedure Previous;
{ mdi related routine}
procedure Tile;
{ mdi related routine}
procedure ArrangeIcons;
{ mdi related property}
property ClientHandle;

View File

@ -101,11 +101,7 @@ begin
GlobalNameSpace.BeginWrite;
Screen.FSaveFocusedList.Remove(Self);
RemoveFixupReferences(Self, '');
if FormStyle <> fsMDIChild then
Hide
else
if Assigned(Menu) and Assigned(Application.MainForm) and Assigned(Application.MainForm.Menu) then
Application.MainForm.Menu.Unmerge(Menu);
if FormStyle <> fsMDIChild then Hide;
DoDestroy;
// don't call the inherited method because it calls Destroying which is already called
end;
@ -663,24 +659,18 @@ begin
inherited WMSize(Message);
if not (csDestroying in ComponentState) then
begin
FDelayedWMSize := True;
Inc(FDelayedEventCtr);
Application.QueueAsyncCall(@DelayedEvent, 0);
end;
FDelayedWMSize := True;
Inc(FDelayedEventCtr);
Application.QueueAsyncCall(@DelayedEvent, 0);
end;
procedure TCustomForm.WMMove(var Message: TLMMove);
begin
inherited WMMove(Message);
if not (csDestroying in ComponentState) then
begin
FDelayedWMMove := True;
Inc(FDelayedEventCtr);
Application.QueueAsyncCall(@DelayedEvent, 0);
end;
FDelayedWMMove := True;
Inc(FDelayedEventCtr);
Application.QueueAsyncCall(@DelayedEvent, 0);
end;
procedure TCustomForm.DelayedEvent(Data: PtrInt);
@ -806,26 +796,12 @@ end;
procedure TCustomForm.CMActivate(var Message: TLMessage);
begin
if (FormStyle=fsMDIChild) and
Assigned(Menu) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) and
Assigned(Application.MainForm.Menu)
then
Application.MainForm.Menu.Merge(Menu);
Activate;
end;
procedure TCustomForm.CMDeactivate(var Message: TLMessage);
begin
Deactivate;
if (FormStyle=fsMDIChild) and
Assigned(Menu) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) and
Assigned(Application.MainForm.Menu)
then
Application.MainForm.Menu.Unmerge(Menu);
end;
procedure TCustomForm.AddHandler(HandlerType: TFormHandlerType;
@ -1402,7 +1378,7 @@ begin
if FormStyle = fsMDIFORM then
begin
Exit;
// ToDo
end
else
begin
@ -2238,15 +2214,12 @@ function TCustomForm.CloseQuery: boolean;
Result:=true;
end;
var
I: Integer;
begin
if FormStyle = fsMDIForm then
begin
// Query children forms whether we can close
if not Check(Self) then exit(False);
for I := 0 to MDIChildCount - 1 do
if not MDIChildren[I].CloseQuery then Exit(False);
// TODO: mdi logic
end;
Result := True;
if Assigned(FOnCloseQuery) then
@ -3240,22 +3213,6 @@ begin
TWSCustomFormClass(WidgetSetClass).Tile(Self);
end;
{------------------------------------------------------------------------------
Method: TForm.ArrangeIcons
Params: None
Returns: Nothing
Arranges the minimized MDI icons in an MDI form.
ArrangeIcons works only if the form FormStyle = fsMDIForm.
------------------------------------------------------------------------------}
procedure TForm.ArrangeIcons;
begin
if (FormStyle <> fsMDIForm) then
Exit;
if HandleAllocated and not (csDesigning in ComponentState) then
TWSCustomFormClass(WidgetSetClass).ArrangeIcons(Self);
end;
//==============================================================================
{ TFormPropertyStorage }

View File

@ -50,20 +50,6 @@ begin
inherited MenuChanged(Sender, Source, Rebuild);
end;
procedure TMainMenu.Merge(Menu: TMainMenu);
begin
if Assigned(Menu) then
Items.MergeWith(Menu.Items)
else
Items.MergeWith(nil);
end;
procedure TMainMenu.Unmerge(Menu: TMainMenu);
begin
if Assigned(Menu) and (Items.Merged = Menu.Items) then
Items.MergeWith(nil);
end;
{------------------------------------------------------------------------------
Method: TMainMenu.Create
Params: AOwner: the owner of the class

View File

@ -136,11 +136,11 @@ begin
FHandle := TWSMenuItemClass(WidgetSetClass).CreateHandle(Self);
CheckChildrenHandles;
if MergedParent <> nil then
if Parent <> nil then
begin
MergedParent.HandleNeeded;
Parent.HandleNeeded;
//DebugLn('TMenuItem.CreateHandle Attaching ... ',Name,':',ClassName);
if MergedParent.HandleAllocated then
if Parent.HandleAllocated then
TWSMenuItemClass(WidgetSetClass).AttachMenu(Self);
if HandleAllocated then
@ -172,7 +172,6 @@ begin
FItems.Delete(Index);
Cur.FParent := nil;
Cur.FOnChange := nil;
InvalidateMergedItems;
MenuChanged(Count = 0);
end;
@ -202,8 +201,6 @@ begin
Dec(i);
end;
end;
if Assigned(FMerged) then
MergeWith(nil);
FreeAndNil(FItems);
FreeAndNil(FActionLink);
FreeAndNil(FImageChangeLink);
@ -213,7 +210,6 @@ begin
FParent.FItems.Remove(Self);
if FCommand <> 0 then TWSMenuItemClass(WidgetSetClass).CloseCommand(FCommand);
//debugln('TMenuItem.Destroy B ',dbgsName(Self));
FreeAndNil(FMergedItems);
inherited Destroy;
end;
@ -347,41 +343,28 @@ procedure TMenuItem.CheckChildrenHandles;
function GetMenu(Item: TMenuItem): TMenu;
begin
Result := nil;
repeat
if Assigned(Item.FMergedWith) then
begin
if Assigned(Item.FMergedWith.Menu) then
Result := Item.FMergedWith.Menu;
Item := Item.FMergedWith;
end else
begin
if Assigned(Item.Menu) then
Result := Item.Menu;
Item := Item.Parent;
end;
until (Item = nil);
Result := Item.Menu;
Item := Item.Parent;
until (Result <> nil) or (Item = nil);
end;
var
i: Integer;
AMenu: TMenu;
AMergedItems: TMergedMenuItems;
begin
if FItems = nil then
Exit;
AMenu := GetMenu(Self);
AMergedItems := MergedItems;
for i := 0 to AMergedItems.InvisibleCount-1 do
if AMergedItems.InvisibleItems[i].HandleAllocated then
AMergedItems.InvisibleItems[i].DestroyHandle;
for i := 0 to AMergedItems.VisibleCount-1 do
if FItems <> nil then
begin
if AMergedItems.VisibleItems[i].HandleAllocated and (GetMenu(AMergedItems.VisibleItems[i]) <> AMenu) then
AMergedItems.VisibleItems[i].DestroyHandle;
AMergedItems.VisibleItems[i].HandleNeeded;
AMenu := GetMenu(Self);
for i := 0 to Count - 1 do
begin
if Items[i].Visible then
begin
if Items[i].HandleAllocated and (GetMenu(Items[i]) <> AMenu) then
Items[i].DestroyHandle;
Items[i].HandleNeeded;
end;
end;
end;
end;
@ -390,11 +373,6 @@ begin
Application.Hint := GetLongHint(Hint);
end;
procedure TMenuItem.InvalidateMergedItems;
begin
FreeAndNil(FMergedItems);
end;
{------------------------------------------------------------------------------
Function: TMenuItem.GetChildren
Params: Proc - proc to be called for each child
@ -556,30 +534,6 @@ begin
if FParent <> nil then Result := FParent.IndexOf(Self);
end;
function TMenuItem.GetMergedItems: TMergedMenuItems;
begin
if not Assigned(FMergedItems) then
FMergedItems := TMergedMenuItems.Create(Self);
Result := FMergedItems;
end;
function TMenuItem.GetMergedParent: TMenuItem;
begin
Result := Parent;
if Assigned(Result) and Assigned(Result.MergedWith) then
Result := Result.MergedWith;
end;
function TMenuItem.GetMergedParentMenu: TMenu;
var
Item: TMenuItem;
begin
Item := Self;
while Item.MergedParent <> nil do
Item := Item.MergedParent;
Result := Item.FMenu;
end;
{------------------------------------------------------------------------------
Function: TMenuItem.GetParent
Params: none
@ -807,12 +761,13 @@ begin
//DebugLn('TMenuItem.DestroyHandle ',dbgsName(Self),' ',dbgs(Self));
if Assigned(FItems) then
begin
for i := FItems.Count - 1 downto 0 do
i := FItems.Count - 1;
while i >= 0 do
begin
TMenuItem(FItems[i]).DestroyHandle;
dec(i);
end;
end;
if Assigned(FMerged) then
for i := FMerged.Count - 1 downto 0 do
FMerged[i].DestroyHandle;
TWSMenuItemClass(WidgetSetClass).DestroyHandle(Self);
FHandle := 0;
end;
@ -899,7 +854,6 @@ begin
Item.FOnChange := @SubItemChanged;
FItems.Insert(Index, Item);
InvalidateMergedItems;
if HandleAllocated and Item.Visible then
Item.HandleNeeded;
MenuChanged(FItems.Count = 1);
@ -938,19 +892,36 @@ end;
Returns the index of the menuitem of all visible menuitems
------------------------------------------------------------------------------}
function TMenuItem.VisibleIndexOf(Item: TMenuItem): Integer;
procedure RaiseVisibleInconsistency;
begin
raise Exception.Create('TMenuItem.VisibleIndexOf '+dbgsName(Item)+' is visible, but not in parents list');
end;
var
i: Integer;
CurMenuItem: TMenuItem;
IsMerged: Boolean;
AMergedItems: TMergedMenuItems;
begin
if not Item.Visible then
Exit(-1);
AMergedItems := GetMergedItems;
for I := 0 to AMergedItems.VisibleCount-1 do
if AMergedItems.VisibleItems[I]=Item then
Exit(I);
Result := -1;
if (FItems = nil) or (Item=nil) or (not Item.Visible) then
Result := -1
else
begin
Result := 0;
i := 0;
while (i<FItems.Count) do
begin
CurMenuItem := TMenuItem(FItems[i]);
if CurMenuItem.Visible then
begin
if CurMenuItem=Item then Exit;
Inc(Result);
end;
Inc(i);
end;
Result := -1;
if Item.Visible then
RaiseVisibleInconsistency;
end;
end;
{------------------------------------------------------------------------------
@ -999,11 +970,8 @@ end;
function TMenuItem.IsInMenuBar: boolean;
------------------------------------------------------------------------------}
function TMenuItem.IsInMenuBar: boolean;
var
AMergedParent: TMenuItem;
begin
AMergedParent := MergedParent;
Result := (AMergedParent <> nil) and (AMergedParent.FMenu <> nil) and (AMergedParent.FMenu is TMainMenu);
Result := (FParent <> nil) and (FParent.FMenu <> nil) and (FParent.FMenu is TMainMenu);
end;
{------------------------------------------------------------------------------
@ -1097,30 +1065,6 @@ begin
Result:=Parent.VisibleIndexOf(Self);
end;
procedure TMenuItem.MergeWith(const aMenu: TMenuItem);
var
i: Integer;
begin
if (Assigned(aMenu) and (csDestroying in aMenu.ComponentState))
or (FMerged=aMenu) then
Exit;
if Assigned(FMerged) then
begin
for i := 0 to FMerged.Count-1 do
FMerged[i].DestroyHandle;
FMerged.FMergedWith := nil;
end;
FMerged := aMenu;
if Assigned(FMerged) then
begin
FMerged.FMergedWith := Self;
FMerged.FreeNotification(Self);
end;
InvalidateMergedItems;
CheckChildrenHandles;
end;
procedure TMenuItem.WriteDebugReport(const Prefix: string);
var
Flags: String;
@ -1512,8 +1456,6 @@ begin
end;
FVisible := AValue;
end;
if MergedParent<>nil then
MergedParent.InvalidateMergedItems;
end;
procedure TMenuItem.UpdateImage(forced: Boolean);

View File

@ -72,43 +72,16 @@ var
depthLen: integer;
{$endif}
setComboWindow: boolean;
WindowInfo: PWin32WindowInfo;
begin
{$if defined(MSG_DEBUG) or defined(DBG_SendPaintMessage)}
depthLen := Length(MessageStackDepth);
if depthLen > 0 then
MessageStackDepth[depthLen] := '#';
{$endif}
WindowInfo := GetWin32WindowInfo(Window);
PrevWndProc := WindowInfo^.DefWndProc;
PrevWndProc := GetWin32WindowInfo(Window)^.DefWndProc;
if (PrevWndProc = nil) or (PrevWndProc = @WindowProc) // <- prevent recursion
then begin
if WindowInfo^.WinControl is TCustomForm then
begin
case TCustomForm(WindowInfo^.WinControl).FormStyle of
fsMDIForm:
begin
if Msg <> WM_COMMAND then
Result := Windows.DefFrameProcW(Window, Win32WidgetSet.MDIClientHandle, Msg, WParam, LParam)
else
if (LoWord(WParam)=SC_CLOSE) or
(LoWord(WParam)=SC_MAXIMIZE) or
(LoWord(WParam)=SC_MINIMIZE) or
(LoWord(WParam)=SC_RESTORE) or
(LoWord(WParam)=SC_NEXTWINDOW) or
(LoWord(WParam)=SC_PREVWINDOW)
then
Result := Windows.DefFrameProcW(Window, Win32WidgetSet.MDIClientHandle, Msg, WParam, LParam)
else
Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam);
end;
fsMDIChild:
Result := Windows.DefMDIChildProcW(Window, Msg, WParam, LParam);
else
Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam);
end;
end else
Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam);
Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam)
end
else begin
// combobox child edit weirdness: combobox handling WM_SIZE will compare text
@ -1969,7 +1942,6 @@ var
R: TRect;
ACtl: TWinControl;
LMouseEvent: TTRACKMOUSEEVENT;
MaximizedActiveChild: WINBOOL;
{$IF NOT DECLARED(WM_DPICHANGED)} // WM_DPICHANGED was added in FPC 3.1.1
const
WM_DPICHANGED = $02E0;
@ -2056,16 +2028,6 @@ begin
if HIWORD(lParam) = 0 then //if not system menu
begin
TargetObject := GetPopMenuItemObject;
// Check if the menu was the maximized icon menu for an MDI child window and ignore it in that case
if (LoWord(LParam)=0) and (lWinControl=Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm) then
begin
MaximizedActiveChild := False;
if SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIGETACTIVE, 0, Windows.WPARAM(@MaximizedActiveChild)) <> 0 then
begin
if MaximizedActiveChild then
TargetObject := nil;
end;
end;
if TargetObject is TMenuItem then
begin
LMessage.Msg := LM_ACTIVATE;
@ -2078,16 +2040,6 @@ begin
WM_MENUSELECT:
begin
TargetObject := GetMenuItemObject((HIWORD(Integer(WParam)) and MF_POPUP) <> 0);
// Check if the menu was the maximized icon menu for an MDI child window and ignore it in that case
if (LoWord(WParam)=0) and (lWinControl=Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm) then
begin
MaximizedActiveChild := False;
if SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIGETACTIVE, 0, Windows.WPARAM(@MaximizedActiveChild)) <> 0 then
begin
if MaximizedActiveChild then
TargetObject := nil;
end;
end;
if TargetObject is TMenuItem then
TMenuItem(TargetObject).IntfDoSelect
else
@ -2467,13 +2419,6 @@ begin
SetLMessageAndParams(Msg, True);
end; // case Msg of
// Update MDI form client bounds
if WinProcess and (Msg=WM_SIZE) and (Window=Application.MainFormHandle) and (Application.MainForm.FormStyle=fsMDIForm) then
begin
Win32WidgetSet.UpdateMDIClientBounds;
WinProcess := False;
end;
if WinProcess then
begin
PLMsg^.Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);

View File

@ -129,7 +129,6 @@ type
FMetrics: TNonClientMetrics;
FMetricsFailed: Boolean;
FDefaultFont: HFONT;
FMDIClientHandle: HWND;
FWaitHandleCount: dword;
FWaitHandles: array of HANDLE;
@ -151,7 +150,6 @@ type
function WinRegister: Boolean;
procedure CreateAppHandle;
function GetMDIClientHandle: HWND;
protected
function CreateThemeServices: TThemeServices; override;
function GetAppHandle: THandle; override;
@ -203,11 +201,6 @@ type
procedure HandleWakeMainThread(Sender: TObject);
property DefaultFont: HFONT read FDefaultFont;
// MDI client handle (if any)
property MDIClientHandle: HWND read GetMDIClientHandle;
procedure UpdateMDIClientBounds;
{$I win32winapih.inc}
{$I win32lclintfh.inc}

View File

@ -403,17 +403,8 @@ begin
PostQuitMessage(AMessage.wParam);
break;
end;
// Handle MDI form accelerators
if Assigned(Application) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) and
TranslateMDISysAccel(Win32WidgetSet.MDIClientHandle, @AMessage)
then begin
// handled by TranslateMDISysAccel
end else begin
TranslateMessage(@AMessage);
DispatchMessageW(@AMessage);
end;
TranslateMessage(@AMessage);
DispatchMessageW(@AMessage);
end;
end else
if retVal = WAIT_TIMEOUT then
@ -644,31 +635,6 @@ begin
Windows.PostMessage(FAppHandle, WM_NULL, 0, 0);
end;
procedure TWin32WidgetSet.UpdateMDIClientBounds;
function CalculateClientArea: TRect;
var
I: Integer;
begin
Windows.GetClientRect(Application.MainFormHandle, Result);
for I := 0 to Application.MainForm.ControlCount - 1 do
if Application.MainForm.Controls[I].Visible then
case Application.MainForm.Controls[I].Align of
alLeft: Inc(Result.Left, Application.MainForm.Controls[I].Width);
alTop: Inc(Result.Top, Application.MainForm.Controls[I].Height);
alRight: Dec(Result.Right, Application.MainForm.Controls[I].Width);
alBottom: Dec(Result.Bottom, Application.MainForm.Controls[I].Height);
end;
end;
var
R: TRect;
begin
if not (Assigned(Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm)) then Exit;
R := CalculateClientArea;
MoveWindow(Win32WidgetSet.MDIClientHandle, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, True);
end;
{ Private methods (in no significant order) }
{------------------------------------------------------------------------------
@ -731,26 +697,6 @@ begin
Windows.DeleteMenu(SysMenu, SC_MOVE, MF_BYCOMMAND);
end;
function TWin32WidgetSet.GetMDIClientHandle: HWND;
const
MDIClientW: array[0..9] of WideChar = ('M', 'D', 'I', 'C', 'L', 'I', 'E', 'N', 'T', #0);
var
CCS: TCLIENTCREATESTRUCT;
begin
if (FMDIClientHandle=0) and
Assigned(Application) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) then begin
CCS.hWindowMenu := 0;
CCS.idFirstChild := 0;
FMDIClientHandle := CreateWindowW(@MDIClientW, nil,
WS_CHILD or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_VSCROLL or WS_HSCROLL,
0, 0, 0, 0, Application.MainForm.Handle, 0, HInstance, @CCS);
ShowWindow(FMDIClientHandle, SW_SHOW);
end;
Result := FMDIClientHandle;
end;
function TWin32WidgetSet.CreateThemeServices: TThemeServices;
begin
Result := TWin32ThemeServices.Create;

View File

@ -2457,15 +2457,9 @@ begin
Result := Boolean(Windows.GetWindowRect(Handle, @R));
SetWidthHeightFromRect(R);
end;
end else
begin
// rcNormalPosition is not valid for MDI children se we use GetWindowRect instead
if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_MDICHILD) <> 0 then begin
Windows.GetWindowRect(Handle, R);
SetWidthHeightFromRect(R);
end else
SetWidthHeightFromRect(WP.rcNormalPosition);
end;
end
else
SetWidthHeightFromRect(WP.rcNormalPosition);
WindowInfo := GetWin32WindowInfo(Handle);
@ -3291,12 +3285,7 @@ end;
------------------------------------------------------------------------------}
function TWin32WidgetSet.SetForegroundWindow(HWnd: HWND): boolean;
begin
// MDI children need to use WM_MDIACTIVATE to bring themselves into the foreground
if (GetWindowLong(HWnd, GWL_EXSTYLE) and WS_EX_MDICHILD) <> 0 then begin
SendMessage(GetParent(HWnd), WM_MDIACTIVATE, HWnd, 0);
Result := True;
end else
Result := Windows.SetForegroundWindow(HWnd);
Result := Windows.SetForegroundWindow(HWnd);
end;
function TWin32WidgetSet.SetMenu(AWindowHandle: HWND; AMenuHandle: HMENU): Boolean;

View File

@ -468,10 +468,6 @@ begin
Windows.SetWindowPos(Handle, 0, IntfLeft, IntfTop, IntfWidth, IntfHeight, SWP_NOZORDER or SWP_NOACTIVATE);
end;
LCLControlSizeNeedsUpdate(AWinControl, True);
// If this control is a child of an MDI form, then we need to update the MDI client bounds in
// case this control has affected the client area
if Assigned(Application.MainForm) and (AWinControl.Parent=Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm) then
Win32WidgetSet.UpdateMDIClientBounds;
end;
class procedure TWin32WSWinControl.SetColor(const AWinControl: TWinControl);
@ -549,12 +545,7 @@ begin
{$ifdef RedirectDestroyMessages}
SetWindowLong(Handle, GWL_WNDPROC, PtrInt(@DestroyWindowProc));
{$endif}
// Instead of calling DestroyWindow directly, we need to call WM_MDIDESTROY for MDI children
if Assigned(Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm) and
(AWinControl is TCustomForm) and (TCustomForm(AWinControl).FormStyle=fsMDIChild) then
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIDESTROY, Handle, 0)
else
DestroyWindow(Handle);
DestroyWindow(Handle);
end;
class procedure TWin32WSWinControl.Invalidate(const AWinControl: TWinControl);
@ -580,11 +571,7 @@ const
VisibilityToFlag: array[Boolean] of UINT = (SWP_HIDEWINDOW, SWP_SHOWWINDOW);
begin
Windows.SetWindowPos(AWinControl.Handle, 0, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or VisibilityToFlag[AWinControl.HandleObjectShouldBeVisible]);
// If this control is a child of an MDI form, then we need to update the MDI client bounds in
// case altering this control's visibility has affected the client area
if Assigned(Application.MainForm) and (AWinControl.Parent=Application.MainForm) and (Application.MainForm.FormStyle=fsMDIForm) then
Win32WidgetSet.UpdateMDIClientBounds;
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or VisibilityToFlag[AWinControl.HandleObjectShouldBeVisible])
end;
class procedure TWin32WSWinControl.ScrollBy(const AWinControl: TWinControl;

View File

@ -83,16 +83,6 @@ type
const APopupParent: TCustomForm); override;
class procedure SetShowInTaskbar(const AForm: TCustomForm; const AValue: TShowInTaskbar); override;
class procedure ShowHide(const AWinControl: TWinControl); override;
{mdi support}
class function ActiveMDIChild(const AForm: TCustomForm): TCustomForm; override;
class function Cascade(const AForm: TCustomForm): Boolean; override;
class function GetClientHandle(const AForm: TCustomForm): HWND; override;
class function GetMDIChildren(const AForm: TCustomForm; AIndex: Integer): TCustomForm; override;
class function Next(const AForm: TCustomForm): Boolean; override;
class function Previous(const AForm: TCustomForm): Boolean; override;
class function Tile(const AForm: TCustomForm): Boolean; override;
class function ArrangeIcons(const AForm: TCustomForm): Boolean; override;
class function MDIChildCount(const AForm: TCustomForm): Integer; override;
end;
{ TWin32WSForm }
@ -404,7 +394,6 @@ var
lForm: TCustomForm absolute AWinControl;
Bounds: TRect;
SystemMenu: HMenu;
MaximizeForm: Boolean = False;
begin
// general initialization of Params
PrepareCreateWindow(AWinControl, AParams, Params);
@ -436,22 +425,6 @@ begin
end;
end;
end;
if (not (csDesigning in lForm.ComponentState)) and
(lForm.FormStyle=fsMDIChild) and
(lForm <> Application.MainForm) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) then
begin
Parent := Win32WidgetSet.MDIClientHandle;
if Parent <> 0 then
begin
Flags := Flags or WS_CHILD;
FlagsEx := FlagsEx or WS_EX_MDICHILD;
// If there is already a maximized MDI child, we'll need to maximize the new one too
if Assigned(Application.MainForm) and Assigned(Application.MainForm.ActiveMDIChild) then
MaximizeForm := Application.MainForm.ActiveMDIChild.WindowState=wsMaximized;
end;
end;
CalcFormWindowFlags(lForm, Flags, FlagsEx);
pClassName := @ClsName[0];
WindowTitle := StrCaption;
@ -488,22 +461,6 @@ begin
// create window
FinishCreateWindow(AWinControl, Params, False);
if (not (csDesigning in lForm.ComponentState)) and
(lForm.FormStyle=fsMDIChild) and
(lForm <> Application.MainForm) and
Assigned(Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) then
begin
// Force a resize event to align children
GetWindowRect(Params.Window, Bounds);
lForm.BoundsRect := Bounds;
// New MDI forms are always activated
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIACTIVATE, Params.Window, 0);
// Maximize the form if there was already a maximized MDI child
if MaximizeForm then
lForm.WindowState := wsMaximized;
end;
Result := Params.Window;
// remove system menu items for bsDialog
@ -776,130 +733,6 @@ begin
Windows.ShowWindow(AWinControl.Handle, SW_HIDE);
end;
class function TWin32WSCustomForm.ActiveMDIChild(const AForm: TCustomForm): TCustomForm;
var
ActiveChildHWND: HWND;
PInfo: PWin32WindowInfo;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
ActiveChildHWND := SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIGETACTIVE, 0, 0);
if ActiveChildHWND=0 then Exit(nil);
PInfo := GetWin32WindowInfo(ActiveChildHWND);
if not (PInfo^.WinControl is TCustomForm) then Exit(nil);
Result := TCustomForm(PInfo^.WinControl);
end else
Result := nil;
end;
class function TWin32WSCustomForm.Cascade(const AForm: TCustomForm): Boolean;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDICASCADE, 0, 0);
Result := True;
end else
Result := False;
end;
class function TWin32WSCustomForm.GetClientHandle(const AForm: TCustomForm): HWND;
begin
if AForm.FormStyle=fsMDIForm then
Result := Win32WidgetSet.MDIClientHandle
else
Result := 0;
end;
class function TWin32WSCustomForm.GetMDIChildren(const AForm: TCustomForm;
AIndex: Integer): TCustomForm;
var
ChildHWND: HWND;
PInfo: PWin32WindowInfo;
Index: Integer;
begin
Index := 0;
Result := nil;
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
ChildHWND := GetWindow(Win32WidgetSet.MDIClientHandle, GW_CHILD);
while ChildHWND <> 0 do
begin
if (GetWindowLong(ChildHWND, GWL_EXSTYLE) and WS_EX_MDICHILD) <> 0 then
begin
PInfo := GetWin32WindowInfo(ChildHWND);
if PInfo^.WinControl is TCustomForm then
begin
if Index=AIndex then Exit(TCustomForm(PInfo^.WinControl));
Inc(Index);
end;
end;
ChildHWND := GetWindow(ChildHWND, GW_HWNDNEXT);
end;
end;
end;
class function TWin32WSCustomForm.Next(const AForm: TCustomForm): Boolean;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDINEXT, 0, 1);
Result := True;
end else
Result := False;
end;
class function TWin32WSCustomForm.Previous(const AForm: TCustomForm): Boolean;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDINEXT, 0, 0);
Result := True;
end else
Result := False;
end;
class function TWin32WSCustomForm.Tile(const AForm: TCustomForm): Boolean;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDITILE, MDITILE_HORIZONTAL, 0);
Result := True;
end else
Result := False;
end;
class function TWin32WSCustomForm.ArrangeIcons(const AForm: TCustomForm): Boolean;
begin
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIICONARRANGE, 0, 0);
Result := True;
end else
Result := False;
end;
class function TWin32WSCustomForm.MDIChildCount(const AForm: TCustomForm): Integer;
var
ChildHWND: HWND;
PInfo: PWin32WindowInfo;
begin
Result := 0;
if (AForm.FormStyle=fsMDIForm) and (Application.MainForm=AForm) then
begin
ChildHWND := GetWindow(Win32WidgetSet.MDIClientHandle, GW_CHILD);
while ChildHWND <> 0 do
begin
if (GetWindowLong(ChildHWND, GWL_EXSTYLE) and WS_EX_MDICHILD) <> 0 then
begin
PInfo := GetWin32WindowInfo(ChildHWND);
if PInfo^.WinControl is TCustomForm then
Inc(Result);
end;
ChildHWND := GetWindow(ChildHWND, GW_HWNDNEXT);
end;
end;
end;
class procedure TWin32WSCustomForm.ShowModal(const ACustomForm: TCustomForm);
var
Parent: HWND;

View File

@ -184,7 +184,6 @@ var
FirstMenuItem: TMenuItem;
SiblingMenuItem: TMenuItem;
i: integer;
AMergedItems: TMergedMenuItems;
begin
Result := MakeLResult(0, MNC_IGNORE);
MenuItemIndex := -1;
@ -194,15 +193,13 @@ begin
FirstMenuItem := TMenuItem(ItemInfo.dwItemData);
if FirstMenuItem = nil then exit;
AMergedItems := FirstMenuItem.MergedParent.MergedItems;
for i := 0 to AMergedItems.VisibleCount-1 do
i := 0;
while (i < FirstMenuItem.Parent.Count) and (MenuItemIndex < 0) do
begin
SiblingMenuItem := AMergedItems.VisibleItems[i];
SiblingMenuItem := FirstMenuItem.Parent.Items[i];
if IsAccel(ACharCode, SiblingMenuItem.Caption) then
begin
MenuItemIndex := i;
break;
end;
MenuItemIndex := SiblingMenuItem.MenuVisibleIndex;
inc(i);
end;
if MenuItemIndex > -1 then
Result := MakeLResult(MenuItemIndex, MNC_EXECUTE);
@ -600,24 +597,26 @@ const
function IsLast: Boolean;
var
AMergedItems: TMergedMenuItems;
Index, i: Integer;
begin
AMergedItems := AMenuItem.MergedParent.MergedItems;
Result := (AMergedItems.VisibleCount>0) and (AMergedItems.VisibleItems[AMergedItems.VisibleCount-1]=AMenuItem);
Index := AMenuItem.Parent.IndexOf(AMenuItem);
for i := Index + 1 to AMenuItem.Parent.Count - 1 do
if AMenuItem.Parent.Items[i].Visible then
Exit(False);
Result := True;
end;
var
MenuState: TThemedMenu;
Metrics: TVistaBarMenuMetrics;
Details, Tmp: TThemedElementDetails;
BGRect, BGClip, WndRect, TextRect, ImageRect, ItemRect: TRect;
BGRect, BGClip, WndRect, TextRect, ImageRect: TRect;
IconSize: TPoint;
TextFlags: DWord;
AFont, OldFont: HFONT;
IsRightToLeft: Boolean;
Info: tagMENUBARINFO;
AWnd, ActiveChild: HWND;
AWnd: HWND;
CalculatedSize: TSIZE;
MaximizedActiveChild: WINBOOL;
begin
if (ItemState and ODS_SELECTED) <> 0 then
MenuState := tmBarItemPushed
@ -635,8 +634,8 @@ begin
// draw backgound
// This is a hackish way to draw. Seems windows itself draws this in WM_PAINT or another paint handler?
AWnd := TCustomForm(AMenuItem.GetMergedParentMenu.Parent).Handle;
if (AMenuItem.MergedParent.VisibleIndexOf(AMenuItem) = 0) then
AWnd := TCustomForm(AMenuItem.GetParentMenu.Parent).Handle;
if (AMenuItem.Parent.VisibleIndexOf(AMenuItem) = 0) then
begin
/// if we are painting the first item then request full repaint to draw the bg correctly
if (GetProp(AWnd, 'LCL_MENUREDRAW') = 0) then
@ -655,28 +654,6 @@ begin
OffsetRect(Info.rcBar, -WndRect.Left, -WndRect.Top);
Tmp := ThemeServices.GetElementDetails(BarState[(ItemState and ODS_INACTIVE) = 0]);
ThemeDrawElement(AHDC, Tmp, Info.rcBar, nil);
// if there is any maximized MDI child, the call above erased its icon... so we'll
// need to redraw the icon again
if (AMenuItem.GetMergedParentMenu.Parent=Application.MainForm) and
(Application.MainForm.FormStyle=fsMDIForm) then
begin
MaximizedActiveChild := False;
ActiveChild := HWND(SendMessage(Win32WidgetSet.MDIClientHandle, WM_MDIGETACTIVE, 0, Windows.WPARAM(@MaximizedActiveChild)));
if ActiveChild <> 0 then
begin
if MaximizedActiveChild then
begin
if GetMenuItemRect(AWnd, Info.hMenu, 0, @ItemRect) then
begin
OffsetRect(ItemRect, -WndRect.Left, -WndRect.Top);
DrawIconEx(AHDC, ItemRect.Left + (ItemRect.Width - 16) div 2, ItemRect.Top + (ItemRect.Height - 16) div 2,
GetClassLong(ActiveChild, GCL_HICONSM),
16, 16, 0, 0,
DI_NORMAL);
end;
end;
end;
end;
end;
BGRect := ARect;
@ -1327,7 +1304,7 @@ procedure TriggerFormUpdate(const AMenuItem: TMenuItem);
var
lMenu: TMenu;
begin
lMenu := AMenuItem.GetMergedParentMenu;
lMenu := AMenuItem.GetParentMenu;
if (lMenu<>nil) and (lMenu.Parent<>nil)
and (lMenu.Parent is TCustomForm)
and TCustomForm(lMenu.Parent).HandleAllocated
@ -1342,12 +1319,12 @@ begin
FillChar(MenuInfo, SizeOf(MenuInfo), 0);
MenuInfo.cbSize := sizeof(TMenuItemInfo);
MenuInfo.fMask := MIIM_FTYPE; // don't retrieve caption (MIIM_STRING not included)
GetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
GetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
if Value then
MenuInfo.fType := MenuInfo.fType or Flag
else
MenuInfo.fType := MenuInfo.fType and (not Flag);
Result := SetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
Result := SetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
TriggerFormUpdate(AMenuItem);
end;
@ -1380,7 +1357,7 @@ var
MenuInfo: MENUITEMINFO; // TMenuItemInfoA and TMenuItemInfoW have same size and same structure type
WideBuffer: widestring;
begin
if (AMenuItem.MergedParent = nil) or not AMenuItem.MergedParent.HandleAllocated then
if (AMenuItem.Parent = nil) or not AMenuItem.Parent.HandleAllocated then
Exit;
FillChar(MenuInfo, SizeOf(MenuInfo), 0);
@ -1389,7 +1366,7 @@ begin
cbSize := sizeof(TMenuItemInfo);
fMask := MIIM_FTYPE or MIIM_STATE; // don't retrieve current caption
end;
GetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
GetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
with MenuInfo do
begin
// change enabled too since we can change from '-' to normal caption and vice versa
@ -1414,7 +1391,7 @@ begin
fState := MFS_DISABLED;
end;
end;
SetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
SetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
// MIIM_BITMAP is needed to request new measure item call
with MenuInfo do
@ -1422,7 +1399,7 @@ begin
fMask := MIIM_BITMAP;
dwTypeData := nil;
end;
SetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
SetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
// set owner drawn
with MenuInfo do
@ -1430,7 +1407,7 @@ begin
fMask := MIIM_FTYPE; // don't set caption
fType := (fType or MFT_OWNERDRAW) and not (MIIM_STRING or MFT_SEPARATOR);
end;
SetMenuItemInfoW(AMenuItem.MergedParent.Handle, AMenuItem.Command, False, @MenuInfo);
SetMenuItemInfoW(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);
TriggerFormUpdate(AMenuItem);
end;
@ -1441,21 +1418,18 @@ var
ParentOfParent: HMenu;
CallMenuRes: Boolean;
WideBuffer: widestring;
ItemIndex: Integer;
begin
if AMenuItem.MergedParent=nil then
Exit;
ParentMenuHandle := AMenuItem.MergedParent.Handle;
ParentMenuHandle := AMenuItem.Parent.Handle;
FillChar(MenuInfo, SizeOf(MenuInfo), 0);
MenuInfo.cbSize := sizeof(TMenuItemInfo);
// Following part fixes the case when an item is added in runtime
// but the parent item has not defined the submenu flag (hSubmenu=0)
if AMenuItem.MergedParent.MergedParent <> nil then
if AMenuItem.Parent.Parent <> nil then
begin
ParentOfParent := AMenuItem.MergedParent.MergedParent.Handle;
ParentOfParent := AMenuItem.Parent.Parent.Handle;
MenuInfo.fMask := MIIM_SUBMENU;
CallMenuRes := GetMenuItemInfoW(ParentOfParent, AMenuItem.MergedParent.Command, False, @MenuInfo);
CallMenuRes := GetMenuItemInfoW(ParentOfParent, AMenuItem.Parent.Command, False, @MenuInfo);
if CallMenuRes then
begin
// the parent menu item is not defined with submenu flag
@ -1463,29 +1437,13 @@ begin
if MenuInfo.hSubmenu = 0 then
begin
MenuInfo.hSubmenu := ParentMenuHandle;
CallMenuRes := SetMenuItemInfoW(ParentOfParent, AMenuItem.MergedParent.Command, False, @MenuInfo);
CallMenuRes := SetMenuItemInfoW(ParentOfParent, AMenuItem.Parent.Command, False, @MenuInfo);
if not CallMenuRes then
DebugLn(['SetMenuItemInfo failed: ', GetLastErrorReport]);
end;
end;
end;
ItemIndex := AMenuItem.MergedParent.VisibleIndexOf(AMenuItem);
if ItemIndex<0 then
begin
DebugLn(['Invisible menu item: ', AMenuItem.Name, ' (', AMenuItem.Caption, ')']);
Exit;
end;
// MDI forms with a maximized MDI child insert a menu at the first index for
// the MDI child's window menu, so we need to take that into account
if Assigned(Application.MainForm) and
(Application.MainForm.Menu=AMenuItem.MergedParent.Menu) and
(Application.MainForm.FormStyle=fsMDIForm) and
Assigned(Application.MainForm.ActiveMDIChild) and
(Application.MainForm.ActiveMDIChild.WindowState=wsMaximized)
then
Inc(ItemIndex);
with MenuInfo do
begin
if AMenuItem.Enabled then
@ -1528,7 +1486,7 @@ begin
if AMenuItem.Default then
fState := fState or MFS_DEFAULT;
end;
CallMenuRes := InsertMenuItemW(ParentMenuHandle, ItemIndex, True, @MenuInfo);
CallMenuRes := InsertMenuItemW(ParentMenuHandle, AMenuItem.Parent.VisibleIndexOf(AMenuItem), True, @MenuInfo);
if not CallMenuRes then
DebugLn(['InsertMenuItem failed with error: ', GetLastErrorReport]);
TriggerFormUpdate(AMenuItem);
@ -1545,27 +1503,27 @@ var
MenuInfo: MENUITEMINFO; // TMenuItemInfoA and TMenuItemInfoW have same size and same structure type
CallMenuRes: Boolean;
begin
if Assigned(AMenuItem.MergedParent) then
if Assigned(AMenuItem.Parent) then
begin
ParentHandle := AMenuItem.MergedParent.Handle;
ParentHandle := AMenuItem.Parent.Handle;
RemoveMenu(ParentHandle, AMenuItem.Command, MF_BYCOMMAND);
// convert submenu to a simple menu item if needed
if (GetMenuItemCount(ParentHandle) = 0) and Assigned(AMenuItem.MergedParent.MergedParent) and
AMenuItem.MergedParent.MergedParent.HandleAllocated then
if (GetMenuItemCount(ParentHandle) = 0) and Assigned(AMenuItem.Parent.Parent) and
AMenuItem.Parent.Parent.HandleAllocated then
begin
ParentOfParentHandle := AMenuItem.MergedParent.MergedParent.Handle;
ParentOfParentHandle := AMenuItem.Parent.Parent.Handle;
FillChar(MenuInfo, SizeOf(MenuInfo), 0);
with MenuInfo do
begin
cbSize := sizeof(TMenuItemInfo);
fMask := MIIM_SUBMENU;
end;
GetMenuItemInfoW(ParentOfParentHandle, AMenuItem.MergedParent.Command, False, @MenuInfo);
GetMenuItemInfoW(ParentOfParentHandle, AMenuItem.Parent.Command, False, @MenuInfo);
// the parent menu item is defined with submenu flag then reset it
if MenuInfo.hSubmenu <> 0 then
begin
MenuInfo.hSubmenu := 0;
CallMenuRes := SetMenuItemInfoW(ParentOfParentHandle, AMenuItem.MergedParent.Command, False, @MenuInfo);
CallMenuRes := SetMenuItemInfoW(ParentOfParentHandle, AMenuItem.Parent.Command, False, @MenuInfo);
if not CallMenuRes then
DebugLn(['SetMenuItemInfo failed: ', GetLastErrorReport]);
// Set menu item info destroys/corrupts our internal popup menu for the
@ -1573,7 +1531,7 @@ begin
if not IsMenu(ParentHandle) then
begin
ParentHandle := CreatePopupMenu;
AMenuItem.MergedParent.Handle := ParentHandle;
AMenuItem.Parent.Handle := ParentHandle;
end;
end;
end;
@ -1603,7 +1561,7 @@ var
EnableFlag: DWord;
begin
EnableFlag := MF_BYCOMMAND or EnabledToStateFlag[Enabled];
Result := Boolean(Windows.EnableMenuItem(AMenuItem.MergedParent.Handle, AMenuItem.Command, EnableFlag));
Result := Boolean(Windows.EnableMenuItem(AMenuItem.Parent.Handle, AMenuItem.Command, EnableFlag));
TriggerFormUpdate(AMenuItem);
end;

View File

@ -117,24 +117,6 @@ type
TMenuMeasureItemEvent = procedure(Sender: TObject; ACanvas: TCanvas;
var AWidth, AHeight: Integer) of object;
TMergedMenuItems = class
private
fList: array[Boolean] of TList; // visible
function GetInvisibleCount: Integer;
function GetInvisibleItem(Index: Integer): TMenuItem;
function GetVisibleCount: Integer;
function GetVisibleItem(Index: Integer): TMenuItem;
public
constructor Create(const aParent: TMenuItem);
destructor Destroy; override;
class function DefaultSort(aItem1, aItem2, aParentItem: Pointer): Integer; static;
property VisibleCount: Integer read GetVisibleCount;
property VisibleItems[Index: Integer]: TMenuItem read GetVisibleItem;
property InvisibleCount: Integer read GetInvisibleCount;
property InvisibleItems[Index: Integer]: TMenuItem read GetInvisibleItem;
end;
TMenuItem = class(TLCLComponent)
private
FActionLink: TMenuActionLink;
@ -153,9 +135,6 @@ type
FOnDrawItem: TMenuDrawItemEvent;
FOnMeasureItem: TMenuMeasureItemEvent;
FParent: TMenuItem;
FMerged: TMenuItem;
FMergedWith: TMenuItem;
FMergedItems: TMergedMenuItems;
FMenuItemHandlers: array[TMenuItemHandlerType] of TMethodList;
FSubMenuImages: TCustomImageList;
FSubMenuImagesWidth: Integer;
@ -177,8 +156,6 @@ type
function GetCount: Integer;
function GetItem(Index: Integer): TMenuItem;
function GetMenuIndex: Integer;
function GetMergedItems: TMergedMenuItems;
function GetMergedParent: TMenuItem;
function GetParent: TMenuItem;
function IsBitmapStored: boolean;
function IsCaptionStored: boolean;
@ -189,7 +166,6 @@ type
function IsImageIndexStored: Boolean;
function IsShortCutStored: boolean;
function IsVisibleStored: boolean;
procedure MergeWith(const aMenu: TMenuItem);
procedure SetAutoCheck(const AValue: boolean);
procedure SetCaption(const AValue: TTranslateString);
procedure SetChecked(AValue: Boolean);
@ -250,7 +226,6 @@ type
function GetImageList: TCustomImageList;
function GetParentComponent: TComponent; override;
function GetParentMenu: TMenu; virtual;
function GetMergedParentMenu: TMenu; virtual;
function GetIsRightToLeft:Boolean; virtual;
function HandleAllocated : Boolean;
function HasIcon: boolean; virtual;
@ -259,7 +234,6 @@ type
procedure IntfDoSelect; virtual;
function IndexOf(Item: TMenuItem): Integer;
function IndexOfCaption(const ACaption: string): Integer; virtual;
procedure InvalidateMergedItems;
function VisibleIndexOf(Item: TMenuItem): Integer;
procedure Add(Item: TMenuItem);
procedure Add(const AItems: array of TMenuItem);
@ -287,17 +261,13 @@ type
const AMethod: TMethod; AsFirst: boolean = false);
procedure RemoveHandler(HandlerType: TMenuItemHandlerType;
const AMethod: TMethod);
property Merged: TMenuItem read FMerged;
property MergedWith: TMenuItem read FMergedWith;
public
property Count: Integer read GetCount;
property Handle: HMenu read GetHandle write FHandle;
property Items[Index: Integer]: TMenuItem read GetItem; default;
property MergedItems: TMergedMenuItems read GetMergedItems;
property MenuIndex: Integer read GetMenuIndex write SetMenuIndex;
property Menu: TMenu read FMenu;
property Parent: TMenuItem read GetParent;
property MergedParent: TMenuItem read GetMergedParent;
property Command: Word read FCommand;
function MenuVisibleIndex: integer;
procedure WriteDebugReport(const Prefix: string);
@ -426,8 +396,6 @@ type
procedure MenuChanged(Sender: TObject; Source: TMenuItem; Rebuild: Boolean); override;
public
constructor Create(AOwner: TComponent); override;
procedure Merge(Menu: TMainMenu);
procedure Unmerge(Menu: TMainMenu);
property Height: Integer read GetHeight;
property WindowHandle: HWND read FWindowHandle write SetWindowHandle;
published
@ -681,114 +649,6 @@ begin
RegisterNoIcon([TMenuItem]);
end;
{ TMergedMenuItems }
constructor TMergedMenuItems.Create(const aParent: TMenuItem);
procedure SearchVis(const aGroupIndex: Integer; out outIndex: Integer; out outReplace: Boolean);
var
AItem: TMenuItem;
I: Integer;
begin
outReplace := False;
for I := 0 to VisibleCount-1 do
begin
AItem := VisibleItems[I];
if AItem.GroupIndex=aGroupIndex then
begin
outIndex := I;
outReplace := True;
Exit;
end else
if AItem.GroupIndex>aGroupIndex then
begin
outIndex := I;
Exit;
end;
end;
outIndex := -1;
end;
var
B, AReplace: Boolean;
I, AItemIndex: Integer;
AItem: TMenuItem;
begin
inherited Create;
for B := Low(fList) to High(fList) do
fList[B] := TList.Create;
for I := 0 to aParent.Count-1 do
fList[aParent.Items[I].Visible].Add(aParent.Items[I]);
if Assigned(aParent.FMerged) then
begin
for I := 0 to aParent.FMerged.Count-1 do
begin
AItem := aParent.FMerged.Items[I];
if AItem.Visible then
begin
SearchVis(AItem.GroupIndex, AItemIndex, AReplace);
if AItemIndex>=0 then
begin
if AReplace then
begin
fList[False].Add(VisibleItems[AItemIndex]); // copy to invisible list
fList[True].Items[AItemIndex] := AItem // replace
end else
fList[True].Insert(AItemIndex, AItem); // insert
end else
fList[True].Add(AItem); // add
end else
fList[False].Add(AItem); // add to invisible
end;
end;
end;
class function TMergedMenuItems.DefaultSort(aItem1, aItem2,
aParentItem: Pointer): Integer;
var
Item1: TMenuItem absolute aItem1;
Item2: TMenuItem absolute aItem2;
begin
Result := Item1.GroupIndex-Item2.GroupIndex;
if Result=0 then
begin
if Pointer(Item1.Parent)=aParentItem then
Result := 1
else
Result := -1;
end;
end;
destructor TMergedMenuItems.Destroy;
var
B: Boolean;
begin
for B := Low(fList) to High(fList) do
fList[B].Destroy;
inherited Destroy;
end;
function TMergedMenuItems.GetInvisibleCount: Integer;
begin
Result := fList[False].Count;
end;
function TMergedMenuItems.GetInvisibleItem(Index: Integer): TMenuItem;
begin
Result := TMenuItem(fList[False].Items[Index]);
end;
function TMergedMenuItems.GetVisibleCount: Integer;
begin
Result := fList[True].Count;
end;
function TMergedMenuItems.GetVisibleItem(Index: Integer): TMenuItem;
begin
Result := TMenuItem(fList[True].Items[Index]);
end;
{$I menu.inc}
{$I menuitem.inc}
{$I mainmenu.inc}

View File

@ -101,7 +101,6 @@ type
class function Next(const AForm: TCustomForm): Boolean; virtual;
class function Previous(const AForm: TCustomForm): Boolean; virtual;
class function Tile(const AForm: TCustomForm): Boolean; virtual;
class function ArrangeIcons(const AForm: TCustomForm): Boolean; virtual;
class function MDIChildCount(const AForm: TCustomForm): Integer; virtual;
end;
TWSCustomFormClass = class of TWSCustomForm;
@ -255,11 +254,6 @@ begin
Result := False;
end;
class function TWSCustomForm.ArrangeIcons(const AForm: TCustomForm): Boolean;
begin
Result := False;
end;
class function TWSCustomForm.Tile(const AForm: TCustomForm): Boolean;
begin
Result := False;