Skip to Content
Author's profile photo Enno Wulff

Hacking SAPGUI

Today I found an application where I was stunned for a moment.

via GIPHY

This:

It took some seconds and investigation before I found out how this icon could be set at this position of the SAPGUI.

Containers All Around

If you want to place a control somewhere on the SAPGUI, you need a container. The most common containers are:

  • CL_GUI_DOCKING_CONTAINER for docking a container to one side of the dynpro
  • CL_GUI_CUSTOM_CONTAINER for implementing custom controls inside a dynpro
  • CL_GUI_DIALOGBOX_CONTAINER for displaying a resizeable amodal popup
  • CL_GUI_SPLITTER_CONTAINER which provides several containers divided by a splitter
  • CL_GUI_EASY_SPLITTER_CONTAINER which provides two containers divided by a splitter

They all ere inherited by super class CL_GUI_CONTAINER.If you take a look at the sub classes of CL_GUI_CONTAINER then you will find another container class: CL_GUI_GOS_CONTAINER.

This is the container where I placed the attention image of the screen shot.

Coding Is Believing

Here is the minimum of code for hacking the SAPGUI

REPORT.
PARAMETERS p_test.
INITIALIZATION.

  DATA(picture) = NEW cl_gui_picture( parent = NEW cl_gui_gos_container( width = 38 ) ).
  DATA url TYPE cndp_url.
  CALL FUNCTION 'DP_PUBLISH_WWW_URL'
    EXPORTING
      objid                 = 'ACHTUNG'
      lifetime              = cndp_lifetime_transaction
    IMPORTING
      url                   = url
    EXCEPTIONS
      dp_invalid_parameters = 1
      no_object             = 2
      dp_error_publish      = 3.
  IF sy-subrc = 0.
    picture->load_picture_from_url_async( url = url ).
    picture->set_display_mode( picture->display_mode_fit ).
  ENDIF.

More Experiments

I simply love things that are unusual or “impossible”. Therefore I started some experimenting with the “new” container.

Multiple instances

I found out that it can be used multiple times, which gives a lot more options…

The following code displays the icons as shown above. Clicking on checkbox P_SHOW shows or hides the attention image.

Clicking on an icon brings up an information message.

REPORT.

PARAMETERS p_test.
PARAMETERS p_show AS CHECKBOX DEFAULT 'X' USER-COMMAND dummy.

CLASS info DEFINITION.
  PUBLIC SECTION.
    METHODS icon IMPORTING name TYPE clike RETURNING VALUE(info) TYPE REF TO info.
    METHODS pic  IMPORTING name TYPE clike RETURNING VALUE(info) TYPE REF TO info.
    METHODS constructor IMPORTING width TYPE i.
    METHODS with_text IMPORTING text TYPE clike RETURNING VALUE(info) TYPE REF TO info..
    METHODS hide.
    METHODS show.
  PROTECTED SECTION.
    DATA picture TYPE REF TO cl_gui_picture.
    METHODS handle_click FOR EVENT picture_click OF cl_gui_picture.
    DATA text TYPE string.
ENDCLASS.

CLASS info IMPLEMENTATION.

  METHOD constructor.
    picture = NEW cl_gui_picture( parent = NEW cl_gui_gos_container( width = width ) ).
    picture->set_registered_events( VALUE #(
                ( eventid = cl_gui_picture=>eventid_picture_click )
                ) ).
    SET HANDLER handle_click FOR picture.
  ENDMETHOD.
  METHOD icon.

    picture->load_picture_from_sap_icons( name ).
    picture->set_display_mode( picture->display_mode_fit ).
    info = me.
  ENDMETHOD.
  METHOD pic.
    DATA url TYPE cndp_url.
    CALL FUNCTION 'DP_PUBLISH_WWW_URL'
      EXPORTING
        objid                 = CONV w3objid( name )
        lifetime              = cndp_lifetime_transaction
      IMPORTING
        url                   = url
      EXCEPTIONS
        dp_invalid_parameters = 1
        no_object             = 2
        dp_error_publish      = 3.
    IF sy-subrc = 0.
      picture->load_picture_from_url_async( url = url ).
      picture->set_display_mode( picture->display_mode_fit ).
    ENDIF.

    info = me.

  ENDMETHOD.

  METHOD with_text.
    me->text = text.
    info = me.
  ENDMETHOD.

  METHOD handle_click.
    CHECK text IS NOT INITIAL.
    MESSAGE text TYPE 'I'.
  ENDMETHOD.

  METHOD hide.
    picture->set_visible( space ).
  ENDMETHOD.
  METHOD show.
    picture->set_visible( 'X' ).
  ENDMETHOD.

