Событие щелчка всплывающего меню delphi не просто выполняется при щелчке мышью по пункту меню, а выполняется после выполнения некоторой функции

Когда я программно выскакиваю всплывающее меню, используя кнопку button1, а когда всплывающее меню, то щелкаю элемент item1 всплывающего меню, чтобы вызвать обработчик события.

После этого нажмите кнопку2.

Я ожидаю, что появится сообщение "Process Popup".

Но результат "Item1 Clicked!".

Что происходит и как я могу получить результат, который я ожидаю.

     //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 ответа

Вот что происходит: когда отображается всплывающее меню, оно запускает свой собственный цикл сообщений. При щелчке по пункту меню событие щелчка публикуется в очереди сообщений приложений. IOW, это не действует немедленно. Затем всплывающее меню закрывается, и выполнение продолжается с установкой FMsg на "Process popup". Затем цикл обработки сообщений приложения извлекает сообщение, которое было отправлено щелчком меню, и затем вызывает Item1Click, который присваивает "Item1 clicked" для FMsg.

Как изменить Чтобы получить ожидаемый результат, вам придется помешать нормальной обработке сообщений, например, вызвав Application.ProcessMessages сразу после PopupMenu.Popup. Но я не рекомендую это делать. Лучше переосмыслить свой дизайн.

Если вы установите некоторые контрольные точки и используете F8 для пошагового выполнения кода, вы увидите, что не так.

В любом случае, причина, по которой отображается сообщение: "Item1 Clicked!" потому что в это время установлена ​​переменная FMsg.

Поток вашего кода выглядит так:

 //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;

ПРИМЕЧАНИЕ. Вызов "PopMenu1.Popup(APoint.X, APoint.Y)" не останавливает ваш код в ожидании того, на какой элемент всплывающего окна вы нажмете. Я думаю, что вы перепутали функциональность всплывающего меню с модальными формами (диалогами), где код на самом деле ждет модального результата, возвращаемого из такой формы.

Другие вопросы по тегам