Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: How do you update a Main Menu at run time?


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 8 - Last Post: May 2, 2017 1:54 AM Last Post By: Richard Simon
Richard Simon

Posts: 54
Registered: 10/7/07
How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 27, 2017 5:27 AM
Does anyone know how to effectively update a main menu's child items? For example a recent files list, or to enable / disable cut copy & paste items depending on whether something is selected, or the clipboard has data on it. I have all kinds of child and grandchild items that need creating / destroying / enabling / disabling etc. depending on what the user has done within my application.

The obvious place to do this is when the user clicks on the top level menu item, but since Main Menu items that have child items do not respond to the OnClick event (a bug which I reported to Embarcadero over a year ago but has STILL not been fixed RSP-17594) I cannot figure a sensible way to do this. Of course if you reconfigure the menu items within the code executed by a menu item itself, there is a danger that this can lead to AV errors.

I am sure that other people must have encountered the same problem and was wondering if anyone had come up with a neat solution. I would really appreciate some help with this as I am stuck!
Markus Humm

Posts: 5,113
Registered: 11/9/03
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 27, 2017 10:25 AM   in response to: Richard Simon in response to: Richard Simon
Am 27.04.2017 um 14:27 schrieb Richard simon:
Does anyone know how to effectively update a main menu's child items? For example a recent files list, or to enable / disable cut copy & paste items depending on whether something is selected, or the clipboard has data on it. I have all kinds of child and grandchild items that need creating / destroying / enabling / disabling etc. depending on what the user has done within my application.

The obvious place to do this is when the user clicks on the top level menu item, but since Main Menu items that have child items do not respond to the OnClick event (a bug which I reported to Embarcadero over a year ago but has STILL not been fixed RSP-17594) I cannot figure a sensible way to do this. Of course if you reconfigure the menu items within the code executed by a menu item itself, there is a danger that this can lead to AV errors.

I am sure that other people must have encountered the same problem and was wondering if anyone had come up with a neat solution. I would really appreciate some help with this as I am stuck!

Hello,

one solution, even if not really neat, would be to do the updating
triggered by a timer which is fired at the end of the code run when
clicking on a item which causes such a change. At least the AV should be
gone then. Just make the timer interval short enough.

Greetings

Markus
Richard Simon

Posts: 54
Registered: 10/7/07
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 28, 2017 11:10 AM   in response to: Markus Humm in response to: Markus Humm
Markus Humm wrote:
Am 27.04.2017 um 14:27 schrieb Richard simon:
Does anyone know how to effectively update a main menu's child items? For example a recent files list, or to enable / disable cut copy & paste items depending on whether something is selected, or the clipboard has data on it. I have all kinds of child and grandchild items that need creating / destroying / enabling / disabling etc. depending on what the user has done within my application.

The obvious place to do this is when the user clicks on the top level menu item, but since Main Menu items that have child items do not respond to the OnClick event (a bug which I reported to Embarcadero over a year ago but has STILL not been fixed RSP-17594) I cannot figure a sensible way to do this. Of course if you reconfigure the menu items within the code executed by a menu item itself, there is a danger that this can lead to AV errors.

I am sure that other people must have encountered the same problem and was wondering if anyone had come up with a neat solution. I would really appreciate some help with this as I am stuck!

Hello,

one solution, even if not really neat, would be to do the updating
triggered by a timer which is fired at the end of the code run when
clicking on a item which causes such a change. At least the AV should be
gone then. Just make the timer interval short enough.

Greetings

Markus

Thanks for this suggestion Markus.
Yes I can see this is a possible workaround which I may well try. It's a bit messy as the appropriate code needs to added to every Menu Item's method. But it is do-able.
Regards
Rick
Hans Jakobsen

Posts: 103
Registered: 9/10/01
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 1, 2017 1:32 AM   in response to: Richard Simon in response to: Richard Simon
Richard simon wrote:
Thanks for this suggestion Markus.
Yes I can see this is a possible workaround which I may well try. It's a bit messy as the appropriate code needs to added to every Menu Item's method. But it is do-able.

It does not have to be complicated or messy to implement this work around. You can for example make a simple thread class that does it, so if you want to delay the function call "DoOpenNewWindow" by 5 milliseconds call this line:

tDelayProcThread.Create(5, DoOpenNewWindow);


Here is the source code for the thread:

  tDelayProcThread = class(TThread)
    private
    protected
      fThreadProc: TThreadProcedure;
      fTimeDelayMS: integer;
      procedure Execute; override;
    public
      constructor Create(aTimeDelayMS: integer; aThreadProc: TThreadProcedure);
  end;
 
implementation
 
constructor tDelayProcThread.Create(aTimeDelayMS: integer; aThreadProc: TThreadProcedure);
begin
  inherited Create(false);
  fThreadProc := aThreadProc;
  fTimeDelayMS := aTimeDelayMS;
  FreeOnTerminate := true;
