Have you received someday an error from your ABAP object saying that "The statement SELECTION-SCREEN is not allowed within FORM routines and function modules." and you wondered why it is blocked to manipulate the five custom function codes on selection-screen? Well, definitely I have and it was really annoying as I wanted to be able to dynamically assign the slection-screen function key depending if it's already used by program or not.

 

To make long story short - I was correcting one day an old-style written code to include two additional function keys on selection-screen, which were "Favorite variants" and "Clear All fields". They are quite useful but you always had to attach an include(s) to your program and then call specific forms from it. One of the include contained the lines with statements SELECTION-SCREEN FUNCTION KEY 1 & 2, the other defnition for TABLES: sscrfields. I've move the logic to class instead of includes so I could get rid of the need of having them in the programs but I couldn't do anything with this statement as it's not possible to use it within the method. So I've let this statement to be added manually always while using the "Favorite" and "Clear All Fields" function.

Few days ago I've started to work on the created class again while users wants the favorite function to be extended, so after some refactoring and cleaning of my old bad programming, I've decided to check again if there is no really possibility to show or hide the function key on the selection-screen dynamically from method call. 

 

I knew already that whenever you handle selection-screen then program RSDBRUNT is called which is manipulating the output of the selection screen and also the GUI status. 

After some debugging I found interesting global variables there: CURRENT_SCREEN and CURRENT_SCR. 

CURRENT_SCREEN contained the information about active function keys and CURRENT_SCR together with lots other information - the table which is used to exclude function codes from GUI Status.

 

So I've started to change this values during the runtime of the program and I saw that selection-screen is reacting on the changes... this means I have a way to manipulate function keys dynamically!

Here is a sample class that shows how this can be done. What is really nice is that although I'm assigning the structure SSCRFIELDS dynamically, it's not needed to declare it explicitly in the program.

class zcl_selection_screen_functions definition
  public
  final
  create public .

  public section.
    class-methods activate_ss_button
      importing i_button type i.
    class-methods deactivate_ss_button
      importing i_button type i.
    class-methods fill_button_info
      importing i_button    type i
                i_text      type gui_text optional
                i_icon      type icon_d  optional
                i_icon_text type gui_ictext  optional
                i_quickinfo type gui_info  optional.

  protected section.
  private section.
    class-methods change_function_visibility importing i_button  type i
                                                       i_visible type abap_bool.
ENDCLASS.



CLASS ZCL_SELECTION_SCREEN_FUNCTIONS IMPLEMENTATION.

  method activate_ss_button.
    change_function_visibility(
        i_button  i_button
        i_visible abap_true  ).

  endmethod.


  method change_function_visibility.
    datacurrent_screen type string value '(RSDBRUNT)CURRENT_SCREEN'.
    field-symbols<current_screen> type sydb0_screen.
    assign (current_screento <current_screen>.
    if sy-subrc eq and i_button between and 5.
      data(offseti_button 1.
      <current_screen>-func_keys+offset(1i_visible.
    endif.

    datacurrent_scr type string value'(RSDBRUNT)CURRENT_SCR'.
    field-symbols<current_scr> type SYDB0_SCR_STACK_LINE.
    assign (current_scrto <current_scr>.
    if sy-subrc eq and i_button between and 5.
      data(button|FC0{ i_button }|.
      if i_visible eq abap_true.
        delete <current_scr>-excl where fcode eq button.
      else.
        if not line_exists(  <current_scr>-excl[ fcode button ] ).
           append value #fcode button to  <current_scr>-excl.
        endif.
      endif.
    endif.
  endmethod.


  method deactivate_ss_button.

    change_function_visibility(
        i_button  i_button
        i_visible abap_false  ).

  endmethod.

  method fill_button_info.
    check i_button between and and
          not i_text is initial or
            not i_icon is initial ).

    field-symbols<sscrfields> type sscrfields.
    datascreenfields_name type string.

    screenfields_name =  |({ sy-cprog })SSCRFIELDS|.
    assign (screenfields_nameto <sscrfields>.
    if sy-subrc eq 0.
      assign component |FUNCTXT_0{ i_button }| of structure <sscrfields> to field-symbol(<button_text>).
      if sy-subrc eq 0.
        <button_text> =  value smp_dyntxticon_id i_icon
                               icon_text i_icon_text
                               text i_text
                               quickinfo i_quickinfo
                                                ).
      endif.
    endif.
  endmethod.
ENDCLASS.sleeted

As we have a class then we can prepare little demo for using it. As you can see bellow, I'm activating the button only if checkbox is selected, then I'm deactivating it when it's empty. Try to do this with SELECTION-SCREEN FUNCTION KEY... :-)

report zdemo_ssfunc_01.

parametersp_active as checkbox user-command actfunc.


at selection-screen output.
  if p_active eq abap_true.
    zcl_selection_screen_functions=>activate_ss_button).
    zcl_selection_screen_functions=>fill_button_info(
     exporting
      i_button    1
      i_text      'Button 1'
      i_icon      =  icon_abap
      i_icon_text 'I am here'
 *        i_quickinfo =
    ).
  else.
    zcl_selection_screen_functions=>deactivate_ss_button).
  endif.

 

To give you the short info about the result of the program, please look on the GIF bellow.

 

Have fun!