精华内容
下载资源
问答
  • 1、事务码MM01,把物料组设为选填字段。 2、找到物料组的屏幕字段。 ...3、在后台根据屏幕字段找到对应字段组。后台路径:后勤-常规—物料主数据—字段选择—给字段...5、在字段参考里找到UERP,就可以设置字段的显...

    1、事务码MM01,把物料组设为选填字段。

     

    2、找到物料组的屏幕字段。

     

     

     

     

    3、在后台根据屏幕字段找到对应字段组。后台路径:后勤-常规—物料主数据—字段选择—给字段组分配字段。点击后面的箭头进入下一屏幕。

     

    4、物料组的显示、隐藏、可选、必填跟工厂、物料类型等都有关系。比如说找到物料类型Z40的字段参考。

     

    5、在字段参考里找到UERP,就可以设置字段的显示、隐藏、可选或是必填了。

     

    5、我把这里设为可选条目,但是在用事务码MM01创建物料主数据的时候,物料类型为Z40的物料组仍旧是必填项目,这是因为决定这个屏幕字段是什么状态由多个条件决定。比如决定物料组这个屏幕字段是否为隐藏、显示、可选或必填是由工厂、物料类型、行业领域、事务代码来共同决定。

    而且状态也有优先顺序,优先顺序是:隐藏、显示、必输、可选,如果在工厂、物料类型,行业领域、事务代码这些条件的字段参考中有一项为必输,那么这个字段一定为必输,因为必输优先顺序在可选前面,仅仅设置一项字段参考是不起作用的。

    6、查找事务码的参考字段。后台路径:后台常规—物料主数据—配置物料主记录—分配屏幕序列到用户/物料类型/事务/工厂部门

     

    双击事务处理屏幕参考。

     

     

     

    总结:一定要理解字段参考的逻辑,当你需要设置一个屏幕字段为显示、隐藏、可填或者必输的时候,要理清楚这个屏幕字段是根据哪个条件来设置的,字段参考就是条件,还要考虑状态的优先顺序,比如说如果有一个条件设置为隐藏,那么这个屏幕字段一定是隐藏的,因为隐藏的优先级最高。

    转载于:https://www.cnblogs.com/275147378abc/p/5699077.html

    展开全文
  • android锁定屏幕通知When Google brought notifications to Android’s lock screen, it was a game changer. Instant access to important and relevant data is one of the things that makes smartphones so ...
    android锁定屏幕通知

    android锁定屏幕通知

    IMG_8324

    When Google brought notifications to Android’s lock screen, it was a game changer. Instant access to important and relevant data is one of the things that makes smartphones so prevalent and clutch in our lives. But when that data is personal, you don’t want it showing up on your lock screen for anyone to peer over and see. Fortunately, Google baked in a way to hide this sort of content.

    当Google将通知带到Android的锁定屏幕时,它改变了游戏规则。 即时访问重要和相关的数据是使智能手机如此流行并紧紧抓住我们生活的原因之一。 但是,当这些数据是个人数据时,您不希望其显示在锁定屏幕上,任何人都可以浏览并查看。 幸运的是,Google以隐藏这种内容的方式诞生了。

    Essentially, instead of showing the entire notification on the lock screen, this setting will let you show only the app it’s from–the content of the message or notification will be hidden until you unlock the phone, as seen in the photo above. There are a few exceptions–it won’t hide the content of a weather notification, for example–but most things, such as email, SMS, and other notifications, will have their contents hidden.

    本质上,如上图所示,此设置将使您仅显示其来源应用程序,而不是在锁定屏幕上显示整个通知-消息或通知的内容将被隐藏,直到您解锁手机为止。 有一些例外情况-例如,它不会隐藏天气通知的内容-但大多数内容(例如电子邮件,SMS和其他通知)将隐藏其内容。

    The process is similar across most Android devices, with the biggest difference being (unsurprisingly) on Samsung Galaxy devices. Given that, I’ll break this guide down into two sections: Galaxy devices, and basically everything else. Keep in mind that these settings may not be in exactly the same place across all devices, but you’ll definitely be in the ballpark.

    在大多数Android设备上,此过程相似,最大的区别是(毫无疑问)在Samsung Galaxy设备上。 鉴于此,我将本指南分为两部分:Galaxy设备,以及基本上所有其他内容。 请记住,这些设置在所有设备上可能不一定完全相同 ,但是您肯定会处于困境。

    NOTE: before you can hide sensitive data on the lock screen, you’ll need to have a PIN, Pattern, or other form of lock screen security set up, so be sure to enable that first.

    注意:在锁定屏幕上隐藏敏感数据之前,您需要设置PIN码,图案或其他形式的锁定屏幕安全性,因此请务必先启用该功能

    如何在大多数Android设备上隐藏敏感通知数据 (How to Hide Sensitive Notification Data on Most Android Devices)

    I’ll be using a Nexus 6P with stock Android for this tutorial, but the process will be identical on all other current-generation Nexus devices. It will also be very similar on HTC, Motorola, and LG devices, though the wording or location inside the menu may vary slightly.

    在本教程中,我将使用带有现货Android的Nexus 6P,但此过程在所有其他当前版本的Nexus设备上都相同。 在HTC,Motorola和LG设备上,它也将非常相似,尽管菜单中的措辞或位置可能略有不同。

    The first thing you’ll need to do is jump into the Settings menu. You can do this by dragging the notification shade down twice, then tapping the cog icon. Alternatively, you can use the “Settings” icon in the app drawer.

    您需要做的第一件事是跳到“设置”菜单。 您可以通过将通知阴影向下拖动两次,然后点击齿轮图标来实现。 或者,您可以使用应用程序抽屉中的“设置”图标。

    Screenshot_20160429-103748
    Screenshot_20160429-103807

    In the Settings menu, scroll down to the Device section and select “Sound & notification.”

    在“设置”菜单中,向下滚动到“设备”部分,然后选择“声音和通知”。

    Screenshot_20160429-110154

    Here’s where you may start seeing a bit more variation in wording. On Nexus devices, you’re looking for the entry close to the bottom that reads “When device is locked.” On others it may be slightly different—on LG devices, for example, it’s titled “Lock screen.”

    您可能会在这里开始看到措辞上的更多变化。 在Nexus设备上,您正在寻找底部附近的条目,内容为“设备锁定时”。 在其他设备上,可能会稍有不同,例如,在LG设备上,标题为“锁定屏幕”。

    Screenshot_20160429-115942

    Give that option a tap. This should open a simple menu with a few option: “Show all notification content,” “Hide sensitive notification content,” and “Don’t show notifications at all.”

    轻按该选项。 这应该打开一个简单的菜单,其中包含以下几个选项:“显示所有通知内容”,“隐藏敏感的通知内容”和“完全不显示通知”。

    You can opt to not show notifications on the lock screen, but that takes away a useful feature. So, in this case, we recommend selecting “Hide sensitive notification content.”

    您可以选择不在锁定屏幕上显示通知,但这会带走有用的功能。 因此,在这种情况下,我们建议选择“隐藏敏感的通知内容”。

    Screenshot_20160429-111222
    Screenshot_20160429-111228

    That’s pretty much it. Moving forward, you’ll see that most notifications have their contents hidden for your privacy.

    就是这样。 往前看,您会发现大多数通知都隐藏了其内容,以保护您的隐私。

    Screenshot_20160429-114800

    如何在三星Galaxy设备上隐藏敏感通知数据 (How to Hide Sensitive Notification Data on Samsung Galaxy Devices)

    Samsung always has to be different, doesn’t it? Instead of keeping things simple and in the default location, good ol’ Sammy decided to move things around a bit. While slightly annoying, I’ll concede that it actually makes a bit more sense where Samsung puts this option: in the Security menu, where other lock screen options are found.

    三星总是必须与众不同,不是吗? 好的萨米并没有把事情保持在默认位置,而是决定将其移动一点。 虽然有些烦人,但我承认,三星在何处放置此选项实际上更有意义:在“安全”菜单中,可以找到其他锁定屏幕选项。

    So, the first thing you’ll want to do in jump into the Settings menu by pulling down the notification shade, then tapping the cog icon. You can also get to it by heading in to the app drawer and selecting the “Settings” icon.

    因此,您要做的第一件事就是通过下拉通知栏,然后点击齿轮图标来跳到“设置”菜单。 您也可以通过转到应用程序抽屉并选择“设置”图标来进行操作。

    Screenshot_20160429-111809
    Screenshot_20160429-111902

    In Settings, scroll down and select the “Lock screen and security” entry.

    在“设置”中,向下滚动并选择“锁定屏幕和安全性”条目。

    Screenshot_20160429-111921

    The “Notifications on lock screen” option is the one you’re looking for here, so go ahead and give that a tap once you’ve found it.

    “锁定屏幕上的通知”选项是您要在此处找到的选项,因此,找到后请轻按一下。

    Screenshot_20160429-112419

    Unlike other Android devices, which just offer a simple dropdown, Galaxy devices have a whole new menu here that combines what is normally found in a couple of different places on other Android devices. For this tutorial, however, we’re only concerned with one setting: “Content on lock screen.”

    与其他Android设备(仅提供简单的下拉菜单)不同,Galaxy设备在此处具有一个全新的菜单,该菜单结合了通常在其他Android设备的几个不同位置找到的菜单。 但是,对于本教程,我们仅关注一种设置:“锁定屏幕上的内容”。

    Screenshot_20160429-112427

    Tapping on this option will open a small drop down menu with three options: “Show content,” “Hide content,” and “Do not show notifications.” Go ahead and choose “Hide content.”

    轻触此选项将打开一个小的下拉菜单,其中包含三个选项:“显示内容”,“隐藏内容”和“不显示通知”。 继续并选择“隐藏内容”。

    Screenshot_20160429-112435

    That’s it—from now on, your notifications will not show their contents on the lock screen.

    就是这样-从现在开始,您的通知将不会在锁定屏幕上显示其内容。

    Screenshot_20160429-120627


    While certainly not the most robust form of security on its own, hiding sensitive information on your phone’s lock screen will certainly keep curious eyes out of your personal business. And since it requires a secure lock screen to be set up in the first place, you can be at least a little more confident that your data is safe should your phone become lost or stolen.

    虽然肯定不是最强大的安全措施,但在手机的锁定屏幕上隐藏敏感信息肯定会使您的个人业务望而却步。 而且由于首先需要设置安全的锁定屏幕,因此,如果手机丢失或被盗,您至少可以更有信心确保数据安全。

    翻译自: https://www.howtogeek.com/253076/how-to-hide-sensitive-notifications-on-your-android-lock-screen/

    android锁定屏幕通知

    展开全文
  • Code设置 屏幕流逻辑Screen Flow Logic 对话屏幕中的字段命名大小写问题 示例:屏幕元素自动参考数据词典(或程序)中的表或结构字段 Function Codes的读写机制 ok_code的定义 为什么要将ok_code


    对话屏幕Dynpro(SE51)

    屏幕元素

    屏幕属性

    l  屏幕序号(Screen number)。四个数字组成的序列号,用于在程序中确定屏幕,该序号在同一个ABAP程序内部是唯一的。

    l  屏幕类型(Screen type)。ABAP中的屏幕类型包括普通屏幕、模式对话框、选择屏幕和子屏幕等。普通屏幕一般占据整个用户窗口,而模态对话框只占据用户窗口的一部分;选择屏幕是根据程序中定义的select-option和parameters自动生成的,一般不用于对话程序设计中;子屏幕则可以显示在不同屏幕的某个区域之中。

    l  后续屏幕(Next screen)。定义当前屏幕的后续屏幕序号,即系统的对话处理器结束当前屏幕的处理之后,应前往的下一个屏幕。通过后续屏幕,可以把事务中的一系统屏幕连接起来,形成一个屏幕序列,如果某个屏幕的后续屏幕值为0或没有设置,则表明该屏幕是一个屏幕序列的结束。该属性可以在程序中动态控制。

    l  光标位置(Cursor position)。屏幕初始状态的光标位置,一般默认状态下,光标位于屏幕中的第一个输出字段。在程序设计中,可以动态地替换属性中定义的初始光标位置。

    l  屏幕组(Screen group)。可以将一系列的屏幕组合在一个4字符的屏幕组中,屏幕组ID运行期间存储于系统字段sy-dyngr中,用于程序对多个屏幕整体操作。

    l  行列范围(Lines/columns)。用于设定屏幕所占据的空间,如果屏幕较大,系统将自动生成滚动条。

    l  上下文菜单(Context memu),用于设定属于整个屏幕的上下文菜单(右键菜单)。

     

    每一个屏幕都有一个OK_CODE字段,但不显示在屏幕上。用户触发PAI事件的操作所对应的Function Code就会存储到这个字段中,然后再传递到ABAP程序中相同名称的全局变量中,必须为每个屏幕分配这个名叫OK_CODE的屏幕元素,否则虽然可以触发事件,但Function Code不能在屏幕与ABAP程序之间进行传递了

    在屏幕中也可以像ABAP程序那样读写系统预置的系统变量,但是,在屏幕中系统变量是通过结构SYST来管里的,而不是SY,所以,你必须使用SYST-<name>来定位它们

    PAI事件的触发、屏幕元素Function Code设置

    1.         如果复选框单选按钮没有设置Function Code,则它们就会像普通的输入框一样,即使状态发生了改变,也不会触发PAI事件。但是对于按钮,即使没有设置Function Code,也会触发PAI事件,此时的Function Code 为空。

    2.         如果复选框与单选按钮设置Function Code,则复选框与单选按钮不只是简单的输入元素,而且还会触发PAI事件。

    3.         以下屏幕元素可以触发PAI事件

    ?       点击屏幕上的某个按钮

    ?       点击了某个已分配了Function Code的单选按钮或复选框

    ?       点击了某个菜单或标准工具条、应用工具条件上的按钮

    ?       快捷键

    ?       从下拉框中选择条目

    4.         不同的屏幕元素的Function Code的设置方式如下:

    ?       屏幕中的按钮、复选框、单选按钮、下拉框的Function Code都是通过屏幕元素 attributes来设置的(注:如果是选择屏幕,则通过USER-COMMAND选项来设置)

    ?       而菜单、standard toolbar、application toolbar中的Function Code是通过GUI status来设置的

    ?       快捷键所对应的Function Code也是通过GUI status来设置的

    屏幕流逻辑Screen Flow Logic

    屏幕流逻辑包括四种事件块:

    PROCESS BEFORE OUTPUT.
    ...
    PROCESS AFTER INPUT.
    ...
    PROCESS ON HELP-REQUEST.
    ...
    PROCESS ON VALUE-REQUEST.

    ...
    前两个一定要有,当都出现时请按上面顺序写

    当你创建一个新屏幕时,头两个事件块会自动的创建。运行时触发时间点如下:

    ?       PROCESS BEFORE OUTPUT (PBO)

    在前一屏幕的PAI事件后或当前屏幕显示之前自动触发,你可以在这个块中对数据进行初始化赋值。在PBO结束时,屏幕将会显示出来。

    ?       PROCESS AFTER INPUT (PAI)

    当用户操作(如F8,点击按钮,回车、或点击带Function Code的单选/复选按钮,可选择带Function Code下拉框中的某选项时)了屏幕上某个功能元素时就会触发,你可以在这个块中如对输入值的检查。PAI事件结束后,系统将会调用一下屏幕或者返回到屏幕调用处(ABAP程序)继续执行

    ?       PROCESS ON HELP-REQUEST (POH) and PROCESS ON VALUE-REQUEST (POV)

    当用户按F1与F4时触发,处理完之后返回到当前屏幕

    对话屏幕中的字段命名大小写问题

    在对话屏幕中为输入字段命名时,名字一定要大小,否则在屏幕逻辑流中用到该字段时则会出错:


    原因就是在屏幕设计界面中,命名时写成了小写了:


    所以屏幕字段命名时一定要大写(好像小写时,如果不在屏幕逻辑流中使用时也是可行的,但一旦用在屏幕逻辑流中进,就会出问题),正确的做法是在输入名称之后,回车一下,则名称会自动转换为大小:


    Element list中的命名为大小即可:


    示例:屏幕元素自动参考数据词典(或程序)中的表或结构字段

    如果屏幕上的元素字段参考的是数据词典的字段(屏幕元素的名称为表名-字段名的形式)时,必须在ABAP程序里使用TABLES语句来定义这个表接口,这样就可以通过这个表接口在屏幕与ABAP程序之间自动的进行数据传递:


    另外,也可以是只引用一个或几个数据词典中某个表中一个或几个字段,不一定要引用整张表。再次,这些参照词典中的字段需要将以下钩上:


    当给某个屏幕字段命名时,如果这个字段的名称为“表名(或结构)-字段名形式时,回车时系统会提示:


    当点击Yes后,该字段的Parameter ID会自动的设置为 MARA-MATNR字段所对应Data Element所设置的Parameter ID,另外,From dict.也会自动被钩上,但时,SET ParameterGET Parameter 没有自动钩上,如果需要通过SAP Memory传递值,则需要将这两个手动钩上:


    Data Element中的Parameter ID选择屏幕是没有任何作用的,如下面的语句不能用来在SAP Memory中传递值:

    PARAMETERSm TYPE mara-matnr.

    除非使用MEMORY ID 选项才起作用:

    PARAMETERSm TYPE mara-matnr MEMORY ID mat.注,这里的MEMORY ID不一定要设置成与MATNR所对应的Data Element设置的Parameter ID一样,这里可以随便设置,如XXX

    所以选择屏幕中的参数选项 MEMORY ID的作用就等同于对话屏幕中的SET/GET Parameter,它们是作用是相同的(都是针对SAP Memory),只不过一个用于选择屏幕中,一个用于对话屏幕。


    ABAP程序如下:

    TABLESspfli.
    DATAwa_spfli TYPE spfli. "只要与屏幕字段名前缀结构同名即可自动绑定

    CALL SCREEN 200.

    MODULE get_data INPUT.
      SELECT SINGLE countryfr cityfrom airpfrom INTO CORRESPONDING FIELDS OF spfli
        FROM spfli WHERE carrid =  spfli-carrid AND connid  spfli-connid.
    ENDMODULE.

    运行程序,输入条件后回车,结果屏幕如下:


    注:由于Airline配置了Check Table,如果输入的Airline不合法,则不会执行PAI事件,所以在执行PAI事件前,数据词典中所设置的数据有效性会先进行检查。

    Function Codes的读写机制

    当用户在对话屏幕上触发一个命令时,会将命令所对应的Function Code复制到对话屏幕上一个特殊的隐藏字段OK_CODE中,如果在ABAP中具有一个与对话屏幕这个隐藏字段同名的OK_CODE时,则在屏幕字段向内存字段进行同名拷贝时,屏幕上的这个隐藏字段OK_CODE的值也将会被自动拷贝到程序中的这个字段中,然后就可以在PAI事件块里调用ABAP中的Module中使用此隐藏字段

    如果触发PAI时的Function Code为空,则不会放入到对话屏幕中定义的OK_CODE 字段中(SYST- UCOMM与SY-UCOMM也不会发生改变:还是保留上次PAI的Function Code),


    注意,此图还有点问题,如果是针对回车键(命令行中未输入内容时回车)是对的,但如果按的是屏幕中的未分配Function Code的按钮时,虽然不会重置OK_CODE,但还是会重置SYST- UCOMM 与 SY-UCOMM。

    ok_code的定义


    为什么要将ok_code拷贝一次?

    在程序中你应该使用OK_CODE来代替SY-UCOMM,这有两种原因:第一,ABAP程序可以完全控制在它里面定义的变量,第二,你不应该修改ABAP系统变量的值。然而,你必须在ABAP程序中清空OK_CODE,因为以下几个原因:如果一个屏幕中的某个按钮未设置Function Code时也是可以触发PAI事件时,并且由于其Function Code此时为空而不会去设置OK_CODE(但此时SYST- UCOMM 或 SY-UCOMM会被重新设置为空),这样的话OK_CODE中的值还为上一次触发PAI时所设置的Function Code。所以一般情况下在使用OK_CODE之前,先将OK_CODE拷贝到SAVE_OK变量中,并随后将OK_CODE清空,以便为下一次PAI事件所使用做准备(比如下一屏幕直接在屏幕上按回车时,Function Code为空,因为在回车时命令框里没有输入任何命令,则此时OK_CODE字段不会被设置,所以还回沿用上次所设置的OK_CODE,所以就会出现问题),并在MODULE 中针对SAVE_OK来进行编程:

    DATAok_code LIKE sy-ucomm,
         save_ok LIKE ok_code.
    在第一个PAI module中,需要将ok_code放在save_ok中,并清空ok_code,其他PAI module中就直接使用save_ok即可
    MODULE user_command_0100 INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      CASE save_ok.

        WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
          LEAVE PROGRAM.
        WHEN OTHERS.
      ENDCASE.
    ENDMODULE.

    其实还有一种方案可能替换这种使用前拷贝方案:就是还是针对OK_CODE编程,不另外定义save_ok,而是在每个屏幕的 PBO 里将ABAP中的OK_CODE清空。

    另外如果在 Command Line

    未输入内容时就按回车(其实光标在屏幕上输入框里按回库也是这样,只要命令行没有输入内容时),此时的Function Code也是空,此时除OK_CODE还是会被重置, 并且SYST- UCOMM 与 SY-UCOMM也不会被重新设置为空。

     

    每个屏幕的OK字段都可以用不同的名字,但是,最好的做法是每个屏幕中的OK字段都叫OK_CODE,这样的话ABAP程序中只需要定义一个名称为OK_CODE的变量即可以接受所屏幕中的OK字段值(即Function Code)

    图形化用户接口 GUI

    GUI主要有:

    1、 标题栏:当前屏幕的标题,GUI Title

    2、 菜单条:包含了可扩展的菜单,其中每个子菜单项都指向一个应用程序的功能,其中“System”、“Help”两个菜单项不能被应用程序更改和扩展,因此这类菜单荋以及其中的子菜单项将出现在每一个应用的屏幕中。

     

    每个屏幕都会有系统标准工具条(Standard Toolbar),包含的按钮代表了所有屏幕中都会用到的系统功能,如保存、回退、取消等。可以为菜单项和工具条项分配功能键(FunctionKeys),这样当用户在屏幕按下相应的功能键时,相当于执行了已经分配了这个功能的菜单项。

    应用工具条(ApplicationToolbar)是与特定应用相关的工具条,集成了当前屏幕常用的功能。


    菜单条、标准工具条、功能键的设置以及应用工具条统称为“GUI Status”,使用SETPF-STATUS xxx来设置的。使用SET TITLEBAR xxx设置标题。

    若为ABAP屏幕分配一个GUI StatusGUI Title,则该屏幕的所有后续屏幕缺省都有了该StatusTitle,如果想在后续的子屏幕中更换成另外一个不同的Title,则需要重新设置

    ABAP中维护GUI Status的工具叫Menu Painter

    除开“System”与“Help”菜单,最多还可以创建6个菜单项


    GUI Status(Menu Painter)

    GUI status为用户提供了屏幕范围内的功能,每一种功能都有一个Function Code,并且当用户选择这个功能时,就会触发PAI事件,在每PAI事件里,这些Function Code将会放到系统变量SYST-UCOMM(SY-UCOMM)中,并且分配给OK_CODE隐藏字段。在Screen中使用OK_CODE之前,必须在Screen Painter中给它分配一个名字。

    (注:这里讲的是对话屏幕上的Status,如果是List Status,则不会有什么PAI事件,也不会将Function Code存储到什么OK_CODE,而是直接触发ABAP报表程序中的 AT USER-COMMAND 事件,可以在此事件中通过ABAP系统全局变量SY-UCOMM来接收传递过来的Function Code

    ABAP程序中的所有Function Code,除了按钮(还有复选框、单选按钮)的Function Code是在Screen Painter中分配的,其他都是在Menu Painter中进行定义与管理的:


    GUI Status可以是让用户很方便的操作屏幕,它代替了命令行

    中的输入。当然我们可以不点击Menu bars、Standard toolbars、Application toolbars或者屏幕中的按钮,直接在Command Line中输入这些菜单、工具条与按钮所对应的Function Code,回车后也可以触发PAI事件。

    Normal Status(Menu Painter详解)


    此种类型的Status用在如下类型的普通屏幕中:


    通过Menu Bar可以创建新的菜单,在创建时不需要分配键盘快捷键,但可以在Function Keys设置部分中的Freely Assigned Function Keys(此类型的Function Key——快捷键,可由用户自己自由分配)中为菜单设置一个键盘快捷键,这样不需要通过鼠标点击菜单而是通过所设置的快捷键来代替鼠标;

    通过Application Toolbar创建应用工具条件上的按钮的过程中,会弹出一个设置快捷键的对话框要求设置快捷键,所以创建自定义应用工具条时一定要分配一个键盘快捷键;

    Function Keys中的Standard Toolbar不需要设置快捷键(正是因为这些为标准工具条,已经为这些固有的图标绑定了快捷键,并且这些快捷键被系统所保留使用),因为这些是预设的标准工具条(因为标准工具条上有哪些功能图标是不能再由我们自己定义了,只能使用上面预设的那几个,如果要使用,只需要输入相应的Function code就代表开启此按钮了),并且已经固定分配了相应的快捷键,系统预设的快捷键如下

    Functionkey

    Icon

    Purpose

    Ctrl+Sor F11

    image022

    Save

    F3

    image023

    Back

    Shift+F3

    image024

    Exit

    Esc or F12

    image025

    Cancel

    Ctrl+P

    image026

    Print

    Ctrl+F

    image027

    Find

    Ctrl+G

    image028

    Find next

    Ctrl+PgUp

    image029

    Firstpage

    PgUp

    image030

    Previous page

    PgDn

    image031

    Nextpage

    Ctrl+PgDn

    image032

    Lastpage

    具体的内置快捷键可以通过以下方式来查看:


    另外,也可以设置一个与菜单或工具条按钮无关的纯粹的快捷键,如上面的Function Code为 SHORTCUT 的快捷键。

    不管是菜单、工具条按钮、还是快捷键最终都会触发PAI事件,并且会将所对应的Function Code会存储到SY-UCOMM系统变量中。

     

    上面的Recommended Function Key Setting(此类型的Function Key——快键捷,已经被系统推荐使用,所以最好不要另作其它用途,如F2为查看详情,相当于鼠标双击)部分的为推荐部分,当不输入FunctionCode时,相应的功能不会被激活,只要输入了Function code则会激活相应功能,Function Code可以任意,相应功能不需要我们写代码去实现了,因为系统已具备这样的功能

    Standard Toolbar栏中预设的图标按钮在默认情况是不会被激活的,只有当输入相应Function Code才会被激活,但此时在Standard Toolbar中只能点击它,具体的功能还是需要在ABAP程序中写代码来实现相应功能,这与Recommended Function Key Setting部分是不一样的

    一般情况下,需至少激活Standard Toolbar中的Backimage023[1] (F3), Exitimage024[1] (shift+F3), and Cancelimage025[1] (F12)中的一个功能,并实现相应代码,以便用户能够离开屏幕(如果将image023[2]的Funcode设为BACK、image024[2]设置为EXITimage025[2]设置为BREAK时(具体什么值与屏幕的类型有关系:选择屏幕、List列表输出屏幕、对话屏幕都是不一样,如要使用系统提供的默认实现,则一定要按要求值给出,具体值请参考后面),会自动的leave program.对话屏幕好像就不行???,选择屏幕好像已自动实现

     

    下面这些Function Keys不会触发PAI事件,它们被保留下来用作其他的功能:

    ?       F1 calls the field help调用字段的帮助

    ?       F4 calls the input help调用输入帮助

    ?       F10 places the cursor in the menu bar将光标定位到菜单条上

    回车: standard toolbar中的回车键

    默认就是被激活的,即使根本没有给屏幕设置过GUI status。只要用户在命令行中按回车键后(不管是否输入了内容),都会触发相应屏幕的PAI事件,并且输入的内容会被当作Function Code传递给SY-UCOMM或OK_CODE(在Screen中)字段(如果未输入,则不会输入到SY-UCOMM或OK_CODE中,但会触发PAI事件)

     

    F2(鼠标双击):预设中,F2已经与鼠标的双击关联起来了,F2已具有了鼠标双击的功能。当用户按了F2或在屏幕上双击了鼠标都会触发PAI事件,所以F2是一个很特别的键,一般不要拿来作其他功能使用。

     

    Shift + F10(鼠标右键):该组合键已经被分配给了鼠标右击功能,不能再用于其他用途。注意:有时鼠标右键弹不出右键菜单,这是因为选中了快捷剪切和粘贴功能了,去掉即可,否则只能使用Shift + F10快捷键或者使用Shift+鼠标右击才能弹出右键菜单:


    选择屏幕与List列表输入屏幕上的标准工具按钮FunctionCode需要如下输入才能使用系统提供的默认的功能(不需要我们再实现):

    选择屏幕:


    List列表:


    Dialog BoxStatus

    此种类型的 Status 用在如下类型模态屏幕中:

    (注意:Dialog Box类型的Status没有Menu BarStandard Toolbar两项


    Reserved Function Keys部分为保留快捷键,如果要相应对应功能,只需要输入Function Code,但要注意的是Function code一定要为上面图中输入的,否则功能将不会被触发(这些功能也已经由系统实现了,我们不需要实现)。另外,如果将Reserved Function Keys部分所配置的Function Code又在Application Toolbar部分进行了分配,这些功能图标将会在对话框屏幕下方出现,如:


    但不知为什么上面红色字体的 ENTER 没有显示??后来找到原因了:是因为Function Code被去激活了


    Context Menu Status


    该类型的Status用作右键菜单


    可以将右键菜单链接到某些屏幕元素,包括输入输出字段、文本字段、表格控件以及屏幕区域等。

     

    具体使用请参考Context Menus for Screen中的示例代码

    Dialog Status for Lists

    Dialog Status for Lists

    快速创建(Status模板)

    可以将系统标准GUI Status作为模板导入到当前程序中,在Menu Painter中选择系统菜单“ExtrasàAdjusttemplate”。

    将系统标准的GUI STATUS导入到当前的GUI STATUS中作为编辑的模板:


    标准Status拷贝

    当需要为ALV报表或普通程序绘制Status时,我们先可以拷贝标准的Status,则在此基础上修改即可:


    上面的ALV工具条是先拷贝自标准条,再在标准条上加一按钮,通过SE41,拷贝程序SAPLSLVC_FULLSCREEN的状态STANDARD_FULLSCREEN过来:


    如果不是ALV,是Write输入时,拷贝:


    两种方式创建屏幕字段

    从词典中获取



    要想在对话屏幕与ABAP程序中进行数据传递,则还得要在ABAP定义中作如下定义才可:

    TABLESsdyn_conn.

    或者是:

    DATA: sdyn_conn TYPE sdyn_conn.(注:此种方式可能会有问题,数据不能传输??)

    从程序中获取





    对话屏幕与程序之间的数据传输

    在ABAP对话屏幕编程中,对话屏幕与程序之间的数据自动传输发生在:屏幕字段名与程序中定义的同名的全局变量之间,此变量一般可以是普通的类型的单变量,但更多是定义成结构体变量。下面以结构体变量为传输体来了解数据传输过程。

    使用TABLE语句来定义一个内存结构体变量,该结构中的字段与对话屏幕上的各输入字段是一一对应的,即名称与类型都相同。TABLE后面的数据类型可以是词典中的结构类型或透明表类型,具定义出来的结构体变量名与后面指定的词典结构类型及透明表类型一致,例如:

    TABLES sdyn_conn.:利用结构体类型sdyn_conn定义了一个结构体变量sdyn_conn
    TABLES sflight.:利用透明表类型sflight定义了一个结构体变量sflight

    因为结构体变量中的各字段与对话屏幕上的各输入字段具有对应关系,因此,该结构体变量被用作屏幕与程序之间的数据传输通道:



    上图中,使用了词典中的结构体类型sdyn_conn定义了一个内存变量sdyn_conn,而对话屏幕100上的各个字段的定义也是来自于结构体类型sdyn_conn,因此,内存变量sdyn_conn将作为屏幕100与调用它的程序之间的数据传输通道:即在屏幕100的PBO事件完成后,内存变量sdyn_conn中的各字段值将自动传输给对应的屏幕字段;当用户在屏幕上点击确认结束输入后,在触发PAI事件之前,各屏幕的字段的值将自动传输给内存变量sdyn_conn相应各同名字段中,因此,可以在PAI事件块中对结构体变量sdyn_conn进行处理。

    工具栏中按键之间的分隔符

    其中“分隔符”的插入方法为:在需要插入分隔符的方框内选择菜单“Edit—>Insert——>Separator line”即可插入分隔符


    Calling ABAP Dialog Modules


    在PBO事件块里,你可以使用MODULE语句来调用在ABAP program里如下定义的dialog module:

    MODULE <mod> OUTPUT.
      ... 
    ENDMODULE.

    在PAI, POH, 与 POV事件块里,你可以使用MODULE语句来调用在ABAP program里如下定义的dialog module:

    MODULE <mod> [INPUT].
    ... 
    ENDMODULE.

    从技术角度来说,在同一个ABAP Program里,两个不同类型的module(OUTPUT、INPUT)可以使用相同的名称,但这不推荐使用。不同的屏幕可以调用ABAP程序里同一个dialog module,所以可以将多个屏幕共同的代码写在一个dialog module里(如将OK_CODE拷贝到SAVE_CODE里,将将OK_CODE清空这一过程),然后在所有的屏幕的PAI事件开头调用这个dialog module。

    MODULE位于ABAP主程序中,相当于该主程序中声明的的不带参数的子程序,因此在ABAP主程序中声明的所有全局变量在MODULE块的程序中都可以进行调用,而且MODULE块内部定义的变量在其他MODULE来说也是全局的,但MODULE外面程序代码中不可引用,而且声明变量的MODULE要在引用变量所在MODULE的前面:

    MODULE status_0100 OUTPUT.
      DATA texttable TYPE tt_text.
      ...
    ENDMODULE.
    MODULE user_command_0100 INPUT.
          CALL METHOD editor->get_text_as_stream
            IMPORTING
              text texttable. 这里的texttable实质上引用是的上面module中声明的变量
    ENDMODULE.

    SY-DYNNR系统变量里存储了当前屏幕的屏幕号。

    在flow logic里,有各种不同的调用dialog modules的方法,flow logic的语法允许你在调用dialog modules时附加一些条件,并且通过控制数据在screen与ABAP program之间的传输入:

    通过Module 对屏幕字段进行检验

             ABAP中的Module经常是用来对屏幕字段输入的值进行检验的,具体请参考这里

    Module的简单调用(所有屏幕字段都会被传输到ABAP程序中)

    可以使用如下的flow logic语句来调用module:

    MODULE <mod>.

    (如果前面未指定FIELD选项,则表示此Module对所有字段都有效,而不是针对某个屏幕字段校验的,相当于选择屏幕的AT SELECTION-SCREEN事件)

    如果你使用这种简单的流逻辑语句来调用module,则数据在屏幕与ABAP程序之间是这样传输的:
    ?   在PAI事件中,所有屏幕字段会在第一个PAI module调用之前(前提是自动输入检查需要通过),就已传递到ABAP程序中相同名的字段中(数据从“对话屏幕”传递到“ABAP程序”中进行处理)。

    ?   在最后一个PBO module调用之后与屏幕显示之前,所有ABAP程序中的同名(与屏幕字段)字段将会传回到屏幕相应字段中(数据从“ABAP程序”传递到“对话屏幕”中进行显示)。

    屏幕字段传输时间点控件(FIELD)

    如果使用前一节的介绍的简单调用Module的方式来调用dialog  module时,所有的屏幕字段在PAI事件块处理开始之前都会传递到ABAP程序。

    screen flow logic 中的FIELD语句可以用来控制在什么时候将屏幕字段传递到ABAP程序中相应的字段中。

    FIELD <f>.

    使用FIELD语句后,屏幕字段<f>需要在该语句处理完后才传递到ABAP程序相应的字段中,在后没有带module选项时,仅仅只是控制屏幕字段传输到ABAP程序中的时间点,如需对屏幕字段进行检验,需要在屏幕字段值传递到ABAP程序之前,通过以下语句来实现检验:

    FIELD <field_name> MODULE <module_name>:可以用来对屏幕字段field_name进行检验使用,检验的代码写在module_name中。这相当于选择屏幕的 AT SELECTION-SCREEN ON < field_name>的作用,即Module只对<field_name>字段起作用,因此Module是专门用来校验此屏幕字段的

     

    仅只有未出现在FIELD语句中的屏幕字段才会在PAI事件块处理传输到ABAP程序中去。所以当某个屏幕字段出现在FIELD语句中,并且在该 FIELD语句未执行完之前,不要在PAI dialog modules中使用该屏幕字段(该屏幕字段相关的FIELD语句执行完成之后才可以在后续的PAI dialog modules调用中使用),否则,ABAP程序同名字段中的值使用的是前一次对话屏幕中所设置的值。

    FIELD可以被使用在PAI、POH、POV事件中,但在PBO中不起作用。


    PROCESS BEFORE OUTPUT.
      MODULE init_screen_100.
    PROCESS AFTER INPUT.
      MODULE user_command_0100.
      MODULE module_1.
      "box2屏幕字段在该语句执行完后,且在module_2调用之前,才会传递ABAP程序中,所以
      "在该语句执行完之前ABAP程序中相应字段是不会有值
      FIELD box2.
      MODULE module_2.
      "box1、box3屏幕字段在该语句执行完后,且在module_3调用之前,才会传递ABAP程序中,所以
      "在该语句执行完之前ABAP程序中相应字段是不会有值
      FIELDbox1box3.
      MODULE module_3.

     

    DATAok_code LIKE sy-ucomm,
          save_ok LIKE ok_code,
          box1box2box3box4,
          mod1_result1mod1_result2mod1_result3mod1_result4,
          mod2_result1mod2_result2mod2_result3mod2_result4,
          mod3_result1mod3_result2mod3_result3mod3_result4.
    CALL SCREEN 200.
    MODULE init_screen_100 OUTPUT.
      SET PF-STATUS 'SDSS'.
      CLEARbox1box2box3box4.
    ENDMODULE.   
    MODULE user_command_0100 INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      IF save_ok 'CANCEL'.
        LEAVE PROGRAM.
      ENDIF.
    ENDMODULE
    MODULE module_1 INPUT.
      mod1_result1 box1.
      mod1_result2 box2.
      mod1_result3 box3.
      mod1_result4 box4.
    ENDMODULE
    MODULE module_2 INPUT.
      mod2_result1 box1.
      mod2_result2 box2.
      mod2_result3 box3.
      mod2_result4 box4.
    ENDMODULE.                  
    MODULE module_3 INPUT.
      mod3_result1 box1.
      mod3_result2 box2.
      mod3_result3 box3.
      mod3_result4 box4.
    ENDMODULE.          

    ?      由于BOX4未在FIELD语句出现过,所以在PAI事件之前就已经传递到ABAP程序中,所以在module_1、module_2、module_3三个PAI dialog modules里BOX4字段都是有值的。

    ?      BOX2屏幕字段要在FIELD BOX2.语句之后才能传递取ABAP相应的BOX2字段中去,所以在module_1中是BOX2字段是没有值的,但在module_2、module_3中会有值。

    ?      而BOX1、BOX3需要在FIELD: box1, box3.语句后才能传递取ABAP相应的BOX1、BOX3字段中去,所以在module_1、module_2中不会有值,只有在module_3中才有值。

    AT EXIT-COMMAND

    如果某个屏幕字段有一些约束检查(如参照的是某个数据表中的字段),则需要先通过这些字段的检测,才会触发PAI事件。如果某个屏幕字段为必须,但没有输入时,点击工具条中的退出按钮或屏幕中的按钮时是不会起作用的,这就意味着在输入检测通不过的情况下,PAI事件块里的正常MODULE语句是不会被执行的,如屏幕中的文本框为必输入,点击工具条中的Cancel按钮或者是屏幕中的Cancel按钮时无法退出程序:


    为了避免这个问题:在输入不合法的情况下也可以退出程序,可以使用以下几步:

    1.         设置成E类型的Function Codes

    可以将屏幕中的按钮与GUIstatus上的按钮的Function Code的类型设置为E类型。

    将屏幕中的按钮的Function Code设置为E类型:


    同样,在GUI statusStandard Toolbar栏中,我们一般需要将Backimage023[3] (F3), Exitimage024[3] (shift+F3), and Cancelimage025[3] (F12)所对应的Function Code类型设置为E类型(因为这三个按钮一般是用来退出程序来使用的):


    2.         EXIT-COMMAND

    对于E类型的Function Code,可以使用如下语句在PAI事件块中来触发:

    MODULE <mod> AT EXIT-COMMAND.

    不管该语句在screen flow logic的PAI事件块里的什么地方,都会在字段的约束自动检测之执行,因此,此时其他的屏幕字段的值不会被传递到ABAP程序中去,当该MODULE执行完后,如果未退出该屏幕,则会进行正常PAI(即PAI事件块里没有带EXIT-COMMAND选项的MODULE语句)事件块。

    该语句在字段约束自动检测之前会被执行,一般用来正常退屏幕来使用,如果未使用LEAVE语句退出屏幕,则会在这之后还会继续进行字段的自动检测,检测完后还会继续PAI的处理(即执行PAI事件块中不带EXIT-COMMAND选项的MODULE语句)

    注意:PAI事件块里只有第一个附加EXIT-COMMAND选项的MODULE语句者会被执行(只要有一类型为E的Function Code按钮被点击就会执行),其他附加EXIT-COMMAND选项的MODULE语句不会被执行,如:

    PROCESS AFTER INPUT.
      MODULE execute1.
      "只要是E类的Function Code都会执行
      MODULE cancel AT EXIT-COMMAND.
      "永远都不会执行
      MODULE back AT EXIT-COMMAND.
      MODULE execute2.

    上面的 MODULE execute1.与MODULE execute2.两个语句会在字段约束自动检测通过之后才会被执行,而MODULE cancel AT EXIT-COMMAND语句则会在字段约束自动检测之前就会被执行,由于MODULE back AT EXIT-COMMAND语句是第二个事EXIT-COMMAND选项的MODULE语句,所以永远都不会被执行了。

    带执行条件的MODULE

    这里的FIELD与前面的数据传输控制(FIELD)的使用是一样的:只有当FIELD <f>执行完成后,后面ABAP中<mod>中才能读到字段<f>的值,在这之前的module中是没有数据的。

    FIELD dynp_field MODULE mod [ {ON INPUT}
    | {ON REQUEST}
    | {ON *-INPUT}
    | {ON {CHAIN-INPUT|CHAIN-REQUEST}}
    | {AT CURSOR-SELECTION}.



    1、单个字段检查(即调用module)

    FIELD <FLD1> MODULE <MDL1>.

    2、单个字段被多个MODULE检查

    FIELD <FLD1> MODULE <MDL1>,MODULE <MDL2>.

    3、检查多个字段,使用CHAIN

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1>.
        MODULE <mdl2>.
      ENDCHAIN.
    表示FLD1,FLD2,FLD3,FLD4会被MDL1,MDL2检查。

    4、不是初始值(即不为空时、非初始值)才检查,该事件适合于对屏幕新增数据的检查

    FIELD <FLD1> MODULE <MDL1> ON INPUT.
    ON INPUT表示初始值改变(即不为空、非初始值)时执行。
    特殊情况:
    FIELD <FLD1> MODULE <MDL1> ON *-INPUT.
    表示用户输入字段首字输入’*’,并切输入字段属性设置了“*”的属性,MODULE才会调用。

    5、屏幕字段输入框中的值发生变化时检查(如在原本为空值的字段中输入数据,或修改某字段的值),该事件适合于屏幕中字段的值变更时的检查

    FIELD <FLD1> MODULE <MDL1> ON REQUEST.

    6、CHAIN中不是初始值检查

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1> ON CHAIN-INPUT.
        MODULE <mdl2>.
      ENDCHAIN.
    注意:CHAIN-INPUT表示FLD1,FLD2,FLD3,FLD4不是初始值时执行MDL1检查

     

    FIELD… MODULE…(单个屏幕字段)

    FIELD <f> MODULE <mod> ON INPUT|REQUEST|*-INPUT. 

    在编辑屏幕的PAI的时候,对字段的检查一般用field xxx module xxx或者用chain。有两种操作可供选择,一种是on input,另一种是on request。

    ?      ON INPUT:只要该字段不为初始值就会触发module。不同类型字段的初始值是不一样的:如果是字符类型其初始值为Space;数字类型的为zero(不同类型的具体初始值请参考《ABAP BC Programming.docx》)。即使用户在输入框输入了值,但这个值为初始值时也不会触发

    ?      ON REQUEST:该字段发生变化后触发module

    例如,有两个字段,a、b,两个module,check_a check_b:

    field module check_a on input.

    field module chec_b on request.

    无论a发生任何变化,只要a不为空,则每一次回车都会触发check_a;

    反之,只有b发生变化后才会触发check_b,如果两次回车中间b没有发生变化,则不会触发check_b。

    注:此方式与CHAIN不同,不能如下写法:

      FIELD a. " FIELD与MODULE只能写在同一语句中
      MODULE check_a ON INPUT.

      FIELD a,b. "Chain中时,FIELD后面不能跟多个字段
      MODULE check_a ON INPUT.

      FIELD a.
      MODULE check_a ON CHAIN-INPUT. "但可以使用CHAIN-?是否有意思没有测试

    ?      ON *-INPUT

    如果屏幕字段<f>的输入内容第一个字符为“*”,并且该屏幕字段<f>设置了“* Entry”属性,且没有ON INPUT时,则会调用<mod>module ,并且首字符星号不会被传递到ABAP程序中去。



    1、单个字段检查(即调用module)

    FIELD <FLD1> MODULE <MDL1>.

    2、单个字段被多个MODULE检查

    FIELD <FLD1> MODULE <MDL1>,MODULE <MDL2>.

    3、检查多个字段,使用CHAIN

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1>.
        MODULE <mdl2>.
      ENDCHAIN.
    表示FLD1,FLD2,FLD3,FLD4会被MDL1,MDL2检查。

    4、不是初始值(即不为空时、非初始值)才检查,该事件适合于对屏幕新增数据的检查

    FIELD <FLD1> MODULE <MDL1> ON INPUT.
    ON INPUT表示初始值改变(即不为空、非初始值)时执行。
    特殊情况:
    FIELD <FLD1> MODULE <MDL1> ON *-INPUT.
    表示用户输入字段首字输入’*’,并切输入字段属性设置了“*”的属性,MODULE才会调用。

    5、屏幕字段输入框中的值发生变化时检查(如在原本为空值的字段中输入数据,或修改某字段的值),该事件适合于屏幕中字段的值变更时的检查

    FIELD <FLD1> MODULE <MDL1> ON REQUEST.

    6、CHAIN中不是初始值检查

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1> ON CHAIN-INPUT.
        MODULE <mdl2>.
      ENDCHAIN.
    注意:CHAIN-INPUT表示FLD1,FLD2,FLD3,FLD4不是初始值时执行MDL1检查

     

    FIELD… MODULE…(单个屏幕字段)

    FIELD <f> MODULE <mod> ON INPUT|REQUEST|*-INPUT. 

    在编辑屏幕的PAI的时候,对字段的检查一般用field xxx module xxx或者用chain。有两种操作可供选择,一种是on input,另一种是on request。

    ?      ON INPUT:只要该字段不为初始值就会触发module。不同类型字段的初始值是不一样的:如果是字符类型其初始值为Space;数字类型的为zero(不同类型的具体初始值请参考《ABAP BC Programming.docx》)。即使用户在输入框输入了值,但这个值为初始值时也不会触发

    ?      ON REQUEST:该字段发生变化后触发module

    例如,有两个字段,a、b,两个module,check_a check_b:

    field module check_a on input.

    field module chec_b on request.

    无论a发生任何变化,只要a不为空,则每一次回车都会触发check_a;

    反之,只有b发生变化后才会触发check_b,如果两次回车中间b没有发生变化,则不会触发check_b。

    注:此方式与CHAIN不同,不能如下写法:

      FIELD a. " FIELD与MODULE只能写在同一语句中
      MODULE check_a ON INPUT.

      FIELD a,b. "Chain中时,FIELD后面不能跟多个字段
      MODULE check_a ON INPUT.

      FIELD a.
      MODULE check_a ON CHAIN-INPUT. "但可以使用CHAIN-?是否有意思没有测试

    ?      ON *-INPUT

    如果屏幕字段<f>的输入内容第一个字符为“*”,并且该屏幕字段<f>设置了“* Entry”属性,且没有ON INPUT时,则会调用<mod>module ,并且首字符星号不会被传递到ABAP程序中去。


    CHAINENDCHAIN(多个屏幕字段)

    不能嵌套。可以将多个屏幕字段组织在一块进行验证。此语句的作用就是相当于选择屏幕的AT SELECTION-SCREEN ON BLOCK block事件,用来对一个逻辑块的屏幕字段进行校验,这里的逻辑块是按Module前FIELD选项指定的屏幕字段来划分的,如下的

    CHAIN.
      FIELD<f1><f2>,<fi...>.
      MODULE <mod1> ON CHAIN-INPUT|CHAIN-REQUEST.
      FIELD<g1><g2>,<gi...>.
      MODULE <mod2> ON CHAIN-INPUT|CHAIN-REQUEST.
      ... 
    ENDCHAIN.

    只要<fi>中某个字段满足条件(<mod1>后面的CHAIN-INPUT与CHAIN-REQUEST条件),<mod1>就会被调用,而只要<fi>或<gi>中的某个字段满足条件,则<mod2>就会被调用。如果在module中检测不通过(如MESSAGE… E类消息时),则CHAIN…ENDCHAIN之外的所有其他屏幕字段将会被锁定且置灰,这与选择屏幕的AT SELECTION-SCREEN ON BLOCK校验是一样的

     

    CHAIN.
      FIELD<f1><f2>,<fi...>.
      FIELD <f> MODULE <mod1> ON INPUT|REQUEST|*-INPUT|CHAIN-INPUT|CHAIN-REQUEST
      MODULE <mod2> ON CHAIN-INPUT|CHAIN-REQUEST.
    ENDCHAIN.

    <mod1>被调用的条件是所对应字段<f>满足ON后面指定的条件即可执行。<mod2>被调用的条件是只要<fi>或<f>中的某个字段满足条件即可执行。


    1、单个字段检查(即调用module)

    FIELD <FLD1> MODULE <MDL1>.

    2、单个字段被多个MODULE检查

    FIELD <FLD1> MODULE <MDL1>,MODULE <MDL2>.

    3、检查多个字段,使用CHAIN

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1>.
        MODULE <mdl2>.
      ENDCHAIN.
    表示FLD1,FLD2,FLD3,FLD4会被MDL1,MDL2检查。

    4、不是初始值(即不为空时、非初始值)才检查,该事件适合于对屏幕新增数据的检查

    FIELD <FLD1> MODULE <MDL1> ON INPUT.
    ON INPUT表示初始值改变(即不为空、非初始值)时执行。
    特殊情况:
    FIELD <FLD1> MODULE <MDL1> ON *-INPUT.
    表示用户输入字段首字输入’*’,并切输入字段属性设置了“*”的属性,MODULE才会调用。

    5、屏幕字段输入框中的值发生变化时检查(如在原本为空值的字段中输入数据,或修改某字段的值),该事件适合于屏幕中字段的值变更时的检查

    FIELD <FLD1> MODULE <MDL1> ON REQUEST.

    6、CHAIN中不是初始值检查

      CHAIN.
        FIELD <fld1>.
        FIELD <fld2>,<fld3>,<fld4>.
        MODULE <mdl1> ON CHAIN-INPUT.
        MODULE <mdl2>.
      ENDCHAIN.
    注意:CHAIN-INPUT表示FLD1,FLD2,FLD3,FLD4不是初始值时执行MDL1检查

     

    FIELD… MODULE…(单个屏幕字段)

    FIELD <f> MODULE <mod> ON INPUT|REQUEST|*-INPUT. 

    在编辑屏幕的PAI的时候,对字段的检查一般用field xxx module xxx或者用chain。有两种操作可供选择,一种是on input,另一种是on request。

    ?      ON INPUT:只要该字段不为初始值就会触发module。不同类型字段的初始值是不一样的:如果是字符类型其初始值为Space;数字类型的为zero(不同类型的具体初始值请参考《ABAP BC Programming.docx》)。即使用户在输入框输入了值,但这个值为初始值时也不会触发

    ?      ON REQUEST:该字段发生变化后触发module

    例如,有两个字段,a、b,两个module,check_a check_b:

    field module check_a on input.

    field module chec_b on request.

    无论a发生任何变化,只要a不为空,则每一次回车都会触发check_a;

    反之,只有b发生变化后才会触发check_b,如果两次回车中间b没有发生变化,则不会触发check_b。

    注:此方式与CHAIN不同,不能如下写法:

      FIELD a. " FIELD与MODULE只能写在同一语句中
      MODULE check_a ON INPUT.

      FIELD a,b. "Chain中时,FIELD后面不能跟多个字段
      MODULE check_a ON INPUT.

      FIELD a.
      MODULE check_a ON CHAIN-INPUT. "但可以使用CHAIN-?是否有意思没有测试

    ?      ON *-INPUT

    如果屏幕字段<f>的输入内容第一个字符为“*”,并且该屏幕字段<f>设置了“* Entry”属性,且没有ON INPUT时,则会调用<mod>module ,并且首字符星号不会被传递到ABAP程序中去。


    ON INPUTON CHAIN-INPUT区别

    CHAIN.
        FIELD:f1,f2.
        FIELDf3 MODULE mod1 ON INPUT.
      ENDCHAIN.

    只有f3包含非初始值时才调用mod1

    CHAIN.
        FIELD:f1,f2.
        FIELD:f3 MODULE mod1 ON CHAIN-INPUT.
      ENDCHAIN

    f1,f2,f3中任一字段包含非初始值時都調用mod1.

    注意on input 与on chain-input的不同

    AT CURSOR-SELECTION鼠标双击时调用

    在AT CURSOR-SELECTION语句调用之前,先也要通过字段有效性检测这一过程,这与AT EXIT-COMMAND是不一样的(它会绕过字段输入有效检测过程),屏幕字段的值会按照FIELD语句的出现的顺序传递到ABAP程序中,但此时Function Code不会传递到ABAP程序中去,所以此时SY-UCOMM与OK_CODE不受影响,存放的值还是上一次的值。

    MODULE <mod> AT CURSOR-SELECTION.

    当鼠标双击(或F2)输入/输出( I/O)类型的屏幕字段时(比如下图中屏幕字段类型为 I/O 的屏幕字段)才会调用<mod>:



    注意:要使鼠标双击屏幕输入元素时AT CURSOR-SELECTION生效,还必须在GUI Status里设置:将F2(一般使用F2,不要使用别的快捷键,因为F2本来就是系统预设的鼠标功能)所对应的Function CodeCS,并且Function TypeS,此时才能激活鼠标双击功能:



    还可以与FIELD一起使用:

    FIELD <f> MODULE <mod> AT CURSOR-SELECTION.

    或者,针对多个屏幕字段时:

    CHAIN.
      FIELD<f1><f2>,...
      MODULE <mod> AT CURSOR-SELECTION.
    ENDCHAIN.

    上面这两种方式下,只有当鼠标双击(或F2)I/O 类型字段<f>或<fi>屏幕字段时,<mod>才会被调用(注意:<f>或<fi>只能是I/O 类型的屏幕字段)。

     

    AT CURSOR-SELECTION语句调用优先顺序:

    ?        如果有某个屏幕字段可能有以下三种语句:MODULE <mod> AT CURSOR-SELECTION(包括在CHAIN…ENDCHAIN里的语句)、FIELD <f> MODULE <mod> AT CURSOR-SELECTION有关,则带FIELD的语句会先执行(不管FIELD语句这三者前还是后),其他的语句不再被执行。

    ?        对于同一个屏幕字段<f>,如果有多条FIELD  <f>  MODULE  <mod>  AT  CURSOR-SELECTION语句,则只有第一条会被执行

    ?        如果有多条MODULE <mod> AT CURSOR-SELECTION 的语句,则只有最后一条语句会被执行

     

    示例:



    DATAok_code LIKE sy-ucomm,
          input1
    (20),
          input2
    (20),
          input3
    (20),
          fld
    (20).
    CALL SCREEN 200.
    MODULE init_screen_0100 OUTPUT.
      
    SET PF-STATUS 'STATUS_100'.
    ENDMODULE.                   
    MODULE cancel INPUT.
      
    LEAVE PROGRAM.
    ENDMODULE.                   
    MODULE cursor INPUT.
      
    GET CURSOR FIELD fld.
      
    MESSAGE  i001(00WITH  'cursor: ' fld.
    ENDMODULE.                   
    MODULE module_1 INPUT.
      
    MESSAGE i001(00WITH 'module_1'.
    ENDMODULE.                   
    MODULE module_2 INPUT.
      
    MESSAGE i001(00WITH 'module_2 '.
    ENDMODULE.                   
    MODULE module_* INPUT.
      
    MESSAGE i001(00WITH 'module_*'.
    ENDMODULE.                 
    MODULE c1 INPUT.
      
    GET CURSOR FIELD fld.
      
    MESSAGE i001(00)  WITH  'c1: ' fld.
    ENDMODULE.                                       
    MODULE c2 INPUT.
      
    GET CURSOR FIELD fld.
      
    MESSAGE i001(00)  WITH 'c2: ' fld.
    ENDMODULE




    在GUI status STATUS_100中,image068图标被激活,且Function Code为CANCEL,类型为E。快捷键F2也被激活,Function Code为 CS类型为S。

    ?   只要1或2输入框不为空时,MODULE_1将被调用

    ?   只要3个框任何一个输入内容发生了改变,则MODULE_2就会被用调用

    ?  只要输入框3输入的内容以*开头,则会调用MODULE_*(注意:屏幕字段INPUT3需要设置“* Entry”属性才能触发)

    ?  当在INPUT1上按F2或双击时,c1会被调用(因为带FIELD的要比不带FIELD的语句调用优先级要高);如果将第20行注掉,则此时cursor会被调用(因为有多条不带FIELD的语句时,最后一条才会被执行,所以要想在INPUT1上双击时调用c2,则需要将19、20都注掉)

    ?  当在INPUT2或INPUT3上按F2或双击时,cursor会被调用,而c2不会被调用,因为有多条不带FIELD的语句时,最后一条才会被执行

    ABAP Statements for Screens

    SET PF-STATUS

    SET PF-STATUS <stat> [OF PROGRAM <prog>] [EXCLUDING <f>|<itab>].

    给屏幕设置STATUS(屏幕菜单、工具条)

    DATA fcode TYPE TABLE OF sy-ucomm
    ... 
    MODULE status_0100 OUTPUT
      "去激活Function code为CHANGE、SAVE的功能
      APPEND 'CHANGE'  TO fcode
      APPEND 'SAVE' TO fcode
      SET PF-STATUS 'STATUS_0100' EXCLUDING fcode
    ENDMODULE.

    SET TITLEBAR、激活Title Bar

    SET TITLEBAR title [OF PROGRAM prog][WITH text1 ... text9].

    除非另外有一个SET TITLEBAR重新设置了Title,否则当前屏幕及后继屏幕的Tile一样。占位符placeholders &1 ... &9可以被相应的text1 ... text9所替换,如果要显示一个&,则要在Title中使用&&来代替

    DATAtitle  TYPE string
          prog   TYPE string
          p1     TYPE c LENGTH 10
          p2     TYPE c LENGTH 10
    ... 
    MODULE status_0100 OUTPUT
      ... 
      title 'TITLE_0100'
      prog  '...'
      p1 '...'
      p2 '...'
      SET TITLEBAR title OF PROGRAM prog WITH p1 p2
      ... 
    ENDMODULE.



    GET CURSORFIELD

    GET CURSOR FIELD<f>[OFFSET<off>][LINE<lin>][VALUE<val>] [LENGTH<len>] [AREA area]..

    当用户在屏幕上进行操作后,我们需要知道光标操作所在哪个屏幕元素上,这个典型应用是F2(或鼠标双击)。该语句就是找出光标所在屏幕元素,它会将光标所在屏幕是元素的名称写入<f>变量中,如果光标在屏幕字段里,则SY-SUBRC为0,否则为4。

    ?     OFFSET将光标所在屏幕元素内容中的位置写到变量off中

    ?     LINE如果光标落在了table control表格控件中的某行,则将光标所在的行号写到lin变量中。如果光标不在table control表格控件中,则lin的值为0.

    ?     VALUE将屏幕字段的内容(指显示模式下的内容,也就是说还包括格式字符)写到val变量中

    ?     LENGTH将屏幕字段的显示长度写入到len变量中

    ?     AREA

    LIST屏幕的光标读取与定位请参考GET CURSOR FIELD、GET CURSOR LINE








    DATAok_code LIKE sy-ucomm,
          save_ok LIKE ok_code.
    DATAinput_output(20TYPE c,
          fld(20TYPE c,
          off TYPE i,
          val(20TYPE c,
          len TYPE i.
    CALL SCREEN 200.
    MODULE user_command_0100 INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      CASE save_ok.
        WHEN 'CANCEL'.
          LEAVE PROGRAM.
        WHEN 'SELE'.
          GET CURSOR FIELD fld OFFSET off VALUE val LENGTH len.
      ENDCASE.
    ENDMODULE.    
    MODULE init_screen_0100 OUTPUT.
      SET PF-STATUS 'SDSS'.
    ENDMODULE.

    SET CURSOR FIELD

    光标定位一是可以通过屏幕属性静态的设置

    二是在PBO中动态的指定光标位置:

    SET CURSOR FIELD <f> [OFFSET <off>].

    输入检测

    自动输入检测

    屏幕的自动检测在所有屏幕字段内容传递到ABAP程序中之前,也在screen flow logic处理之前发生。如果想绕过自动检测之前就要调用module,则需要在调用时使用 AT EXIT-COMMAND选项

    如果自动检测出现了错误,消息将显示在屏幕的状态条上显示,相应字段继续等待正确的输入,只有当所有输入都通过了自动检测后才会触发PAI正常处理(AT EXIT-COMMAND选项的调用除外)。自动检查以如下顺序来运行:

    1.      必输字段检测

    2.      数据格式检测

    3.      ABAP Dictionary检测

    ?       如果参照的字段为foreign key,则会进行Check Table检测

    ?       fixed values检测





    发现在一个自动联动现象:当SDYN_CONN-CARRID、SDYN_CONN-CONNID同时出现时,自动就具有联动功能,如果输入了SDYN_CONN-CARRID的值,则SDYN_CONN-CONNID的值会受它影响,如果不输入就选择SDYN_CONN-CONNID的值,则SDYN_CONN–CARRID框中的值会自动填上。

    屏幕逻辑流中进行检测FIELD…VALUES

    已过时

    在ABAP Dialog Modules进行检测

    当检测不通过时,可以在相应的module中发送warning (type W) 或者 error (type E)类型的消息,PAI处理就会暂停,直到输入通过检测后才会继续向后执行。

    FIELD <f> MODULE <mod>.

    当<mod>中发送出警告或错误类型的信息时,相应字段<f>将会要求重新输入,一旦输入检测通过后,将继续后面的PAI语句的处理,以前的module不会再次调用。

    CHAIN.
      FIELD<f1><f2>,... 
      MODULE <mod1>
      FIELD<g1><g2>,... 
      MODULE <mod2>.
      ... 
    ENDCHAIN.

    当<mod1>或者<mod2>中发送出警告或错误类型的信息时,所以出现在CHAIN…ENDCHAIN块FIELD语句中的屏幕字段将会要求重新输入,其他屏幕字段被锁定且置灰不能输入。一旦输入检测通过后,将继续进后面的PAI语句的处理,以前的module不会再次调用




    PROCESS BEFORE OUTPUT.
      MODULE init_screen_0100.
    PROCESS AFTER INPUT.
      MODULE cancel AT EXIT-COMMAND.
      FIELD input1 MODULE module_1.
      FIELD input2 MODULE module_2.
      FIELD input3 MODULE module_3.
      CHAIN.
        FIELD input4.
        MODULE chain_module_1.
        FIELD input5.
        FIELD input6 MODULE chain_module_2.
      ENDCHAIN.
      MODULE execution.

     

    DATAok_code LIKE sy-ucomm,
          input1 TYPE i,
          input2 TYPE i,
          input3 TYPE i,
          input4 TYPE i,
          input5 TYPE i,
          input6 TYPE i,
          sum TYPE i.
    CALL SCREEN 200.
    MODULE init_screen_0100 OUTPUT.
      SET PF-STATUS 'SDSS'.
    ENDMODULE
    MODULE init_screen_100 OUTPUT.
      CLEARinput1input2input3input4input5input6.
      SET PF-STATUS 'SDSS'.
    ENDMODULE
    MODULE cancel INPUT.
       LEAVE PROGRAM.
    ENDMODULE.
    MODULE module_1 INPUT.
      IF input1 < 50.
        MESSAGE 'module_1: input1 < 50' TYPE 'E'.
      ENDIF.
    ENDMODULE.   
    MODULE module_2 INPUT.
      IF input2 < 100.
        MESSAGE 'module_2: input3 < 100' TYPE 'E'.
      ENDIF.
    ENDMODULE
    MODULE module_3 INPUT.
      IF input3 < 150.
        MESSAGE 'module_3: input1 < 150' TYPE 'E'.
      ENDIF.
    ENDMODULE
    MODULE chain_module_1 INPUT.
      IF input4 < 10.
        MESSAGE 'chain_module_1: input4 < 10' TYPE 'E'.
      ENDIF.
    ENDMODULE.   
    MODULE chain_module_3 INPUT.
      IF input4 > 20.
        MESSAGE 'chain_module_3 : input4 > 20' TYPE 'E'.
      ENDIF.
    ENDMODULE.
    MODULE chain_module_2 INPUT.
      CLEAR sum.
      sum sum input4input5input6.
      IF sum <= 100.
        MESSAGE 'chain_module_2: (input4 + input5 + input6) <= 100' TYPE 'E'.
      ENDIF.
    ENDMODULE.
    MODULE execution INPUT.
      MESSAGE 'execution:' TYPE 'I'.
    ENDMODULE.

    Search help (F4)

    F4 Help也叫“Input Help”,而Search help又是Input Help的一种

    对话屏幕字段绑定搜索帮助


    F4IF_FIELD_VALUE_REQUEST:通过函数绑定搜索帮助


    Domain固定值fixed values

    参考这里

    检查表Check Table --- Value Table

    也可以在Domain中指定一个值表(Value Table)作为字段取值范围的限制,但是与指定固定值的方式不同的是,为一个Domain简单地指定一个取值表不会导致用户的输入被自动校验,也不会自动出现F4 Help。只有通过表外键image079按钮将该Value Table指定为主表之后,一个值表才能真正成为Check Table。所以要想成为真正有效的Check Table,必须要做两个操作:

    一是要为字段对应的Domain设置Value Table(即主表,其实这一步不是必须的,在通过image079[1]按钮指定主表时,可以不用指定为字段所参照的元素所对应Domain所设置的Value Table,而是指定其他的主表也是可以的—— 但最好不要这样做,Value Check时会出其他问题),

    二是要为表字段通过image079[2]为它设置外键。





    检查表(主表:SCOUNTER)的主键字段与外键表(从表:SBOOK)中的外键字段一一对应进行校验。

    外键的检验也只能用于屏幕用户的输入检查,如果用ABAP程序直接向表中插入记录,则此处定义的外键检查不起作用

    PARAMETERS p_carid TYPE sbook-carrid VALUE CHECK.
    PARAMETERS p_cuter TYPE sbook-counter VALUE CHECK.

    F4命中清单中的所有数据都来自于主表:



    注:命中清单中的ID列即CARRID背景色不是蓝色,所以选择一条时,不会自动填充屏幕字段P_CARID原因是对应的Search Help中的CARRID参数对应的EXP没有打上钩


    如果将这个钩打上,则会相应列背景色会为蓝色,且会自动填充,达到联动效果

     

    一般当某个外键所参照主表的主键上如果设置了搜索帮助(如上面COUNTER外键所引用的主表主键字段SCOUNTER-COUNTNUM已分配搜


    索“SCOUNTER_CARRIER_AIRPORT”:

    ),则这个主表主键上的搜帮助会带到从表中相应外键上来,请看上面的SBOOK-COUNTER外键字段的搜索帮助也为“SCOUNTER_CARRIER_AIRPORT”,该搜索帮助决定了整个F4 Help处理及显示过程(如联动查询及自动填充效果)。另外,虽然主表主键上的搜索帮助会带到相应外键上来,但带过来后还可以修改,比如上面示例中带过来的搜索帮助中,CARRID参数所对应的EXP没有钩上,所以示例中的屏幕字段P_CARID不能使用命中清单中的ID列来自动填中,所以我们可以新建一个搜索帮助,并将CARRID搜索参数所对应的EXP钩上,则可达到自动上屏幕的效果;

    另外,有些外键所参照的主表主键没有指定搜索帮助,此时参考的从表(或主表)屏幕字段的F4 Help就只有一个简单的字段了,如上面SBOOK-LOCCURKEY字段:


    PARAMETERS p_cur TYPE sbook-LOCCURKEY VALUE CHECK.


    SE11创建基本搜索帮助(Elementary Search Help),及参数说明

    创建搜索帮助时,搜索帮助的数据源可以来于:表/视图(通过“选择方法”指定)、ABAP程序(通过“搜索帮助出口”指定)。下面以视图为源来创建搜索帮助。

    SE11中,SAP提供了一种“帮助视图”,专门为维护搜索帮助设立的,该类视图提供表的关联信息,不会在数据库服务器上占用实际的物理空间。

    创建交货订单信息相关视图:

    l  LIKP:交货单的表头

    l  VBUK:交货单状态

    l  KNA1:客户主数据

    需要在帮助视图中显示的字段有:LIKP-VBELN交货单号;LIKP-KUNNR货物送达方的编码;KNA1-NAME1送达方的名称;VBUK-WBSTK交货单状态,“C”表示已交货





    基本索引帮助:最基本也是“集合搜索帮助”组成部分的帮助,如果按F4后显示条件限制对话框,则只会有一个限制条件页面;

    集合搜索帮助(collective search help):是由多个基本索引帮助组成的,中可以包含多个search help,这个也就是我们看到的选择界面有多个tab的那种情况。如果按F4后显示条件限制对话框,则会有多个条件限制页面TAB标签,即可以选择不同的“基本索引帮助”来筛选数据



    l  简短描述:设置的简短描述不是限制对话框中的标题。限制对话框中的标题如何设置???

    l  选择方法(selecttion method):可以是选数据表,或者是视图。当所选择的表有text table时,会自动填充下面的“文本表”标签,并且search help会根据用户登录语言自动选择相应的text

    l  限制对话框行为:按F4后是否弹出条件过滤对话框,有以下三种选择:

    2  立即显示值:在按F4后立即显示命中清单,不会弹出限制对话框,通常如果命中清单记录很少时则建议使用该选项。

    2  具有值限制的对话:立即显示限制值的对话框。如果正常情况下可能条目的清单非常大,则选择该选项。

    2  根据值集合的对话:如果命中清单包含的条目小于100个,那么立即显示该命中清单。如果其包含的条目多余100个,那么显示限制值用的对话框。

    l  快捷键:此键只在该基本搜索帮助包括到某个集合搜索帮助里时,才可使用(有意义)??作用是在集合搜索帮助的限制对话框中,出现了多个限制TAB标签页面,所以可以使用此处设置的键快速切换到相应的TAB标签页面????

    HOT KEY是用来做多个search help合并时用到的,决定出现的顺序。

    l  搜索帮助出口(search help exit):可以用作此搜索帮助的增强函数,对搜索出来的数据进一步进行处理。如下面出口中,在命中清单显示之前,对数据进行过滤处理:


    (代码中STRING+3(4)取的是搜索帮助的第一个参数,但如果是在 CALLCONTROL-STEP = RETURN时间点时,STRING+0(4)才是第一个搜索帮助参数,因RECORD_TAB在不同时间点可能是变化着的,具体请参照后面IMP、EXP参数详细说明)

    l  搜索帮助参数:来自于数据库表或视图中的字段

    定义search help的parameter时,你需要定义它是IMPORT还是EXPORT。同fm一样IMPORT和EXPORT PARAMETER构成了search help的interface。

    2  IMP:输入参数。表示屏幕上相应字段是否作为搜索帮助的过滤条件(即报表选择屏幕上的字段的值是否从报表选择屏幕上传递到搜索帮助中去)

    如果是F4字段时,屏幕字段中的值包含“*”时,才会将F4字段传递到Search Help中。除开F4屏幕字段外,而其他只要是Link到了相应的Search Help参数的屏幕字段,则不管IMP是否钩选上,只要相应屏幕字段中有值,则会传入到搜索中作为过滤条件。所以IMP是否钩选上,只会影响该参数所Link到的F4屏幕字段值是否传入到搜索帮助,而其他非F4屏幕字段,只要与搜索帮助相应参数Link过,不管IMP参数是否钩先,则屏幕字段值都会传入到搜索帮助中。

    另外,如果要对已传入的屏幕字段值进行再次修改,则可以将搜索帮助的“对话框性为—对话类型”设为“C 具有值限制的对话”,传入的屏幕字段值会在弹出限制对话框中相应字段中显示,此时就可以对这些值做进一步修改;如果没有弹出限制对话框,则屏幕上传入的值不会再次被修改的可能,会直接传入到搜索帮助作为过滤条件



    注:上图中只有屏幕字段是参照表或结构字段而非通过编程来绑定Help时,在搜索帮助查询时,除了可以将F4屏幕字段传入到搜索帮助中(前提是值中有“*”,且IMP被钩选过了)作为搜索帮助的过滤条件,其他非F4屏幕字段(与搜索参数有Link关系的屏幕字段)的值也会传入到搜索帮助中作为搜索条件;在返回时,会将相应的命中清单中的列(这些列与屏幕字段是有映射关系)自动填充到相应的屏幕字段中。另外,如果是通过程序方式 MATCHCODE绑定(或其通过Data Element绑定)时,则在查询时不会将其他非F4屏幕字段传入到搜索帮助时,也不会在返回时填充其他非F4屏幕字段,在返回时,会默认返回 EXP中第一个钩选列到F4屏幕字段中



    注:IMP与EXP一定要至少一个被钩选,在将此搜索帮助分配给表字段时,IMP或EXP被钩选的列才会出现在分配界面,否则在绑定过程的分配界面是不会出现这些参数的

    TABLES:zsflight.
    SELECT-OPTIONS:so_carr FOR zsflight-carrid,"  MATCHCODE OBJECT ZH_SCARR,"航线代码
                   so_conn FOR zsflight-connid,"  MATCHCODE OBJECT ZH_SPFLI."航班代码
                   so_from for zsflight-CITYFROM.



    2  EXP:输出参数,表示搜索帮助的此列会从搜索帮助中传递到报表选择屏幕上(表示F4选中一条记录后显示到屏幕上文本框中的值——背景字段为浅蓝色的列的数据会被输出,输出的数据可能是多列。注:只有当EXP钩上且相应字段出现在了屏幕上,才会自动填充到相应屏幕字段,如果没有钩上——没钩上的字段背景色为白色,即使出现在了屏幕上,选择命中清单时也不会自动填充),且F4字段一定要将EXP钩上(否则选择后F4字段不能上屏)。可以通过return_tab(具体可以参考自定义对话屏幕字段F4中相应代码解释)参数接收用户所选择的数据。


    是否显示为浅蓝色,是由SHLP-FIELDPROP内表参数中SHLPOUTPUT字段的值来决定的;但如果是通过“Attaching to Data Elements”或直接通过编程方式使用Search Help时,即使EXP有多列被钩选,也只有最前面被钩选的列的背景色为浅蓝色,如果此时也要使被钩选的所有EXP列背景色为浅蓝色,则可以通过修改内表中SHLPOUTPUT字段的值来达此目的,因为调试发现在CALLCONTROL-STEP= DISP 时间点之前时,如果此时SHLPOUTPUT的值为X,则显示出来的命中清单相应列背景色就是浅蓝色的:



    (注:此内表实质上就是用来存储“搜索帮助参数”属性列表的。刚进入F4IF_SHLP_EXIT_EXAMPLE时,搜索帮助参数EXP列中只要是被钩选的列,它所对应此内表的 SHLPOUTPUT列都会是 X ——上图就是首次进入出口函数时SHLP-FIELDPROP内表的内存状态,但运行到CALLCONTROL-STEP= DISP 时间点时,只有EXP列中第一个被钩选的列所对应的SHLPOUTPUT字段的值为X,其他都会清空,所以需要在CALLCONTROL-STEP= DISP 时间点修改此内表值,下面为CALLCONTROL-STEP= DISP 时间点时内表 SHLPOUTPUT的内存状态:



    另外,不管时搜索帮助参数的EXP列钩选了多少个,返回时,命中清单中所选记录的所有列都会返回,这可以通过观察F4IF_SHLP_EXIT_EXAMPLE的RECORD_TAB内表参数获知,因为RECORD_TAB在不同的时间点存储了不同的数据——如果刚好是在CALLCONTROL-STEP= DISP时间点之后,存储的是搜索帮助所有命中的记录(如从数据库中搜索出来的所有数据);如果是在CALLCONTROL-STEP= RETURN时间点时,存储的则是用户选中的记录。下面就来在这两个时间点来看看RECORD_TAB内表数据:

    2  CALLCONTROL-STEP= DISP时:



    2  当从命中清单中选中第一条记录进入到F4IF_SHLP_EXIT_EXAMPLE函数后,此时是CALLCONTROL-STEP= RETURN时间点:




    上面两个时间点来看,RECORD_TAB内表中STRING字段存储的就是命中清单与用户选中记录的数据,并且是将这些数据的多列拼接起来之后存储在此字段中的(注:不管搜索帮助参数中的LPOS是否设置为0或留空时,所有搜索帮助的参数还是都会被拼接起来存储在此字段中,与LPOS设置无关),这些拼接在一起的数据是通过F4IF_SHLP_EXIT_EXAMPLE的SHLP-FIELDDESCR内表参数中的OFFSET(按字节来计算的)及INTLEN(内部长度,按字节来计算的)来划分的,并且在不同的CALLCONTROL-STEP时间点时,OFFSET的取值是变化的,且时间与上面两种是相对应的:

    2  CALLCONTROL-STEP= DISP时:




    2  当从命中清单中选中第一条记录进入到F4IF_SHLP_EXIT_EXAMPLE函数后,此时是CALLCONTROL-STEP= RETURN时间点:



    l  LPOS(列表):命中清单中各列的显示顺序,如果为0或留空的列则不会显示。位置编号不能在列中出现多次,但是允许有间隔。另外,在基本搜索帮助中,至少在命中清单中出现一个参数

    l  SPOS:搜索帮助的过滤条件,对搜索结果进行过滤。如果在命中清单显示之前,弹出限制对话框,则还可以进一步修改那些从选择屏幕上带过来的条件值。此数字就是限制搜索帮助选择条件屏幕字段摆放顺序,如果为0或留空的列则不会出在限制条件页中

    l  SDis:如果勾选了,则在弹出的限制对话框中对应的字段用户不可输入,是只读的。下面是前面创建的Search Help,其中搜索参数WBSTKSDis钩上了,所以弹出的限制对话框中所对应的屏幕字段不能进行修改:



    l  Modified:如果这个勾打上的话,数据元素(Data Element)列,变成可修改状态,也就是说可以为这个字段指定其它数据元素

    l  缺省值:此处设置的默认值是被相应的SPos列所使用的。可以有三种值设置方式:a ‘literal’(in quotes), a parameter ID(ZRD), or a system field (SY-UNAME).

    F4IF_SHLP_EXIT_EXAMPLE出口函数参数说明及实例

    u 出口函数参数

    下面以ZH_SPFLI搜索帮助来理解F4IF_SHLP_EXIT_EXAMPLE出口函数各参数:






    TABLESzsflight.
    SELECT-OPTIONS:s_carrid FOR zsflight-carrid, "航线代码
                   s_connid 
    FOR zsflight-connid, "航班代码
                   s_ctyfrm 
    FOR zsflight-cityfrom. "
    起飞城市




    以上面搜索帮助为例,运行报表程序,并在出口函数中设置断点,来理解一下F4IF_SHLP_EXIT_EXAMPLE出口函数各参数:




    l  SHLP参数




    2  2  SHLPNAME   搜索帮助名

    2     2  SHLPTYPE 搜索帮助的类型,取值如下:

    SH    Search help                                                                      搜索帮助

    CH   Check table                                                                      表检查

    CT    Check table with text table                                       有文本表的检查表

    FV    Fixed values for domains                                           域的固定值

    DV   Fixed values from flow logic                                               流逻辑的固定值

    CA   Calendar help                                                                           日历帮助

    CL    Time help                                                                         时间帮助

    SR    Search help for data element (temporary)                  数据元素的搜索帮助(临时)

    MC  Matchcode                                                                      匹配代码

    MI   Matchcode ID                                                                          匹配代码标识

    IN    Internal Table                                                                           内表


    2  INTDESCR搜索帮助的内部信息,一般程序使用不到

    2  INTERFACE 包含了Help中的所有参数,当前使用哪个参数为F4屏幕字段,屏幕字段与Help参数映射信息(映射关系是通过SHLPFIELDVALFIELD两列来映射),以及传入的F4屏幕字段的值(其他非F4屏幕字段的值不会在这里存储,而是在SHLP-SELOPT存储的)



    2  FIELDDESCR注要描述了Help各参数在命中清单RECORD_TAB-STRING中的偏移量与长度,便于各字段值的读取:



    2  FIELDPROP实质上存储的就是Help参数属性,与Search Help SE11维护界面里的相同



    2  SELOPT存储了选择屏幕与限制对话框屏幕上所有与此Help Link过的字段值,即这些会作为搜索帮助的过滤条件



    l  CALLCONTROL参数

    Callcontrol-step:  该字段的值是由系统设置,并且你可以在程序中进行修改它。出口函数会在处理的每一步(时间点)都会调用一次This field is set by the system and can be changed by your code.  The function module will be called once for each step of the process, with some conditional exceptions noted below.

    1.  SELONE

    Call before selecting an elementary search help. The possible elementary search helps are already in SHLP_TAB. This timepoint can be used in a search help exit of a collective search help to restrict the selection possibilities for the elementary search helps.

    在选择基本元素搜索帮助之前调用。所有基本搜索帮助都已经放在了SHLP_TAB中了。该时间点是用来在集合搜索帮助中限制某些基本搜索帮助是否可选(应该就是在该时间点用来控制某个基本搜索帮助在弹出限制对话框中是否显示出来)

    Entries that are deleted from SHLP_TAB in this step are not offered in the elementary search help selection. If there is only one entry remaining in SHLP_TAB, the dialog box for selecting elementary search helps is skipped. You may not change the next timepoint.

    The timepoint is not accessed again if another elementary search help is to be selected during the dialog.

    2.  PRESEL1

    After selecting an elementary search help. Table INTERFACE has not yet been copied to table SELOPT at this timepoint in the definition of the search help (type SHLP_DESCR_T). This means that you can still influence the attachment of the search help to the screen here. (Table INTERFACE contains the information about how the search help parameters are related to the screen fields).

    在选择一个基本搜索帮助后调用。在该时间点上,SHLP/SHLP_TAB中的表INTERFACE不再复制到表SELOPT,这就意味着你仍然可以在这里影响搜索帮助到屏幕的映射关系(表INTERFACE包含了关于搜索帮助参数到屏幕字段的映射信息)

    3.  PRESEL

    Before sending the dialog box for restricting values. This timepoint is suitable for predefining the value restriction or for completely suppressing or copying the dialog.

    在限制对话框中的条件值发送之前调用。该时间点适合于对预定义值进行控制

    4.  SELECT

    Before selecting the values. If you do not want the default selection, you should copy this timepoint with a search help exit. DISP should be set as the next timepoint.

    选值之前调用(如果有弹出限制对话框,则会在弹出限制对话框中点击确认按钮后调用)。如果你不想使用默认选择,那就应该使搜索帮助退出该时间点,将DISP设置成下一个时间点

    5.  DISP

    Before displaying the hit list. This timepoint is suitable for restricting the values to be displayed, e.g. depending on authorizations.

    在命中清单显示之前调用。该时间用于控制搜索帮助的输出结果。例如,在输出搜索结果时对用户检查权限,删除未授权的数据

    5.         RETURN (usually as return value for the next timepoint一般作为下一个时间点的返回值)

    set by your code if one hit was found during selection

    The RETURN timepoint should be returned as the next step if a single hit was selected in a search help exit.

    如果在一个搜索帮助退出中选择了一个单独命中,那么就将RETURN时间点作为下一步返回

    It can make sense to change the F4 flow at this timepoint if control of the process sequence of the Transaction should depend on the selected value (typical example: setting SET/GET parameters). However, you should note that the process will then depend on whether a value was entered manually or with an input help.

    如果对事务处理序列的控制取决于已选中的值(典型例子:设置SET/GET参量),那么在该时间点上改变F4的流程就是有意义的。然而,应该注意到,该处理将取决于一个值是手工输入的还是用输入帮助输入的。

    7.  RETTOP

    follows RETURN if called from a collective search help

    You only go to this timepoint if the input help is controlled by a collective search help. It directly follows the timepoint RETURN. The search help exit of the collective search help, however, is called at timepoint RETTOP.

    只有当输入帮助由集合搜索帮助控制时,才转到该时间点。它直接跟着时间点RETURN。然而,集合搜索帮助的搜索帮助退出是在时间点RETTOP上调用的。

    8.  EXIT (only for return as next timepoint仅为了下一个时间点的返回)

    set by your code.  Terminates the search help process

    The EXIT timepoint should be returned as the next step if the user had the opportunity to terminate the dialog within the search help exit.

    如果用户有机会在一个搜索帮助退出中终止对话,那么EXIT时间点应作为下一步返回

    9.  CREATE

    The CREATE timepoint is only accessed if the user selects the function "Create new values". This function is only available if field CUSTTAB of the control string CALLCONTROL was given a value not equal to SPACE earlier on.

    仅当用户选择函数“创建新值”时,才访问CREATE时间点。且当赋予控制参数CALLCONTROL所对应的结构体中的字段CUSTTAB为非空值时,该时间点才是有效的。

    The name of the (customizing) table to be maintained is normally entered there. The next step returned after CREATE should be SELECT so that the newly entered value can be selected and then displayed.

    正常的情况下,在那里输入将要维护的表(定制)的名字。CREATE之后,返回的下一步应该是SELECT,这样才能选择新输入的值,并且随后显示。

    10. APP1, APP2, APP3

    If further pushbuttons are introduced in the hit list with function module F4UT_LIST_EXIT, these timepoints are introduced. They are accessed when the user presses the corresponding pushbutton.

    如果带有函数模块F4UT_LIST_EXIT的命中列表包含了更深一层的按钮,那么也会介入这些时间点。当用户单击相应的按钮时,就能访问这些时间点。

     

    :如果F4帮助是一个集合搜索帮助,那么就在时间点SELONE和RETTOP上调用集合搜索帮助的出口。(RETTOP仅当用户选择一个值)。在所有的其也时间点上,调用选择的元素搜索帮助的出口。

    如果F4帮助是一个基本搜索帮助,不执行RETTOP时间点。在时间点SELONE(当时)调用元素搜索帮助的出口,其他准备工作都在时间点PRESEL1上执行

     

    Table中的接口定义:


    l  SHLP_TAB

    Table of elementary search helps

    存储所有的基本搜索帮助,行结构与Changing接口中的SHL结构类似

    l  RECORD_TAB

    用来存储命中清单上将要显示的所有记录数据。另外,在选择命中清单上某条件数据返回时,该内表也会存储被选中记录

    u 出口函数实例1




    下面创建一个与F4IF_SHLP_EXIT_EXAMPLE函数一样的出口函数ZFVBELN_FIND_EXIT:

    FUNCTION zfvbeln_find_exit.
    *"----------------------------------------------------------------------
    *"*"Local Interface:
    *"  TABLES
    *"      SHLP_TAB TYPE  SHLP_DESCT
    *"      RECORD_TAB STRUCTURE  SEAHLPRES
    *"  CHANGING

    *"     VALUE(SHLP) TYPE  SHLP_DESCR
    *"     VALUE(CALLCONTROL) LIKE  DDSHF4CTRL STRUCTURE  DDSHF4CTRL
    *"----------------------------------------------------------------------
      "此内表用于存储命中清单数据.注:字段的名称一定要与搜索参数名一样,但顺序可以不同,
      DATABEGIN OF lt_tab OCCURS 0,
            wbstk TYPE wbstk,
            lfdat TYPE lfdat_v,
            vbeln TYPE vbeln_vl,
        END OF lt_tab.
      "用于存储从选择屏幕上传进的屏幕字段的选择条件值
      DATAr_vbeln TYPE RANGE OF vbeln_vl WITH HEADER LINE,
            r_lfdat TYPE RANGE OF lfdat_v WITH HEADER LINE,
            r_wbstk TYPE RANGE OF wbstk WITH HEADER LINE,
            wa_selopt LIKE LINE OF shlp-selopt."
      "callcontrol-step
    该字段的值是由系统设置,并且你可以在程序中进行修改它。出口函数会在处理的每一步(时间点)都会调用一次
      IF callcontrol-step 'SELECT'."如果有弹出限制对话框,则会在弹出限制对话框中点击确认按钮后step值才为SELECT
        "shlp-selopt存储的是经过映射转换后选择屏幕上字段的值,而不是直接为
        "选择屏幕字段名,而是转映射为Help参数名后再存储到 selopt 内表中,
        "屏幕字段到Help参数映射是通过 shlp-interface 来映射的
        LOOP AT shlp-selopt INTO wa_selopt.
          CASE  wa_selopt-shlpfield.
            WHEN 'VBELN'."由于屏幕字段已映射为了Help相应参数,所以这里不是S_VBELN
              MOVE-CORRESPONDING wa_selopt TO r_vbeln.
              APPEND r_vbeln.
            WHEN 'LFDAT'.
              MOVE-CORRESPONDING wa_selopt TO r_lfdat.
              APPEND r_lfdat.
            WHEN 'WBSTK'.
              MOVE-CORRESPONDING wa_selopt TO r_wbstk.
              APPEND r_wbstk.
          ENDCASE.
        ENDLOOP.
        "根据屏幕上传进的条件查询数据
        SELECT likp~vbeln likp~lfdat vbuk~wbstk INTO CORRESPONDING FIELDS OF TABLE lt_tab
          FROM likp INNER JOIN vbuk ON likp~vbeln vbuk~vbeln
          WHERE likp~vbeln IN r_vbeln AND
                likp~lfdat IN r_lfdat AND
                vbuk~wbstk IN r_wbstk.
        "该函数的作用是将内表 lt_tab 中的数据转换成record_tab,即将某内表中的数据显示在命中清单中
        CALL FUNCTION 'F4UT_RESULTS_MAP'
          TABLES
            shlp_tab    shlp_tab
            record_tab  record_tab
            source_tab  lt_tab
          CHANGING
            shlp        shlp
            callcontrol callcontrol.
        "注:下一个时间点一定要直接设置为 DISP,否则命中清单不会有值,也不显示出来
        "从表面上看,SELECT时间点下一个就是 DISP时间点,按理是不需要设置为DISP,
        "但如果不设置为DISP,出口函数在执行完后,系统会转入DISP时间点执行(即再次调用此出口函数)
        ",但再次进入此出口函数时,record_tab内表已经被清空了(是否可以通过判断callcontrol-step的值来决定走什么新的逻辑代码来解决此问题?)。如果这里直接设置为DISP,就好比欺骗
        "了系统一样,告诉系统当前执行的正是DISP时间点,而不是SELECT,系统就不会再转到 DISP时间点了
        "而是直接显示。还有一个主要的时间点就是:CALLCONTROL-STEP= RETURN
        callcontrol-step = 'DISP'.
      ENDIF.
    ENDFUNCTION.

     

    选择屏幕代码:

    DATAZSTRUCT TYPE ZSTRUCT.
    SELECT-OPTIONS:s_vbeln FOR  ZSTRUCT-vbeln,
                   s_lfdat FOR  ZSTRUCT-lfdat,
                   s_wbstk FOR  ZSTRUCT-wbstk.


    u 实例2:非主键搜索帮助创建删除重复项的方法

    通过se11创建非主键字段的搜索帮助,在命中清单中会出现重复项。这需要在搜索帮助的search help exit里面建一个自建的搜索帮助出口函数在函数中将重复项去掉。具体代码增加地方如下:

    FUNCTION zeh_lxsecond.
       IF callcontrol-step 'DISP'.
        SORT RECORD_TAB.
           DELETE ADJACENT DUPLICATES FROM RECORD_TAB COMPARING ALL FIELDS."zsecond.
        EXIT.
      ENDIF.
    ENDFUNCTION.

    创建集合搜索帮助(Collective Search Help)

    集合搜索帮助可以包含多个基本搜索帮助,但是最好保证所包含的搜索帮助中至少存在一个相同的参数,如前面两节“SE11创建搜索帮助(以视图为数据源),及参数说明”中的ZH_VBELN搜索帮助、“出口函数参数及实例——出口函数实例”中的ZH_VBELN_01搜索帮助,都包含了系统参数VBELN,可以分别参照交货单的送达方查找单号,或者通过交货日期来查找交货单号:



    下面创建一个名为 ZH_VBELN_02 的集合搜索帮助:


    在搜索帮助参数中,这里输入搜索参数一般都来源于包含的所有基本搜索帮助的参数(注:包含进来的这些参数要在基本搜索帮助里要么是IMP参数,要么是EXP参数,否则加进来激活时会报错,比如这里的WBSTK,由于在两个基本搜索帮助中都没有钩选IMPEXP,所以这里不能加进来),这里的 IMP(导入)、EXP(导出)与基本搜索帮助里的IMP EXP作用是一样的,但这里的IMP EXP会覆盖基本搜索中的IMP EXP,输入输出参数以此集合帮助中设置的为准,除开IMPEXP以集合搜索帮助中的为准外,其他的LPosSPosSDis则以各自的基本元素搜索帮助中的设置为准




    然后再将ZH_VBELNZH_VBELN_01两个基本搜索帮助包含进来,并分配参数:



    然后再将集合搜索帮助绑定到自定的结构上面:


    最后在报表程序中Link这个结构:

    DATAzstruct TYPE zstruct.
    SELECT-OPTIONS:s_vbeln FOR  zstruct-vbeln,
                   s_lfdat FOR  zstruct-lfdat,
                   s_kunnr FOR  zstruct-kunnr,
                   s_name1 FOR  zstruct-name1,
                   s_wbstk FOR  zstruct-wbstk.




    注:发现集合搜索帮助在屏幕字段中输入“*”后,发现如果本应该是输出字段的,最后在命中清单中却不是输出字段(背景色不是浅蓝色的了),如果含有“*”还是正常,这是系统的一个bug吗??

    表/结构字段绑定搜索帮助的两种方式

    首先必须要创建一个Search Help,然后将表字段链接到这SH也有两种方法

    1.         直接在SE11的表字段上(这种方式按F4键可能会带出多个值,具体要看SH的参数而定),如图:



    2.         通过数据元素实现Search help,如图:


    Search help绑定方式

    1.    Attaching to Data Elements


    注:绑定的搜索参数MSEHI一定要是输出参数,但可以不是输入参数,所以IMP不必选中,但EXP一定要选中。所以Data Element中绑定的搜索参数可能是搜索帮助的输入参数(屏蔽字段可以传入到搜索帮助),但一定是输出参数

    2.    Attaching to Check Tables

    Check Table即主表,引用此Check Table的表即从表,为某个表字段设置Check Table的过程实质上就是为某个表字段设置外键的过程,所以Check Table与外键是同一概念

    CheckTable(主表)的所有关键字键都会自动的成为搜索帮助的输入输出参数。如果CheckTable有 text Table,则这个text Table的第一个text field 根据用户登录语言也会显示出来

    3.    Attaching to a Table Field or Structure Field

    如果搜索帮助的EXP参数被分配到了表字段,则当用户在命中清单上选择一条数据时,此参数的内容会返回到相应屏幕字段;如果搜索帮助的IMP分配到了表字段,则F4屏幕字段的值会传入到搜索帮助中



    4.    Attaching to Screen Fields

    搜索帮助可以直接绑定到屏幕字段上,在这种情况下,这个搜索帮助只能用在此屏幕中。如果同一个字段在不同的屏幕上使用,则最好将搜索帮助绑定到参照表或结构字段上会共用一些

    可以通过以下几种方式将搜索帮助直接绑定到屏幕字段上:

    l  在屏幕设计界面Screen Painter中的字段属性Search help中设置搜索帮助名称

    l  The name of the search help can be defined for selection screens in ABAP reports in the PARAMETERS or SELECT-OPTIONS statement directly following the supplement AS SEARCH PATTERN.

    l  …MATCHCODE OBJECT search_help… ???

    以上方式都只会将搜索帮助的第一个EXP参数分配到绑定的字段,结果就是命中清单中只有一列值返回到屏幕中



    When you call the input help for a screen field, there is first a check if an input help is defined for the field on the screen. There are three cases here. If there is a programmed help with PROCESS ON VALUE-REQUEST, it is executed. If there is no programmed help, the system tries to call the search help assigned to the field on the screen. If no search help is assigned to the field on the screen, the help defined with FIELD SELECT or FIELD VALUESis offered.

    PROCESS ON VALUE-REQUEST,再MATCHCODE OBJECT,最后FIELD SELECT or FIELD VALUES

    If no input help is defined for the field on the screen, the system tries to call the search help attached to the table field(表字段). If there is no search help here, it tries to display the check table help(检查表). There are two cases here. If a search help is attached to the check table, it is displayed. Otherwise only the key values of the check table are displayed. If there is a text table for the check table, the text for the key value is added in the user’s logon language.

    先看是否绑定了检查表Check Table,再看表字段是否绑定了搜索帮助如果这两种同时出现,则会优先使用Check Table

    If there is no check table for the field, the system tries to call the search help from the data element. If there is no search help for the data element either, existing domain fixed values are displayed. The calendar help and time help are automatically provided for fields with data type DATS and TIMS.

    如果以上都不存在搜索帮助时,则看data element是否绑定了帮助,如果没有,再看domain是否存在fixed values。最后是系统提供的DATS and TIMS类型Help

    SE11测试Search Help


    此种测试方式是在没有写报表程序的情况下,也可以对Help进行测试,不同的是这里的选择屏幕是动态生成的,且模拟的是那种通过表或结构字段绑定的Search Help(非程序绑定),所以通过此种方式模拟具有联动效果(屏幕字段可以传入到搜索帮助中作为过滤条件,从命中清单返回的结果可以自动填充到相应的屏幕字段中)

    通过程序绑定表字段中的搜索帮助、动态生成搜索帮助(绑定到某个内表)并联动

    本实例中,屏幕字段 CARRIER 的Search help是程序在运行时,通过F4IF_FIELD_VALUE_REQUEST(另一个与此函数相似的函数为:F4_FIELD_ON_VALUE_REQUEST——描述:该功能模块完成对于屏幕上的字段,增加F4帮助功能,通过输入的表名、字段名、检索帮助名来绑定,从而获取输入值)函数绑定到一个表字段上(该表字段上已绑定过搜索帮助);下面实例中CONNECT的Search help是通过函数F4IF_INT_TABLE_VALUE_REQUEST绑定到一个内表上实现的。

    在本实例中,CARRIER与 CONNECT具有联带效果,即CONNECT 的命中清单的数据受到 CARRIER 屏幕字段值的约束,二是从CONNECT 的命中清单返回时,会将CONNCT对应的 CARRIER自动填充:


    对话屏幕代码:

    PROCESS BEFORE OUTPUT.
      MODULE init.

    PROCESS AFTER INPUT.
      MODULE cancel AT EXIT-COMMAND.
    PROCESS ON VALUE-REQUEST.
      FIELD carrier MODULE value_carrier.
      FIELD connect MODULE value_connection.

    ABAP程序代码:

    TYPESBEGIN OF values,
        carrid TYPE spfli-carrid,
        connid TYPE spfli-connid,
      END OF values.
    "用来自动接受对话屏幕上传过来的屏幕字段值
    DATAcarrier(3TYPE c,
          connect(4TYPE c.

    DATAprogname LIKE sy-repid ,
          dynnum  LIKE sy-dynnr,
          dynpro_values TYPE TABLE OF dynpread,"所有屏幕字段信息(包括值)
          field_value LIKE LINE OF dynpro_values,
          values_tab TYPE TABLE OF values."4命中清单数据

    "调用对话屏幕
    CALL SCREEN 200.

    MODULE init OUTPUT.
      progname sy-repid.
      dynnum  sy-dynnr.
    ENDMODULE.                    "init OUTPUT

    "对话屏幕中CARRIER屏幕字段的Search Help实现
    MODULE value_carrier INPUT.
      DATA:return_tab  TYPE TABLE OF ddshretval WITH HEADER LINE.
      "F4IF_FIELD_VALUE_REQUEST函数的作用是在运行时,可以动态的为某个屏幕字段
      "设置Search Help,这个被引用的Help来自某个表(或结构)字段上绑定的Help。
      "该函数实质上就是在运行时调用某个Search Help,直到用户从命中清单上选中某
      "条件记录(之前一直会阻塞),才会去执行后面的代码
      CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST'
        EXPORTING  "将对话屏幕中的CARRIER字段的Search Help设置成 DEMOF4HELP 表中的CARRIER1
                  "字段上所绑定的Search Help
          tabname     'DEMOF4HELP'"搜索帮助来自于哪个表
          fieldname   'CARRIER1'"搜索帮助来自于哪个表的哪表字段
    SEARCHHELP='DEMO_F4_DE'"明确帮助具体来自于表字段DEMOF4HELP-CARRIER1上的DEMO_F4_DE帮助(可省略此参数)
            SHLPPARAM = 'CARRID'"指定搜索帮助(DEMO_F4_DE)中的哪个参数(CARRID)绑定到屏幕字段(CARRIER)上如果不指定,则默认将搜索帮助中的第一个参数(CARRID)绑定到屏幕字段(CARRIER)上
         " DEMOF4HELP-CARRIER1上绑定的搜索帮助DEMO_F4_DE的CARRID参数绑定到CARRIER 屏幕字段上
          dynpprog    progname
          dynpnr      dynnum
          dynprofield 'CARRIER'
    VALUE=''"用来指定F4屏幕字段(CARRID)的值,如果该值包含了通配符* 将会传入到搜索帮助里作为搜索帮助的过滤条件,一般情况下,不用设置此值,因为如果 DYNPPROG, DYNPNR, STEPL 这些参数可用的情况,会自动去获取相应屏幕字段的值
    MULTIPLE_CHOICE = 'X'"命中清单中的记录是否可以多选,即命中清单中记录前是否有复选框
    SELECTION_SCREEN =''"是否使用屏幕字段CARRIER所参照的Domain中设置的 value table
        TABLES
          return_tab  return_tab."用来接收从命中清单上选中并返回的记录

      """"将用户从命中清单中选中的记录填充到对话屏幕相应的字段中(注:下面更新屏幕字段的代码应该也可以由F4IF_FIELD_VALUE_REQUEST函数的回调接口CALLBACK_FORM来代替,当然没有连带效果,所以不需要采用此方式
      CLEARfield_valuedynpro_values[].
      "填充对话屏幕中的CARRIER屏幕字段
      "field_value-fieldname = 'CARRIER'.
      "field_value-fieldvalue =  return_tab-fieldval.
      "APPEND field_value TO dynpro_values.

    "由于carrier屏幕字段本身此时为F4字段,所以可以直接赋值就可以更新屏幕中的值,所以可以不用使用 DYNP_VALUES_UPDATE 函数的方式来更新,但下面的CONNECT屏幕字段就不可以采用这种直接赋值方式来更新屏幕中的值,因为它是非F4字段
    carrier = return_tab-fieldval.

      "清空对话屏幕上的connect屏幕字段(因为CARRIER与CONNECT为主从关系,当主发生变化后,原来的子肯定会失败,所以要重新清空)
      field_value-fieldname 'CONNECT'.
      field_value-fieldvalue =  ''.
      APPEND field_value TO dynpro_values.

      """"更新对话屏幕上相应的屏幕字段的值(CARRIER与CONNECT)
      CALL FUNCTION 'DYNP_VALUES_UPDATE'
        EXPORTING
          dyname     progname
          dynumb     dynnum
        TABLES
          dynpfields dynpro_values.
    ENDMODULE.                     

    "对话屏幕中CONNECT屏幕字段的Search Help实现
    MODULE value_connection INPUT.
      CLEARfield_valuedynpro_values[].
      field_value-fieldname 'CARRIER'.
      APPEND field_value TO dynpro_values.
      field_value-fieldname 'CONNECT'.
      APPEND field_value TO dynpro_values.
      "POV事件中,屏幕上的字段的值不像PAI里那样可以直接读取到,所以使用这个函数来读取
      "Read screen field values before PAI field transport
      CALL FUNCTION 'DYNP_VALUES_READ'
        EXPORTING
          dyname             progname
          dynumb             dynnum
          translate_to_upper 'X'
        TABLES      "需要读取哪几个屏幕字段的值?并且还是通过该内表返回
          dynpfields         dynpro_values."存储读取到的屏幕字段值

      READ TABLE dynpro_values  INTO field_value WITH KEY fieldname 'CONNECT'.
      connect field_value-fieldvalue.
      "读取屏幕字段CARRIER中所输入的值
      READ TABLE dynpro_values  INTO field_value WITH KEY fieldname 'CARRIER'.
      carrier field_value-fieldvalue.

      IF  field_value-fieldvalue IS NOT INITIAL.
        "联动查询: connect屏幕字段的值受carrier屏幕字段值的约束
        "注:实际上这里可以不用屏幕上传进来的carrier屏幕条件值,而直接像ELSE语句那
        "样查询出所有数据,因为这里查询出来的数据(values_tab)不是命中清单中最终
        "要显示的数据,当下面在调用 F4IF_INT_TABLE_VALUE_REQUEST 函数的过程中,会对
        "传进的values_tab根据屏幕上输入的条件值做进一步的数据过滤(根据屏幕上哪些字段
        "来过滤,是在 f4callback Form中指定)。所以可以在这里不用数据过滤,而只是
        "将过滤条件在 f4callback Form中指定一下,由Search help在显示命中清单之前自己过滤即可
        SELECT carrid connid FROM spfli
           INTO CORRESPONDING FIELDS OF TABLE values_tab
           WHERE carrid field_value-fieldvalue.
      ELSE."如果CARRIER屏幕字段没有输入内容,则不使用联动查询,此时查询所有
        SELECT carrid connid FROM spfli
          INTO CORRESPONDING FIELDS OF TABLE values_tab.
      ENDIF.

      CLEARreturn_tab[].
      "在程序运行时,将某个内表动态的用作Search help的数据来源,即使用该函数
      "可以将某个内表转换为Search help。注:调用该函数与调用 F4IF_FIELD_VALUE_REQUEST
      "一样会阻塞,直到用户在命中清单上选中某条记录返回之后,再会继续执行后面的代码
      CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
        EXPORTING "如果 values_tab 是一个全局的数据词典类型,如 MARA 表名就可以用在这里,
                   "此时在回调F4CALLBACK中使用到字段名称(F001、F002等)的地方就可以直接使用该数据
                   "词典中的字段名称;如果 values_tab 不是全局的(比如这里定义的 values_tab是局部的),
                   "所以不能使用,此时在回调F4CALLBACK中要使用字段的名称的地方只能使用形如:F0001、F0002
    *     DDIC_STRUCTURE   = 'itab'
                  "下面三个参数是将动态生成的Search help 绑定到哪个程序的哪个屏幕号中的哪个屏幕字段上面
          dynpprog         progname
          dynpnr           dynnum
          dynprofield      'CONNECT'
                  "命中清单(values_tab)中的哪列(CONNID)的值回填到屏幕字段CONNECT中
          retfield         'CONNID'
                  "Value return: C: cell by cell, S: structured 返回值形式?
          value_org        'S'"这里一定要是 S,否则没有值
          callback_program sy-repid
          callback_form    'F4CALLBACK'"Form会在F4IF_INT_TABLE_VALUE_REQUEST调用后立即执行
                    "通过调试观察callcontrol-step为空,所以应该是在调用Search help的出口函数
    "F4IF_SHLP_EXIT_EXAMPLE处理之前就调用了。官方解释called immediately before 
    "calling the F4 processor

          window_title     'Title for the hit list'"命中清单的窗口的标题
        TABLES
          value_tab        values_tab"Search help命中清单的数据就来源于此内表
          return_tab       return_tab."接收从命中清单中用户选中的记录
    ENDMODULE.                    "value_connection INPUT
    "实际上F4IF_FIELD_VALUE_REQUEST函数也有这样的回调接口
    FORM f4callback TABLES record_tab STRUCTURE seahlpres
                    CHANGING shlp TYPE shlp_descr
                             callcontrol LIKE ddshf4ctrl.
      "****除了将CONNECT填充到屏幕,carrier也需要
      DATAinterface LIKE LINE OF shlp-interface.
      READ TABLE shlp-interface INTO interface INDEX 1.
      "F001 F002为动态生成的Search help的参数,且F002已经映射到了屏幕字段CONNECT
      "(在调用F4IF_INT_TABLE_VALUE_REQUEST过程通过参数已指明),除了CONNECT本身
      "F4字段回填到屏幕中,屏幕字段CARRIER也要需要能够自动从命中清单中自动填充,这
      "就需要屏幕字段CARRIER与Search help的F001参数作一个映射关系,这个映射关系就是
      "在这里指明的
      interface-shlpfield 'F0001'.
      interface-valfield 'CARRIER'.
      interface-value =  carrier."CARRIER屏幕字段中传过来的值,
      interface-f4field ''."CARRIER屏幕字段不是F4字段
      APPEND interface TO shlp-interface.
    ENDFORM.                

    通过TR_F4_HELP实现简单Search Help(数据来源于内表)

    P_LGOR屏幕字段的F4搜索帮助的最后整体效果如下:


    在该实例中,屏幕字段P_WERKS参照的Data Elementwerks_d绑定了一个搜索帮助:H_T001W_C,但这个帮助是Collective srch hlp类型的帮助:



    并且H_T001W_T还是一个Append search help,它又包含H_T001W


    H_T001W才是最终的基本元素搜索帮助:


    P_WERKS屏幕字段上按F4键,弹出的搜索帮助效果如下(可以看出弹出的限制对话框中的屏幕字段都是由H_T001W基本元素帮助的SPos一起决定的):


    PARAMETERSp_werks TYPE werks_d 
    p_lgort TYPE lgort_d.

    AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_lgort.
      DATAl_index LIKE sy-index,
            l_lines LIKE sy-index.
      "命中清单表格的列标题
      DATABEGIN OF ls_title,
             t1(4),
             t2(4),
             t3(40),
       END OF ls_title.

      ls_title-t1 '库位'.
      ls_title-t2 '工厂'.
      ls_title-t3 '库位描述'.

      DATABEGIN OF gt_itab OCCURS 10,"命中清单
         lgort(4),
         werks(4),
         lgobe(40),
       END OF gt_itab.

      DATAdynpfields LIKE dynpread OCCURS 10 WITH HEADER LINE .
      dynpfields-fieldname 'P_WERKS'.
      APPEND dynpfields.
      "Read screen field values before PAI field transport
      "POV事件中,屏幕上的字段的值不像PAI里那样可以直接读取到,所以使用这个函数来读取
      CALL FUNCTION 'DYNP_VALUES_READ'
        EXPORTING
          dyname     sy-repid"当前程序名
          dynumb     sy-dynnr"当前屏幕号
        TABLES
          dynpfields dynpfields.

      DATAg_werks(4).
      READ TABLE dynpfields WITH KEY fieldname 'P_WERKS'.
      g_werks dynpfields-fieldvalue.

      SELECT werks lgort lgobe INTO CORRESPONDING FIELDS OF TABLE gt_itab FROM t001l.
      "由于屏幕上的g_werks可能没有输入,所以不能直接使用在上面的SQL中,而是先查出所有再删除
      IF g_werks NE space.
        DELETE gt_itab WHERE werks <> g_werks.
      ENDIF.

      "General F4 help (with single/multiple selection)
      "通过TR_F4_HELP函数实质简单的F4 Help(并可以单选与多选)
      CALL FUNCTION 'TR_F4_HELP'
        EXPORTING
          iv_title              'Pls select one line'
          is_sel_title1         ls_title
          iv_number_of_rows     20
          iv_no_of_key_columns  1
          iv_width_of_titles    'X'
          iv_multiple_selection 'X'
          iv_with_sort_icon     'X'
          iv_with_printer_icon  'X'
          iv_with_filter_icon   'X'
          iv_with_search_icon   'X'
          iv_show_also_1        'X'
        TABLES
          it_sel_table          gt_itab
        CHANGING
          cv_selected_index     l_index"命中清单中用户选择并返回的记录索引
        EXCEPTIONS
          no_lines              1
          no_line_picked        2.

      "如果用户选择了数据
      IF sy-subrc 0.
        READ TABLE gt_itab INDEX l_index."读取用户选中的命中清单中的记录

        "由于P_LGORT本身就是F4字段,所以可用不用DYNP_VALUES_UPDATE函数
        "就可以直接更新屏幕就的字段,但 P_WERKS 必须使用此函数来更新
        ",而不能像P_LGORT屏幕字段那样直接赋值进行更新
        "dynpfields-fieldname = 'P_LGORT'.
        "dynpfields-fieldvalue =  gt_itab-lgort.
        "APPEND dynpfields .

        "由于P_LGORT是F4字段,所以可以直接采用赋值方式就可以更新
        p_lgort gt_itab-lgort.

        "但P_WERKS非F4字段,所以不能直接采用上面赋值方式来更新,要使用DYNP_VALUES_UPDATE函数
        dynpfields-fieldname 'P_WERKS'.
        dynpfields-fieldvalue =  gt_itab-werks.
        APPEND dynpfields .

        CALL FUNCTION 'DYNP_VALUES_UPDATE'
          EXPORTING
            dyname     sy-repid
            dynumb     sy-dynnr
          TABLES
            dynpfields dynpfields.
      ENDIF.

    Search Help三种不同绑定方(表字段、Check Table、Struct)式实现同样效果

    1.     通过表字段绑定Help

    此种方式需要使用SE11创建Search Help,然后将Search Help绑定到某表字段上,并将其他Search Help的参数也分配到其它表字段上


    下图中将Search Help参数分配给表字段:




    TABLES:zsflight.
    SELECT-OPTIONS:so_carr FOR zsflight-carrid,"  MATCHCODE OBJECT ZH_SCARR,"航线代码
                   so_conn 
    FOR zsflight-connid,"  MATCHCODE OBJECT ZH_SPFLI."航班代码
                   so_from 
    for zsflight-CITYFROM.
    起飞城市



    只要在上图中的命中清单中选择一数据后,会将选中记录的相应列自动填充相应屏幕字段(Help参数里打上钩的EXP——如果EXP列没有打钩,就不会自动填充到相应字段中?且这些列所分配的表字段在程序中被Link到屏幕字段),达到联动效果(搜索与返回都会产生联动:搜索SO_CONN时,会将SO_CARR与SO_FROM屏幕字段一起传入到搜索帮助里,并且从命中清单返回到屏幕时,SO_CARR与SO_FROM屏幕字段也会使用选中命中清单的相应列来自动填充)

    2.     通过Check Table实现Search Help

    此种方式不需要使用SE11来创建真正的Search Help,只需要为相应的表字段指定外键,则会自动为此表字段设置Check Table,一旦表字段有Check Table后,不需为该表字段绑定Search Help,所有Link具有Check Table约束的表字段屏幕字段时都会自动拥有Search Help。

    Check Table实质上就是一种给从表字段设置外键的过程,Search Help的数据来源于主表。

    还是以上面创建的表为例,来通过设置Check Table来达到实现Search Help的目的:ZSFLIGHT表中的主键有三个字段:MANDT、CARRID、CONNID,其中MANDT已经设置了Check Table T000,下面为CARRID、CONNID两个字段设置Check Table:


    设置Check Table后,表的相关信息如下:


    同样的屏幕代码,只不过此时屏幕字段的Search Help是由Check Table(主表)来实现的:

    TABLES:zsflight.
    SELECT-OPTIONS:so_carr FOR zsflight-carrid,"  MATCHCODE OBJECT ZH_SCARR,"航线代码
                   so_conn FOR zsflight-connid,"  MATCHCODE OBJECT ZH_SPFLI."航班代码
                   so_from for zsflight-CITYFROM.起飞城市

    与上面第一种方式不同的是,由于ZSFLIGHT的CITYFROM不是外键(未设置Check Table),所以表字段ZSFLIGHT-CITYFROM Link选择屏幕字段SO_FROM的值不会传到Search Help中,从命中清单返回时也不会自动填充该屏幕字段:


    另外,使用Check Table实现Search Table时,好像对限制框是否弹出来不能进行设置?

    3.     绑定到结构字段

    此种方式只是将第一种方式的表换成了结构,在程序中Link此结构就可以了,其绑定帮助的过程与表字段是一样的。


    DATAzstruct TYPE zstruct.
    SELECT-OPTIONS:so_carr FOR zstruct-carrid,"  MATCHCODE OBJECT ZH_SCARR,"航线代码
                   so_conn 
    FOR zstruct-connid,"  MATCHCODE OBJECT ZH_SPFLI,"航班代码
                   so_from 
    FOR zstruct-cityfrom."
    起飞城市


    此种设计方式与第一种效果完全一样,不会像第二种Check Table那样,屏幕字段SO_FROM也会传入。

     

    其实,除了上面三种方式后,结构实质上也可以设置Check Table,所以与上面第二种方式一样,也可以实质Search Help。

     

     

     

    动态修改屏幕

    与选择屏幕一样,对话屏幕也有对应的SCREEN内表(下面这些属性是可以动态修改的):

    Component

    Length

    Type

    Description

    Attribute(Screen Painter中对应的静态属性)

    NAME

    30

    C

    Name of the screen field

    如果参数是select-options类型参数,则参数名以LOW与HIGH后缀来区分。

    TABLESmara.
    DATAitab TYPE STANDARD TABLE OF string WITH HEADER LINE.
    SELECT-OPTIONSs_exmp FOR mara-matnr.
    AT SELECTION-SCREEN OUTPUT.
      LOOP AT SCREEN.
        APPEND screen-name TO itab.
      ENDLOOP.
    START-OF-SELECTION.
      LOOP AT itab.
        WRITE/ itab.
      ENDLOOP.

    image153[4]

    Name

    GROUP1

    3

    C

    Modificationgroup1

    Group1

    GROUP2

    3

    C

    Modificationgroup2

    Group2

    GROUP3

    3

    C

    Modificationgroup3

    Group3

    GROUP4

    3

    C

    Modificationgroup4

    Group4

    REQUIRED

    1

    C

    Fieldinputis mandatory必输入

    该选项可以解决这个问题:在钩选某个复选框后显示某个必输字段,但当这个必输框显示出来后,如果去掉钩时想隐藏时,此时输入框中必须有值,否则钩去掉了,但该输入框还是没有被隐藏。解决的办法是:将输入框的这个属性设置为2,去掉OBLIGATORY选项(不去掉也会被忽略),并在AT SELECTION-SCREEN ON field事件里时进行为空验证

     

    取值为 0:不必输,框中前面也没有钩

           1:必输,框中前面有钩

           2:不必输,但框中前面有钩,此时需要手动检验

    image154[4]

    REPORT  zjzjtest.
    PARAMETERS p_rd1 RADIOBUTTON GROUP gp1 USER-COMMAND mxx.
    PARAMETERS p_rd2 RADIOBUTTON GROUP gp1.
    PARAMETERS p_lclfil(128MODIF ID mxy.

    AT SELECTION-SCREEN OUTPUT.
      LOOP AT SCREEN.
       IFp_rd2 'X' AND screen-group1 'MXY'.
          screen-active '1'.
          screen-required '2'.
          MODIFY SCREEN.
        ELSEIF screen-group1 'MXY'.
          screen-active '0'.
          screen-required '2'.
          MODIFY SCREEN.
        ENDIF.
      ENDLOOP.

      AT SELECTION-SCREEN ON p_lclfil.
      IF p_rd2 IS NOT INITIAL
        AND sy-ucomm <> 'MXX'
        AND p_lclfil IS INITIAL.
        MESSAGE e055(00).
      ENDIF.

    Mandatoryfield

    INPUT

    1

    C

    Fieldis readyfor input可输入

    通过此属性可以控制输入框的可输入性。

    复选框是否可输入可以参考这里 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)

    如果是复选框(Check Box)与单选按钮(Radio Button),则当此属性设置为0时,则不可输入,并且会变灰(前提是要静态属性INVisible没有设置),这与输入框不太一样(输入在不能输入的情况下也不会变灰)

    image155[4]

    选中not possible时,表示只显示,不能输入:
    image156[4]

    possible与recommended都是可选,但不区别是什么??

    required选项:表示必输入字段

    Input

    image157[4]

    OUTPUT

    1

    C

    Fieldis for displayonly仅显示,不输入输入。当选中此静态属性后,Input Field清除选中且置灰不能再选择

    Output

    INTENSIFIED

    1

    C

    Fieldis highlighted高亮度显示字段

    input类型的fields(可输入字段)中的内容会从黑色变为红色,

    output类型的fields(不可输入字段)中的内容会从黑色变为蓝色

    bright

    INVISIBLE

    1

    C

    Fieldis suppresse字段内容不可见,不单指隐藏整个输入字段(如screen-Input=0,screen-Invisible=1时,整个字段会被隐藏,但如果只有screen-Invisible=1,只输入字段本身不会被隐藏,而只是输入框中的内容被显示为******)

    image158[4]

    Invisible

     

    LENGTH

    1

    X

    Fieldlength

    可以对input/outputfields或者是 Outputonlyfields进行设置,其值不能大于Screen Painter里静态设置的显示长度的值

    VisLg

    ACTIVE

    1

    C

    Fieldis active激(字段可见并用于输入)

    Input/Output/Invisible(三个静态属性都设置时才相当于ACTIVE)

    DISPLAY_3D

    1

    C

    Three-dimensional box

    输入框四周会有线框,否则没有

    Two-dimensional

    VALUE_HELP

    1

    C

    Inputhelpbuttondisplay激活输入帮助

    Inputhelp

    REQUEST

    1

    C

    Inputexists

    默认为0,如果设置为1,则作用好比修改了屏幕字段内容,这时会执行PAI块里的ON REQUEST或者ONCHAIN-REQUEST的模块调用,而不管是屏幕字段的内容是否真正的改变了

    -

    最后一列(Attribute)表示屏幕字段在Screen Painter中所对应的各自静态属性。上面动态属性除了LENGTH属性之外,设置为1表示激活该动态属性,0表示去激活该动态属性

    Screen Painter里的静态属性Output Only在上表SCREEN内表中没有对应的动态属性,所以该属性不能动态的修改


    Output Only:表示屏幕字段只能显示,不能被修改

     

    你可以在PBO中通过如下代码进行属性修改:

    AT SELECTION-SCREEN OUTPUT.

    LOOP AT SCREEN.
      ...
      MODIFY SCREEN.
      ... 
    ENDLOOP.

    若已经在Screen Painter 中静态地将一个屏幕字段设置为不可见的,则要想在程序中将其修改成可见,不能使用语句SCREEN-ACTIVE = 1,而应该使用SCREEN-INVISIBLE = 0;但如一个屏幕字段在Screen Painter中被静态地设置为可见的,则可以通过语句SCREEN-ACTIVE = 0将其设置为不可见,此语句相当于下面三个语句的组合使用:

    SCREEN-INVISIBLE = 1、SCREEN-INPUT = 0、SCREEN-OUTPUT = 0

     

    在PBO开始时ACTIVE通常为1,除非设置了这样的静态属性:INPUT = 0, OUTPUT = 0, and INVISIBLE = 1,则ACTIVE会自动设为0。另外,如果设置动态属性INPUT = 0, OUTPUT = 0, and INVISIBLE = 1,则此时ACTIVE 相当于 0(其实则此时ACTIVE设置任何值都会被忽略,即使设置为1也不会有效果)。ACTIVE属性的唯一目的是,让你能够通过一个单独的属性就能将屏幕字段inactive掉。

    在ACTIVE, INPUT, OUTPUT, 与INVISIBLE动态属性之间存在着一种特定优先规则,它们还有受屏幕字段的静态属性所影响,但ACTIVE动态属性在Screen Painter中没有与之对应的静态属性。不同组合设置效果如下:

    ACTIVE

    INPUT

    OUTPUT

    INVISIBLE

    Effect

    1

    1

    1

    0

    屏幕字段会显示,即使静态属性Invisible被设置

    屏幕字段的内容会显示

    屏幕字段可以输入,即使静态属性Input未被设置。但是,如果静态属性Outputonly被设置后,屏幕字段将不能输入。

    1

    1

    0

    0

    屏幕字段会显示,即使静态属性Invisible被设置,但不能设置静态属性Outputonly。

    屏幕字段的内容不显示

    屏幕字段可以输入,即使静态属性Input未被设置。

    1

    0

    1

    0

    屏幕字段会显示,即使静态属性Invisible被设置

    屏幕字段的内容会显示

    屏幕字段不能输入,即使设置了Input静态属性

    1

    0

    0

    0

     

    屏幕字段会显示,即使静态属性Invisible被设置,但不能设置静态属性Outputonly。

    屏幕字段的内容不显示

    屏幕字段不能输入,即使设置了静态属性Input

    1

    1

    1

    1

    屏幕字段会显示,即使静态属性Invisible被设置,但不能设置静态属性Outputonly。

    屏幕字段的内容显示为*星号

    屏幕字段可以输入,即使静态属性Input未被设置。但输入的内容会替换为*星号

    1

    1

    0

    1

    屏幕字段会显示,即使静态属性Invisible被设置,但不能设置静态属性Outputonly。

    屏幕字段的内容显示为*星号

    屏幕字段可以输入,即使静态属性Input未被设置。但输入的内容会替换为*星号

    1

    0

    1

    1

    屏幕字段去激活

    屏幕字段不显示,不管你设置何种静态属性

    0

    0

    0

    1

    屏幕字段去激活

    屏幕字段不显示,不管你设置何种静态属性

    如果设置了静态属性 Output only,则会忽略动态属性INPUT、OUTPUT的设置。

     

    具体实例请参考:DEMO_DYNPRO_MODIFY_SCREEN,下面是这个示例程序0100屏幕中6个输入框在Screen Painter中INPUT、OUTPUT   、OUTPUT ONLY、INVISIBLE静态属性的初始值:





    REPORT DEMO_DYNPRO_MODIFY_SCREEN .

    "定义选择屏幕,下面定义的10屏幕字段的属性对应于上面表格后面10动态属性
    SELECTION-SCREEN BEGIN OF SCREEN 1100.
    SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME NO INTERVALS.
    PARAMETERSact AS CHECKBOX DEFAULT '1',"ACTIVE
                inp AS CHECKBOX DEFAULT '1',"INPUT
                out AS CHECKBOX DEFAULT '1',"OUTPUT
                inv AS CHECKBOX DEFAULT '0'."INVISIBLE
    SELECTION-SCREEN END OF BLOCK b1.

    SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME NO INTERVALS.
    PARAMETERSreq AS CHECKBOX DEFAULT '0',"REQUIRED
                d3d AS CHECKBOX DEFAULT '1',                    "DISPLAY_3D
                hlp AS CHECKBOX DEFAULT '0',"VALUE_HELP
                int AS CHECKBOX DEFAULT '0'."INTENSIFIED
    SELECTION-SCREEN END OF BLOCK b2.

    SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME NO INTERVALS.
    PARAMETERS rqs AS CHECKBOX DEFAULT '0'."REQUEST
    SELECTION-SCREEN END OF BLOCK b3.

    SELECTION-SCREEN BEGIN OF BLOCK b4 WITH FRAME NO INTERVALS.
    PARAMETERS  len TYPE i DEFAULT 10.
    SELECTION-SCREEN END OF BLOCK b4."LENGTH
    SELECTION-SCREEN END OF SCREEN 1100.


    DATAfield1(10TYPE c,
          field2(10TYPE c,
          field3(10TYPE c,
          field4(10TYPE c,
          field5(10TYPE c,
          field6(10TYPE c.
    DATAok_code TYPE sy-ucomm,
          save_ok TYPE sy-ucomm.
    DATAitab LIKE TABLE OF screen WITH HEADER LINE.
    DATA length(2TYPE c.
    field1 field2 field3  '0123456789'.

    CALL SCREEN 100.
    MODULE status_0100 OUTPUT.
      CLEARitabitab[].
      SET PF-STATUS 'SCREEN_100'.
      "如果不是点击MODIFY,则屏幕元素会使用Screen Painter中设置的静态属性来初始化屏幕
      ",实际上管是第几次调用PBO,每次调用时SCREE内表的状态都会与Screen Painter中设置的静
      "态属性是一致的,所以只要执行PBO,如果不修改SCREEN内表,则屏幕就会以Screen Painter
      "中的静态属性来显示,所以为什么在点击 List 按钮并关掉弹出的对话框后,主屏幕又恢
      "复到最初的状态。同样,Undo 按钮也是如此,因为点击了Undo按钮与关闭List弹出对话
      "框后都调用了这个PBO,但又没有修改SCREEN,所以主屏幕恢复到了最初状态
      "
      IF save_ok 'MODIFY'.
        itab-name 'PBO:'.
        APPEND itab.
        LOOP AT SCREEN.
          IF screen-group1 'MOD'.
            "将屏幕字段的静态属性状态都存储起来,因为只要开始了PBO,则SCREEN就会与
            "Screen Painter中设置的静态属性保持一致,除非在PBO中进行了修改
            MOVE-CORRESPONDING screen TO itab.
            APPEND itab.
          ENDIF.
        ENDLOOP.

        "为了选择屏幕1100能正确显示出当前属性状态,需要将内部状态(0、1只适于
        "用屏幕字段动态属性设置)转换为复选择框能识别的状态值(0->空格、1->X)
        PERFORM change_input CHANGING:
                actinpoutinvreqintd3dhlprqs.
        "弹出屏幕字段属性修改选择屏幕,各复选框中的值
        CALL SELECTION-SCREEN 1100 STARTING AT 37 5.
        "将用户输入的复选框的值(空格、X)转换为屏幕字段属性值(空格->0、X->1)
        "这样在下面就可以通过SCREEN内表来修改屏幕字段的状态了
        PERFORM change_input CHANGING:
                actinpoutinvreqintd3dhlprqs.
        MESSAGE s888(sabapdocuWITH act inp out inv."& & & &
        CLEAR itab.
        APPEND itab.
        LOOP AT SCREEN.
          IF screen-group1      'MOD'.
            screen-active      act.
            screen-input       inp.
            screen-output      out.
            screen-invisible   inv.
            screen-required    req.
            screen-intensified int.
            screen-display_3d  d3d.
            screen-value_help  hlp.
            screen-request     rqs.
            screen-length      len.
            MODIFY SCREEN.
          ENDIF.
        ENDLOOP.
        CLEAR itab.
        itab-name        'Entry:'.
        itab-active      act.
        itab-input       inp.
        itab-output      out.
        itab-invisible   inv.
        itab-required    req.
        itab-intensified int.
        itab-display_3d  d3d.
        itab-value_help  hlp.
        itab-request     rqs.
        itab-length      len.
        APPEND itab.
        CLEAR  itab.
        APPEND itab.
      ENDIF.
    ENDMODULE.
    MODULE cancel INPUT.
      LEAVE PROGRAM.
    ENDMODULE.
    MODULE user_command_0100 INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      CASE save_ok.
        WHEN 'MODIFY'.
          "离开当前屏幕并跳转到 100屏幕,这里可以省略,
          "因为100屏幕的下一屏幕静态属性设置的就是100
    *      LEAVE TO SCREEN 100.
        WHEN 'LIST'.
          CLEAR itab.
          itab-name 'PAI:'.
          APPEND itab.
          LOOP AT SCREEN.
            IF screen-group1 'MOD'.
              MOVE-CORRESPONDING screen TO itab.
              APPEND itab.
            ENDIF.
          ENDLOOP.
          CALL SCREEN 200 STARTING AT 37 5
                          ENDING   AT 87 22.
    *            CALL SCREEN 200 .
      ENDCASE.
    ENDMODULE.
    MODULE requested INPUT.
      MESSAGE s888(sabapdocuWITH 'MODULE ... ON REQUEST called'.
    ENDMODULE.         
    MODULE status_0200 OUTPUT.
      SET PF-STATUS 'SCREEN_200'.
      "让当前屏幕(200屏幕)不弹出来。该语句作用是:如果该语句用在PBO中,当前屏幕不会显示,
      "但会继续后续的PBO处理,且前一屏幕还会继续保持显示。该语句不能使用在PBO之外的块处理中。该语句的一般是与LEAVE TO LIST-PROCESSING一起使用,当使用LEAVE TO LIST-PROCESSING之后,控制权从屏幕转向了输出列表,所有的Write输出结果都会写到输出列表中(否则这些Write语句会输入到对话屏幕中),如果此时不想显示屏幕200,则可以使用此语句来过路此屏幕,当然这可以使用LEAVE SCREEN.语句来代替此语句,但LEAVE SCREEN需要放在PBO的最后面(因为LEAVE SCREEN后面的语句是不会再执行的),但SUPPRESS DIALOG可以放在PBO中的任何位置
    "注:如果在被压制的屏幕的PAI事件中弹出了任何类型的消息,则被压制的屏幕还是会显示出来。
      SUPPRESS DIALOG.
    "LEAVE SCREEN.
    离开当前屏幕跳转到当前屏幕的下一屏幕,注:如果全要使用此语句代替SUPPRESS DIALOG,则要放Module的最后面
      "LEAVE TO LIST-PROCESSING将控制权从对话屏幕转向输出列表处理器LISTPROCESSING,让当前屏幕的PBO与PAI中的Write输出语句将结果都输出到该输出列表List屏幕之上
      "离开这里(200屏幕)并到达(TO)列表处理,并且(AND)设置其nextscreen 为0,即关闭List时,会结束输出列表屏幕并返回到该屏幕序列最开始调用处主屏幕100(如果未使用RETUN选项,则点击List标准工具栏上的Back按钮时,会返回到当前屏200所设置的下一屏幕——静态属性设定与动态指定都可)
      "该语句不会挂起当前屏幕的PBO处理,执行后会立即继续执行后续语句,这与LEAVE TO SCREEN XXX是不同的
      LEAVE TO LIST-PROCESSING AND RETURN TO SCREEN 0.
      FORMAT COLOR COL_HEADING ON.
      WRITE10 'ACT'14 'INP'18 'OUT'22 'INV'26 'REQ',
             30 'INT'34 'D3D'38 'HLP'42 'RQS'46 'LEN'.
      FORMAT COLOR COL_HEADING OFF.
      ULINE.
      LOOP AT itab.
        IF itab-name ' '.
          ULINE.
        ELSEIF itab-name 'PBO:' OR itab-name 'PAI:'.
          FORMAT COLOR COL_NORMAL ON.
        ELSE.
          FORMAT COLOR COL_NORMAL OFF.
        ENDIF.
        len itab-length.
        length ' '.
        IF len NE 0.
          length len.
        ENDIF.
        WRITE/(8itab-name,
                 11 itab-active,
                 15 itab-input,
                 19 itab-output,
                 23 itab-invisible,
                 27 itab-required,
                 31 itab-intensified,
                 35 itab-display_3d,
                 39 itab-value_help,
                 43 itab-request,
                 47 length.
      ENDLOOP.
    ENDMODULE.    
    FORM change_input CHANGING val TYPE any.
      IF val 'X'.
        val '1'.
      ELSEIF val ' '.
        val '0'.
      ELSEIF val '1'.
        val 'X'.
      ELSEIF val '0'.
        val ' '.
      ENDIF.
    ENDFORM.   
    module USER_COMMAND_0200 input.
      save_ok ok_code.
      CLEAR ok_code.
    endmodule.  

    复合屏幕元素


    图标Status Icons(ICON_CREATE)

    可以使用ICON_CREATE函数来为Status Field image165[4]生成符合某种格式的Icon信息串(选择屏幕上带图标按钮实例请参考这里):



    REPORT DEMO_DYNPRO_STATUS_ICONS.

    DATA value TYPE i VALUE 1.
    DATAstatus_icon TYPE icons-text,
          icon_name(20),
          icon_text(10).
    CALL SCREEN 100.
    MODULE set_icon OUTPUT.
      CASE value.
        WHEN 1.
          icon_name 'ICON_GREEN_LIGHT'.
          icon_text =  'Low'.
        WHEN 2.
          icon_name 'ICON_YELLOW_LIGHT'.
          icon_text 'Middle'.
        WHEN 3.
          icon_name 'ICON_RED_LIGHT'.
          icon_text =  'High'.
        ENDCASE.
      CALL FUNCTION 'ICON_CREATE'
        EXPORTING
          name  icon_name"图标名称
          text  icon_text"图标文本(显示在图标的后面)
          info  'Status'"图标快速提示信息
          add_stdinf 'X'"图标快速提示信息开关
        IMPORTING
          RESULT  status_icon."图标字符串
    ENDMODULE.
    MODULE change."切换图标
      CASE value.
        WHEN 1.
          value 2.
        WHEN 2.
          value 3.
        WHEN 3.
          value 1.
      ENDCASE.
    ENDMODULE.



    右键菜单Context Menus for Screen

    Context menu是右键点击的时候在鼠标的位置弹出的。在定义screen object的时候可以定义是否提供context menu(screen,input fields,table controls和box等),当选择context menu的一个object时,事件处理就会执行应用程序的一个subroutine,这种机制传递了一个指向subroutine的reference,程序通过这个menu reference来显示menu。可以通过menu painter来创建menu或者动态创建menu。当执行一个menu function时,application program得到control并响应用户输入。Context menu被分配给output fields,当你给box,table control或screen分配context menu时,所有没有分配context menu从属于它的output fields都会继承这个context menu。可以通过object navigator来创建context menu,也可以通过menu painter来创建。Context menu是一种特殊的GUI STATUS,它有name,descripative text和status type:context menu

    可以通过CL_CTMENU类的静态方法load_gui_status来load通过Menu painter预先定义好的context menu。通过其他方法可以重新创建和动态修改context menu。如果用户通过context menu激活了一个function(菜单项),这个function的function code就会填到command field中并根据function type触发相应的PAI。Cl_ctmen除了静态方法load_gui_status外还有一系列的方法用来动态修改context menu,这些方法在ON_CTMENU_<context>中调用。

    在Screen Painter中可以通过元素的

    来设置context menu(不是具体某个菜单项,它是一个菜单上下文,相当于一个菜单容器,它里面有什么样的菜单项)的构造处理。如果没有给某个元素设置context menu,则该元素会继承上一级的元素的菜单(如某个Frame中某个元素未设置,则它会继续直Frame所设置的上下文菜单,如果Frame未设置,则会继续屏幕所设置的)

    如果某元素绑定context menu后,当在元素上鼠标右键(不会触发PAI事件,只有当选择某个具体菜单项时才会触发PAI)时,会自动调用ON_CTMENU_<context>(<context>为context menu的ID)这样的一个Form,所以可以在回调该From时动态的定义context menu的构造过程

    对于每一个分配给元素的context menu,在运行时会自动创建一个CL_CTMENU对象,当用户右击请求这个context menu时,会将这个context menu的引用传递给下面所示的这个Form:

    FORM ON_CTMENU_<context> USING <l_menu> TYPE REF TO cl_ctmenu.
      ... 
    ENDFORM.

    对象传递给这个Form时,context menu中是没有菜单项的,这时可以在这个Form中使用CL_CTMENU对象相关方法来动态的构造context menu

    右键菜单示例:

    利用“CL_CTMENU”类中的各种方法可以实现许多功能,如方法“load_gui_status”允许使用系统预定义的上下文菜单;可通过方法“add_menu”或者“add_submenu”来添加其他的同级菜单对象或者子菜单,以及添加分隔线、激活或者禁止选择(菜单项呈灰色)等。

     

    通过Menu Painter创建context menu时,类型要选择Context Menu:


    这里创建CONTEXT_MENU_1CONTEXT_MENU_2CONTEXT_MENU_3三个context menu




    以及普通类型的SCREEN_101


    REPORT demo_dynpro_context_menu.

    DATAfield1 TYPE i VALUE 10,
          field2 TYPE DECIMALS 4.
    DATAprog TYPE sy-repid,
          flag(1TYPE c VALUE 'X'.
    DATAok_code TYPE sy-ucomm,
          save_ok TYPE sy-ucomm.
    prog sy-repid.
    CALL SCREEN 100.
    MODULE status_0100 OUTPUT.
      IF flag 'X'.
        SET PF-STATUS 'SCREEN_101' EXCLUDING 'REVEAL'.
      ELSEIF flag ' '.
        SET PF-STATUS 'SCREEN_101' 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 ** ).
        WHEN 'CUBICROOT'.
          field2 field1 ** ).
      ENDCASE.
    ENDMODULE.            
    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'"CANCEL
          menu    l_menu.
    ENDFORM.              
    FORM on_ctmenu_frame USING l_menu TYPE REF TO cl_ctmenu.
      CALL METHOD cl_ctmenu=>load_gui_status
        EXPORTING
          program prog
          status  'CONTEXT_MENU_2'"HIDE
          menu    l_menu.
      CALL METHOD cl_ctmenu=>load_gui_status
        EXPORTING
          program prog
          status  'CONTEXT_MENU_1'"CANCEL
          menu    l_menu.
      IF flag ' '."如果已点击过 HIDE ,则此时HIDE菜单设置为不可用
        DATAfcodes TYPE ui_functions .
        APPEND 'HIDE' TO fcodes .
        CALL METHOD l_menu->disable_functions
          EXPORTING
            fcodes fcodes.
      ENDIF.
    ENDFORM.                
    FORM on_ctmenu_reveal USING l_menu TYPE REF TO cl_ctmenu.
      CALL METHOD cl_ctmenu=>load_gui_status
        EXPORTING
          program prog
          status  'CONTEXT_MENU_3'"REVEAL
          menu    l_menu.
      CALL METHOD cl_ctmenu=>load_gui_status
        EXPORTING
          program prog
          status  'CONTEXT_MENU_1'"CANCEL
          menu    l_menu.
      IF flag 'X'."如果已点击过 REVEAL ,则此时REVEAL菜单设置为不可用
        DATAfcodes TYPE ui_functions .
        APPEND 'REVEAL' TO fcodes .
        CALL METHOD l_menu->disable_functions
          EXPORTING
            fcodes fcodes.
      ENDIF.
    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  '平方'.
      CALL METHOD calculate_menu->add_function
        EXPORTING
          fcode 'CUBE'
          text  '立方'.
      CALL METHOD calculate_menu->add_function
        EXPORTING
          fcode 'SQUAREROOT'
          text  '开平方'.
      CALL METHOD calculate_menu->add_function
        EXPORTING
          fcode 'CUBICROOT'
          text  '开立方'.
      "=======将上面动态创建的上下文菜单挂到当前(计算)菜单下面,成为子菜单
      CALL METHOD l_menu->add_submenu
        EXPORTING
          menu calculate_menu
          text '计算'.
    ENDFORM.




    运行效果如下:


    由于Field2已经隐藏,所Hide Result右键不可用

    Field2上没有设置Menu,所以继承自FRAME



    在FRAME之外,显示屏幕的标准Context Menus

    子屏幕Subscreens

    如果是通过屏幕编辑器创建的子屏幕是,则在创建子屏幕时,需要指定屏幕的类型为子屏幕类型:

    并且Next Screen一定要设置成自己。子屏幕需要放在子屏幕区域,且不能超过区域大小

     

    另外,除了像上面那样通过屏幕编辑器来创建子屏幕外,还可以通过通过SELECTION-SCREEN BEGIN OF SCREEN dynnr AS SUBSCREEN语句在ABAP程序代码中来定义子屏幕,定义后也可能通过下面的CALL SUBSCREEN语句来调用,而不一定要使用屏幕绘制器绘制的屏幕

     

    子屏幕限制:

    ?       尽量不要将子屏幕中的元素名称与主屏幕或其他子屏幕设置相同,因为相同时需要对ABAP程序的相应全局部分做额外处理(只是尽量,但也是可以将多个不同子屏幕中相同名称的屏幕元素对应到同一个ABAP程序中的全局变量,如后面例子中4个子屏幕共用同一ABAP程序中全局变量field,而且这4个子屏幕上都有一个名为field的输入框)

    ?       子屏幕中没有OK_CODE字段,使用的是主屏幕中的OK_CODE field;

    ?       子屏幕的flowlogic不能包括MODULE... AT EXIT- COMMAND的语句,类型为E的Function Code仅只能在主屏幕中处理;

    ?       子屏幕flowlogic中不能包含SET TITLEBAR,SET PF-STATUS,SETSCREEN,LEAVE SCREEN,or LEAVE TO SCREEN这些语句,任何这些语句都会引起运行错误,不能在子屏幕中改变主屏幕的GUI Status

     

    在主屏幕的flow logic中使用CALL SUBSCREEN将子屏幕include进行来,语句如下:

    PROCESS BEFORE OUTPUT.
      ...
      CALL SUBSCREEN <area> INCLUDING [<prog>] <dynp>.
      ...
    子屏幕都需要放在主屏幕中的某个指定的<area>区域元素中。

     

    为了调用子屏幕的PAI事件,需要在主屏幕的PAI flow logic里如下调用:

    PROCESS AFTER INPUT.
      ...
      CALL SUBSCREEN <area>.
      ...
    该语句的作用等效于调用(触发)了子屏幕中的PAI事件块

     

    不能够将CALL SUBSCREEN语句放在CHAIN and ENDCHAIN 或者 LOOP and ENDLOOP之间调用。SY-DYNNR会在CALL SUBSCREEN开始到结束之前发生修改,且为子屏幕的屏幕号,并在返回到主屏幕时修改成主屏幕的屏幕号

     

    示例:DEMO_DYNPRO_SUBSCREENS

    先要画两个可以存储子屏幕的区域控件:


    先要画两个可以存储子屏幕的区域控件:

    image187[4]image188[4]

    效果:

    image189[4]image190[4]

    image191[4]

    报表主程序:

    REPORT demo_dynpro_subscreens.

    DATA: ok_code TYPE sy-ucomm,
          save_ok TYPE sy-ucomm.

    DATA: number1(4TYPE n VALUE'0110',"需显示的子屏幕
          number2(4TYPE n VALUE'0130', "
    field(10TYPEc, field1(10TYPEc, field2(10TYPEc."field为4个子屏幕共有的输入框
    CALLSCREEN100."调用主屏幕
    MODULE status_100 OUTPUT.
    SET PF-STATUS 'SCREEN_100'."主屏幕的UI设置,只有一个标准工具栏上“取消”按钮
    ENDMODULE.

    MODULE fill_0110 OUTPUT.
    field = 'Eingabe 1'(001)."110子屏幕显示前,为子屏幕上输入框赋初始值
    ENDMODULE.

    MODULE fill_0120 OUTPUT."120子屏幕显示前,为子屏幕上输入框赋初始值
    field = field1.
    ENDMODULE.

    MODULE fill_0130 OUTPUT.
    field = 'Eingabe 2'(002).
    ENDMODULE.

    MODULE fill_0140 OUTPUT.
    field = field2.
    ENDMODULE.

    MODULE cancel INPUT."如果点击了标准工具栏上的“取消”按钮后退出整个程序
    LEAVEPROGRAM.
    ENDMODULE.

    MODULE save_ok INPUT.
      save_ok = ok_code.
    CLEAR ok_code.
    ENDMODULE.

    MODULE user_command_0110 INPUT.
    IF save_ok = 'OK1'.
        number1 = '0120'.
        field1 = field.
    CLEARfield.
    ENDIF.
    ENDMODULE.

    MODULE user_command_0130 INPUT.
    IF save_ok = 'OK2'.
        number2 = '0140'.
        field2 = field.
    CLEARfield.
    ENDIF.
    ENDMODULE.

    MODULE user_command_100 INPUT.
    CASE save_ok.
    WHEN'SUB1'.
          number1 = '0110'.
    WHEN'SUB2'.
          number1 = '0120'.
    CLEAR field1.
    WHEN'SUB3'.
          number2 = '0130'.
    WHEN'SUB4'.
          number2 = '0140'.
    CLEAR field2.
    ENDCASE.
    ENDMODULE.

    100主对话屏幕:

    image192[4]image193[4]

    image194[4]

    子屏幕:

    image195[4]image196[4]image197[4]

    image198[4]image199[4]image200[4]

    image201[4]image202[4]image203[4]

    image204[4]image205[4]image206[4]

     

     

     

    Tabstrip(Tab条)

    从技术角度来看,Tab条中的每一个Tab page是由子屏幕与Table Title按钮组成的:

    image207[4]

    所以,每一个Tab page是由一个Tab Title(实质上就是一个按钮,Tab title与按钮具有一样的属性)、一个子屏幕区域(用来Include子屏幕)组成的:

    image208[4]

    image209[4]

    功能代码类型设置为“P”表示当用户按下这个TAB页按钮时,不触发主屏幕后台的PAI事件,如果FctType留空,则会触发

    Ref.Field表示该TAB页按钮与其对应的要显示的子屏幕的连接,在PBO流逻辑中将使用这个“Ref.Field”调用对应的子屏幕

    image210[4]

    静态的Tabstrip(多个子屏幕区域)

    必须为每一个Tab title分配一个单独的子屏幕区域,并且tabe title的Funcode的类型为P,还需在主屏幕的PBO块中加载所有的subscreens,以及在主屏幕的PAI块中调用每个subscreens的PAI事件。

    当切换Tab page时,主屏幕的PAI事件不会触发(但子屏幕事件是否触PAI发看是否满足以下两个条件:一是在主屏幕的PAI块中调用了子屏幕的PAI事件了,即调用了CALL SUBSCREEN: <area>这样的语句;二是子屏幕中的元素确是触发了PAI事件,如点击了子屏幕中的某个按钮),所以在切换期间是不会对子屏幕中进行input checks数据检测动作,input checks数据检测动作需要等到点击主屏幕上的某个具有Function Code的元素时才触发(如F8)。所以静态的Tabstrip适用于显示数据,而不适合于输入数据。

    对于静态的Tabstrip,需要在主屏幕的PBO与PAI中一次性(仅需一次)加载所有的子屏幕:

    PROCESS BEFORE OUTPUT.
      ...
      CALL SUBSCREEN<area1> INCLUDING [<prog1>] <dynp1>,
                         <area2> INCLUDING [<prog2>] <dynp2>,
                         <area3> INCLUDING [<prog3>] <dynp3>,
      ...

    PROCESS AFTER INPUT.
      ...
      CALL SUBSCREEN<area1>,
      <area2>,
      <area3>,
      ...

    动态的Tabstrip(共用一个子屏幕区域)

    所有的table title共用一个子屏幕区域,这是通过Screen Painter中Table Title元素的image211[4]属性来设定共享的。此时Table Title的Function code类型不指定,因此当每次进行切换时,会触发主屏幕的PAI事件,这样如果主屏幕的PAI块中调用了子屏幕的PAI事件,则子屏幕的PAI事件也会被调用。另外,在切换到其他Tab page之前会进行当前子屏幕的input checks数据检测动作,只有通过了input checks数据检测动作后才能切换到其他Tab page。另外,不像静态Tabstrip那样一次性全部将子屏幕加载到Tabstrip控件中,而是每次切换时include相应的子屏。

    对于动态的Tabstrip,需要在主屏幕的PBO与PAI中多次(但每次只加载一个子屏幕)动态加载某个子屏幕:

    PROCESS BEFORE OUTPUT.
      ...
      CALL SUBSCREEN <area> INCLUDING [<prog>] <dynp>.
      ...

    PROCESS AFTER INPUT.
      ...
      CALL SUBSCREEN <area>.
      ...

    静态Tabstrip示例

    image212[4]

    image213[4]

    image214[4]

    REPORT DEMO_DYNPRO_TABSTRIP_LOCAL.
    "定义TABSTRIP,名称需也Screen Painter中的名相同
    CONTROLS mytabstrip TYPE TABSTRIP.

    DATAok_code TYPE sy-ucomm,
          save_ok TYPE sy-ucomm.
    "需要显示(激活)的 Tab Title
    mytabstrip-activetab 'PUSH2'.
    CALL SCREEN 100.
    MODULE status_0100 OUTPUT.
      SET PF-STATUS 'SCREEN_100'.
    ENDMODULE.              
    MODULE cancel INPUT.
      LEAVE PROGRAM.
    ENDMODULE.             
    MODULE user_command INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      IF save_ok 'OK'.
        MESSAGE i888(sabapdocuWITH 'MYTABSTRIP-ACTIVETAB ='
                                      mytabstrip-activetab.
      ENDIF.
    ENDMODULE
    image215[4]

    动态Tabstrip示例

    这个示例是将上面静态的改成了动态的,基本上一样

    image216[4]

    image217[4]

    报表程序:

    CONTROLS mytabstrip TYPE TABSTRIP.
    DATAok_code TYPE sy-ucomm,
          save_ok TYPE sy-ucomm.
    DATA  number TYPE sy-dynnr.

    mytabstrip-activetab 'PUSH2'.
    number '0120'.

    CALL SCREEN 100.
    MODULE status_0100 OUTPUT.
      SET PF-STATUS 'SCREEN_100'.
    ENDMODULE.
    MODULE cancel INPUT.
      LEAVE PROGRAM.
    ENDMODULE.
    MODULE user_command INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      IF save_ok 'OK'.
        MESSAGE i888(sabapdocuWITH 'MYTABSTRIP-ACTIVETAB =' mytabstrip-activetab.
      ELSE.
        mytabstrip-activetab = save_ok.
        CASE save_ok."点击Tab Title时需要手动切换Tab
          WHEN 'PUSH1'.
            number '0110'.
          WHEN 'PUSH2'.
            number '0120'.
          WHEN 'PUSH3'.
            number '0130'.
        ENDCASE.
      ENDIF.
    ENDMODULE.

    选择屏幕中的 Tabstrip

    选择屏幕中的 Tabstrip 示例请参考这里

    通过向导创建Tabstrip

    选择工具栏中的image218[4],绘制控件时,会弹出向导界面:

    image219[4]

    输入Tabstrip对象名:

    image220[4]

    输入每个Tab标签的标题,输入的个数也决定了Tab标签的个数:

    image221[4]

    每个Tab标签页面需要单独分配一个子屏幕,定义好页面后,系统将自动分配功能代码并为每个页面自动分配一个子屏幕:

    image222[4]

    输入生成的代码所存放的Include文件名:

    image223[4]

    完成后屏幕绘制上会生成名为TAB01的Tab标签控件:

    image224[4]

    根据生成的代码来看,向导所采用的是动态Tabstrip方式生成的:

    PROCESS BEFORE OUTPUT.
    *&SPWIZARD: PBO FLOW LOGIC FOR TABSTRIP 'TAB01'
      MODULE TAB01_ACTIVE_TAB_SET.
      CALL SUBSCREEN TAB01_SCA
        INCLUDING G_TAB01-PROG G_TAB01-SUBSCREEN.
    * MODULE STATUS_1001.
    *

    PROCESS AFTER INPUT.
    *&SPWIZARD: PAI FLOW LOGIC FOR TABSTRIP 'TAB01'
      CALL SUBSCREEN TAB01_SCA.
      MODULE TAB01_ACTIVE_TAB_GET.
    * MODULE USER_COMMAND_1001.

     

    REPORT  zjzj_tabstripwizard.
    CALL SCREEN 1001.

    *&SPWIZARD: FUNCTION CODES FOR TABSTRIP 'TAB01'
    CONSTANTSBEGIN OF C_TAB01,
                 TAB1 LIKE SY-UCOMM VALUE 'TAB01_FC1',
                 TAB2 LIKE SY-UCOMM VALUE 'TAB01_FC2',
               END OF C_TAB01.
    *&SPWIZARD: DATA FOR TABSTRIP 'TAB01'
    CONTROLS:  TAB01 TYPE TABSTRIP.
    DATA:      BEGIN OF G_TAB01,
                 SUBSCREEN   LIKE SY-DYNNR,
                 PROG        LIKE SY-REPID VALUE 'ZJZJ_TABSTRIPWIZARD',
                 PRESSED_TAB LIKE SY-UCOMM VALUE C_TAB01-TAB1,
               END OF G_TAB01.
    DATA:      OK_CODE LIKE SY-UCOMM.

    *&SPWIZARD: OUTPUT MODULE FOR TS 'TAB01'. DO NOT CHANGE THIS LINE!
    *&SPWIZARD: SETS ACTIVE TAB

    MODULE TAB01_ACTIVE_TAB_SET OUTPUT.
      TAB01-ACTIVETAB G_TAB01-PRESSED_TAB.
      CASE G_TAB01-PRESSED_TAB.
        WHEN C_TAB01-TAB1.
          G_TAB01-SUBSCREEN '1002'.
        WHEN C_TAB01-TAB2.
          G_TAB01-SUBSCREEN '1003'.
        WHEN OTHERS.
    *&SPWIZARD:      DO NOTHING
      ENDCASE.
    ENDMODULE.

    *&SPWIZARD: INPUT MODULE FOR TS 'TAB01'. DO NOT CHANGE THIS LINE!
    *&SPWIZARD: GETS ACTIVE TAB

    MODULE TAB01_ACTIVE_TAB_GET INPUT.
      OK_CODE SY-UCOMM.
      CASE OK_CODE.
        WHEN C_TAB01-TAB1.
          G_TAB01-PRESSED_TAB C_TAB01-TAB1.
        WHEN C_TAB01-TAB2.
          G_TAB01-PRESSED_TAB C_TAB01-TAB2.
        WHEN OTHERS.
    *&SPWIZARD:      DO NOTHING
      ENDCASE.
    ENDMODULE.

    结论:通过上面的实例的实现,发现向导Tab控件比手动写的Tab控件要简单得多,所以尽量采用向导生成的方式来生成Tab控件。

     

     

    Custom Controls(自定义控件)

    自定义控件是通过Screen Painter的image225来创建的区域与放在该区域中的应用控件组成的。通过image225[1]只是创建了用来存放具体应用组件的一个区域(即容器),需要放什么则是通过一系列相应类来编程实现的。

     

    SAP Control Framework的事件类型
    System events:
    该事件发生时,不会触发PBO和PAI事件(所以也不会自动发生数据传输)。这类事件的优点是:事件处理方法会第一时间自动调用,不管input checks检测是否通过,因为事件处理方法总是在PAI触发之前执行,而PAI事件触前才进行input checks检测,所以input checks检测是在事件处理方法调用之后才进行;这类事件的缺点是:有可能屏幕字段的内容不会传递到ABAP程序中,这就会造成下一屏幕显示的数据为过时数据,但我们可以在事件处理方法中通过cl_gui_cfw=>set_new_ok_code手动设置Function code ,让PAI事件触发,则屏幕字段内容肯定会被传递到ABAP程序中去,所以这样可以避免这个问题。

    image226

    Application events:
    该事件在PAI处理完后会自动触发(这种情况下屏幕字段已经传输到程序变量),你也可以在PAI事件当中使用CL_GUI_CFW=>DISPATCH来人为触发Application events事件的处理,当事件处理方法调用完后,控制权又会返回到DISPATCH的调用点继续执行PAI事件。

    此种类型的事件的优点如下:可以控制事件处理方法在何时调用,并且在调用前数据已经传递到ABAP程序中了;缺点是:如果input checks检测不通过时,事件处理方法是不会被执行的。image227

    注意:此图有点问题,因为在没有使用DISPATCH的情况下,当PAI事件执行完后,也会自动的调用事件处理方法)

     

    CL_GUI_SPLITTER_CONTAINER

    主要功能就是container的拆分。

    CONSTRUCTOR:构造方法,主要参数:

    PARENT -- Parent Container,待拆分的cl_gui_container的引用

    ROWS –需要显示多少行,举例,你想把container分成上下两个部分,那么rows = 2

    COLUMNS – 需要分成多少列

    接下来主要是一些setter和getter方法

    SET_BORDER 设置边框的格式,space:不设置 ‘X’:设置

    SET_ROW_HEIGHT — GET_ROW_HEIGHT 用来设置行的高度

    SET_COLUMN_WIDTH - GET_COLUMN_WIDTH 设置列的宽度

    SET_ROW_MODE - GET_ROW_MODE 设置行的模式

    SET_COLUMN_MODE - GET_COLUMN_MODE 设置列的模式

    下面这四个方法原理一样,主要设置splitter的属性,例如能不能移动等等

    SET_ROW_SASH - GET_ROW_SASH

    SET_COLUMN_SASH - GET_COLUMN_SASH

    get_container方法用来获取指定的拆分格子,参数:

             row:      第几行

        column:   第几列

        container:获取到的格子引用,其类型还是一cl_gui_container类型的Container

     

    SAP的GUI的类列表

    CLASS NAME

    Super CLASS NAME

    DESCRIPTIO

    CL_GUI_OBJECT

     

    Proxy Class for a GUI Object

    CL_FORMPAINTER_BASEWINDOW

    CL_GUI_OBJECT

    SAP Form Painter Window Base Class

    CL_FORMPAINTER_BITMAPWINDOW

    CL_FORMPAINTER_BASEWINDOW

    SAP Form Painter Bitmap Window Class

    CL_FORMPAINTER_TEXTWINDOW

    CL_FORMPAINTER_BASEWINDOW

    SAP Form Painter Text Window Class

    CL_GUI_CONTROL

    CL_GUI_OBJECT

    Proxy Class for Control in GUI

    CL_DSVAS_GUI_BUSIGRAPH

    CL_GUI_CONTROL

    DSVAS: Proxy for Business Graphic

    CL_GFW_GP_PRES_CHART

    CL_GUI_CONTROL

    GFW: Product-specific section of CL_GUI_GP_PRES (Chart)

    CL_GFW_GP_PRES_PIG

    CL_GUI_CONTROL

    GFW: product specific section for web view

    CL_GFW_GP_PRES_SAP

    CL_GUI_CONTROL

    GFW: product-specific section of CL_GUI_GP_PRES (SAP BUSG)

    CL_GUI_ALV_GRID_BASE

    CL_GUI_CONTROL

    Basis Class for ALV Grid

    CL_CALENDAR_CONTROL_SCHEDULE

    CL_GUI_ALV_GRID_BASE

    Calendar View (Day, Week, Month)

    CL_GUI_ALV_GRID

    CL_GUI_ALV_GRID_BASE

    ALV List Viewer

    CL_ALV_DD_LISTBOX

    CL_GUI_ALV_GRID

    D&D List Box

    CL_BUKF_CAT_GRID

    CL_GUI_ALV_GRID

    Key Figures - Grid of categories

    CL_BUKF_DSRC_GRID

    CL_GUI_ALV_GRID

    Key Figures - Grid for Data sources

    CL_BUKF_FILTER_GRID

    CL_GUI_ALV_GRID

    Key Figures - Filter for Key Figure

    CL_BUKF_KF_GRID

    CL_GUI_ALV_GRID

    Key Figures - Grid for Key Figures

    CL_BUKF_TERMS_GRID

    CL_GUI_ALV_GRID

    Key Figures - Grid for terms

    CL_FTR_GUI_ENTRY_ALV

    CL_GUI_ALV_GRID

    Class: ALV Grid Control for Initial Screen (Without Toolbar)

    CL_GFW_GP_GRID_ALV

    CL_GUI_ALV_GRID

    ALV grid proxy

    CL_GUI_AQQGRAPHIC_ADAPT

    CL_GUI_CONTROL

    Network Adapter

    CL_GUI_AQQGRAPHIC_CONTROL

    CL_GUI_CONTROL

    BW Basis Class Network Control

    CL_GUI_AQQGRAPHIC_NETPLAN

    CL_GUI_AQQGRAPHIC_CONTROL

    Network Control

    CL_GUI_BARCHART

    CL_GUI_CONTROL

    Bar chart wrapper

    CL_GUI_BORDERPAINTER

    CL_GUI_CONTROL

    SAP Border Painter Control Proxy Class

    CL_GUI_BTFEDITOR

    CL_GUI_CONTROL

    SAP BTF Editor Control Proxy Class

    CL_GUI_CALENDAR

    CL_GUI_CONTROL

    Calendar Control Proxy Class

    CL_GUI_CHART_ENGINE_WIN

    CL_GUI_CONTROL

    Graphics: Presentation Graphics (SAP GUI for Windows)

    CL_GUI_CONTAINER

    CL_GUI_CONTROL

    Abstract Container for GUI Controls

    CL_GUI_CONTAINER_INFO

    CL_GUI_CONTAINER

    Information on Container Controls

    CL_GUI_CUSTOM_CONTAINER

    CL_GUI_CONTAINER

    Container for Custom Controls in the Screen Area

    CL_GUI_DIALOGBOX_CONTAINER

    CL_GUI_CONTAINER

    Container for Custom Controls in the Screen Area

    CL_ECL_VIEWER_FRAME

    CL_GUI_DIALOGBOX_CONTAINER

    Manage EAI Control in Own Window

    CL_GUI_ECL_VIEWERBOX

    CL_GUI_DIALOGBOX_CONTAINER

    ECL Viewer as Dialog Box

    CL_GUI_DOCKING_CONTAINER

    CL_GUI_CONTAINER

    Docking Control Container

    CL_GUI_EASY_SPLITTER_CONTAINER

    CL_GUI_CONTAINER

    Reduced Version of Splitter Container Control

    CL_EU_EASY_SPLITTER_CONTAINER

    CL_GUI_EASY_SPLITTER_CONTAINER

    Internal Test; Do Not Use

    CL_GUI_GOS_CONTAINER

    CL_GUI_CONTAINER

    Generic Object Services Container

    CL_GUI_SIMPLE_CONTAINER

    CL_GUI_CONTAINER

    Anonymous Container

    CL_GUI_SPLITTER_CONTAINER

    CL_GUI_CONTAINER

    Splitter Control

    CL_GUI_ECL_2DCOMPARE

    CL_GUI_CONTROL

    Compare Module for 2D Viewer

    CL_GUI_ECL_3DCOMPARE

    CL_GUI_CONTROL

    Compare Module for 3D Viewer

    CL_GUI_ECL_3DMEASUREMENT

    CL_GUI_CONTROL

    Measurement Module for 3D Viewer

    CL_GUI_ECL_3DSECTIONING

    CL_GUI_CONTROL

    Sectioning Module for 3D Viewer

    CL_GUI_ECL_MARKUP

    CL_GUI_CONTROL

    Markup (Redlining) Component

    CL_GUI_ECL_PMI

    CL_GUI_CONTROL

    PMI Module for the 3D Viewer

    CL_GUI_ECL_PRIMARYVIEWER

    CL_GUI_CONTROL

    Basis Class for ECL Viewers (2D und 3D)

    CL_GUI_ECL_2DVIEWER

    CL_GUI_ECL_PRIMARYVIEWER

    Engineering Client 2D Viewer

    CL_GUI_ECL_3DVIEWER

    CL_GUI_ECL_PRIMARYVIEWER

    Engineering Client 3D Viewer

    CL_GUI_ECL_VIEWER

    CL_GUI_CONTROL

    Proxy Class for Engineering Client Viewer

    CL_GUI_FORMPAINTER

    CL_GUI_CONTROL

    SAP Form Painter Control Proxy Class

    CL_GUI_GLT

    CL_GUI_CONTROL

    Internal; Do Not Use!

    CL_GUI_GP

    CL_GUI_CONTROL

    GFW: Superclass of all graphics proxies

    CL_GUI_GP_GRID

    CL_GUI_GP

    GFW: Grid proxy

    CL_GUI_GP_HIER

    CL_GUI_GP

    GFW: Structure graphics

    CL_GUI_GP_PRES

    CL_GUI_GP

    GFW: Business graphic

    CL_GUI_GRLT

    CL_GUI_CONTROL

    Internal; Do Not Use !! ( restricted license - see docu)

    CL_GUI_HTML_EDITOR

    CL_GUI_CONTROL

    HTML Editor

    CL_GUI_ILIDRAGNDROP_CONTROL

    CL_GUI_CONTROL

    Interactive List: Drag & Drop

    CL_GUI_MOVIE

    CL_GUI_CONTROL

    SAP Movie Control

    CL_GUI_NETCHART

    CL_GUI_CONTROL

    Network wrapper

    CL_GFW_GP_HIER_SAP

    CL_GUI_NETCHART

    GFW: Product-specific section of CL_GUI_GP_HIER (NETZ)

    CL_GUI_PDFVIEWER

    CL_GUI_CONTROL

    PDF Viewer

    CL_GUI_PICTURE

    CL_GUI_CONTROL

    SAP Picture Control

    CL_GFW_GP_PRES_WEB

    CL_GUI_PICTURE

    GFW: product specific section for web view

    CL_GUI_RTF_EDITOR

    CL_GUI_CONTROL

    SAP SAPscript Editor Control

    CL_GUI_SAPSCRIPT_EDITOR

    CL_GUI_RTF_EDITOR

    SAP SAPscript Editor Control

    CL_GUI_SELECTOR

    CL_GUI_CONTROL

    SAPSelector: Control for selecting colors or bitmaps

    CL_GUI_SPH_STATUS_CONTROL

    CL_GUI_CONTROL

    SAPphone: Status Event Control

    CL_GUI_TABLEPAINTER

    CL_GUI_CONTROL

    SAP Table Painter Control Proxy Class

    CL_GUI_TIMER

    CL_GUI_CONTROL

    SAP Timer Control

    CL_GUI_TOOLBAR

    CL_GUI_CONTROL

    Toolbar Control

    CL_CCMS_AL_GUI_TOOLBAR

    CL_GUI_TOOLBAR

    Alerts: GUI Toolbar Used in the Visual Framework

    CL_GUI_WCF_WWP

    CL_GUI_CONTROL

    Internal Tool - DO NOT USE

    CL_KW_AUTOMATION_CONTROL

    CL_GUI_CONTROL

    Helper Class for General Automation Objects

    CL_LC_EDITOR_CONTROL

    CL_GUI_CONTROL

    Lifecycle Editor Control

    CL_GCM_LCEDITOR_CONTROL

    CL_LC_EDITOR_CONTROL

    Control for the display of definition life cycles

    CL_SOTR_SPELLCHECKER

    CL_GUI_CONTROL

    Interface with OTR Spellchecker

    CL_SRM_BASE_CONTROL

    CL_GUI_CONTROL

    SRM Control

    CL_SRM_STACKED_CONTROL

    CL_SRM_BASE_CONTROL

    RM Control with Stack

    CL_TREE_CONTROL_BASE

    CL_GUI_CONTROL

    Internal Tree Control Class

    CL_GUI_SIMPLE_TREE

    CL_TREE_CONTROL_BASE

    Simple Tree Control

    CL_ITEM_TREE_CONTROL

    CL_TREE_CONTROL_BASE

    Internal Tree Control Class

    CL_GUI_COLUMN_TREE

    CL_ITEM_TREE_CONTROL

    Column Tree Control

    BDMT_CONTROL

    CL_GUI_COLUMN_TREE

    Administers Tree Control for Monitoring

    CL_BUCC_TREE

    CL_GUI_COLUMN_TREE

    Consistency Checks - Library Tree

    CL_GFW_COLUMN_TREE

    CL_GUI_COLUMN_TREE

    Do not use!!!!!!!!

    CL_GFW_GP_HIER_SAPTREE

    CL_GFW_COLUMN_TREE

    GFW: Product-specific section of CL_GUI_GP_HIER

    CL_HU_COLUMN_TREE

    CL_GUI_COLUMN_TREE

    Tree that Displays Handling Units

    CL_GUI_LIST_TREE

    CL_ITEM_TREE_CONTROL

    List Tree Control

    C_OI_CONTAINER_CONTROL_PROXY

    CL_GUI_CONTROL

    For Internal Use

    SCE_HTML_CONTROL_EVENT_HANDLER

    CL_GUI_CONTROL

    Event Handler for SCE HTML Control

    CL_ALV_TREE_BASE

    CL_GUI_CONTROL

    Basis Class ALV Tree Control

    CL_GUI_ALV_TREE

    CL_ALV_TREE_BASE

    ALV Tree Control

    CL_GCM_WORKLIST_TREE

    CL_GUI_ALV_TREE

    CM: Worklist

    CL_PT_GUI_TMW_ALV_TREE

    CL_GUI_ALV_TREE

    Small Modification to CL_GUI_ALV_TREE

    CL_GUI_ALV_TREE_SIMPLE

    CL_ALV_TREE_BASE

    Simple ALV Tree

    CL_SIMPLE_TREE_VIEW_MM

    CL_GUI_ALV_TREE_SIMPLE

    Simplest Kind of Tree

    CL_GUI_ECATT_RECORDER

    CL_GUI_CONTROL

    SAP eCATT Recorder Control - To be used by eCATT only!

    CL_GUI_TEXTEDIT

    CL_GUI_CONTROL

    SAP TextEdit Control

    CL_GCM_TEXTEDIT

    CL_GUI_TEXTEDIT

    CM: Long text control

    CL_SOTR_TEXTEDIT

    CL_GUI_TEXTEDIT

    Edit Control for the OTR

    CL_GUI_HTML_VIEWER

    CL_GUI_CONTROL

    HTML Control Proxy Class

    CL_BFW_HTML_VIEWER_POC

    CL_GUI_HTML_VIEWER

    Browser Framework: Proxy for HTML Control

    CL_CCMS_BSP_VIEWER

    CL_GUI_HTML_VIEWER

    HTML Control Proxy Class

    CL_CCMS_AL_OBJ_DET_HTML_VIEWER

    CL_CCMS_BSP_VIEWER

    Alerts: Component That Displays Object Properties with HTML

    CL_CCMS_FROG_HTML_VIEWER

    CL_GUI_HTML_VIEWER

    CL_GUI_FROG_HTML_VIEWER

    CL_SSF_HTML_VIEWER

    CL_GUI_HTML_VIEWER

    Smart Forms: Enhanced HTML Viewer

    CL_GUI_ECL_MATRIX

    CL_GUI_OBJECT

    Represents a Complete Data Type with 13 Floats

    CL_GUI_RESOURCES

    CL_GUI_OBJECT

    GUI Resources (Fonts, Colors, ...)

    CL_WF_GUI_RESOURCES

    CL_GUI_RESOURCES

    Getting Front Settings

    CL_WF_GUI_RESOURCES_4_HTML

    CL_GUI_RESOURCES

    Get Front Settings for HTML Generation

    CL_KW_AUTOMATION_OBJECT

    CL_GUI_OBJECT

    For Internal Use

    CL_TABLEPAINTER_BASETABLE

    CL_GUI_OBJECT

    SAP Table Painter Table Base Class

    CL_TABLEPAINTER_TABLE

    CL_TABLEPAINTER_BASETABLE

    SAP Table Painter Table Class

    CL_TABLEPAINTER_TEMPLATE

    CL_TABLEPAINTER_BASETABLE

    SAP Table Painter Template Class

    C_OI_AUTOMATION_OBJECT

    CL_GUI_OBJECT

    For Internal Use

    CL_GUI_FRONTEND_SERVICES

    CL_GUI_OBJECT

    Frontend services

     

    自定义类事件处理示例:

    "事件源
    CLASS vehicle DEFINITION INHERITING FROM object.
      PUBLIC SECTION.
        "实例事件
        EVENTStoo_fast EXPORTING value(p1TYPE i
        "静态事件
        CLASS-EVENTStoo_fast_static EXPORTING value(p1TYPE i.
        METHODSaccelerate,show_speed IMPORTING msg TYPE string.
        CLASS-METHODSstatic_meth.
      PROTECTED SECTION.
        DATA speed TYPE i .
    ENDCLASS.                   

    CLASS vehicle IMPLEMENTATION.
      METHOD accelerate."非静态方法触发事件
        speed speed + 1.
        IF speed > 5.
          "触发实例事件
          RAISE EVENT too_fast EXPORTING p1 speed .
          "触发静态事件
          RAISE EVENT too_fast_static  EXPORTING p1 speed .
          speed 5.
        ENDIF.
      ENDMETHOD.  
      METHOD static_meth."静态方法触发事件
        "静态方法不能确发实例事件
        "RAISE EVENT too_fast EXPORTING p1 = speed .
        "触发静态事件
        RAISE EVENT too_fast_static  EXPORTING p1 .
      ENDMETHOD.                
      METHOD show_speed.
        WRITE/  'show_speed: ' ,msg.
      ENDMETHOD.                    
    ENDCLASS.                    

    "监听器
    CLASS handler DEFINITION.
      PUBLIC SECTION.
        METHODS:"实例处理方法
             "事件处理方法的定义,参数一定要与事件定义时的参数名一致,sender为事件源
            handle_1 FOR EVENT too_fast OF vehicle IMPORTING p1 sender,
            "如果省略了sender,则 handle_2 不能访问sender对象
            handle_2 FOR EVENT too_fast OF vehicle IMPORTING p1 ,
            "注意:静态事件不会传递 sender 参数
            handle_11 FOR EVENT too_fast_static OF vehicle IMPORTING p1.
        CLASS-METHODS:"静态处理方法
           handle_3 FOR EVENT too_fast OF vehicle IMPORTING p1 sender,
           handle_4 FOR EVENT too_fast OF vehicle IMPORTING p1,
           handle_33 FOR EVENT too_fast_static OF vehicle IMPORTING p1.
    ENDCLASS.

    CLASS handler IMPLEMENTATION.
      METHOD handle_1.
        sender->show_speedmsg 'handle_1' ).
        WRITE'handle_1:' p1.
      ENDMETHOD.         
      METHOD handle_2.
        "不能访问sender对象
        "sender->show_speed( ).
        WRITE'handle_2:' p1.
      ENDMETHOD
      METHOD handle_11.
        WRITE'handle_11:' p1.
      ENDMETHOD
      METHOD handle_3.
        sender->show_speedmsg 'handle_3' ).
        WRITE'handle_3:' p1.
      ENDMETHOD
      METHOD handle_4.
        WRITE'handle_4:' p1.
      ENDMETHOD
      METHOD handle_33.
        WRITE'handle_33:' p1.
      ENDMETHOD
    ENDCLASS

    DATAo_vehicle TYPE REF TO vehicle,
          o_handler TYPE REF TO handler.

    START-OF-SELECTION.
      CREATE OBJECTo_vehicle,o_handler.
      "实例事件处理方法 注册
      SET HANDLER o_handler->handle_1 FOR  o_vehicle.
      SET HANDLER o_handler->handle_2 FOR ALL INSTANCES.
      SET HANDLER handler=>handle_3 FOR ALL INSTANCES.
      SET HANDLER handler=>handle_4 FOR ALL INSTANCES.
      "静态事件处理方法注册:对事件处理方法所对应的类的所有实例都有效
      SET HANDLER o_handler->handle_11.
      SET HANDLER handler=>handle_33.
      DO TIMES.
        CALL METHOD o_vehicle->accelerate.
      ENDDO.

    自定义控件事件处理示例:

    image228image229

    REPORT demo_custom_control.
    * Declarations *****************************************************
    "事件处理器(即监听器)
    CLASS event_handler DEFINITION.
      PUBLIC SECTION.
        "handle_f1方法用来处理cl_gui_textedit控件的F1事件
        "handle_f4方法用来处理cl_gui_textedit控件的F4事件
        METHODShandle_f1 FOR EVENT f1 OF cl_gui_textedit
                 IMPORTING sender,
                 handle_f4 FOR EVENT f4 OF cl_gui_textedit
                 IMPORTING sender.
    ENDCLASS.

    DATAok_code LIKE sy-ucomm,
          save_ok LIKE sy-ucomm.
    DATAinit,
          "自定义容器
          container TYPE REF TO cl_gui_custom_container,
          "文本编辑器,后面会放到自定义容器中
          editor    TYPE REF TO cl_gui_textedit.
    "事件列表,存放需要触发的事件
    DATAevent_tab TYPE cntl_simple_events,
          event     TYPE cntl_simple_event.
    DATAline(256TYPE c,
          text_tab LIKE STANDARD TABLE OF line,
          field LIKE line.
    DATA handle TYPE REF TO event_handler.
    * Reporting Events ***************************************************
    START-OF-SELECTION.
      line 'First line in TextEditControl'.
      APPEND line TO text_tab.
      line '--------------------------------------------------'.
      APPEND line TO text_tab.
      line '...'.
      APPEND line TO text_tab.
      CALL SCREEN 100.
    * Dialog Modules *****************************************************
    MODULE status_0100 OUTPUT.
      SET PF-STATUS 'SCREEN_100'.
      IF init IS INITIAL."只做一次
        init 'X'.
        "TEXTEDIT为Screen Painter中自定义容器名
        CREATE OBJECT container
          EXPORTING
            container_name 'TEXTEDIT'.
        CREATE OBJECT editor
          EXPORTING
            parent container."将文件编辑器控件放入自定义容器中
        CREATE OBJECT handle.

        "文本编辑器需要触发(使用RAISE EVENT语句触发)的事件列表,即你要告诉文本编辑控件
        "需要使用 RAISE EVENT 语句触发哪些事件(因为只在类中进行定义了的事件是不会自动触
        "发的,需要我们使用 RAISE EVENT 这个的语句来进行触发,然后监听这些事件的事件处理
        "方法就会被回调),这与自己定义普通类事件原理是一样的(请参见vehicle类中的accelerate
        "方法,此方法触发了too_fast与too_fast_static两个事件,只不过文本编辑器中触发事件的
        "语句不需要我们写了,我们只需要告诉文本编辑器控件需要触发哪些事件,它就会使用RAISE EVENT
        "语句自动帮我们去触发了)
        event-eventid cl_gui_textedit=>event_f1.
        event-appl_event ' '.                     "system event
        APPEND event TO event_tab.
        event-eventid cl_gui_textedit=>event_f4.
        event-appl_event 'X'.                     "application event
        APPEND event TO event_tab.

    "为了将事件从屏幕终端传回到后台服务器程序中处理,需要调以下方法注册需要被传递回的事件
        CALL METHODeditor->set_registered_events
                     EXPORTING events event_tab.
        "监听方法向文本编辑控件注册(上面event_tab事件列表只管触发哪些事件,
        "至于触发后,需回调哪些方法来进行事件处理则要在这里指定)
        SET HANDLER handle->handle_f1
                    handle->handle_f4 FOR editor.
      ENDIF.
      "向文本编辑中写东西
      CALL METHOD editor->set_text_as_stream
        EXPORTING
          text text_tab.
    ENDMODULE.                  
    MODULE cancel INPUT.
      LEAVE PROGRAM.
    ENDMODULE.                  
    MODULE user_command_0100 INPUT.
      save_ok ok_code.
      CLEAR ok_code.
      CASE save_ok.
        WHEN 'INSERT'.
          CALL METHOD editor->get_text_as_stream
            IMPORTING
              text text_tab.
        "此Function Code是后面手动设置触发的,并不是某个屏幕元素所
        "对应的Function Code
        WHEN 'F1'.
          "按F1时,由于F1是系统事件,所以不会触发PAI,如果要执行到
          "这里,需要在事件处理方法中手动触发,所以按F1时,先执行
          "事件处理方法handle_f1,再才去执行PAI事件
          MESSAGE 'PAI triggered by handler method' TYPE 'I'.
        WHEN OTHERS."
          "按F4时,由于F4是应用类事件,所以会触发PAI事件,所以当按
          "F4后,先执行这里的PAI事件,再去执行相应事件处理方法:handle_f4
          MESSAGE 'PAI triggered by application event' TYPE 'I'.
          "调用此句后,会立即去执行后面的事件处理方法handle_f4(执行完后回到这里继续执行),如果将此
          "语句注掉,但等PAI事件执行之后,还是会去调用事件处理方法handle_f4
          "如果触发的是系统事件,如前面的F1,则不需要调用dispatch
          "dispatch:此方法可以触发application event,如果不调用这个方法,application event
          "会在PAI处理结束后自动调用事件处理方法。
          CALL METHOD cl_gui_cfw=>dispatch.      "for application events
          MESSAGE 'PAI after event handling' TYPE 'I'.
      ENDCASE.
      SET SCREEN 100.
    ENDMODULE.                  

    * Class Implementations **********************************************
    CLASS event_handler IMPLEMENTATION.
      METHOD handle_f1.
        DATA row TYPE i.
        MESSAGE 'F1 event handling' TYPE 'I'.
        "获取光标在文本编辑中的位置
        CALL METHOD sender->get_selection_pos
          IMPORTING
            from_line row.
        "取文本编辑中光标所在行的文本,并放到文本框中
        CALL METHOD sender->get_line_text
          EXPORTING
            line_number row
          IMPORTING
            text        field.
        "set_new_ok_code:设置一个新的Function code.该方法只能用于处理system event的
        "handler方法中,以此手动触发PAI处理
        "系统事件默认是不会触发PAI的,如果需要触发,则需要在事件处理方法中手动触发。注意:当事件处理方法执行完后才触发PAI
        CALL METHOD cl_gui_cfw=>set_new_ok_code   "raise PAI for system events
             EXPORTING new_code 'F1'.
        "清空缓冲,让服务器端与屏幕终端同步
        CALL METHOD cl_gui_cfw=>flush.
      ENDMETHOD.                                              
      METHOD handle_f4.
        DATA row TYPE i.
        MESSAGE 'F4 event handling' TYPE 'I'.
        CALL METHOD sender->get_selection_pos
          IMPORTING
            from_line row.
        CALL METHOD sender->get_line_text
          EXPORTING
            line_number row
          IMPORTING
            text        field.
        CALL METHOD cl_gui_cfw=>flush.
      ENDMETHOD.                                            
    ENDCLASS.                  

    Table Controls表格控件

    程序创建

    image230 image231

    image232 image233

    在Screen Painter中,Table的每一列都是一个文本框控件,也需要为每一个列统一命名:

    image234

    在设计时,如果要给表格增加列头或列体时,在表格控件所在的以外区域先将文本框与标签创建好,再托入到表格控件相应位置。

    另外,如果表格中的列都是来自于词典中的透明表时或结构时,可以这样来做:首先画一个表格控件,并将透明表或词典结构作为表格控件的命:

    image235

    然后从词典中引用字段:

    image236

    并将选择的字段拖入到表格控件中:

    image237

    如果需要让表格中的项可以选择的话,需要在设计表格控件时,指定透明表或词典结构中的某个字段作为选择列

    image238

     

    PROGRAM  sapmtz60 .
    TABLES:sflight.
    "注:不要使用如下定义,要使用上面数据词典方式,否则屏幕字段的值与ABAP程序
    "无法传递(屏幕字段与ABAP中同名才能进行传递),但屏幕设计中使用的数据词典
    "sflight-XXXX的命名方式,所以这里只能使用 TABLES 语句来进行定义
    *DATA: sflight TYPE sflight.
    DATAok_code(4),
          rowspage TYPE i,"表格控件可以显示的最大行数,用来实现翻页功能(一屏中可显示的最大行数)
          lastrowdisp TYPE i ,"表格控件中显示的最后一行数据的索引
          line_count TYPE i."表格中实际显示的行数(一屏可能没有显示满)

    ==============================

    在运行时,flights是一个结构,里面的cols字段是一个包含所有有列信息的内表,可以对这个内表进行处理:如隐藏某列

    data :ls_col like line of flights-cols.

    ls_col-invisible 1.
    modify flights-cols index sy-tabix from ls_colWHERE screen-name = 'TZODA_WARNING-BUN'.

    ==============================

     

    CONTROLSflights TYPE TABLEVIEW USING SCREEN 200."使用CONTROLS定义表格,定义表格后才能使用
    DATA int_flights LIKE sflight OCCURS WITH HEADER LINE.

    * ====================================PBO
    MODULE status_0100 OUTPUT.
      SET PF-STATUS 'TD0100'.
      SET TITLEBAR '100'.
    ENDMODULE.

    MODULE status_0200 OUTPUT.
      SET PF-STATUS 'TD0200'.
      SET TITLEBAR '100'.
    ENDMODULE.                 " STATUS_0100  OUTPUT

    MODULE display_flights OUTPUT.
        "注意,该module当内表为空时,PBO中的Loop循环还是会执行
         sflight int_flights."将程序中的值同步到屏幕字段中
        "1、sy-loopc在PBO的LOOP循环中的值默认就是表格控件可以显示的最大数据行数(
        "即可用作每页显示多少条数据,而不管内表中的数据是否可以填满表格可显示的最大行)
        "2、但在PAI的LOOP循环中的值为当前屏幕表格控件实际显示的数据行数(因为有时表格
        "中数据显示不满)
        "3、如果退出PBO与PAI的Loop中后,sy-loopc的值恢复为0
        rowspage sy-loopc."记录每页显示满时能显示的行数(每次循环时的值都与第一次相同)
      "flights-top_line记录了当前正在循环行的index,一出PAI或PBO中的
      "LOOP语句后,flights-top_line的值就会恢复到表格将要显示的第一行
      "数据的索引号
        "记下表格中显示的最后一行数据的索引(随着循环增加会增加)
        lastrowdisp flights-top_line.
    ENDMODULE.
    * ====================================PAI
    MODULE user_command_0100 INPUT.
      CASE ok_code.
          "按回车时,Function Code为空
        WHEN space.
          "获取表格控件中需要显示的所有数据
          SELECT  FROM sflight INTO TABLE int_flights
                                WHERE  carrid sflight-carrid
                                AND    connid sflight-connid .
          "设置表格控件中显示的第一行为int_flights内表中的第1行
          flights-top_line 1.
          "设置表格控件数据行总数,一般为所对应内表的总行数,如果
          "小于内表总行数,则显示内表中前部分数据
          DESCRIBE TABLE int_flights LINES flights-lines.
          CLEAR ok_code.
      ENDCASE.
    ENDMODULE.
    MODULE user_command_0200 INPUT.
      DATAff TYPE i .
      ff flights-top_line.
      CASE ok_code.
        WHEN 'CANC'.
          CLEAR ok_code.
          SET SCREEN 100."设置下屏幕为第一屏幕(100)
          LEAVE SCREEN."离开当前屏幕(200)后,系统会自动转换到一下屏幕(100)
        WHEN 'EXIT'.
          CLEAR ok_code.
          SET SCREEN 0"设置下屏幕为0,即当前屏幕结束后,整个屏幕序列会结束
          LEAVE SCREEN.
        WHEN 'BACK'.
          CLEAR ok_code.
          SET SCREEN 100LEAVE SCREEN.
        WHEN 'NEW'.
          CLEAR ok_code.
          SET SCREEN 100LEAVE SCREEN.
        WHEN 'P--'.
          CLEAR ok_code.
          PERFORM paging USING 'P--'.
        WHEN 'P-'.
          CLEAR ok_code.
          PERFORM paging USING 'P-'.
        WHEN 'P+'.
          CLEAR ok_code.
          PERFORM paging USING 'P+'.
        WHEN 'P++'.
          CLEAR ok_code.
          PERFORM paging USING 'P++'.
      ENDCASE.
    ENDMODULE.
    MODULE exit_0100 INPUT.
      CASE ok_code.
          "WHEN语句中不能使用OR,否则只有第一个有效
    *    WHEN 'CANC' OR 'EXIT' OR 'BACK'.
        WHEN 'CANC'.
          CLEAR ok_code.
          "设置当前屏幕的下一屏幕为0,如果跳转的下一屏幕为0,则
          "会自动结束当前屏幕序列,所以此时后面的 leave screen 可以去掉
          SET SCREEN 0.
          "但加上以下语句后,可以立马结束当前屏幕,如果没有,则
          "下一步会去执行屏幕的PAI事件,所以最好是加上
          LEAVE SCREEN.
        WHEN 'EXIT' .
          CLEAR ok_code.
          SET SCREEN 0.LEAVE SCREEN.
        WHEN 'BACK'.
          CLEAR ok_code.
          SET SCREEN 0.LEAVE SCREEN.
      ENDCASE.
    ENDMODULE.
    MODULE modi_flights INPUT.
      int_flights sflight."将屏幕字段中的内容同步到程序中
      "flights-top_line记录了当前正在循环行的index,一出PAI或PBO中的
      "LOOP语句后,flights-top_line的值就会恢复到表格将要显示的第一行
      "数据的索引号
      MODIFY int_flights INDEX flights-top_line.
      "sy-loopc为当前表格中显示的行数
      line_count sy-loopc.
    ENDMODULE.

    * ====================================FORM
    FORM paging USING code."翻页功能,实质就是对flights-top_line的设置
      DATAi TYPE i.

      CASE code.
        WHEN 'P--'."首页
          flights-top_line 1.
        WHEN 'P-'."上一页
          "点击翻页按钮与滚动鼠标时,在PAI的module中,flights-top_line的值还是
          "当前表格显示的第一行数据的索引,当PAI执行完后,鼠标滚动后在随后
          "的PBO中flights-top_line会自动调节(所以鼠标滚动时不需要处理),而点翻页按钮时则需要在这里手动
          "调节,然后才能在下一屏幕的PBO中正确使用
          flights-top_line flights-top_line rowspage.
          IF flights-top_line <= 0.
            flights-top_line 1.
          ENDIF.
        WHEN 'P+'."下一页
          IF line_count rowspage AND lastrowdisp < flights-lines .
            flights-top_line lastrowdisp + 1.
          ENDIF.
        WHEN 'P++'."最后一页
          "表格控件满显示时可能才有下一页
          IF line_count rowspage AND lastrowdisp < flights-lines .
            =  flights-lines lastrowdisp .
            IF i <= rowspage"如果剩下的不足一页或刚好一页时
              flights-top_line lastrowdisp + 1.
            ELSE."如果剩下的多余一页时,取最后一页
              flights-top_line flights-lines rowspage + 1.
            ENDIF.
          ENDIF.
      ENDCASE.
    ENDFORM.

     

    Screen 200 Flow logic:

    PROCESS BEFORE OUTPUT.
      MODULE status_0200.
      "将内表中的数据显示(绑定)到表格控件(可显示区域)中,cursor表示从内表
      "中的哪一行开始循环(即哪一行显示在表格控件的第一行),并且随着循环,
      "flights-top_line会自动加1(即flights-top_line记录了当前循环到了内表中
      "的哪一行数据了,因此flights-top_line可以在PAI的Loop循环调用的Module
      "中使用。所以flights-top_line除了用来设置将内表中的哪一行显示为表格中
      "的第一行外,还记录了当前循环到了内表中的哪一行了,但退出循环立即恢复
      "成循环时的初始值)
      "循环次数:当内表中的数据行足够时,循环次数为表格能显示的最大数据行数;
      "当内表中的数据行不足填满表格时,循环次数由内表行决定(一定要注意的是:
      "如果当内表为空时,此时也表现为内表行不足,但此时的循环次数又由表格能
      "显示的最大行数决定了,所以当内表为空时小心)
      LOOP AT int_flights WITH CONTROL flights CURSOR flights-top_line.
        "将内表中的数据行显示到表格控件的相对应的行中
        MODULE display_flights.
      ENDLOOP.

      "表格控件在鼠标滚动与点翻页按钮时会触发,但下面代码只是为了点击翻页按钮实现的,因为没有
      "下面这些代码,表格控件的滚动功能也会存在
    PROCESS AFTER INPUT.
      "1、在PAI中还必须再循环一次(哪怕是空循环,否则编译不能通过),这是为了将
      "表格中当前显示的数据行再次传递到ABAP程序中去。在这循环期间,程序可以使
      "用SY-LOOPC系统变量来获知表格中当前显示的有多少行数据将被传递到ABAP程序
      "中(因为只有显示出的数据才有可能发生了变化)
      "2、在循环的过程中,flights-top_line的初始值为当前表格中显示的第一行记录
      "的索引号(对应绑定内表中的索引),并且每循环一次也会自动加1(这里的
      "flights-top_line与PAI中的作用是一样的,但退出循环时会恢复到当前表格显示
      "的第一行记录索引)
      "3、可循环次数为系统变量sy-loopc的值
      "4、在PAI中,此类循环不能像上面PBO那样附加选项
      LOOP AT int_flights .
        MODULE modi_flights.
      ENDLOOP.
      MODULE user_command_0200.

    通过向导创建

    通过向导创建出来的表格可以同时实现数据的批量输入、输出及维护

    本例通过表SPFLI为数据源来演示

    由于数据表格可能实现批量维护操作,在ABAP报表主程序中定义两个内表:XSPFLI与YSPFLI,XSPFLI用于保存更新前的数据,YSPFLI用于保存修改后的数据,参照内表YSPFLI对物理表SPFLI进行修改操作,便能将中新增或修改的数据更新到数据库中;而对于在表格中被删除的数据,可以在数据更新前通过两张对比来获取:

    REPORT  zjzj_hello.
    TABLES:spfli.
    DATA:xspfli LIKE STANDARD TABLE OF spfli WITH HEADER LINE,
         yspfli LIKE STANDARD TABLE OF spfli WITH HEADER LINE.
    CALL SCREEN 1001.

    双击程序中的 1001,创建1001对话屏幕,并且为该屏幕创建名为T001的GUI:

    image239

    绘制1001屏幕:

    选择工具条中的Table Control(with Wizard)image240,并在屏幕上拖动,系统将会弹出表控件向导初始页面:

    image241

    为表格控制命名:

    image242

    表格控件的数据源可以是物理表,也可以是程序中的内表(但只能为标准内表),这里我们引用程序中的标准内表YSPFLI作为数据源:

    image243

    选择表格控件中需要展示的表字段:

    image244

    表格控制属性设置:

    image245

    image246
    image247

    表格控件附带按钮:

    image248

    image249

    指定用来存放表格向导产生的代码的INCLUDE文件名:

    image250

    image251

    image252

    双击表格控件,在表格控件属性框中还可以进一步设置表格属性(从弹出的表格控件属性框可以看到,与非向导的表格控件是一样的)

     

    完成后可以看到生成的代码,代码与上面程序创建表格控件

    image253image254

    但向导创建完后,但运行是没有数据的:

    image255

    下面将数据从SPFLI表中查出来,并将所获取的数据存放到YSPFLI中,且查询代码需要放在CALL SCREEN之前:

    image256

    再次运行,结果如下:

    image257

    从上图可以看出,“保存”与“退出”按钮都还未激活,原因就是还没有给对话屏幕程序加上GUI,下面给设置:

    image258

    运行结果:

    image259

    下面来实现这两个按钮的点击触发功能代码:

    在1001屏幕逻辑流的PAI块里,加上如下调用Module代码:MODULE USER_COMMAND_1001.,然后再在ZSCREEN04_TAB Include文件里加上与数据库表同步的代码:

    MODULE user_command_1001 INPUT.
      ok_code sy-ucomm.
      IF ok_code 'BREAK'.
        LEAVE TO SCREEN 0.
      ELSEIF ok_code 'SAVE'.
        LOOP AT yspfli."未被删除的数据就是要被从数据库中删除的数据
          DELETE TABLE xspfli FROM yspfli.
        ENDLOOP.

        DELETE spfli FROM TABLE xspfli.
        MODIFY spfli FROM TABLE yspfli.
        COMMIT WORK.

      ENDIF.
      CLEAR:ok_code.
    ENDMODULE.    

     

     

    结论:通过上面的实例的实现,发现向导表格比手动写的表格控件要简单得多,而且还具有很好的维护功能与翻页功能,所以尽量采用向导生成的方式来生成表格控件

    Tree Control 树

    image260image261image262

     

    PARAMETERS carrid TYPE scarr-carrid DEFAULT'AA'.

    DATA:ok_code LIKE sy-ucomm,
          save_code LIKE ok_code,
          container_name1 TYPE scrfname VALUE'MYTREE',"Tree容器名称
          tree_r TYPEREFTOcl_gui_simple_tree,"Tree控件引用
          container_r TYPEREFTO cl_gui_custom_container."Tree容器引用
    DATA: node_table LIKETABLEOF mtreesnode,"用于构造Tree数据内表:节点内表
          node1 TYPE mtreesnode."节点
    DATA:nodekey(100),nodedisp(200)."节点名与显示的文本名

    CLASS cl_event_handle DEFINITION."定义事件处理类
    PUBLICSECTION.
    "用于处理事件的方法:双击节点时会触发
    METHODS handle_dbclick FOREVENT node_double_click OF cl_gui_simple_tree
    IMPORTING node_key.
    ENDCLASS.              

    CLASS cl_event_handle IMPLEMENTATION."实现
    METHOD handle_dbclick."
        nodekey = node_key.
    READTABLE node_table WITHKEY node_key = node_key INTO node1.
        nodedisp = node1-text.
    ENDMETHOD.                 
    ENDCLASS.                

    "声明对象引用
    DATA event_handler TYPEREFTO cl_event_handle.

    START-OF-SELECTION.
    CREATE OBJECT event_handler."创建事件处理对象
    CALLSCREEN100.

    MODULE status_0100 OUTPUT.
    IF container_r ISINITIAL.
    PERFORM create_tree.
    ENDIF.
    ENDMODULE.             

    MODULE user_command_0100 INPUT.
      save_code = ok_code.
    CLEAR ok_code.
    CASE save_code.
    WHEN'BACK'.
    LEAVEPROGRAM.
    ENDCASE.
    ENDMODULE.               

    FORM create_tree.
    "创建树所在父容器对象
    CREATE OBJECT container_r EXPORTING container_name = container_name1.
    "创建树对象.创建时需要传入父容器
    CREATE OBJECT tree_r EXPORTING parent = container_r
    "节点选择模式:单选
                                     node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single.
    "子程序 make_data 负责从数据库中获取数据到树内表中
    PERFORM get_data.
    "将子程序 make_data 构造好的内表传递给树对象的 add_nodes 方式,构造节点
    CALLMETHOD tree_r->add_nodes
    EXPORTING
          table_structure_name = 'MTREESNODE'
          node_table           = node_table.
    PERFORM register_event."注册节点双击事件
    ENDFORM.                   

    FORM make_node USINGvalue(nkey) TYPE string"节点名
    value(nname) TYPE string"节点文本
    value(pnode) TYPE string"父节点名,如果为空则为根节点
    value(is_leaf) TYPE string."是否叶节点
    CLEAR node1.
      node1-node_key = nkey.
      node1-text = nname.
      node1-relatkey = pnode.

    IF is_leaf = 'X'.
        node1-relatship = cl_gui_simple_tree=>relat_last_child.
        node1-isfolder = ''.
    ELSE.
    CLEAR node1-relatship.
        node1-isfolder = 'X'.
    ENDIF.
      node1-hidden = ''.
      node1-disabled = ''.
    CLEAR: node1-exp_image,node1-expander,node1-n_image.
    APPEND node1 TO node_table.
    ENDFORM.                   

    FORM register_event.
    DATA: double_event TYPE cntl_simple_event,
            eventlist TYPE cntl_simple_events.
      double_event-eventid = cl_gui_simple_tree=>eventid_node_double_click.
      double_event-appl_event = 'X'.
    APPEND double_event TO eventlist.
    "树所需要监听的事件列表
    CALLMETHOD tree_r->set_registered_events
    EXPORTING
    events = eventlist.
    "指定tree_r的事件处理方式为event_handler的handle_dbclick方法
    SETHANDLER event_handler->handle_dbclick FOR tree_r.
    ENDFORM.                  

    FORM get_data.
    DATA: s1 TYPE string,s2 TYPE string,s3 TYPE string.
    DATA:wa1 TYPE scarr,wa2 TYPE spfli,wa3 TYPE sflight.
    SELECT * FROM scarr INTO wa1 WHERE carrid = carrid.
        s1 = wa1-carrname.
    PERFORM  make_node USING s1 s1 ''''.
    SELECT * FROM spfli INTO wa2 WHERE carrid = carrid.
    CHECK wa2-cityfrom ISNOTINITIAL.
    CHECK wa2-cityto ISNOTINITIAL.
    CONCATENATE wa2-cityfrom '------' wa2-cityto INTO s2.
    PERFORM make_node USING s2 s2 s1 ''.
    SELECT * FROM sflight INTO wa3 WHERE carrid = carrid AND connid = wa2-connid.
            s3 = wa3-fldate.
    PERFORM make_node USING s3 s3 s2 'X'.
    ENDSELECT.
    ENDSELECT.
    ENDSELECT.
    ENDFORM.               

    ALV Grid Control

    请参考《ALV.docx》文档中的“OO ALV->创建ALV”章节

    多行文本编辑器

    先创屏幕100,然后放一个名为EDITOR的自定义控件容器,用来存放多行文本编辑器:

    image263

    工具栏中新增保存按钮:

    image264

     

    在开发前,先讲讲长文本:

    在以前,使用过READ_TEXT函数读取过各种各样的长文本,比如物料长文本、销售长文本等,在读取里时,一般需要传递长文本对象名、长文本ID、及长文本名称,READ_TEXT函数参数如下:

    image265

    与读取函数READ_TEXT对应的是写函数SAVE_TEXT,它是将长文本以固有的格式存储到相应的物理表中,其中有一个重要的入参HEADER,其类型参照了THEAD结构(实质上为STXH表结构),用于存储长文本相关的各种属性:

    image266

    image267

    长文本最后都存储到了STXHSTXL两个物理表中。在使用READ_TEXT与SAVE_TEXT时,都需要指定长文本对象以及文本ID,这些是通过SE75来维护的:

    image268

    上面看到的物料长文本对象及文本ID,在物料维护时可以看到:

    image269

    SAP中的长文本都是以文本对象和文本ID分类别类存储到STXH、STXL两个物理表中,所以想将长字符串,比如这里编辑器中的文本以长文本形式存储到表中,则需要先定义对应的文本对象及文本ID,并且在定义文本对象时,可以指定长文本的格式:如每行的字符个数,这里我们创建需要在下面程序使用的文本对象Z001:

    image270

    image271

    当运行后面程序后,文本编辑器中的文本会以长文本的形式存储到STXH与STXL两个物理表中,STXH表存储的为长文本相关头信息,STXL存储的是真正的数据,但长文本是以LRAW类型存储的,在屏幕上不能直接显示出来:

    image272

    image273

    image274

    最后程序运行结果如下:

    image275

    image276

    REPORT  zjzj_text_editor.
    DATAeditor_container TYPE REF TO cl_gui_custom_container,"容器
          editor TYPE REF TO cl_gui_textedit."文本编辑器
    CONSTANTSc_line_length TYPE i VALUE 72."文本编辑器中每行最多允许的字符个数
    TYPESBEGIN OF st_text,"存放行文本类型
      line TYPE c LENGTH c_line_length,
      END OF st_text.
    TYPEStt_text TYPE STANDARD TABLE OF st_text."存放编辑器长文本表类型
    DATAit_lines TYPE STANDARD TABLE OF tline,
          wa_thead LIKE thead."SAVE_TEXT函数的header参数所需表头数据
    """"以下这些参数就是以前读取长文本函数 READ_TEXT 中常使用的参数
    wa_thead-tdobject 'Z001'."长文本对象
    wa_thead-tdid 'ZT01'."长文本ID
    wa_thead-tdname sy-repid."长文本名称:SAP里很多的业务长文本名所采用的拼接规则都不太一样,需要仔细分析,这里直接使用程序名
    wa_thead-tdspras sy-langu."长文本语言

    CALL SCREEN 100.

    MODULE status_0100 OUTPUT.
      SET PF-STATUS 'T001'.
      CREATE  OBJECT editor_container "创建容器对象
           EXPORTING
             container_name =  'EDITOR'.
      CREATE OBJECT editor"创建文本编辑器
          EXPORTING
            parent editor_container
            "换行模式——0: OFF; 1: wrap a window border;窗口边缘换行 2: wrap at fixed position
            wordwrap_mode 2
            "从第几个字符开始换行——position of wordwrap, only makes sense with wordwrap_mode=2
            wordwrap_position c_line_length
            "eq 1: change wordwrap to linebreak; 0: preserve wordwraps
            wordwrap_to_linebreak_mode 1
            max_number_chars 720.

      DATA texttable TYPE tt_text.
      DATA ls_header TYPE thead."用来存储读取到的长文本相关属性信息
      REFRESH it_lines.
      "读取长文本
      CALL FUNCTION 'READ_TEXT'
        EXPORTING
          client                  sy-mandt
          id                      wa_thead-tdid
          language                sy-langu
          name                    wa_thead-tdname
          object                  wa_thead-tdobject
        IMPORTING
          header                  ls_header
        TABLES
          lines                   it_lines
        EXCEPTIONS
          id                      1
          language                2
          name                    3
          not_found               4
          object                  5
          reference_check         6
          wrong_access_to_archive 7.
      "如果是第一次运行本程序,则数据库表 STXH、STXL两个表中不会有数据
      ",此时READ_TEXT会抛出异常
      IF sy-subrc <> 0.
        MESSAGE '无此文本TYPE 'I'.
      ENDIF.
      MESSAGE ls_header TYPE 'I'."将长文本相关属性信息打印到状态栏

      "将从表中读取到的长文本转换为能在文本编辑器显示的文本
      CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT'
        EXPORTING
          language    sy-langu
        TABLES
          itf_text    it_lines
          text_stream texttable.

      "将内表数据赋值给文本编辑器
      CALL METHOD editor->set_text_as_stream
        EXPORTING
          text texttable.
    ENDMODULE.

    MODULE user_command_0100 INPUT.
      CASE sy-ucomm.
        WHEN 'SAVE'.
          "从文本编辑器中读取文本到内表中
          CALL METHOD editor->get_text_as_stream
            IMPORTING
              text texttable.
          "将文本编辑器中的长文本数据转换为附带信息的可存储到表中的标准格式的长文本
          CALL FUNCTION 'CONVERT_STREAM_TO_ITF_TEXT'
            EXPORTING
              language    sy-langu
            TABLES
              text_stream texttable
              itf_text    it_lines.
          "将内表数据通过函数转换为 LRAW 类型并存放到指定的物理表中
          CALL FUNCTION 'SAVE_TEXT'
            EXPORTING
              client          sy-mandt
              header          wa_thead
              savemode_direct 'X'
            TABLES
              lines           it_lines.
      ENDCASE.
    ENDMODULE.

    Call屏幕

    image277

    call screen 200 starting at 37 5
                          ending   at 87 22.

    在Menu Painter中设计200屏幕时,Screen Type选择的是Modal dialog box,但此选项不是导致屏幕200本身以弹出对话框的形式显示,其意思与Call 选择屏幕时的选项AS WINDOW的使用相同。

    屏幕是否以对话框的形式显示,是由starting at选项决定的,这与Calling选择屏幕中的选项是一样的

    弹出确认对话框

    image278

     DATAl_answer TYPE c.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
    *     TITLEBAR                    = ' '
    *     DIAGNOSE_OBJECT             = ' '

          text_question               'Confirm to import?'
         text_button_1               'Yes'(001)
    *     ICON_BUTTON_1               = ' '
         text_button_2               'No'(002)
    *     ICON_BUTTON_2               = ' '
    *     DEFAULT_BUTTON              = '1'
    *     DISPLAY_CANCEL_BUTTON       = 'X'
    *     USERDEFINED_F1_HELP         = ' '
    *     START_COLUMN                = 25
    *     START_ROW                   = 6
    *     POPUP_TYPE                  =
    *     IV_QUICKINFO_BUTTON_1       = ' '
    *     IV_QUICKINFO_BUTTON_2       = ' '

       IMPORTING
         answer                      l_answer
    *   TABLES
    *     PARAMETER                   =

       EXCEPTIONS
         text_not_found              1
         OTHERS                      2
                .
      CHECK l_answer '1'.







    展开全文
  • 设置文字位于屏幕中间

    千次阅读 2018-01-15 15:26:39
    开始的时候把问题想复杂了,...假如右侧 设置 隐藏的时候 ,文字相对于屏幕就有些不在中间地方了。 思路,首先可以动态控制内容的 padding 或者 margin 来进行控制。具体偏移值得计算如下: public int px2dip(floa

    开始的时候把问题想复杂了,还好同事提醒了一下。主要描述一种思路,再配套一些关键代码。
    问题场景:标题栏一般分 返回、内容、设置(或者其它) 三部分,文字一般处于屏幕中间位置。假如右侧 设置 隐藏的时候 ,文字相对于屏幕就有些不在中间地方了。
    思路,首先可以动态控制内容的 padding 或者 margin 来进行控制。具体偏移值得计算如下:

    public  int px2dip(float pxValue){
        float scale = getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale * 3 + 0.5f);// 3 是 自己定义的
    }

    具体设置偏移值的代码举例如下:

    private void initEdtCenterLocation(){
        int imgW = img.getWidth();//图片宽度
        int result = px2dip(imgW);
        editText.setPadding(result,0,0,0);
    }

    注意:
    1、获取控件宽高的代码要在UI绘制完成后 获取,否则获取到的值为0
    2、如果内容过长会产生换行的情况,这时候要避免因为设置 padding 或者 margin而导致的空白问题,这里需要提前测量文字所要绘制的长度大小,这里可以具体百度一下,是有这方面代码的。
    3、如果中间的控件是EditText ,用户可以进行输入,这里要实现EditText的TextWatch监听,来进行动态更改偏移值。

    展开全文
  • oc,UITextFiled,怎么实现点击屏幕键盘自动隐藏和输入密码加密功能
  • 一、设置固定列 二、隐藏
  • xrandr设置屏幕分辨率,重启后失效 xrandr -s 1440x900_59.9 xrandr --output Virtual1 --mode 1440x900 问题描述: ubuntu16.04最初的“系统设置 --> 显示 --> 分辨率”里面只有1024 x 768 和 800 x 600两...
  • Ubuntu顶部有一条用于显示时间等信息的状态栏,而每一个程序却又有一个自己的标题栏,这样在宽屏的显示器上有效的显示面积就少了很多,即便是窗口最大化是,两个顶栏堆在屏幕上非常难看。本文将详细介绍如何自动隐藏...
  • MAC 隐藏属性设置方法

    千次阅读 2015-05-13 18:41:24
     在开始介绍这些隐藏属性开关之前,有必要给各位补充一下基础知识。OS X 操作系统和应用程序,大都是使用 Property List (.plist 文件) 存储用户偏好设置。 我们在系统偏好设置,或应用程序自身的偏好设置中看到的...
  • Loop at screen会loop处理屏幕上的每一个组件,并对其做相应的处理。 SELECTION-SCREEN: BEGIN OF BLOCK B1 WITH FRAME. PARAMETERS S_DATE TYPE DATUM DEFAULT SY-DATUM MODIF ID OO. SELECTION-SCREEN: END OF ...
  • //隐藏地球 viewer.scene.globe.show=false;
  • 窗口全屏 是指隐藏系统顶部用来显示时间、电量、信号等信息的。 标题栏,Activity全屏 是指隐藏程序的标题栏。我们可以在程序代码中设置,也可以通过修改AndroidManifest.xml文件来实现。 1. 修改程序代码 我们...