如何使用RPGLE在显示屏幕上显示消息文件中的消息?

时间:2018-08-10 13:34:09

标签: file io ibm-midrange rpgle

我已经在AS / 400中使用SDA设计了一个屏幕,该屏幕以一个ID号作为输入,并在两个PF中搜索该ID,并在屏幕上的各个字段中显示从这些PF提取的相应值。下面是DSPF代码:

 A*%%TS  SD  20180813  084626  PATELDH     REL-V7R1M0  5770-WDS 
 A*%%EC                                                         
 A                                      DSPSIZ(24 80 *DS3)      
 A          R HEADER                                            
 A*%%TS  SD  20180802  075026  PATELDH     REL-V7R1M0  5770-WDS 
 A                                  2  2USER                    
 A                                  2 30'PRODUCT INQUIRY SCREEN'
 A                                      COLOR(WHT)              
 A                                  2 63DATE                    
 A                                      EDTCDE(Y)               
 A                                  3 63TIME                    
 A          R FOOTER                                            
 A*%%TS  SD  20180802  074433  PATELDH     REL-V7R1M0  5770-WDS 
 A                                      OVERLAY                 
 A                                 22  4'F3=EXIT'               
 A          R DETAIL                                            
 A*%%TS  SD  20180813  073420  PATELDH     REL-V7R1M0  5770-WDS 
 A                                      CA03(03 'EXIT')         
 A                                      CA12(12 'PREVIOUS')     
 A                                      OVERLAY                             
 A                                  7 16'ID:'                               
 A                                 10 16'NAME:'                             
 A                                 12 16'CATEGORY:'                         
 A            @ID       R        I  7 20REFFLD(CATEGORIES/ID AS400KT2/RCATE-
 A                                      GORY)                               
 A            @NAME     R        O 10 22REFFLD(PRODUCTS/NAME AS400KT2/RPROD-
 A                                      UCTS)                               
 A            @CATEGORY R        O 12 26REFFLD(CATEGORIES/CATEGORY AS400KT2-
 A                                      /RCATEGORY)                         
 A          R MSGSFL                    SFL                                 
 A*%%TS  SD  20180803  054959  PATELDH     REL-V7R1M0  5770-WDS             
 A                                      SFLMSGRCD(24)                       
 A            MSGKEY                    SFLMSGKEY                           
 A            MSGQ                      SFLPGMQ(10)                         
 A          R MSGCTL                    SFLCTL(MSGSFL)                      
 A*%%TS  SD  20180813  084626  PATELDH     REL-V7R1M0  5770-WDS             
 A                                      OVERLAY                             
 A                                      SFLDSP                              
 A                                      SFLDSPCTL   
 A                                      SFLINZ      
 A  01                                  SFLEND      
 A                                      SFLSIZ(0002)
 A                                      SFLPAG(0001)
 A            MSGQ                      SFLPGMQ(10) 

我写了一个自由格式的RPGLE代码,使此屏幕正常工作。以下是RPGLE代码:

 FDSPPRD    CF   E             WorkStn                   
 FRPRODUCTS IF   E           K DISK                      
 FRCATEGORY IF   E           K DISK                      
 FRPRODCATEGO  A E           K DISK                      
 DtempID           S                   LIKE(ID)          
 DmsgID            S              7A                     
 DmsgF             S             10A                     
 D getMsg          PR                  EXTPGM('MSGSFLCL')
 D  msgID                         7A                     
 D  msgF                         10A                     
  /Free                                                  
     DoW *In03 = *Off;                                   
      Write HEADER;                                      
      Write FOOTER;                                      
      ExFmt DETAIL;                                      
      If @ID = *Zeros;                                   
          msgID = 'MSG0001';                             
          msgF = 'ASGNMSGF';                             
          getMsg(msgID:msgF);                            
      Else;                       
       Chain @ID RPRODUCTS;       
       If %Found(RPRODUCTS);      
          @NAME = NAME;           
          Chain ID RCATEGORY;     
          If %Found(RCATEGORY);   
             @CATEGORY = CATEGORY;
          EndIf;                  
       EndIf;                     
      EndIf;                      
     EndDo;                       
      *InLR = *On;                
  /End-Free                       

下面是RPGLE程序调用的CL程序,用于从msgfile获取消息文本:

         PGM       PARM(&MSGID &MSGF)             
         DCL       VAR(&MSGID) TYPE(*CHAR) LEN(7) 
         DCL       VAR(&MSGF)  TYPE(*CHAR) LEN(10)

         SNDPGMMSG MSGID(&MSGID) MSGF(&MSGF)      
         ENDPGM                                   

下面是从中读取记录的两个PF:

RPRODUCTS-

 A          R PRODUCTS           
 A            ID             2P 0
 A            NAME          16A  
 A          K ID                 

RCATEGORY-

 A          R CATEGORIES         
 A            ID             2P 0
 A            CATEGORY      15A  
 A          K ID                 

以上所有代码均已成功编译。但是问题是msgf中的msg没有出现在屏幕上。休息所有的工作。当我按Enter键且屏幕上显示空白ID时,仅显示msgf中的msg。有人可以建议一个信息来源,从那里我可以学习这种应用程序的概念。另外,希望对此有所帮助。

1 个答案:

答案 0 :(得分:2)

您没有写MSGCTL记录。如果您不这样写,那么消息子文件将不会显示。您也没有提供MSGQ的值。

使用消息子文件时,通常从程序状态数据结构中获取程序名称,并在程序初始化期间将其放入MSGQ中。它永远不会改变。我还将其传递给将消息发送到消息队列的过程。这样,我知道两个值将相同。如果不是,则消息不会显示。

