Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Wie das Contextmenü erweitern?


motion - Sa 02.10.10 14:57
Titel: Wie das Contextmenü erweitern?
Ich habe eine von TEdit vererbte Komponente erstellt, die einige applikationsspezifische Funktionsweisen erfüllt. Jetzt möchte ich das vom System/VCL gelieferte Kontextmenu um weitere Menüpunkte und funktionen erweitern. Wie kann ich das machen?
Das Contextmenu muss an der TmyEdit Komponente hängen, nicht an jedem einzelnen Form, wo die Komponente eingesetzt wird.
Es gibt es OnContextMenu Event, aber da kriege ich noch keine Objekt übergeben, mit dem ich Zugriff zum Contextmenu bekomme, oder?
Das Autocontextmenü ist ja schon soweit in Ordnung, nur benötige ich dort zwei oder mehr weitere Menüpunkte.


Regan - Mo 04.10.10 18:57

Ich denke, dass die einfachste Methode das Nachbauen dieses Menüs sein wird. Warum? In meinen Fenster-Context-Menüs ist noch ganz anderer Mist drin (z. B. Fenster in den Tray, Fentster immer blinken etc.). Die machen bei deiner Komponente keinen Sinn und würden den Anwender vielleicht verunsichern.
Indem du deinem Edit-Feld ein neues Context-Menü zuweist, wird AFAIK das Standardmenü überschrieben.


motion - Mo 04.10.10 19:55

Okay, das hatte ich befürchtet.
Und das Contaxt Menu dann dynamisch in der Komponente erzeugen sobald rechts geklickt wird?
Wie übernehme ich die default Aktionen und ob die jeweils möglich sind (z.B. kein "einfügen" wenn das Clipboard leer ist)? Muss ich das alles selbst nachbauen?
Hast Du etwas Sample-Code zu Hand?


Regan - Mo 04.10.10 20:39

user profile iconmotion hat folgendes geschrieben Zum zitierten Posting springen:
Okay, das hatte ich befürchtet.
Und das Contaxt Menu dann dynamisch in der Komponente erzeugen sobald rechts geklickt wird?

Ich würde das schon zur Entwicklungszeit etwas machen.

user profile iconmotion hat folgendes geschrieben Zum zitierten Posting springen:
Wie übernehme ich die default Aktionen und ob die jeweils möglich sind (z.B. kein "einfügen" wenn das Clipboard leer ist)? Muss ich das alles selbst nachbauen?

Ich würde das jetzt (ohne genaueres Wissen) mit Ja! beantworten. Ich denke, dass dir das Clipboard da sehr weiterhilft. Zum Einfügen: Nicht prüfen, ob etwas drin ist, sondern ob das, was drin ist, ein Text ist. Der Rest dürfte einfach sein. Bei Fragen dazu erstelle aber bitte ein extra Thema. Das hat mit diesem dann nichts mehr zu tun.

user profile iconmotion hat folgendes geschrieben Zum zitierten Posting springen:
Hast Du etwas Sample-Code zu Hand?

