2009-08-11 14 views
3

In der OnShow-Methode von Delphi formuliere ich, dass ein Dialog automatisch geöffnet werden muss, sobald das Formular geöffnet wird - und ich sollte dies tun können, indem ich einen Klick auf einen Menüeintrag simuliere.WM_COMMAND an ein TMenuItem senden

Wenn Sie jedoch menuitem.Click aufrufen, wird der Dialog geöffnet, bevor das Hauptformular geöffnet wurde - was ich nicht möchte.

Ich erwarte, dass sollte tun, was ich will, aber ich kann nicht finden, welche Parameter für "wparam" übergeben, um den Klick zu meinem Menüpunkt zu senden.

PostMessage(handle, WM_COMMAND, wparam, 0) 

Die MSDN WM_COMMAND docs Diskussion über IDM_ * Identifikatoren, aber wie funktioniert die erscheinen in Delphi?

Antwort

2

Vielleicht können Sie versuchen, den Dialog im OnActivate-Ereignis zu öffnen? Ich bin nicht wirklich sicher, ob die OnActivate wieder andere gefeuert wird, als wenn das Formular angezeigt wird, aber wenn es funktioniert können Sie:

procedure TForm1.FormActivate(Sender: TObject); 
begin 
    Form2.ShowModal; 
    Self.OnActivate := nil; 
end; 
+0

Danke - aber dies wird noch ausgelöst, bevor das Hauptformular tatsächlich erscheint, so erscheint der Dialog 'verwaist'. – Roddy

+0

Ich bin mir sehr sicher, OnActivate wird ausgelöst, nachdem das Formular angezeigt wird, denn wenn das Formular nicht angezeigt wird, wie kann es aktiviert werden. – zz1433

+0

Du hast Recht: Ich habe eine Interaktion mit einer Drittpartei-Komponente, die aktiviert früh aktivieren. – Roddy

0

Würden Sie nicht dies mit einer einmaligen Timer zu tun haben, wenn Sie möchten, dass das Formular wie in einem normalen Show/ShowModal angezeigt wird, vollständig (0) gezeichnet wird und dann sofort etwas anderes tun?

 
tmrKickOff : a TTimer, 100 ms interval, disabled at design time, 
fires off a 'tmrKickOffTimer' event. 


in form create, 
tmrKickOff.Enabled:=false; //just in case something happened in IDE 

in form show, at end of all other stuff; 
tmrKickOff.Enabled:=true; 

in tmrKickOffTimer 
begin 
    tmrKickOffTimer.Enabled:=false; 
    menuItemClick(nil); 
end; 

mit Entschuldigungen für Stil, Form und jeden Fehler-Trapping :-)

0

das mit etwas Application.OnIdle Ereignisse Alternativ Griff entlang der Linien von ...

if not DialogDone then 
begin 
    MyDialogForm.ShowModal; // or menuItem.Click .... 
    DialogDone := true; 
end; 

OnIdle wird nicht (zum ersten Mal) ausgelöst, bis das Formular angezeigt wird und die Nachrichtenwarteschlange leer ist.

+0

Ich empfehle das nicht. OnIdle sollte für kleine Statusaktualisierungen und möglicherweise Hintergrundverarbeitung verwendet werden. Aber nicht für einzelne Feuerhandlungen. –

0

Ich glaube nicht, dass Sie eine Nachricht direkt an Ihren Menüpunkt senden können, aber Sie können es einfach in das Hauptfenster posten und Ihren Dialog von dort zeigen. Ich mache das und es funktioniert gut, so dass das Dialogfeld (in meinem Fall eine Anmeldeaufforderung) über dem Hauptfenster angezeigt wird, um Verwirrung zu vermeiden.

-Mark

procedure WMPostStartup(var Message: TMessage); message WM_POSTSTARTUP; 

procedure TMainForm.WMPostStartup(var Message: TMessage); 
begin 
    Self.Refresh; 
    // Now show the dialog box. 
end; 
0

Eine Methode, die ich verwendet habe, die markf Lösung sehr simular ist, ist eine neue benutzerdefinierte Nachrichtentyp zu erstellen und senden Sie eine Nachricht, die Art an sich selbst zu verwenden, wenn Sie, dass Sie bestimmen, müssen diese anderen Verfahren nach dem Hauptformular angezeigt auszuführen:

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; 

Das schöne an dieser Methode ist, dass Sie die Kontrolle über die Nachrichtenerzeugung sind, so dass jeder lparam bevölkern können oder wparam Sie später verwenden möchten, indem Sie Ihre Handler. Ich habe die Nachricht direkt über die application.mainform gesendet, aber Sie könnten auch einfach handle für das aktuelle Formular sagen.

5

(. Ich weiß, dass dies eine sehr alte Frage ist aber, obwohl er in irgendeiner Weise nicht gelöst die eigentliche Frage hat wirklich unbeantwortet)
-

Der Befehl Positionsnummer eines ‚TMenuItem‘ ist in die Command Eigenschaft.Laut WM_COMMANDs documentation wäre das hohe Wort von 'wParam' '0' und das niedrige Wort wäre die Menükennung;

PostMessage(Handle, WM_COMMAND, MakeWParam(MyMenuItem.Command, 0), 0); 

oder einfach;

PostMessage(Handle, WM_COMMAND, MyMenuItem.Command, 0); 


Mit einem Menüpunkt Popup würde es einen kleinen Unterschied: die VCL verarbeitet Nachrichten Popup-Menüs mit einem anderen Utility-Fenster. Die globale PopupList Variable hat den Griff dazu in seiner Window Eigenschaft;

PostMessage(PopupList.Window, WM_COMMAND, MyPopupMenuItem.Command, 0); 
+0

+1; Danke, ich war auf der Suche nach etwas, das das heute macht. –

+0

+1 für den Punkt über Popup-Menüs – jpfollenius