end;
 
procedure tDelayProcThread.Execute;
begin
  Sleep(fTimeDelayMS);
  TThread.Queue(nil, fThreadProc);
end;
Richard Simon

Posts: 54
Registered: 10/7/07
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 1, 2017 4:51 AM   in response to: Hans Jakobsen in response to: Hans Jakobsen
Hans Jakobsen wrote:
Richard simon wrote:
Thanks for this suggestion Markus.
Yes I can see this is a possible workaround which I may well try. It's a bit messy as the appropriate code needs to added to every Menu Item's method. But it is do-able.

It does not have to be complicated or messy to implement this work around. You can for example make a simple thread class that does it, so if you want to delay the function call "DoOpenNewWindow" by 5 milliseconds call this line:

tDelayProcThread.Create(5, DoOpenNewWindow);


Here is the source code for the thread:

  tDelayProcThread = class(TThread)
    private
    protected
      fThreadProc: TThreadProcedure;
      fTimeDelayMS: integer;
      procedure Execute; override;
    public
      constructor Create(aTimeDelayMS: integer; aThreadProc: TThreadProcedure);
  end;
 
implementation
 
constructor tDelayProcThread.Create(aTimeDelayMS: integer; aThreadProc: TThreadProcedure);
begin
  inherited Create(false);
  fThreadProc := aThreadProc;
  fTimeDelayMS := aTimeDelayMS;
  FreeOnTerminate := true;
end;
 
procedure tDelayProcThread.Execute;
begin
  Sleep(fTimeDelayMS);
  TThread.Queue(nil, fThreadProc);
end;

So should I update the main menu from within the thread?
Hans Jakobsen

Posts: 103
Registered: 9/10/01
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 1, 2017 5:00 AM   in response to: Richard Simon in response to: Richard Simon
Richard simon wrote:
So should I update the main menu from within the thread?

When times is up, it queues the message to the main thread, so its safe to update the GUI from the function.

This line queues it in the main thread:
TThread.Queue(nil, fThreadProc);
Richard Simon

Posts: 54
Registered: 10/7/07
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 2, 2017 1:54 AM   in response to: Hans Jakobsen in response to: Hans Jakobsen
Hans Jakobsen wrote:
Richard simon wrote:
So should I update the main menu from within the thread?

When times is up, it queues the message to the main thread, so its safe to update the GUI from the function.

This line queues it in the main thread:
TThread.Queue(nil, fThreadProc);

Because within my application, controls on my main form can be dragged around and dropped to reposition them as well as being selected and deslected by clicking, if the user moves the mouse while the menu is being repopulated (or clicks outside the menu popup to cancel it) controls get inadvertently moved around on the main form. So whilst I can see the thinking behind this workaround, sadly for me it does not seem to work at the moment.
Bob Carson

Posts: 62
Registered: 10/8/04
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 27, 2017 1:36 PM   in response to: Richard Simon in response to: Richard Simon
I have an app that adds Menu Items to the Main Menu Main Module when Showing a new window. The Main Menu is part of the main module created in screen design. A menu item called Windows is part of the main menu. I add this code to the Show event of each window called:

Var WKMENUITEM : TMenuItem;
begin

WKMENUITEM := TMenuItem.Create(Main1.mnuWindows);

WKMENUITEM.Text := 'Contact Maintenance';
Main1.mnuWindows.AddObject(WKMENUITEM);
WKMENUITEM.OnClick := Main1.mnuCompContMaintClick;

end.
Obviously, the menu item Text and OnClick Event will be specific for the window or module called.This code gave a protection fault, so I took it out:
// WKMENUITEM.Parent := Main1.mnuWindows;
This is the app I use this : www.accessoryware.com/download/pfinmgr4.exe
Richard Simon

Posts: 54
Registered: 10/7/07
Re: How do you update a Main Menu at run time?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 28, 2017 11:06 AM   in response to: Bob Carson in response to: Bob Carson
Bob Carson wrote:
I have an app that adds Menu Items to the Main Menu Main Module when Showing a new window. The Main Menu is part of the main module created in screen design. A menu item called Windows is part of the main menu. I add this code to the Show event of each window called:

Var WKMENUITEM : TMenuItem;
begin

WKMENUITEM := TMenuItem.Create(Main1.mnuWindows);

WKMENUITEM.Text := 'Contact Maintenance';
Main1.mnuWindows.AddObject(WKMENUITEM);
WKMENUITEM.OnClick := Main1.mnuCompContMaintClick;

end.
Obviously, the menu item Text and OnClick Event will be specific for the window or module called.This code gave a protection fault, so I took it out:
// WKMENUITEM.Parent := Main1.mnuWindows;
This is the app I use this : www.accessoryware.com/download/pfinmgr4.exe

Thanks for this Bob.
I think that if the new window is created by the menu item being amended it may cause an access violation.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02