Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Fr 08.03.19 19:23 
Hallo!

Ich habe nun nach einiger Suche eine Möglichkeit gefunden, auf das Schliessen eine PopupMenus zu reagieren:
www.delphipraxis.net...e-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?

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 08.03.19 20:13 
Guten Abend galagher,

die verschachtelte Send() Methode innerhalb der WndProc() Methode verschickt eine selbstangelegt Nachricht im Msg-Parameter. Man könnte das noch erweitern und z.B. anstelle des wParam-Parameters, self.Name mitschicken, in etwa:

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

Getestet hab ich das jetzt nicht.
Sollte es funktionieren, könnte man entsprechend reagieren:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure CMMenuClosed(var Msg: TMessage ); message CM_MENUCLOSED;
procedure TMainForm.CMMenuClosed(var msg: TMessage);
var
  popupName: string;
begin
  popupName := PChar(msg.WParam);
end;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Fr 08.03.19 20:36 
Hallo Frühlingsrolle!

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Man könnte das noch erweitern und z.B. anstelle des wParam-Parameters, self.Name mitschicken, in etwa:

ausblenden 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)),  //<- hier ist ein Fehler!
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.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 08.03.19 20:55 
Das liegt an der tollen Codeformatierung des verlinkten Beitrags. "Message.lparam);" kommt dabei abhanden und der Compiler sucht vergeblich nach einem Semikolon.
Es sollte sogar noch einfacher gehen. Teil' ich dir noch mit, hab' aber noch was zu tun.

Nachtrag

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function GetPopupName(Parent: TWinControl): string;
var
  i: Integer;
begin
  result := '';
  for i := 0 to Parent.ComponentCount - 1 do
  begin
    if Parent.Components[i] is TPopupMenu then
    begin
      result := TPopupMenu(Parent.Components[i]).Name;
      exit;
    end;
  end;
end;

// Aufruf
ShowMessage(GetPopupName(Form1));

Eine direkte WinAPI-Funktion gibt es dafür wohl nicht, oder ich hab sie nicht gefunden.

Mir ist noch aufgefallen, wenn man von der Klasse TPopupList erbt, so gibt die Eigenschaft .Window immer 0 zurück, also ein ungültiges Menu-Handle.
Die Funktion GetMenu() liefert einem das HMENU, nur kommt man damit wieder an keinnen Komponenten-Namen.
FindComponent() verlangt als Parameter schonmal einen Namen, während FindControl() wohl ein Handle als Parameter benötigt, jedoch ein TWinControl und kein TComponent liefert, also einen Vorfahren des TPopupMenu.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 05:02 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:

Nachtrag

ausblenden Delphi-Quelltext
1:
function GetPopupName(Parent: TWinControl): string;					

Naja, das liefert in jedem Fall das erste gefundenene PopupMenu, egal, welches gerade verwendet wird...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 05:46 
So funktioniert es explizit nur für TForm Objekte.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function GetPopupName(Parent: TForm): string;
var
  i: Integer;
begin
  result := '';
  for i := 0 to Parent.ComponentCount - 1 do
  begin
    if Parent.Components[i] is TPopupMenu then
    begin
      if Parent.PopupMenu = TPopupMenu(Parent.Components[i]) then
      begin
        result := TPopupMenu(Parent.Components[i]).Name;
        exit;
      end;
    end;
  end;
end;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 06:53 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 08:27 
Verzeihung, ich nahm an, du wolltest allgemein den Namen des Popup-Objektes wissen.

Dann, wie bereits erwähnt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
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
  // ... wie im verlinkten Post gegeben
end;

// Hauptanwendung

procedure CMMenuClosed(var Msg: TMessage ); message CM_MENUCLOSED;

procedure TMainForm.CMMenuClosed(var msg: TMessage);
var
  popupName: string;
begin
  popupName := PChar(msg.WParam);
end;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 09:53 
Funktioniert leider auch nicht:
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden 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 );
  (*                                  |
                               Das produziert einen Zugriffsfehler!
  *)

  End;
begin
  // ... wie im verlinkten Post gegeben
end;

