Recent

Author Topic: [Solved] Dynamic Popup won't work  (Read 3410 times)

rudi

  • Newbie
  • Posts: 2
[Solved] Dynamic Popup won't work
« on: February 25, 2018, 10:10:33 am »
Hello Together,

I try to use a dynamic popup menu but the OnClick Event is not working. I use Lazarus 1.8.0 on Windows 10. I tried it on Windows 7 too, same problem.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5.         Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids, Types,Menus, StdCtrls;
  6.  
  7. type
  8.  TForm1 = class(TForm)
  9.                 StringGrid1: TStringGrid;
  10.                 procedure PopupReset(Sender: TObject);
  11.                 procedure PopupUpDown(Sender : TObject);
  12.                 procedure StringGrid1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
  13.         private
  14.         public
  15.         end;
  16.  
  17. var
  18.         Form1: TForm1;
  19.  
  20. implementation
  21.  
  22. {$R *.lfm}
  23.  
  24. procedure TForm1.StringGrid1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
  25. var
  26.   Popup : TPopupMenu;
  27.   mi,mb :       TMenuItem;
  28. begin
  29.   Popup := TPopupMenu.Create(StringGrid1);
  30.  
  31.   mi := TMenuItem.Create(Popup);
  32.   mi.Caption := 'Reset';
  33.   mi.OnClick := @PopupReset;
  34.   Popup.Items.Add(mi);
  35.  
  36.   mb := TMenuItem.Create(Popup);
  37.   mb.Caption := 'Change';
  38.   Popup.Items.Add(mb);
  39.  
  40.   mi := TMenuItem.Create(mb);
  41.   mi.Caption := 'Up';
  42.   mi.OnClick := @PopupUpDown;
  43.   mi.Tag := 1;
  44.   mb.Add(mi);
  45.  
  46.   mi := TMenuItem.Create(mb);
  47.   mi.Caption := 'Down';
  48.   mi.OnClick := @PopupUpDown;
  49.   mi.Tag := 2;
  50.   mb.Add(mi);
  51.  
  52.   Popup.PopUp;
  53.  
  54.         Popup.Free;
  55. end;
  56.  
  57.  
  58. procedure TForm1.PopupReset(Sender : TObject);
  59. begin
  60.   StringGrid1.Cells[2,2] := 'Reset';
  61. end;
  62.  
  63. procedure TForm1.PopupUpDown(Sender : TObject);
  64. begin
  65.         if TMenuItem(Sender).Tag=1 then
  66.                 StringGrid1.Cells[2,2] := 'Up';
  67.         if TMenuItem(Sender).Tag=2 then
  68.                 StringGrid1.Cells[2,2] := 'Down';
  69. end;
  70.  
  71. end.
  72.  

On the Mainform I placed a TStringGrid-Component and added the StringGridContextPopup-Action. The Project compiles without errors. The Popup menu opens and i can select the items incl. the submenu, but nothing happens.

Any ideas?

Thank you very much for your help.

rudi
« Last Edit: February 25, 2018, 03:27:50 pm by rudi »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Dynamic Popup won't work
« Reply #1 on: February 25, 2018, 10:31:10 am »
Hello Together,

I try to use a dynamic popup menu but the OnClick Event is not working. I use Lazarus 1.8.0 on Windows 10. I tried it on Windows 7 too, same problem.

On the Mainform I placed a TStringGrid-Component and added the StringGridContextPopup-Action. The Project compiles without errors. The Popup menu opens and i can select the items incl. the submenu, but nothing happens.

Any ideas?

Thank you very much for your help.

rudi

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
  2. var
  3.   Popup : TPopupMenu;
  4.   mi,mb   :   TMenuItem;
  5. begin
  6.   Popup := TPopupMenu.Create(StringGrid1);
  7.  
  8.   mi := TMenuItem.Create(Popup);
  9.   mi.Caption := 'Reset';
  10.   mi.OnClick := @PopupReset;
  11.   Popup.Items.Add(mi);
  12.  
  13.   mb := TMenuItem.Create(Popup);
  14.   mb.Caption := 'Change';
  15.   Popup.Items.Add(mb);
  16.  
  17.   mi := TMenuItem.Create(mb);
  18.   mi.Caption := 'Up';
  19.   mi.OnClick := @PopupUpDown;
  20.   mi.Tag := 1;
  21.   mb.Add(mi);
  22.  
  23.   mi := TMenuItem.Create(mb);
  24.   mi.Caption := 'Down';
  25.   mi.OnClick := @PopupUpDown;
  26.   mi.Tag := 2;
  27.   mb.Add(mi);
  28.  
  29.   Popup.PopUp; //<---- this does not pause the execution here.
  30.  
  31.    Popup.Free;  //<----- this destroyes the dynamic popup before you have achance to select anything.
  32. end;
  33.  