这是我的消息子文件定义:

 A* ========================================================================
 A* Message Subfile
 A* ------------------------------------------------------------------------
 A          R MSGSFL                    SFL
 A                                      SFLMSGRCD(27)
 A            MSGKEY                    SFLMSGKEY
 A            PGMQ                      SFLPGMQ(10)
 A* ------------------------------------------------------------------------
 A* Message Subfile Control
 A* ------------------------------------------------------------------------
 A          R MSGCTL                    SFLCTL(MSGSFL)
 A                                      SFLPAG(1)
 A                                      SFLSIZ(2)
 A                                      SFLDSP SFLDSPCTL
 A                                      SFLINZ
 A  53
 AON53                                  SFLEND
 A            PGMQ                      SFLPGMQ(10)

与您只有几处区别。让我们经历一下。

 A                                      SFLMSGRCD(27)

这是27,因为我使用的是*DS4屏幕尺寸。没问题。

您使用的是OVERLAY,不是因为我先写那种格式,而是只要您在写完MSGCTL之后再写HEADER,就可以了。

您正在使用SFLCLR。没必要,将其删除。

 A  53
 AON53                                  SFLEND

这有点不同。之所以这样做,是因为SFLEND需要一个条件指示器,但是我真的不在乎,无论该指示器说什么,我都希望SFLEND处于活动状态。 (我也将*In53用作常规子文件的SFLEND,所以我不必担心它是打开还是关闭。

我使用子过程发送消息:这是我的代码:

// ----------------------------------------
// SndDspfMsg - sends an *INFO message to the
//     message subfile in a display file.
//
// Parameters:
//  StackEntry - The program call stack entry to which the message is sent.
//               Usually the program name. This must be the same value that
//               is placed in the SFLPGMQ variable in the message subfile
//               control format.
//  MsgId - The Message ID from message file JCMSGF to be sent to the program
//               message Queue.
//  MsgDta - (optional) Data to be used by the message to provide dynamic
//               message content. Defaults to blank.
//  MsgDtaLen - (optional) The length of the message data provided above.
//               This parameter is required if MsgDta is provided. Defaults
//               to zero. If this is not provided or is zero, MsgDta is ignored.
// ----------------------------------------
dcl-proc SndDspfMsg Export;
  dcl-pi *n;
    StkEnt      Char(10)  Const;
    MsgId       Char(7)   Const;
    MsgDta      Char(512) Const Options(*VarSize: *NoPass);
    MsgDtaLen   Int(10)   Const Options(*NoPass);
  end-pi;

  dcl-s Name_t           Char(10) Template Inz('');

  // Call Stack Qualifier - used by message handling APIs
  dcl-ds CallStackQual_t  Qualified Template Inz;
    Module                Like(Name_t) Inz('*NONE');
    Program               Like(Name_t) Inz('*NONE');
  end-ds;

  // Qualified Name
  dcl-ds QualName_t       Qualified Template Inz;
    Name                  Like(Name_t) Inz('');
    User                  Like(Name_t) Inz('');
  end-ds;

  // Standard Error Code Format
  dcl-ds ErrorCdType1_t   Qualified Template Inz;
    BytesProv             Int(10)   Inz(%size(ErrorCdType1_t));
    BytesAvail            Int(10);
    MsgId                 Char(7);
    Data                  Char(1024) Pos(17);
  end-ds;

  dcl-ds MsgFile       LikeDs(QualName_t) Inz(*LikeDs);
  dcl-ds ErrorCd       LikeDs(ErrorCdType1_t) Inz(*LikeDs);

  dcl-s pmMsgDta         Char(512) Inz('');
  dcl-s pmMsgDtaLen      Int(10)   Inz(0);
  dcl-s pmMsgTyp         Char(10)  Inz('*INFO');
  dcl-s pmStkCnt         Int(10)   Inz(0);
  dcl-s pmMsgKey         Char(4)   Inz('');

  // Send Program Message
  dcl-pr qmhsndpm        ExtPgm('QMHSNDPM');
    MessageId            Char(7)    Const;
    MessageFile          LikeDs(QualName_t) Const;
    MessageDta           Char(512)  Const Options(*Varsize);
    MessageLen           Int(10)    Const;
    MessageType          Char(10)   Const;
    StackEntry           Char(4102) Const Options(*Varsize);
    StackCounter         Int(10)    Const;
    MessageKey           Char(4);
    Error                LikeDs(ErrorCdType1_t);
    StackEntryLen        Int(10)    Const Options(*NoPass);
    StackEntryQual       LikeDs(CallStackQual_t)
                                    Const Options(*NoPass);
    ScreenWaitTime       Int(10)    Const Options(*NoPass);
    StackEntryType       Char(10)   Const Options(*NoPass);
    Ccsid                Int(10)    Const Options(*NoPass);
  end-pr;      

  // Handle *NoPass Parms
  if %parms() >= %parmnum(MsgDtaLen);
    pmMsgDtaLen = MsgDtaLen;
  endif;

  // if Message Data is provided,
  if pmMsgDtaLen > 0;
    pmMsgDtaLen = min(%size(pmMsgDta): pmMsgDtaLen);
    pmMsgDta = %subst(MsgDta: 1: pmMsgDtaLen);
  endif;

  MsgFile.Name = 'JCMSGF';
  qmhsndpm(MsgId: MsgFile: pmMsgDta: pmMsgDtaLen:
           pmMsgTyp: StkEnt: pmStkCnt: pmMsgKey:
           ErrorCd);
end-proc;

这应该使您的消息子文件正常工作。至于为什么未填充其他字段的原因,可能在文件中找不到您的产品ID和类别ID。注意,由于ID被映射到显示文件,产品文件和类别文件,因此该程序运行时产品ID和类别ID将是相同的值。这似乎不是您想要的。如果您在处理该问题时遇到问题,请提出一个新问题。