When i programatically pop up the popup-menu using button1 click, and when poped up the meun then click the item1 of popup menu item to call event handler.

After then click the button2.

I expect the message is displayed 'Process Popup'.

But result is 'Item1 Clicked!'.

What's happening and how can i get the result what i expect.

     //Popup Menu Item1 Click event handler
     procedure MyForm.Item1Click(Sender: TObject);
     begin
       FMsg := 'Item1 Clicked!';
     end;

     procedure MyForm.ProcessPopup(APoint: TPoint);
     begin
       PopupMenu1.Popup(APoint.X, APoint.Y);
       FMsg := 'Process Popup';
     end;

     procedure MyForm.Button1Click(Sender: TObject);
     begin
       ProcessPopup(Mouse.x, Mouse.Y);
     end;

     procedure MyForm.Button2Click(Sender: TObject);
     begin
       ShowMessage(FMsg);
     end;
2

There are 2 best solutions below

6
On

If you would set some breakpoints and use F8 to step through your code you would see what is wrong.

Anywhay the reason why the message displayed is 'Item1 Clicked!' is becouse that is set to FMsg variable at the time.

The flow of your code is like this:

 //Popup Menu Item1 Click event handler
 procedure MyForm.Item1Click(Sender: TObject);
 begin
   FMsg := 'Item1 Clicked!'; //4. Called after you click on first popup item
 end;

 procedure MyForm.ProcessPopup(APoint: TPoint);
 begin
   PopupMenu1.Popup(APoint.X, APoint.Y); //2. This shows the popup menu
   FMsg := 'Process Popup'; //3. After that FMsg value is set to 'Process Popup'
 end;

 procedure MyForm.Button1Click(Sender: TObject);
 begin
   ProcessPopup(Mouse.x, Mouse.Y); //1. Called first when you ress the mouse button
 end;

 procedure MyForm.Button2Click(Sender: TObject);
 begin
   ShowMessage(FMsg); //5. Finally this is called on Buttom2 click
                      //At this time the value of FMsg is 'Item1 Clicked!' as it
                      //was set last in Item click event handler
 end;

NOTE: Calling "PopMenu1.Popup(APoint.X, APoint.Y)" does not stop your code to wait on which Popup Item will you click. I think you mixed up the popup menu functionality with modal forms (Dialogs) where the code actually do waits for modal result returned from such form.

4
On

What's happening is this: When the popup menu is shown, it runs its own message loop. When the menu item is clicked, the click event is posted to the applications message que. IOW, it is not acted upon immediately. The popup menu is then dismissed and execution continues with setting FMsg to 'Process popup'. The application message loop then fetches the message that was posted by the menu click and subsequently calls Item1Click which assigns 'Item1 clicked' to FMsg.

How to change To get the result you expect you would have to interfere with normal message handling, for example by calling Application.ProcessMessages Right after PopupMenu.Popup. But I do not recommend to do that. Better rethink your design.