MainMenu菜单问题

sinco449 2012-11-15 11:33:56
现在是ToolBar + MainMenu 组合做的主菜单:
主界面MainForm上放一个ToolBar,然后动态创建ToolButton和MenuItem,ToolButton.MenuItem := 一级菜单项,ToolButton.Style := tbsButton。

想要实现的效果如下(点击了某个一级菜单项后,出来子菜单,同时该一级菜单项的颜色仍保持与其他一级菜单项不同,HotTrackColor的颜色):


但实际情况是,鼠标移动到该一级菜单项时,该一级菜单项的背景色确实是HotTrackColor的颜色,但一旦点击该一级菜单项,出来对应的子菜单后,该一级菜单项的颜色又恢复回和其他一级菜单项一样的颜色,违背了初衷,如下:


如果将ToolButton的Style设置为tbsDropDown,那么就在ToolButton就分为2个区域,其中右边的小区域有一个向下三角形。点击ToolButton的左边大区域不会弹出子菜单,只有点击那个小三角形才可以:

...全文
687 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangzs188136923 2012-11-30
  • 打赏
  • 举报
回复
如果不具备写控件的能力,何必非要走这条路。
sinco449 2012-11-29
  • 打赏
  • 举报
回复
引用 10 楼 jiang188136923 的回复:
我们的方法一样,你的漂亮!
如果按照我那样改,如何从TToolBar派生出一个新的控件?
jiangzs188136923 2012-11-29
  • 打赏
  • 举报
回复
我们的方法一样,你的漂亮!
sinco449 2012-11-28
  • 打赏
  • 举报
回复
如何在派生类里重写上面的那3个方法?
sinco449 2012-11-28
  • 打赏
  • 举报
