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.
data: current_screen type string value '(RSDBRUNT)CURRENT_SCREEN'.
field-symbols: <current_screen> type sydb0_screen.
assign (current_screen) to <current_screen>.
if sy-subrc eq 0 and i_button between 1 and 5.
data(offset) = i_button - 1.
<current_screen>-func_keys+offset(1) = i_visible.
endif.
data: current_scr type string value'(RSDBRUNT)CURRENT_SCR'.
field-symbols: <current_scr> type SYDB0_SCR_STACK_LINE.
assign (current_scr) to <current_scr>.
if sy-subrc eq 0 and i_button between 1 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 1 and 5 and
( not i_text is initial or
not i_icon is initial ).
field-symbols: <sscrfields> type sscrfields.
data: screenfields_name type string.
screenfields_name = |({ sy-cprog })SSCRFIELDS|.
assign (screenfields_name) to <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_dyntxt( icon_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.
parameters: p_active as checkbox user-command actfunc.
at selection-screen output.
if p_active eq abap_true.
zcl_selection_screen_functions=>activate_ss_button( 1 ).
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( 1 ).
endif.
To give you the short info about the result of the program, please look on the GIF bellow.
Have fun!