Die Benutzungsoberfläche eines Dynpros wird in der Regel durch einen im Menu Painter definierten GUI-Status vom Typ Dialogstatus festgelegt. Zu jedem Dialogstatus erzeugt das System automatisch ein Standardkontextmenü, das der Benutzer durch einen Klick der rechten Maustaste (oder Auswahl von SHIFT F10) auf dem Bildschirmbild des Dynpros aufrufen kann. Dieses Standardkontextmenü listet alle mit Funktionen verknüpften Funktionstasten auf. Es erleichtert also den Zugang zu allen über die Tastatur erreichbaren Funktionscodes, von denen normalerweise nur die wichtigsten in der Drucktastenleiste liegen.
Zusätzlich zum Standardkontextmenü können auf Dynpros kontextspezifische Menüs für folgende Bildschirmelemente vorgesehen werden:
· Ein-/Ausgabefelder
· Textfelder
· Table Controls
· Rahmen
· Subscreens
Bei Auswahl eines dieser Elemente mit der rechten Maustaste kann dann im ABAP Programm ein dynamisches Kontextmenü erzeugt werden. Dieses Kontextmenü kann beliebige Funktionen auflisten und ist nicht auf Funktionstasten beschränkt. Drucktasten, Ankreuzfelder und Auswahlknöpfe können keine eigenen Kontextmenüs haben. Sie können statt dessen mit eindeutigen Funktionscodes versehen werden.
Kontextmenüs sind Objekte der globalen ABAP Objects Klasse CL_CTMENU. Diese Klasse gehört in der Klassenbibliothek organisatorisch zu den Frontend Services, in denen auch die Klassen des Control Framework (siehe Custom Controls) aufgehoben sind. Sie enthält Methoden, um programmlokale Kontextmenüs dynamisch zu definieren. Als Vorlage können hierbei im Menu Painter statisch (vor)definierte Kontextmenüs verwendet werden.
Die wichtigsten Methoden der Klasse CL_CTMENU sind:
Methode |
Funktion |
LOAD_GUI_STATUS |
Hängt ein im Menu Painter statisch (vor)definiertes Kontextmenü an ein programmlokales Kontextmenü an. |
ADD_FUNCTION |
Hängt eine einzelne Funktion an ein programmlokales Kontextmenü an. |
ADD_MENU |
Hängt ein anderes programmlokales Kontextmenü an ein programmlokales Kontextmenü an. |
ADD_SUBMENU |
Hängt ein anderes programmlokales Kontextmenü als Untermenü an ein programmlokales Kontextmenü an. |
ADD_SEPARATOR |
Hinzufügen einer Trennlinie. |
HIDE_FUNCTIONS |
Funktionen ausblenden |
SHOW_FUNCTIONS |
Funktionen einblenden |
DISABLE_FUNCTIONS |
Funktionen deaktivieren. |
ENABLE_FUNCTIONS |
Funktionen aktivieren. |
SET_DEFAULT_FUNCTION |
Standardfunktion festlegen. D.h. die Funktion wird in der Anzeige hervorgehoben. |
Mit programmlokalen Kontextmenü ist in obiger Tabelle ein Objekt der Klasse CL_CTMENU gemeint. Je nach Kontext wird mit CL_CTMENU unterschiedlich gearbeitet:
Falls auf einem Control mit Kontextmenüs gearbeitet werden soll, richtet es sich nach der Klasse des Controls, ob Objekte der Klasse CL_CTMENU erzeugt werden müssen, oder ob ihre Funktionalität in der Klasse des Controls gekapselt ist und ihre Methoden durch die Methoden der Control-Klasse nach außen gereicht werden. In der Regel sollte ein Control-Benutzer nicht selber für die Erzeugung von Kontextmenüs sorgen müssen, damit keine Konflikte mit der Ereignisbehandlung des Controls entstehen. Mehr dazu findet sich in der Dokumentation der einzelnen Control-Klassen.
Bei der Definition von Kontextmenüs auf Dynpros (und auch auf Listen) werden die zugehörigen Objekte der Klasse CL_CTMENU nicht explizit im Programm sondern automatisch von der Laufzeitumgebung erzeugt. Referenzen auf die Objekte werden als Parameter an spezielle Callback-Routinen im ABAP Programm übergeben.
Um ein Kontextmenü mit einem der oben angegebenen Bildschirmelemente zu verknüpfen, muss in den Attributen des Elements im Screen Painter lediglich eine Kennung context im Feld Contextmenu angegeben werden. Wird für ein Bildschirmelement kein eigenes Kontextmenü angegeben, erbt dieses Element das Kontextmenü des hierarchisch nächsthöheren Elements. Alle Bildschirmelemente ohne eigenes Kontextmenü in einem Rahmen erben beispielsweise das Kontextmenü des Rahmens. Die höchste Hierarchiestufe ist das Standardkontextmenü mit sämtlichen Tastenbelegungen des aktuellen Dialogstatus.
Wenn ein Bildschirmelement mit einem eigenen oder geerbten Kontextmenü verknüpft ist, wird bei Auswahl dieses Elements mit der rechten Maustaste (oder SHIFT F10) ein Unterprogramm
ON_CTMENU_context
im zugehörigen ABAP-Programm aufgerufen (es wird dabei aber nicht PAI ausgelöst!). Dieses Unterprogramm (Callback-Routine) dient der dynamischen Definition des Kontextmenüs und muss in der Verarbeitungslogik programmiert werden. Falls kein passendes Unterprogramm vorhanden ist, wird kein Kontextmenü angezeigt.
Mehrere Bildschirmelemente können mit dem gleichen Kontextmenü contextverknüpft werden. Sie arbeiten dann gemeinsam mit dem gleichen Unterprogramm.
Für jedes in den Bildschirmelementen der zu einem ABAP-Programm gehörigen Dynpros angegebene Kontextmenü context sollte im ABAP-Programm eine entsprechende Callback-Routine programmiert werden:
FORM
ON_CTMENU_context USING l_menu TYPE REF TO cl_ctmenu.
...
ENDFORM.
Jede dieser Routinen muss genau einen USING-Parameter vom Typ einer Referenzvariablen für die Klasse CL_CTMENU haben. Die Laufzeitumgebung erzeugt für jedes bei den Bildschirmelementen angegebene Kontextmenü automatisch ein Objekt dieser Klasse. Bei Auswahl des Bildschirmelements mit der rechten Maustaste (oder SHIFT F10) wird das entsprechende Unterprogramm aufgerufen und eine Referenz auf das zugehörige Objekt an den Formalparameter übergeben.
Das Objekt ist bei seiner Übergabe initial in dem Sinn, dass das Kontextmenü keine Einträge enthält. Im Unterprogramm kann nun mit den oben aufgeführten Methoden des Objekts das Kontextmenü dynamisch und kontextabhängig aufgebaut werden.
Ein im Menu Painter vordefiniertes Kontextmenü ist neben Dialogstatus und Status für Dialogfenster ein weiterer Typ eines GUI-Status. Das Anlegen von Kontextmenüs im Menu Painter der ABAP Workbench ist unter Kontextmenü anlegen beschrieben.
Ein vordefiniertes Kontextmenü bietet die Möglichkeit, Teilmengen der statisch bekannten Funktionscodes eines ABAP Programms kontextabhängig zur Verfügung zu stellen. Mit der Methode LOAD_GUI_STATUS können Kontextmenüs beliebiger ABAP Programme an programmlokale Kontextmenüs angehängt werden. In der Regel verwendet man vordefinierte Kontextmenüs, um die Funktionscodes des Dialogstatus mit der gleichen Semantik aber kontextspezifisch wiederzuverwenden. Nach dem Laden eines vordefinierten Kontextmenüs in ein programmlokales Kontextmenü, kann dieses beliebig modifiziert werden (andere vordefinierte Kontextmenüs anhängen, Funktionen hinzufügen oder entfernen, andere Kontextmenüs einbinden).
Durch die Modifikation vordefinierter Kontextmenüs, oder durch den Aufbau von Kontextmenüs aus neuen Funktionen können kontextabhängig völlig neue Kontextmenüs erstellt werden.
Zum einen können einem Kontextmenü beliebige neue Funktion hinzugefügt werden. Beim Hinzufügen einer neuen Funktion, müssen Funktionstext, Funktionscode und Funktionstyp (wie z.B. E für unbedingten Modulaufruf) angegeben werden.
Zum anderen können beliebige andere programmlokale Kontextmenü-Objekte eingebunden werden. Hierfür muss dem Kontextmenü nur eine Referenz auf ein anderes Kontextmenü übergeben werden (siehe Beispiel unten). Man kann sich in einem Programm also eine Sammlung von Kontextmenü-Objekten erzeugen, und diese nach Bedarf verwenden. Dabei ist auch die Bildung von Untermenüs möglich. Wenn eingebundene Untermenüs wieder Untermenüs enthalten entstehen tief geschachtelte Menüs.
Bei der Gestaltung von Kontextmenüs empfiehlt es sich folgenden Regeln zu folgen:
· Die Funktionen auf Kontextmenüs sollten Teilmengen der Funktionsliste des Programms sein. Dies wird durch die Benutzung vordefinierter Kontextmenüs unterstützt.
· Ein Kontextmenü sollte auf einer Ebene nicht mehr als zehn Einträge enthalten.
· Wenn ein Kontextmenü zu einem Bildschirmelement verwendet wird, dann sollte es auch alle für dieses Element möglichen Funktionen enthalten, zumindest aber die Standardbefehle, wie z.B. Auswählen, Kopieren, Ausschneiden, Einsetzen für kopierbare Felder.
· Die Reihenfolge der Funktionen sollte sein: objektspezifische Befehle, Kopierbefehle, weitere Befehle.
· Bis auf Ausnahmen sollten keine über direkte Auswahl (linke Maustaste) möglichen Befehle in Kontextmenüs dupliziert werden.
Nach der dynamischen Definition des Kontextmenüs in der Callback-Routine, wird es sofort auf dem Bildschirmbild dargestellt. Wählt der Benutzer einen Menüpunkt aus, wird das Ereignis PAI ausgelöst und der entsprechende Funktionscode in sy-ucomm und dem OK-Feld an das ABAP-Programm übergeben.
Das folgende Beispiel zeigt einige der technischen Möglichkeiten bei der Definition von Kontextmenüs, ohne besondere Berücksichtigung der Stilrichtlinien ;-)
REPORT demo_dynpro_context_menu.
DATA: field1 TYPE i VALUE 10,
field2 TYPE p DECIMALS 4.
DATA: prog TYPE sy-repid,
flag(1) TYPE c VALUE 'X'.
DATA: ok_code TYPE sy-ucomm,
save_ok TYPE sy-ucomm.
prog = sy-repid.
CALL SCREEN 100.
MODULE status_0100 OUTPUT.
SET TITLEBAR 'TIT100'.
IF flag = 'X'.
SET PF-STATUS 'SCREEN_100' EXCLUDING 'REVEAL'.
ELSEIF flag = ' '.
SET PF-STATUS 'SCREEN_100' EXCLUDING 'HIDE'.
ENDIF.
LOOP AT SCREEN.
IF screen-group1 = 'MOD'.
IF flag = 'X'.
screen-active = '1'.
ELSEIF flag = ' '.
screen-active = '0'.
ENDIF.
MODIFY SCREEN.
ELSEIF screen-name = 'TEXT_IN_FRAME'.
IF flag = 'X'.
screen-active = '0'.
ELSEIF flag = ' '.
screen-active = '1'.
ENDIF.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
ENDMODULE.
MODULE cancel INPUT.
LEAVE PROGRAM.
ENDMODULE.
MODULE user_command_0100.
save_ok = ok_code.
CLEAR ok_code.
CASE save_ok.
WHEN 'HIDE'.
flag = ' '.
WHEN 'REVEAL'.
flag = 'X'.
WHEN 'SQUARE'.
field2 = field1 ** 2.
WHEN 'CUBE'.
field2 = field1 ** 3.
WHEN 'SQUAREROOT'.
field2 = field1 ** ( 1 / 2 ).
WHEN 'CUBICROOT'.
field2 = field1 ** ( 1 / 3 ).
ENDCASE.
ENDMODULE.
*******************************************************
* Callback-Routines
*******************************************************
FORM on_ctmenu_text USING l_menu TYPE REF TO cl_ctmenu.
CALL METHOD:l_menu->load_gui_status
EXPORTING program = prog
status = 'CONTEXT_MENU_1'
menu = l_menu.
ENDFORM.
FORM on_ctmenu_frame USING l_menu TYPE REF TO cl_ctmenu.
CALL METHOD:l_menu->load_gui_status
EXPORTING
program = prog
status =
'CONTEXT_MENU_2'
menu =
l_menu,
l_menu->load_gui_status
EXPORTING
program = prog
status =
'CONTEXT_MENU_1'
menu =
l_menu,
l_menu->set_default_function
EXPORTING
fcode = 'HIDE'.
ENDFORM.
FORM on_ctmenu_reveal USING l_menu TYPE REF TO cl_ctmenu.
CALL METHOD:l_menu->load_gui_status
EXPORTING
program = prog
status =
'CONTEXT_MENU_3'
menu =
l_menu,
l_menu->load_gui_status
EXPORTING
program = prog
status =
'CONTEXT_MENU_1'
menu =
l_menu,
l_menu->set_default_function
EXPORTING
fcode = 'REVEAL'.
ENDFORM.
FORM on_ctmenu_input USING l_menu TYPE REF TO cl_ctmenu.
DATA calculate_menu TYPE REF TO cl_ctmenu.
CREATE OBJECT calculate_menu.
CALL METHOD: calculate_menu->add_function
EXPORTING
fcode = 'SQUARE'
text =
text-001,
calculate_menu->add_function
EXPORTING fcode = 'CUBE'
text = text-002,
calculate_menu->add_function
EXPORTING fcode = 'SQUAREROOT'
text = text-003,
calculate_menu->add_function
EXPORTING fcode = 'CUBICROOT'
text = text-004,
l_menu->add_submenu
EXPORTING menu = calculate_menu
text = text-005.
ENDFORM.
Die statische Folgedynpronummer von Dynpro 100 ist 100 und sein Layout ist:
Der für Kontextmenüs relevante Teil der Elementliste ist wie folgt:
Name |
Typ |
Inhalt |
Contextmenu |
TEXT |
Text |
Probieren Sie ... |
TEXT |
FRAME |
Frame |
|
FRAME |
TEXT1 |
Text |
Eingabe |
INPUT |
FIELD1 |
I/O |
|
INPUT |
TEXT2 |
Text |
Ergebnis |
|
FIELD2 |
I/O |
|
|
TEXT_IN_FRAME |
Text |
Ergebnis einblenden |
REVEAL |
Die Elemente TEXT2 und FIELD2 haben keine eigenen Kontextmenüs. Sie erben das Kontextmenü FRAME des Rahmens. Ihnen ist die Modifikationsgruppe MOD zugeteilt.
Die Dynproablauflogik ist:
PROCESS
BEFORE OUTPUT.
MODULE status_0100.
PROCESS AFTER INPUT.
MODULE cancel AT EXIT-COMMAND.
MODULE user_command_0100.
Zu diesem ABAP-Programm sind folgende Funktionscodes und GUI-Status statisch definiert:
Funktionscodes |
BACK |
CANCEL |
EXIT |
HIDE |
REVEAL |
Dialogstatus |
|
|
|
|
|
SCREEN_100 |
X |
X |
X |
X |
X |
Kontextmenüs |
|
|
|
|
|
CONTEXT_MENU_1 |
X |
|
|
|
|
CONTEXT_MENU_2 |
|
|
|
X |
|
CONTEXT_MENU_3 |
|
|
|
|
X |
Die Tabelle zeigt, welche GUI-Status welche Funktionscodes enthalten.
Der Dialogstatus SCREEN_100 wird zu PBO statisch gesetzt, wobei abhängig vom Feld FLAG die Funktionscodes HIDE oder REVEAL ausgeblendet werden.
Die Kontextmenüs zu den Bildschirmelementen werden in den Callback-Routinen wie folgt aufgebaut:
TEXT:
Laden des statischen Kontextmenüs CONTEXT_MENU_1 ohne Modifikation. Dieses
Kontextmenü hat eine Zeile Abbrechen.
FRAME:
Aufbau des Kontextmenüs aus den statischen Kontextmenüs CONTEXT_MENU_2 und
CONTEXT_MENU_1. Dieses Kontextmenü hat zwei Zeilen Ergebnis ausblenden und Abbrechen. Die Zeile zum Funktionscode HIDE
wird hervorgehoben dargestellt.
REVEAL:
Aufbau des Kontextmenüs aus den statischen Kontextmenüs CONTEXT_MENU_3 und
CONTEXT_MENU_1. Dieses Kontextmenü hat zwei Zeilen Ergebnis einblenden und Abbrechen. Die Zeile zum Funktionscode REVEAL
wird hervorgehoben dargestellt.
INPUT:
Aufbau des Kontextmenüs durch Einbinden des vierzeiligen lokalen Kontextmenüs
CALCULATE_MENU als Untermenü. Für letzteres wird im Unterprogramm eine lokale
Referenzvariable mit Bezug auf CL_CTMENU angelegt, ein Objekt erzeugt und neue
Funktionscodes SQUARE, CUBE, SQUAREROOT und CUBICROOT hinzugefügt. Beim
Einbinden in das Kontextmenü für INPUT muss ein Text für den Eintrag angegeben
werden, hinter dem das Untermenü hängt.
Bei der Ausführung des Programms, erhält der Benutzer bei Auswahl der rechten Maustaste bzw. SHIFT F10 auf der ersten Zeile das Kontextmenü TEXT, auf der zweiten Zeile das Kontextmenü INPUT und auf der dritten Zeile das Kontextmenü FRAME. Die vierte Zeile ist nach Programmstart ausgeblendet. Auf allen übrigen Bildschirmbereichen erscheint das Standardkontextmenü mit allen statischen Funktionscodes und zusätzlich F1 und F4.
Bei Auswahl einer der neuen dynamischen Funktionen, werden Berechnungen mit der Zahl im Eingabefeld FIELD1 ausgeführt und nach FIELD2 gestellt.
Bei Auswahl der Funktion Ergebnis ausblenden (HIDE) wird das Bildschirmbild dynamisch modifiziert. Dadurch wird die vierte Zeile sichtbar und damit wird das Kontextmenü REVEAL zugänglich.