I suggest to drop a popup menu on the form assign to the popup property of the grid and in menu's onpopup event clear the existing items and recreate them as needed.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Dynamic Popup won't work
« Reply #2 on: February 25, 2018, 01:28:45 pm »
I think you have uncovered a bug in the Windows implementation of TPopupMenu (when you select an item the widgetset fails to locate the correct TMenuItem in a dynamically created menu's Items list).

The code you showed works as expected on linux without any alteration.
taazz's suggestion is a workaround for Windows.

rudi

  • Newbie
  • Posts: 2
[SOLVED] Dynamic Popup won't work
« Reply #3 on: February 25, 2018, 03:24:42 pm »
Hi, I'm back from Brunch,

thank you for your solutions.

@taazz:

I changed creating/freeing into FormCreate/FormDestroy. It works now as expected.
My explanation: I tried to find out the order of execution: I find out that the popup menu works fine when i call 'popup.popup'. The Method 'ContextPopup' is waiting until Popup-Menu is finished. Then ContextPopup is finished (and Popup destroyed). When Popup menu would be 'alive' it now would executes OnClick-Command. Which is not possible because Menu is not existing after .free.

@howardpc:
I think in Linux OnClick-Action is performed directly from popup.popup. So it works in Linux.

So i have learned: Take care of lifetime of objects/components.

Thank you very much for your help.

With best wishes,

rudi
« Last Edit: February 25, 2018, 03:27:29 pm by rudi »

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: [SOLVED] Dynamic Popup won't work
« Reply #4 on: February 25, 2018, 04:13:14 pm »
According to the documentation TrackPopupMenuEx: "A handle to the window that owns the shortcut menu. This window receives all messages from the menu. The window does not receive a WM_COMMAND message from the menu until the function returns."

trayres

  • Jr. Member
  • **
  • Posts: 92
Re: [Solved] Dynamic Popup won't work
« Reply #5 on: April 12, 2018, 06:33:49 am »
I just ran into this problem on Windows, Lazarus 1.8.2

Code: Pascal  [Select][+][-]
  1. procedure TForm1.PageControl1ContextPopup(Sender: TObject; MousePos: TPoint;
  2.   var Handled: boolean);
  3. var
  4.   tabindex: integer;
  5.   pt: TPoint;
  6.   APopupMenu: TPopupMenu;
  7.   APopupMenuItem: TMenuItem;
  8. begin
  9.   tabindex := TPageControl(Sender).IndexOfTabAt(MousePos);
  10.   if tabindex >= 0 then
  11.   begin
  12.     APopupMenu := TPopupMenu.Create(Self);
  13.     APopupMenuItem := TMenuItem.Create(APopupMenu); //FPageControlContextPopup
  14.     APopupMenuItem.Caption := 'Popup Menu test';
  15.     APopupMenuItem.OnClick := @PopupTest;
  16.     APopupMenu.Items.Add(APopupMenuItem);
  17.     APopupMenu.PopUp;
  18.     APopupMenu.Free; //<-Prevents OnClick from firing
  19.   end;
  20. end;

balazsszekely

  • Guest
Re: [Solved] Dynamic Popup won't work
« Reply #6 on: April 12, 2018, 08:16:15 am »
@trayres

Declare APopupMenu as FPopupMenu in the Form private section. Use FormCreate and FormDestroy to create respectively free the object. You can re-use it each time is needed.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: [Solved] Dynamic Popup won't work
« Reply #7 on: April 12, 2018, 11:49:08 pm »
In the above case I think doing a "Application.ProcessMessages" before the FREE will work.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018