Ich krieg's einfach nicht hin!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 10:07 
Kann ich nicht bestätigen:
ausblenden volle Höhe 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:
unit ExPopupList;

interface

uses Controls;

const
  CM_MENUCLOSED   = CM_BASE - 1;
  CM_ENTERMENULOOP = CM_BASE - 2;
  CM_EXITMENULOOP = CM_BASE - 3;

implementation

uses Messages, Forms, Menus;

Type
  TExPopupList = class( TPopupList )
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

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
  Case message.Msg Of
    WM_ENTERMENULOOP: Send( CM_ENTERMENULOOP );
    WM_EXITMENULOOP : Send( CM_EXITMENULOOP );
    WM_MENUSELECT  :
      With TWMMenuSelect( Message ) Do
        If (Menuflag = $FFFFand (Menu = 0Then
          Send( CM_MENUCLOSED );
  End;
  inherited;
end;

Initialization
  PopupList.Free;
  PopupList:= TExPopupList.Create;
end.

Hauptanwendung:

ausblenden volle Höhe 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:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, ExPopupList;

type
  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    DummyItem1: TMenuItem;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure CMMenuClosed(var Msg: TMessage ); message CM_MENUCLOSED;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CMMenuClosed(var msg: TMessage);
var
  popupName: string;
begin
  popupName := PChar(msg.WParam);
  ShowMessage(popupName);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  self.PopupMenu := PopupMenu1;
end;

end.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 10:45 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Kann ich nicht bestätigen

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!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 16:35 
Hm, führst du Delphi mit Adminrechten aus? Bei mir ist das der Fall.

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.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 19:33 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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?

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 19:50 
Das Konto ist egal. Es geht manchmal darum, mit welchen Rechten Delphi ausgeführt wird, wenn man eine Anwendung darin kompiliert.
Viele WinAPI Funktionen, die im Delphi allgegenwertig sind, benötigen Lese- und Schreibrechte, die nur mit Adminrechten ein "korrektes" Ergebnis liefern können.

Wenn der TForm.PopupMenu Eigenschaft nichts zugewiesen wird, weder im Design, noch zur Laufzeit, dann wird die Nachricht auch nicht abgefeuert, demnach auch kein PopupMenu-Name ausgegeben.
Zu einem Fehler kann es somit nicht kommen. Es passiert somit nichts, wenn TForm.PopupMenu nichts zugewiesen wird.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 20:16 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.03.19 20:25 
Die RTTI findest du in den Units (System.)Rtti und (System.)Typinfo. Das sollte in Delphi 10.1 mit dabei sein, egal ob eingeschränkte Version oder nicht.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: Sa 09.03.19 20:31 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Mit RTTI könnte man es zurecht biegen, da bin ich aber nicht so sattelfest darin.

Ich erst recht nicht!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: So 10.03.19 10:14 
Zunächst habe ich einige Methoden in gefälligere Namen umbenannt und zudem einige neue Methoden hinzugefügt:

ausblenden volle Höhe 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;

{ TPopupListEx }
procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ;
begin
    if not (Screen.Activeform  = nilthen
      Screen.ActiveForm.Perform(cm_msg,
        (*Integer(PChar(Screen.ActiveForm.PopupMenu)),*)  //<- Ist nicht zugewiesen und daher nicht verwendbar!
        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(Messagedo
      begin
        if (Menu = 0and (Menuflag = $FFFFthen
        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; //free the "default", "old" list
    PopupList:= TPopupListEx.Create; //create the new one
    // The new PopupList will be freed by
    // finalization section of Menus unit.

finalization
  if Assigned(FPopupMenu) then
    FPopupMenu := nil;  //<- Hier führt .Free zu einem Laufzeitfehler: "Runtime error 217 at 00409495"

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:
ausblenden 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;

//Hier kann man nun mehrere PopupMenus unterscheiden:
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!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2229
Erhaltene Danke: 415

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: So 10.03.19 14:53 
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.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2265
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter, Delphi 10.2 Tokyo Community Edition
BeitragVerfasst: So 10.03.19 19:04 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!