Das sollte dir helfen. [http://delphi.about.com/od/vclusing/a/tclipboard.htm] Zum Prüfen auf Text dann einfach das dort beschriebene CF_TEXT verwenden.


motion - Mo 04.10.10 21:48

Clipboard Benutzung ist kein Problem.
Eher das dynamische Erstellen des Popup-Menus, Plazierung/Anzeige, dynamische Erzeugen der einzelnen Ereignisse etc.


motion - Mo 04.10.10 22:51

Okay, ich habe da jetzt schon mal eine Spur aufgenommen (noch etwas rumgegoogelt).
Ich werde mal schauen, ob ich die nächsten Tage da was ans Laufen kriege (der erste Versuch sieht schon gut aus) und das dann hier posten.


motion - Mo 04.10.10 23:56

So, für heute mache ich erst mal Schluß.
Mein Code sieht schon ganz gut aus (momentan dynamisch erstelltes Popup Menü mit zusätzlicher Funktioner "Einfügen Sonderzeichen"). Erst mal in einem Formular. Wenn das läuft dann muss ich das nur noch für meine MyTEdit-Komponente umwandeln und dann ist das Problem hoffentlich gelöst. Stay tuned.


motion - Di 05.10.10 21:30

So, hier die Lösung (erst mal dyn. Popup-Erzeugung auf einem Formular; das passe ich jetzt direkt an meine TMyEdit Komponente an).

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:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
procedure TForm1.PopupItemClickRueckgaengig(Sender: TObject) ;
begin
  edit1.Undo;
end;
procedure TForm1.PopupItemClickAusschneiden(Sender: TObject) ;
begin
  edit1.CutToClipboard;
end;
procedure TForm1.PopupItemClickKopieren(Sender: TObject) ;
begin
  edit1.copytoclipboard;
end;
procedure TForm1.PopupItemClickEinfuegen(Sender: TObject) ;
begin
  edit1.PasteFromClipboard;
end;
procedure TForm1.PopupItemClickLoeschen(Sender: TObject) ;
begin
  edit1.ClearSelection;
end;
procedure TForm1.PopupItemClickAllesmarkieren(Sender: TObject) ;
begin
  edit1.SelectAll;
end;
procedure TForm1.PopupItemClickEinfgSonderzeichen(Sender: TObject) ;
Var Pos : Byte;
begin
  with edit1 do
    Begin
      Pos:=SelStart;
      text:=copy(text,1,Pos)+TMenuitem(Sender).Caption[1]+copy(text,Selstart,Length(text)-Pos);
      SelStart:=Pos+1;
    end;
end;
procedure TForm1.Edit1ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
const AnzSonderzeichen = 5;
const Zeichen : Array [1..AnzSonderzeichen] of String = ('Ø Durchmesser','± Plus-Minus','½ 1/2','¼ 1/4','¾ 3/4');
var p :Tpopupmenu;
     menuItemRueckgaengig,
     menuItemAusschneiden,
     menuItemKopieren,
     menuItemEinfuegen,
     menuItemLoeschen,
     menuItemAllesMarkieren,
     sep1,sep2,sep3,
     menuItemEinfuegenSonderzeichen : TMenuItem;
     Sonderzeichen : array[1..AnzSonderzeichen] of TmenuItem;
     I : Byte;
begin
  p:=TPopupmenu.create(self);
  menuItemRueckgaengig := TMenuItem.Create(p) ;
  With menuItemRueckgaengig do
    begin
      Caption := 'Rü&ckgängig';
      OnClick := PopupItemClickRueckgaengig;
    End;
  P.Items.Add(menuItemRueckgaengig) ;
  sep1:=TMenuItem.Create(p);
  sep1.caption:='-';
  P.Items.Add(sep1) ;
  menuItemAusschneiden := TMenuItem.Create(p) ;
  With menuItemAusschneiden do
    begin
      Caption := '&Ausschneiden';
      OnClick := PopupItemClickAusschneiden;
    End;
  P.Items.Add(menuItemAusschneiden) ;
  menuItemKopieren := TMenuItem.Create(p) ;
  With menuItemKopieren do
    begin
      Caption := '&Kopieren';
      OnClick := PopupItemClickKopieren;
    End;

  P.Items.Add(menuItemKopieren) ;
  menuItemEinfuegen := TMenuItem.Create(p) ;
  With menuItemEinfuegen do
    begin
      Caption := 'Ein&fügen';
      OnClick := PopupItemClickEinfuegen;
    End;
  P.Items.Add(menuItemEinfuegen) ;
  menuItemLoeschen := TMenuItem.Create(p) ;
  With menuItemLoeschen do
    begin
      Caption := '&Löschen';
      OnClick := PopupItemClickLoeschen;
    End;
  P.Items.Add(menuItemLoeschen) ;
  sep2:=TMenuItem.Create(p);
  sep2.caption:='-';
  P.Items.Add(sep2) ;
  menuItemAllesMarkieren := TMenuItem.Create(p) ;
  With menuItemAllesMarkieren do
    begin
      Caption := 'Alles &markieren';
      OnClick := PopupItemClickAllesMarkieren;
    End;
  P.Items.Add(menuItemAllesMarkieren) ;
  sep3:=TMenuItem.Create(p);
  sep3.caption:='-';
  P.Items.Add(sep3);
  menuItemEinfuegenSonderzeichen := TMenuItem.Create(p) ;
  With menuItemEinfuegenSonderzeichen do
    begin
      Caption := 'Sonderzeichen einfügen';
    End;
  P.Items.Add(menuItemEinfuegenSonderzeichen) ;

  menuItemRueckgaengig.Enabled:=Edit1.CanUndo;
  menuItemAusschneiden.Enabled:=Edit1.SelText<>'';
  menuItemKopieren.Enabled:=Edit1.SelText<>'';
  menuItemEinfuegen.Enabled:=Clipboard.HasFormat(CF_TEXT);
  menuItemLoeschen.Enabled:=Edit1.SelText<>'';

  For I:=1 to AnzSonderzeichen do
    Begin
      Sonderzeichen[i]:=TMenuItem.create(p);
      with sonderzeichen[i] do
        begin
          caption:=Zeichen[I];
          onclick:=PopupItemClickEinfgSonderzeichen;
          p.Items.items[9].add(sonderzeichen[i]);
        end;
    end;

  p.popup (Mouse.CursorPos.X, Mouse.CursorPos.Y);
  Application.Processmessages; //wichtig, sonst reagiert OnClick nicht!

  For I:=1 to AnzSonderzeichen do
    Begin
      Sonderzeichen[I].free;
    end;


  menuItemRueckgaengig.free;
  sep1.free;
  menuItemAusschneiden.free;
  menuItemKopieren.free;
  menuItemEinfuegen.free;
  menuItemLoeschen.free;
  sep2.free;
  menuItemAllesMarkieren.free;
  sep3.free;
  menuItemEinfuegenSonderzeichen.free;
  p.Free;
 handled:=true;
end;