回复
如何从TToolBar类派生出一个新的ToolBar控件? 已经通过修改TToolBar的源码达到了以上的目的,但这样不方便,想将这种修改通过从TToolBar派生出新的ToolBar控件来实现。对写VCL控件不熟悉,现在遇到好多问题,比如如何在派生类里访问父类的私有变量。 procedure TToolBar.ClearTempMenu; var I: Integer; Item: TMenuItem; myset: TCustomDrawState; Flags: TTBCustomDrawFlags; begin myset := []; Flags := []; if (FMenuButton <> nil) then GradientDrawButton(FMenuButton, myset, Flags); // new code if (FButtonMenu <> nil) and (FMenuButton <> nil) and (FMenuButton.MenuItem <> nil) and (FTempMenu <> nil) then begin for I := FTempMenu.Items.Count - 1 downto 0 do begin Item := FTempMenu.Items[I]; FTempMenu.Items.Delete(I); FButtonMenu.Insert(0, Item); end; FTempMenu.Free; FTempMenu := nil; FMenuButton := nil; FButtonMenu := nil; end; end; function TToolBar.CheckMenuDropdown(Button: TToolButton): Boolean; var Hook: Boolean; Menu: TMenu; Item: TMenuItem; I: Integer; ParentMenu: TMenu; APoint: TPoint; LMonitor: TMonitor; myset: TCustomDrawState; Flags: TTBCustomDrawFlags; begin Result := False; if Button = nil then Exit; FCaptureChangeCancels := False; try if Button.DropdownMenu <> nil then FTempMenu := Button.DropdownMenu else if Button.MenuItem <> nil then begin Button.MenuItem.Click; ClearTempMenu; FTempMenu := TPopupMenu.Create(Self); ParentMenu := Button.MenuItem.GetParentMenu; if ParentMenu <> nil then FTempMenu.BiDiMode := ParentMenu.BiDiMode; FTempMenu.HelpContext := Button.MenuItem.HelpContext; FTempMenu.TrackButton := tbLeftButton; Menu := Button.MenuItem.GetParentMenu; if Menu <> nil then FTempMenu.Images := Menu.Images; FButtonMenu := Button.MenuItem; for I := FButtonMenu.Count - 1 downto 0 do begin Item := FButtonMenu.Items[I]; FButtonMenu.Delete(I); FTempMenu.Items.Insert(0, Item); end; end else Exit; SendCancelMode(nil); FTempMenu.PopupComponent := Self; Hook := Button.Grouped or (Button.MenuItem <> nil); if Hook then begin MenuButtonIndex := Button.Index; MenuToolBar := Self; InitToolMenuHooks; end; Perform(TB_SETHOTITEM, -1, 0); try APoint := Button.ClientToScreen(Point(0, Button.ClientHeight)); if FTempMenu.IsRightToLeft then Inc(APoint.X, Button.Width); FMenuDropped := True; LMonitor := Screen.MonitorFromPoint(APoint); if (LMonitor <> nil) and ((GetSystemMetrics(SM_CYMENU) * FTempMenu.Items.Count) + APoint.Y > LMonitor.Height) then Dec(APoint.Y, Button.Height); if GetComCtlVersion = ComCtlVersionIE5 then Button.Invalidate; myset := [cdsHot, cdsSelected]; Flags := []; GradientDrawButton(Button, myset, Flags); // new code FTempMenu.Popup(APoint.X, APoint.Y); finally if Hook then ReleaseToolMenuHooks; end; FMenuButton := Button; if StillModal then Perform(TB_SETHOTITEM, Button.Index, 0); Result := True; finally PostMessage(Handle, CN_DROPDOWNCLOSED, 0, 0); end; end; function TToolBar.GradientDrawButton(Button: TToolButton; State: TCustomDrawState; var Flags: TTBCustomDrawFlags): Boolean; const cInset = 4; var FillColor: TColor; EdgeColor: TColor; R: TRect; X: Integer; Y: Integer; Str: string; ImageList: TCustomImageList; begin Result := False; FBitmap.Canvas.Pen.Assign(Canvas.Pen); FBitmap.Canvas.Brush.Assign(Canvas.Brush); FBitmap.Canvas.Font.Assign(Canvas.Font); ImageList := nil; if gdoGradient in GradientDrawingOptions then begin if (FMenuButton <> nil) or (FTempMenu = nil) then // new code begin FBitmap.SetSize(Width, Height); GradientFillCanvas(FBitmap.Canvas, FGradientStartColor, FGradientEndColor, ClientRect, GradientDirection); FBitmap.Canvas.CopyRect(Rect(0, 0, Button.Width, Button.Height), FBitmap.Canvas, Button.BoundsRect); FBitmap.SetSize(Button.Width, Button.Height); end; end else begin FBitmap.SetSize(Button.Width, Button.Height); FBitmap.Canvas.Brush.Color := Button.Color; FBitmap.Canvas.Brush.Style := bsSolid; FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect); end; if (Button.Style = tbsButton) or (Button.Style = tbsCheck) or (Button.Style = tbsDropDown) or (Button.Style = tbsTextButton) then begin if cdsHot in State then ImageList := HotImages; if not Button.Enabled then ImageList := DisabledImages; if ImageList = nil then ImageList := Images; if (cdsHot in State) or (Button.Down and Button.Enabled) then begin if (gdoHotTrack in GradientDrawingOptions) then begin FillColor := HotTrackColor; if cdsSelected in State then FillColor := GetShadowColor(FillColor, -25); EdgeColor := GetShadowColor(FillColor); R := Rect(0, 0, Button.Width, Button.Height); FBitmap.Canvas.Brush.Color := EdgeColor; if Button.Style = tbsDropDown then Dec(R.Right, cDropDownWidth - (FBitmap.Canvas.Pen.Width div 2)); FBitmap.Canvas.FillRect(R); InflateRect(R, -FBitmap.Canvas.Pen.Width, -FBitmap.Canvas.Pen.Width); FBitmap.Canvas.Brush.Color := FillColor; FBitmap.Canvas.FillRect(R); InflateRect(R, FBitmap.Canvas.Pen.Width, FBitmap.Canvas.Pen.Width); if Button.Style = tbsDropDown then begin R.Left := R.Right; Inc(R.Right, cDropDownWidth - (FBitmap.Canvas.Pen.Width div 2)); FBitmap.Canvas.Brush.Color := EdgeColor; FBitmap.Canvas.FillRect(R); InflateRect(R, -FBitmap.Canvas.Pen.Width, -FBitmap.Canvas.Pen.Width); FBitmap.Canvas.Brush.Color := FillColor; FBitmap.Canvas.FillRect(R); end; end else begin if Button.Down then begin FillColor := cl3DDkShadow; EdgeColor := cl3DLight; end else begin FillColor := cl3DLight; EdgeColor := cl3DDkShadow; end; R := Rect(0, 0, Button.Width, Button.Height); Frame3D(FBitmap.Canvas, R, FillColor, EdgeColor, Canvas.Pen.Width); if Button.Style = tbsDropDown then begin FBitmap.Canvas.MoveTo(R.Right - cDropDownWidth, 0); FBitmap.Canvas.LineTo(R.Right - cDropDownWidth, Button.Height); end; end; end; if (ImageList <> nil) and (Button.ImageIndex >= 0) and (Button.ImageIndex < ImageList.Count) or ((ImageList <> nil) and (Button.Style = tbsTextButton)) then begin if (ShowCaptions and List) or (AllowTextButtons and (Button.Style = tbsTextButton)) then X := cInset else begin X := (Button.Width - ImageList.Width) div 2; if Button.Style = tbsDropDown then Dec(X, cDropDownWidth div 2); end; if (List and not AllowTextButtons) or (AllowTextButtons and (Button.Style = tbsTextButton)) then Y := (Button.Height - ImageList.Height) div 2 else Y := cInset; ImageList.Draw(FBitmap.Canvas, X, Y, Button.ImageIndex, dsTransparent, itImage, Button.Enabled or (csDesigning in ComponentState) or (not Button.Enabled and (ImageList = DisabledImages))); end; if (Button.Style = tbsDropDown) then begin X := Button.Width - ((cDropDownWidth div 2) + (cDropDownWidth div 4)); Y := Button.Height div 2; FBitmap.Canvas.Pen.Color := Button.Font.Color; if not Button.Enabled then FBitmap.Canvas.Pen.Color := clGrayText; FBitmap.Canvas.Brush.Style := bsSolid; DrawArrow(FBitmap.Canvas, sdDown, Point(X, Y), cDropDownWidth div 4); end; if (ShowCaptions and not AllowTextButtons) or (AllowTextButtons and (Button.Style = tbsTextButton)) then begin FBitmap.Canvas.Brush.Style := bsClear; if (ImageList <> nil) and List and ((Button.Style <> tbsTextButton) or ((Button.Style = tbsTextButton) and (Button.ImageIndex <> -1))) then R.Left := ImageList.Width else R.Left := 0; R.Right := Button.Width; Str := Button.Caption; if Button.Style = tbsDropDown then Dec(R.Right, cDropDownWidth - (FBitmap.Canvas.Pen.Width div 2)); if (not List) and (ImageList <> nil) then R.Top := ImageList.Height + cInset else R.Top := (Button.Height div 2) - (FBitmap.Canvas.TextHeight(Str) div 2); R.Bottom := R.Top + FBitmap.Canvas.TextHeight(Str); FBitmap.Canvas.Font.Color := Button.Font.Color; if not Button.Enabled then FBitmap.Canvas.Font.Color := clGrayText; DrawText(FBitmap.Canvas.Handle, Str, Length(Str), R, DT_END_ELLIPSIS or DT_NOCLIP or DT_VCENTER or DT_CENTER); end; end; Canvas.Draw(Button.Left, Button.Top, FBitmap); end;
sinco449 2012-11-28
  • 打赏
  • 举报
