Отправка WM_COMMAND в TMenuItem
В методе OnShow моей формы Delphi я определяю, что диалог должен открываться автоматически после открытия формы, и я должен быть в состоянии сделать это, имитируя щелчок по элементу меню.
Однако при вызове menuitem.Click открывается диалоговое окно до того, как открылась основная форма, а это не то, чего я хочу.
Я ожидаю, что это должно делать то, что я хочу, но я не могу найти, какие параметры передать для "wparam", чтобы отправить щелчок на мой пункт меню.
PostMessage(handle, WM_COMMAND, wparam, 0)
В документах MSDN WM_COMMAND говорится об идентификаторах IDM_*, но как это выглядит в Delphi?
6 ответов
Возможно, вы можете попытаться открыть диалог в событии OnActivate? Я не совсем уверен, что OnActivate будет запущен снова, кроме как при показе формы, но если это так, вы можете использовать:
procedure TForm1.FormActivate(Sender: TObject);
begin
Form2.ShowModal;
Self.OnActivate := nil;
end;
(Я знаю, что это очень старый вопрос, но, несмотря на то, что он каким-то образом решен, реальный вопрос действительно остался без ответа.)
-
Идентификатор элемента команды "TMenuItem" находится в Command
имущество. Согласно документации WM_COMMAND старшее слово wParam будет равно 0, а младшее слово будет идентификатором меню;
PostMessage(Handle, WM_COMMAND, MakeWParam(MyMenuItem.Command, 0), 0);
или просто;
PostMessage(Handle, WM_COMMAND, MyMenuItem.Command, 0);
С элементом всплывающего меню будет небольшая разница: VCL обрабатывает сообщения всплывающих меню с помощью другого окна утилиты. Глобальная переменная PopupList имеет дескриптор Window
имущество;
PostMessage(PopupList.Window, WM_COMMAND, MyPopupMenuItem.Command, 0);
Разве вам не нужно делать это с одноразовым таймером, если вы хотите, чтобы форма отображалась в соответствии с обычным Show/ShowModal, полностью прорисовывалась (и т. Д.), А затем немедленно делала что-то еще?
tmrKickOff: TTimer, интервал 100 мс, отключен во время разработки, запускает событие 'tmrKickOffTimer'. в форме создания, tmrKickOff.Enabled:= FALSE; // на случай, если что-то случилось в IDE в форме показа, в конце всего остального; tmrKickOff.Enabled:= True; в tmrKickOffTimer начать tmrKickOffTimer.Enabled:= FALSE; menuItemClick(ноль); конец;
с извинениями за стиль, форму и любые сообщения об ошибках:-)
Я не думаю, что вы можете отправить сообщение непосредственно в ваш пункт меню, но вы можете просто опубликовать его в главном окне и показать свой диалог оттуда. Я делаю это, и это прекрасно работает, так что диалоговое окно (в моем случае, приглашение для входа в систему) появляется в верхней части главного окна, чтобы избежать путаницы.
-Отметка
procedure WMPostStartup(var Message: TMessage); message WM_POSTSTARTUP;
procedure TMainForm.WMPostStartup(var Message: TMessage);
begin
Self.Refresh;
// Now show the dialog box.
end;
В качестве альтернативы, обработайте событие Application.OnIdle чем-то вроде...
if not DialogDone then
begin
MyDialogForm.ShowModal; // or menuItem.Click ....
DialogDone := true;
end;
OnIdle не будет запускаться (в первый раз), пока форма не отобразится и очередь сообщений не станет пустой.
Один из методов, который я использовал и который очень похож на решение MarkF, - это создание нового типа сообщения, определенного пользователем, и отправка себе сообщения с использованием этого типа, когда вы решите, что вам нужно выполнить этот другой процесс после отображения основной формы:
const
wm_SpecialProc = wm_User + 1;
procedure TForm1.WMSpecialProc(var Message:tMessage); message wm_SpecialProc;
begin
Form2.ShowModal;
end;
procedure TForm1.OnShow(Sender:tObject);
begin
if true then
PostMessage(Application.MainForm.Handle,wm_SpecialProc,0,0);
end;
Хорошая особенность этого метода заключается в том, что вы контролируете генерацию сообщений, поэтому можете заполнить ЛЮБОЙ lparam или wparam, который вы захотите позже использовать в своем обработчике. Я отправил сообщение напрямую через application.mainform, но вы также можете просто сказать, обрабатывать текущую форму.