ENDCLASS.


INITIALIZATION.
  DATA(info)   = NEW info( 38 )->pic( 'ACHTUNG' ).
  DATA(green)  = NEW info( 39 )->icon( icon_led_green )->with_text( 'Everything ok' ).
  DATA(yellow) = NEW info( 39 )->icon( icon_led_yellow )->with_text( 'aargh...' ).
  DATA(red)    = NEW info( 39 )->icon( icon_led_red )->with_text( 'error. error. error.' ).


AT SELECTION-SCREEN OUTPUT.
  CASE p_show.
    WHEN abap_true.
      info->show( ).
    WHEN abap_false.
      info->hide( ).
  ENDCASE.

btw: Method Chaining

Because I like the idea of Paul Hardy to write the code in a way that the code itself says what will happen, I tried to do so in this little report via method chainging:

  DATA(red)    = NEW info( 39 )->icon( icon_led_red )->with_text( 'error. error. error.' ).

It’s not suitable for all methods, but within those little helper classes, I like the way it can be used.

Additional Text

If a container is a container, then I can place any control in it I like. Not too many make sense due to the size of the container, but…

Displaying an editable Text inside this container looks quite weird, but it works:

After this I got some kind of arrogant and wanted to display an HTML document inside the CL_GUI_GOS_CONTAINER. What can I say, it also works:

Even CL_SALV_TABLE is possible:

Purpose

What is the purpose of this nerdy stuff, that absolutely destroys the standard behaviour of the SAPGUI?

via GIPHY

Because I can… 😀

Seriously: I recommend NOT to use it in any of your custom transactions unless you have a really really good reason for it. It will confuse your users strongly…

…Keep on hacking!

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Matthew Billingham
      Matthew Billingham

      Benny Hill! That bastion of PC…

      Chaining has its place, but it can indicate a flaky encapsulation - exposing too much of the inner workings. Like, instead of dog->bark( ), dog->mouth_open( )->air_in( )->sound_out( ).

      Anyway, must dash – and try some of these things!

      Author's profile photo Matthew Billingham
      Matthew Billingham

      In your constructor, this line gives syntax error "No type can be derived from the context for the operator "VALUE"."

      picture->set_registered_events( VALUE #( eventid = cl_gui_picture=>eventid_picture_click ) ).

      I had to use a helper variable.

      DATA events TYPE cntl_simple_events.
      INSERT VALUE cntl_simple_event( eventid = cl_gui_picture=>eventid_picture_click ) INTO TABLE events.
      picture->set_registered_events( events ).

       

      Author's profile photo Enno Wulff
      Enno Wulff
      Blog Post Author

      Hm.

      The implicit usage should work. oh: You missed one bracket:

      picture->set_registered_events( VALUE #( ( eventid = cl_gui_picture=>eventid_picture_click ) ).

      As a workaround you could have specified the type w/o a helper table:

      picture->set_registered_events( 
          VALUE CNTL_SIMPLE_EVENTS( eventid = cl_gui_picture=>eventid_picture_click ) ).
      Author's profile photo Matthew Billingham
      Matthew Billingham

      Sorry, typo in my post. The actual code was copy pasted, and identical to your implicit usage. The workaround you suggest (which I had tried already) says:

      A value of the generic type "CNTL_SIMPLE_EVENTS" cannot be constructed.

      Perhaps our versions of the type groups differ?

      TYPES: BEGIN OF CNTL_SIMPLE_EVENT,
               EVENTID TYPE I,
               APPL_EVENT TYPE C,
             END OF CNTL_SIMPLE_EVENT.
      
      TYPES: CNTL_SIMPLE_EVENTS TYPE TABLE OF CNTL_SIMPLE_EVENT.

      But the above is how it is in my 740 and 750 systems.

       

      Author's profile photo Enno Wulff
      Enno Wulff
      Blog Post Author

      Yes, you are right - CNTL_SIMPLE_EVENTS is a "generic" type because of the missing option "WITH ... KEY".

      So much surprising that the implicit type inhertiance works in my 750 system...

      Author's profile photo Nabheet Madan
      Nabheet Madan

      Enno Wulff crazy stuff. #HackingABAPContainers:).  I actually liked method chaining when we do it particularly in Laravel framework of #PHP it is super powerful!

      Keep sharing the crazy stuff.

      Thanks

      Nabheet

      Author's profile photo Enno Wulff
      Enno Wulff
      Blog Post Author

      I will... 😉