回复
引用 7 楼 sinco449 的回复:
如何在派生类里重写上面的那3个方法?
我试了用override来重写了,但会出错。其实,重写的目的也只是在每个方法里加上那么一两行的新代码(new code标识的那些行),一样要引用父类的私有变量。
hsfzxjy 2012-11-28
  • 打赏
  • 举报
回复
override标识
sinco449 2012-11-19
  • 打赏
  • 举报
回复
引用 4 楼 HSFZXJY 的回复:
这不是美工的活么?
美工也负责敲代码么?
hsfzxjy 2012-11-16
  • 打赏
  • 举报
回复
这不是美工的活么?
t82613586 2012-11-16
  • 打赏
  • 举报
回复
一直用自带的菜单控件,没有再做深入研究
sinco449 2012-11-16
  • 打赏
  • 举报
回复
有两个兄弟热心帮我跟了那个贴子,让我顺利地结贴,非常感谢。
sinco449 2012-11-15
  • 打赏
  • 举报
回复
有没有其他控件可以替代ToolBar?ToolButton不能重绘是个问题,郁闷。 哪位有时间,到我的这个帖子里跟个贴:http://bbs.csdn.net/topics/390252913 那个帖子我在结贴的时候,想要在后面回复写上解决的方法,结果系统提示说因为最末尾连续3个回复都是我发的,不允许我再回复了,需要别人回复一下,我才能回复。

5,927

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