Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Auf das Schliessen eines PopupMenus reagieren
galagher - Fr 08.03.19 20:23
Titel: Auf das Schliessen eines PopupMenus reagieren
Hallo!
Ich habe nun nach einiger Suche eine Möglichkeit gefunden, auf das Schliessen eine PopupMenus zu reagieren:
https://www.delphipraxis.net/26787-pruefen-ob-ein-popupmenue-geoeffnet-ist.html
Nur leider komme ich nicht drauf, wie man, wie dort angesprochen, herausfinden kann, um welches PopupMenu es sich handelt:
Zitat: |
Wie kann man in CMMenuClosed then NAMEN des betreffenden Popup-Menüs erfahren? Geht das überhaupt? |
Zitat: |
Ja das geht, wenn man beim Senden der Nachricht auch noch eine zusätzliche Information hinzufügt (z.B. die Referenz auf die Popup-Instanz). |
Zitat: |
Und wie könnte man in der PRAXIS beim Senden der Nachricht in diesem Beispiel die betreffende Information einfügen? |
Weiss jemand, wie das geht?
Delete - Fr 08.03.19 21:13
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Fr 08.03.19 21:36
Hallo Frühlingsrolle!
Frühlingsrolle hat folgendes geschrieben : |
Man könnte das noch erweitern und z.B. anstelle des wParam-Parameters, self.Name mitschicken, in etwa:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TExPopupList.WndProc(var Message: TMessage); Procedure Send( msg: Integer ); Begin If Assigned( Screen.Activeform ) Then Screen.ActiveForm.Perform( msg, WParam(PChar(self.Name)), Message.lparam ); End; begin end; |
|
Leider klappt es mit
WParam(PChar(self.Name)) nicht. Ich habe etwas herumexperiemtiert und bin auf
Message.WParam(PChar(self.Name)) gekommen -
.Name wird aber nicht erkannt bzw. gibt es das hier nicht. Auch
Message.WParam(PChar(self)) funktioniert nicht, hier meckert der Compiler:
Zitat: |
E2066 Operator oder Semikolon fehlt |
- hier wird offenbar ein
, erwartet, sonst nichts!
Ich verstehe, was du meinst, bekomme es aber nicht hin.
Delete - Fr 08.03.19 21:55
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 06:02
Frühlingsrolle hat folgendes geschrieben : |
Nachtrag
Delphi-Quelltext 1:
| function GetPopupName(Parent: TWinControl): string; | |
Naja, das liefert in jedem Fall das erste gefundenene PopupMenu, egal, welches gerade verwendet wird...
Delete - Sa 09.03.19 06:46
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 07:53
Frühlingsrolle hat folgendes geschrieben : |
So funktioniert es explizit nur für TForm Objekte. |
Das nützt mit für meine Zwecke nichts. Ich möchte herausfinden können, welches PopupMenu das Schliessen ausgelöst hat, also von welchem PopupMenu
Send( CM_MENUCLOSED ); ausgelöst wurde!
Delete - Sa 09.03.19 09:27
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 10:53
Funktioniert leider auch nicht:
Frühlingsrolle hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TExPopupList.WndProc(var Message: TMessage); Procedure Send( msg: Integer ); Begin If Assigned( Screen.Activeform ) Then Screen.ActiveForm.Perform( msg, Integer(PChar(Screen.ActiveForm.PopupMenu.Name)), 0 ); End; begin end; | |
Ich krieg's einfach nicht hin!
Delete - Sa 09.03.19 11:07
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 11:45
Ich leider doch:
Zitat: |
Im Projekt Help.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 006D658E in Modul 'Help.exe'. Lesen von Adresse 00000008' aufgetreten. |
Geht das nur mit PopupMenus der TForm? Ich habe PopupMenus, die zu verschiedenen Komponenten gehören. Bei keiner funktioniert es!
//Edit:
Auch bei PopupMenus von TForm kommt es zu dem Fehler!
Delete - Sa 09.03.19 17:35
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 20:33
Frühlingsrolle hat folgendes geschrieben : |
Hm, führst du Delphi mit Adminrechten aus? Bei mir ist das der Fall. |
Nein, eingeschränktes User-Konto. Muss doch aber egal sein, oder?
Frühlingsrolle hat folgendes geschrieben : |
Die Eigenschaft .Popupmenu ist keiner Klasse eindeutig zuordenbar, daher muss man den Code auf das jeweilige Parent umschreiben.
Mit RTTI könnte man es zurecht biegen, da bin ich aber nicht so sattelfest darin. |
RTTI? Muss ich googeln!
Das Problem ist, dass
Screen.ActiveForm.PopupMenu nicht zugewiesen ist, denn wenn man mit
if Assigned(Screen.ActiveForm.PopupMenu) prüft, wird der Code nicht ausgeführt - ist also nicht zugewiesen.
Was ich nicht verstehe: Das PopupMenu gibt es ja, es gibt gleich mehrere, die jeweils verschiendene Komponenten haben. Sie existieren also, werden auch nirgendwo im Code "destroyed" oder so was in der Art.
Delete - Sa 09.03.19 20:50
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 21:16
Frühlingsrolle hat folgendes geschrieben : |
Viele WinAPI Funktionen, die im Delphi allgegenwertig sind, benötigen Lese- und Schreibrechte, die nur mit Adminrechten ein "korrektes" Ergebnis liefern können. |
Dann muss ich hier wohl aufgeben. Delphi ist unter meinem Adminkonto nicht eingerichtet. Ich kann mein Projekt nicht kompilieren, weil da diverse Komponenten nicht installiert sind.
//Edit: Klar könnte ich das jetzt alles auch im Adminkonto installieren.
Gibt es keinen einfacheren Weg, an das PopupMenu heranzukommen? Irgendwie, irgendwo muss mein Programm ja "wissen", welches PopupMenu gerade geschlossen wird!
Delete - Sa 09.03.19 21:25
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Sa 09.03.19 21:31
Frühlingsrolle hat folgendes geschrieben : |
Mit RTTI könnte man es zurecht biegen, da bin ich aber nicht so sattelfest darin. |
Ich erst recht nicht!
galagher - So 10.03.19 11:14
Zunächst habe ich einige Methoden in gefälligere Namen umbenannt und zudem einige neue Methoden hinzugefügt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78:
| unit ExPopupMenu;
interface
uses Controls, Menus;
const CM_MENU_CLOSED = CM_BASE + 1001; CM_ENTER_MENU_LOOP = CM_BASE + 1002; CM_EXIT_MENU_LOOP = CM_BASE + 1003;
var FPopupMenu: TPopupMenu;
function GetCurrentPopupMenu: TPopupMenu; procedure SetCurrentPopupMenu(const PopupMenu: TPopupMenu);
implementation
uses Messages, Forms;
type TPopupListEx = class(TPopupList) protected procedure WndProc(var Message: TMessage) ; override; private procedure PerformMessage(cm_msg : integer; msg : TMessage) ; end;
procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ; begin if not (Screen.Activeform = nil) then Screen.ActiveForm.Perform(cm_msg, msg.WParam, msg.LParam) ; end;
procedure TPopupListEx.WndProc(var Message: TMessage) ; begin case message.Msg of WM_ENTERMENULOOP: PerformMessage(CM_ENTER_MENU_LOOP, Message) ; WM_EXITMENULOOP : PerformMessage(CM_EXIT_MENU_LOOP, Message) ; WM_MENUSELECT : with TWMMenuSelect(Message) do begin if (Menu = 0) and (Menuflag = $FFFF) then begin PerformMessage(CM_MENU_CLOSED, Message) ; end; end; end; inherited; end;
function GetCurrentPopupMenu: TPopupMenu; begin Result := FPopupMenu; end;
procedure SetCurrentPopupMenu(const PopupMenu: TPopupMenu); begin FPopupMenu := PopupMenu; end;
initialization FPopupMenu := TPopupMenu.Create(nil);
Popuplist.Free; PopupList:= TPopupListEx.Create; finalization if Assigned(FPopupMenu) then FPopupMenu := nil; end. |
Ich habe das nun so gelöst, dass man im OnPopup des jeweiligen PopupMenus eben dieses zuweist, um später auswerten zu können, um welches PopupMenu es sich handelt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| procedure TForm1.PopupMenu1Popup(Sender: TObject); begin SetCurrentPopupMenu(TPopupMenu(Sender)); end;
procedure TForm1.PopupMenuClosed(var msg: TMessage) ; begin if GetCurrentPopupMenu = PopupMenu1 then Showmessage('PopMenu closed'); end;
procedure TForm1.PopupMenuEnter(var msg: TMessage) ; begin if GetCurrentPopupMenu = PopupMenu1 then Showmessage('PopMenu entered'); end;
procedure TForm1.PopupMenuExit(var msg: TMessage) ; begin if GetCurrentPopupMenu = PopupMenu1 then Showmessage('PopMenu exited'); end; |
Ich habe damit mein Ziel erreicht, aber leider nicht "vollautomatisch"!
Vielleicht könnte mit noch jemand sagem, warum es im
finalization-Abschnitt zu einem Laufzeitfehler kommt, wenn ich dort
FPopupMenu.Free verwende, und ob es überhaupt notwenig ist,
FPopupMenu freizugeben!
Delete - So 10.03.19 15:53
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - So 10.03.19 20:04
Frühlingsrolle hat folgendes geschrieben : |
Zu dem Lsufzeitfehler wird es wahrscheinlich deswegen kommen, weil das übergebene Popupmenu1 dadurch an 2 Stellen freigegeben wird, was nicht geht.
Einmal von der Hauptklasse, und dann von deiner Klasse aus.
Es NIL zu setzen, find ich überflüssig. |
Ja, das stimmt wohl, denn ich muss es nicht einmal erzeugen: Es funktioniert auch ohne
.Create.
Natürlich wäre es noch einfacher, einen String zu verwenden und einfach auf
.Name zu prüfen. Es klappt, ist aber dennoch nur eine halbe, oder sagen wir, eine dreiviertel-Lösung, denn ich benötige eben eine Methode, um das PopupMenu erst einmal "bekannt" zu machen. Schön wäre es, wenn das alles automatisch erledigt wird.
Und noch etwas gefällt mir nicht: Man kann auf
FPopupMenu von ausserhalb zugreifen!
Sinspin - So 10.03.19 20:14
Hallo,
galagher hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ; begin if not (Screen.Activeform = nil) then Screen.ActiveForm.Perform(cm_msg, msg.WParam, msg.LParam) ; end; | |
Selbst wenn da ein Popup zugewiesen wäre würde es doch deutlich mehr Sinn machen den LParam zu verwenden und dann dort den Objektzeiger selber zu übergeben.
Generell ist es aber nicht sinnvoll eine bestehende Message zu verbiegen.
Deutlich sinnvoller ist es via PostMessage(Screen.ActiveForm.Handle, WM_MyNotification, WPraram, LParam) eine neue Message zu generieren auf die man via Messagehandler zugreifen kann ohne selber in WindowProc rumpfuschen zu müssen.
galagher hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| initialization FPopupMenu := TPopupMenu.Create(nil);
Popuplist.Free; PopupList:= TPopupListEx.Create; finalization if Assigned(FPopupMenu) then FPopupMenu := nil; end. |
Vielleicht könnte mit noch jemand sagem, warum es im finalization-Abschnitt zu einem Laufzeitfehler kommt, wenn ich dort FPopupMenu.Free verwende, und ob es überhaupt notwenig ist, FPopupMenu freizugeben! |
initialization und
finalization ist Unit level. Diese Abschnitte werden nur einmal beim Starten / Beenden des Programmes ausgeführt.
FPopupMenu ist eine globale Variable in der Du dir merkst welches Popup geclickt wurde. Für diese muss daher weder ein Object erzeugt werden noch muss sie freigegeben werden.
was du mit
Popuplist.Free; bezweckst ist mir an der stelle auch schleierhaft. Das würde zumindest im
finalization mehr Sinn machen.
Delete - So 10.03.19 20:48
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - So 10.03.19 21:07
Sinspin hat folgendes geschrieben : |
Deutlich sinnvoller ist es via PostMessage(Screen.ActiveForm.Handle, WM_MyNotification, WPraram, LParam) eine neue Message zu generieren auf die man via Messagehandler zugreifen kann ohne selber in WindowProc rumpfuschen zu müssen. |
Das übersteigt eindeutig meine Fähigkeiten und auch mein Verständnis!
Sinspin hat folgendes geschrieben : |
initialization und finalization ist Unit level. Diese Abschnitte werden nur einmal beim Starten / Beenden des Programmes ausgeführt.
FPopupMenu ist eine globale Variable in der Du dir merkst welches Popup geclickt wurde. Für diese muss daher weder ein Object erzeugt werden noch muss sie freigegeben werden. |
Ok. Aber es ist doch nicht nur eine einfache Variable wie
String oder
Boolean, sondern ein TPopupMenu, also eine Komponente. Und da dachte ich zuerst, die muss man doch wieder freigeben. Man muss sie (als TPopupMenu) aber noch nicht einmal erzeugen! Ich verstehe das nicht ganz, aber ich akzeptiere es gerne!
Man kann nun nicht mehr von ausserhalb auf FPopupMenu zugreifen, ich habe das aber jetzt geändert. Es ist nun keine globale Variable mehr:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| implementation
uses Messages, Forms;
var FPopupMenu: TPopupMenu; type TPopupListEx = class(TPopupList) |
Sinspin hat folgendes geschrieben : |
was du mit Popuplist.Free; bezweckst ist mir an der stelle auch schleierhaft. Das würde zumindest im finalization mehr Sinn machen. |
Ich habe den Code von
http: so übernommen, ich kannte Popuplist vorher nicht!
galagher - So 10.03.19 21:14
Der Autor von
http://delphi.cjcsoft.net/viewthread.php?tid=45678 hat das so geschrieben. Ok, viele Leute schreiben irgendwas...
Ich gebe aber zu, dass ich nicht weiss, ob das so korrekt ist. Jedenfalls funktionieren beide Varianten. Aber mir kam es natürlich schon seltsam vor, im
initialization-Abschnitt etwas freizugeben...
Zitat: |
The new PopupList will be freed by
finalization section of Menus unit. |
Ist das wirklich so? "The new PopupList" wurde doch explizit mit
.Create erzeugt und im Originalcode gibt es gar keinen
finalization-Abschnitt!
Ich habe den Code jetzt wie von dir vorgeschlagen angepasst.
Delete - So 10.03.19 21:27
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - So 10.03.19 21:36
Frühlingsrolle hat folgendes geschrieben : |
Wird die Anwendung beendet, dann wird die Variable Menus.PopupList in der Unit Menus.pas im Bereich FINALIZATION freigegeben. |
Hätte ich ja nur nachschauen müssen dort!
So weit, so gut.
Danke euch allen für die Hilfe!
Bleibt nur noch, dass nicht ohne weiteres erkannt wird, welches PopupMenu gerade aktiv ist. Egal, wie ich es drehe,
Screen.ActiveForm.PopupMenu ist niemals zugewiesen, daher kann es natürlich auch keine Eigenschaften (wie zB.
Name) davon geben.
Wenn euch dazu etwas einfällt, ich bin ganz Ohr (oder Auge in diesem Fall)! :)
Sinspin - Mo 11.03.19 20:52
galagher hat folgendes geschrieben : |
Der Autor von http://delphi.cjcsoft.net/viewthread.php?tid=45678 hat das so geschrieben. Ok, viele Leute schreiben irgendwas...
Ich gebe aber zu, dass ich nicht weiss, ob das so korrekt ist. Jedenfalls funktionieren beide Varianten. Aber mir kam es natürlich schon seltsam vor, im initialization-Abschnitt etwas freizugeben...
Zitat: | The new PopupList will be freed by
finalization section of Menus unit. |
Ist das wirklich so? "The new PopupList" wurde doch explizit mit .Create erzeugt und im Originalcode gibt es gar keinen finalization-Abschnitt!
Ich habe den Code jetzt wie von dir vorgeschlagen angepasst. |
Ja. Wenn man den Zusammenhang kennt dann macht es so wie dort geschrieben Sinn. Und zwar auch ohne
finalization in deiner unit.
Um das aktive Popup rauszubekommen wird dir nix anderes übrig bleiben als deinen Weg zu nutzen.
Was das PerformMessage angeht... das ist Geschmackssache. Wenn Du allerdings länger laufende Aktionen vorhast als wie im Beispiel, das ändern der Caption, dann solltest du mit PostMessage arbeiten.
Die Verarbeitung der Nachrichten bleibt so wie sie ist. Es wird nun allerding wirklich eine Nachricht (Windows-Botschaft) gesendet und diese erst verarbeitet wenn das Zielfenster seinen Nachrichtenstapel abarbeitet.
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ; begin if Assigned(Screen.Activeform) then PostMessage(Screen.ActiveForm.Handle, cm_msg, msg.WParam, msg.LParam); end; |
galagher - Mo 11.03.19 21:07
Sinspin hat folgendes geschrieben : |
Um das aktive Popup rauszubekommen wird dir nix anderes übrig bleiben als deinen Weg zu nutzen. |
Kann man es denn nicht über
PopupList rausbekommen?
Sinspin - Mo 11.03.19 23:49
Eigentlich bin ich der Meinung: finds doch einfach raus! Da lernste am meißten.
Andererseits, Du wirst noch ein bisschen Spass haben dich mit meinem Quelltext zu befassen. Der sieht saumäßig aus, da einfach nur zusammen geklatscht was nötig ist.
Daher, siehe Anhang ;-).
galagher - Di 12.03.19 22:11
Sinspin hat folgendes geschrieben : |
Andererseits, Du wirst noch ein bisschen Spass haben dich mit meinem Quelltext zu befassen. |
Macht prinzipiell das, was ich mir vorstelle. Man müsste nur an einer geeigneten Stelle
FLatestPopup := nil anbringen, damit, wenn man mit der Maus über ein TMenuItem geht,das PopupMenu erneut erkannt wird. Erst dachte ich,
FLatestPopup := nil gehört entweder ins
CM_EXIT_MENU_LOOP oder ins
CM_MENU_CLOSED, aber beides führt zu einer Zugriffsverletzung.
Und als zweiter Punkt: Warum kann das PopupMenu erst im
WM_MENUSELECT erkannt werden und nicht schon im
CM_ENTER_MENU_LOOP?
TPopupListEx(Popuplist).LatestPopup wird derzeit dort nicht ermittelt.
Ich bekomm's aber nicht so hin, dass es dort funktioniert.
Scheint mir sinnvoller zu sein, das PopupMenu schon im
CM_ENTER_MENU_LOOP zu erkennen und nicht erst, wenn man mit der Maus drübergeht!
Bitte nicht falsch verstehen, das ist keine Kritik! Ich dachte nur, ich kann es so hinbasteln, wie ich es möchte, aber dann funktioniert es nicht.
Sinspin - Mi 13.03.19 08:59
Ist mir schon klar dass du es anders besser finden würdest. Geht mir auch so. Aber ich habe nix gefunden.
Wobei ich auch nicht ernsthaft gesucht habe ob es auch zusätzliche Informationen für den anderen Events gibt.
Das kannst du ja machen. Tante Google wird dir dabei sicher helfen.
galagher - Mi 13.03.19 11:50
Ist nur die Frage, warum man das PopupMenu nicht im CM_ENTER_MENU_LOOP erkennen kann.
Und was das
FLatestPopupbetrifft: Man könnte doch
and (... <> FLatestPopup) (Ich habe den genauen Code jetzt nicht vor mir) weglassen, das muss ich aber noch testen, ob das auch wirklich immer zuverlässig funktioniert.
Und auch das Setzen von
FLatestPopup := nil, das zu einer Zugriffsverletzung führt...
Irgendwie verhält sich der Code etwas seltsam.
Sinspin hat folgendes geschrieben : |
Tante Google wird dir dabei sicher helfen. |
Wenn ich etwas finde oder auf etwas draufkomme, stelle ich es hier rein!
galagher - Sa 16.03.19 22:08
Hallo zusammen!
Ich komme da nicht weiter. Ich dachte mir, warum das Ganze nicht in als eine eigene Komponente TPopupMenuEx realisieren? Gesagt, getan. Ich packe den Code also da rein, aber es tut nicht...
TPopupListEx.PerformMessage und PopupListEx.WndProc arbeiten zwar, PopupListEx.WndProc ruft aber TPopupMenuEx.PopupMenuClosed nicht auf, obwohl alles exakt so ist, wie es war, als ich den Teil, den nun TPopupMenuEx übernehmen soll, noch in Form1 hatte. Verständlich, was ich meine? TPopupMenuEx sollte nach meinem Plan den Part von Form1 übernehmen, TPopupListEx sollte seinen Teil erledigen und gut.
In einem zweiten Schritt hätte ich mir dann überlegt, wie ich ein property OnClose einbaue. So weit kam ich aber zunächst nicht. Es funktionierte einfach nichts richtig.
Dann kam ich auf die Idee, den ganzen PerformMessage-Kram ganz wegzulassen und nur ein property OnClose reinzusetzen. Das hatte ich immerhin schon so hingebracht, dass es funktionierte - allerdings schon gleich beim Popup der Komponente!
Ich krieg's nicht hin. :autsch:
Wie konnten die Programmierer von Borland und/oder Embarcadero denn nur ein OnClose bei einem PopupMenu weglassen? :motz:
Delete - So 17.03.19 00:10
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - So 17.03.19 18:55
Frühlingsrolle hat folgendes geschrieben : |
Zeig mal, wie du es umgesetzt hast.
Ich schau es mir frühestens am SO Abend an. |
Ich musste es erst aus dem __history-Ordner rausfischen, hatte es schon gelöscht! :mrgreen:
Das ist also die Version, in der immerhin schon mal
PerformMessage ausgeführt wird, aber Prozedur
PopupMenuClosed nicht.
Ich habe mich hier erstmal nur auf
PopupMenuClosed beschränkt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75:
| unit ExPopupMenu;
interface
uses Vcl.Controls, System.Classes, Menus, Messages, Forms;
const CM_MENU_CLOSED = CM_BASE + 1001; CM_ENTER_MENU_LOOP = CM_BASE + 1002; CM_EXIT_MENU_LOOP = CM_BASE + 1003;
type TPopupMenuEx = class (TPopupMenu) private FPopupMenu: TPopupMenu; procedure PopupMenuClosed(var msg: TMessage) ; message CM_MENU_CLOSED; public constructor Create(AOwner: TComponent); end;
type TPopupListEx = class(TPopupList) protected procedure WndProc(var Message: TMessage) ; override; private procedure PerformMessage(cm_msg : integer; msg : TMessage) ; end;
implementation
uses Unit1; constructor TPopupMenuEx.Create(AOwner: TComponent); begin FPopupMenu := Self; inherited Create(AOwner); end;
procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ; begin if Assigned(Screen.Activeform) then Screen.ActiveForm.Perform(cm_msg, msg.WParam, msg.LParam) ; end;
procedure TPopupListEx.WndProc(var Message: TMessage) ; begin case message.Msg of WM_ENTERMENULOOP: PerformMessage(CM_ENTER_MENU_LOOP, Message) ; WM_EXITMENULOOP : PerformMessage(CM_EXIT_MENU_LOOP, Message) ; WM_MENUSELECT : with TWMMenuSelect(Message) do begin if (Menu = 0) and (Menuflag = $FFFF) then PerformMessage(CM_MENU_CLOSED, Message) ; end; end; inherited; end;
procedure TPopupMenuEx.PopupMenuClosed(var msg: TMessage) ; begin form1.Caption := 'Ja!'; end;
initialization PopupList:= TPopupListEx.Create; end. |
Sinspin - Mo 18.03.19 18:35
galagher hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| type TPopupMenuEx = class (TPopupMenu) private FPopupMenu: TPopupMenu; procedure PopupMenuClosed(var msg: TMessage) ; message CM_MENU_CLOSED; public constructor Create(AOwner: TComponent); end; | |
Die
procedure PopupMenuClosed solltest du dann aber auch in dem Form deklarieren dass du via
PerformMessage aufrufst. Im Popup bringt das nix. Zumal ein Popup keine Form zu sein scheint.
Ich habe jedenfalls keine WindowProc gefunden die darauf hindeuten würde.
Windowsbotschaften können nur ausgeführt werden wenn dafür auch eine WindowProc da ist in die die selber deklarierten Botschaftsempfänger vom Compiler eingehangen werden.
Wenn ich Heute Abend noch Kopf für sowas habe schau ich nochmal rein.
galagher - Mo 18.03.19 19:23
Sinspin hat folgendes geschrieben : |
Die procedure PopupMenuClosed solltest du dann aber auch in dem Form deklarieren dass du via PerformMessage aufrufst. |
Nun, idealerweise gibt es dann in meiner Komponente ein property, das beim Doppelklick im Objektinspektor genau diese Prozedur in dem Form einfügt. Also zB. property
OnClose (OnClose - ist das eigentlich ein reservierter Ausdruck? Wenn ja, dann eben zB.
OnPopDown). Da doppelklickt man im OI drauf und es wird
procedure TForm1.PopupMenuClosed erstellt.
Das ist der Plan, aber wie ich das hinbekomme, weiss ich nicht.
Delete - Di 19.03.19 18:59
- Nachträglich durch die Entwickler-Ecke gelöscht -
galagher - Do 21.03.19 09:20
Momentan komme ich nicht dazu, aber ich werde mir das noch anschauen und sehen, wie weit ich komme.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!