5

TActionMainMenuBar have a bug with painting root elemetnts without child items.

Using Delphi XE2 / w7-32bit**

how to reproduce:
build menu with TActionMainMenuBar, add some actions to it:

 file  | options | help
 - New
 - Open
 - Save
  -Exit

assign to all actions one empty method

procedure TfrmMain.ActionExecute(Sender: TObject); 
begin 
// 
end;

now run application and try to click on options or help element.
now click on form, but the menu element is still pressed!

any workarounds exists?

upd: look at screenshot, menu element is down, but mouse cursor not on menu, and autocheck is false, and checked is false too.
enter image description here
here is not any colormap on the form, and manager style is platform default

utmost
  • 101
  • 4
  • I don't see any problem/can't reproduce in Delphi 2009. – Andreas Rejbrand Feb 16 '13 at 17:49
  • @AndreasRejbrand are you assigned the empty method? please send me compiled exe, maybe we have some regression in XE2 – utmost Feb 16 '13 at 18:05
  • I can reproduce this is XE2 – davea Feb 16 '13 at 18:23
  • What is supposed to happen? The `Options` menu item is disabled, and so nothing happens when you hover/click it... – Andreas Rejbrand Feb 16 '13 at 18:26
  • @AndreasRejbrand actOption.onexecute must be linked to empty method. just dblclick on it in objectinspector and add // to generated code – utmost Feb 16 '13 at 18:29
  • Same thing happens in Delphi 2010. It should be noted that performing any kind of "visual" action in the event handler seems to solve the problem. e.g. `X:=1` in the action handler displays the same problem, `ShowMessage('Options')` does not. – davea Feb 16 '13 at 18:33
  • @utmost: OK, I only believed that `New`, `Open`, `Save`, and `Exit` had to be linked to empty actions. Still, I don't see anything strange... – Andreas Rejbrand Feb 16 '13 at 18:33
  • HOWEVER, if I use the 'XP Style' and click on some *other* Windows application, so that this form loses its focus, then the last-clicked root item is painted in black instead of gray, so I *do* see an issue, although not quite as severe as the one reported. – Andreas Rejbrand Feb 16 '13 at 18:45
  • I now changed to the 'Twilight Color Map', and then I see the problem as the OP describes it. Yes, this is a problem. +1 on the Q. – Andreas Rejbrand Feb 16 '13 at 18:49
  • 1
    A screenshot would of been good here to illustrate the paint bug you are talking about. –  Feb 16 '13 at 20:48
  • 1
    @Blobby screenshot attached now – utmost Feb 16 '13 at 22:13
  • look at the TThemedMenuButton.DrawBackground in Vcl.ThemedActnCtrls unit : StyleServices.DrawElement(Canvas.Handle, StyleServices.GetElementDetails(MenuStates[MouseInControl, Selected]), PaintRect); the problem in menustates flags? maybe it not updated in some place – utmost Feb 16 '13 at 22:23
  • 1
    Interesting. The default appearance of the `TActionMainMenuBar` looks different on my system (Delphi 2009, Windows 7 Home Premium, Aero). – Andreas Rejbrand Feb 16 '13 at 22:31
  • WTF? here is another bug in TActionMainMenuBar? write in OnExecute `ShowMessage( TAction(Sender).ActionComponent.ClassName );` and call action from ActionMainMenuBar button, u get the exception, but it works fine with ActionToolBar. – utmost Feb 17 '13 at 04:26
  • @utmost - Yeah, menu items don't support actioncomponent, that's how it is designed. See [this answer](http://stackoverflow.com/a/4287411). – Sertac Akyuz Feb 17 '13 at 10:07
  • @utmost - You're welcome. Please post your workaround as an answer (after removing from the question), then you can accept it as the solution (probably after a specific time period though). BTW, I can duplicate the problem you have described with items that have items here, you probably don't observe that however... – Sertac Akyuz Feb 17 '13 at 16:17

2 Answers2

1

here is my workaround:
create custom class like this:


type
  TFastThemedButton = class(TThemedMenuButton)
  protected
    procedure DrawBackground(var PaintRect: TRect); override;
end;

...


procedure TFastThemedButton.DrawBackground(var PaintRect: TRect);
const
  MenuStates: array[Boolean {MouseInControl}, Boolean {Selected}] of TThemedMenu =
    ((tmMenuBarItemNormal, tmMenuBarItemPushed), (tmMenuBarItemHot, tmMenuBarItemPushed));
var
  BannerRect: TRect;
  StartCol, EndCol: TColor;
begin
   Canvas.Brush.Color := ActionBar.ColorMap.Color;
   Canvas.Font := ActionBar.Font;
   StyleServices.DrawElement(Canvas.Handle, StyleServices.GetElementDetails(MenuStates[MouseInControl, (State=bsDown)]), PaintRect);
end;

now in you TActionMainMenuBar.OnGetControlClass add this simple code, and set to buggy actionclients tag=-100


procedure TfrmActions.ActionMainMenuBar1GetControlClass(Sender: TCustomActionBar; AnItem: TActionClient; var ControlClass: TCustomActionControlClass);
begin
  if ControlClass.InheritsFrom(TCustomMenuButton) and then
   begin
    if (AnItem.Tag =-100) and (ControlClass = TThemedMenuButton) then
      ControlClass := TFastThemedButton;
   end;
end;

well, now all root items with -100 tag, works as we wish

utmost
  • 101
  • 4
0

I am using the event MainMenuExitMenuLoop with MainMenu.RecreateControls on all forms with a menu. So far this removes the stuck selection from the menu items.