Get label of USE variable of REPORT control at runtime

Been bit by that local map thing, for sure.

Jeff I added/changed some things for these reasons:

  1. Prototype change WINDOW to REPORT. Works the same, more obvious to pass REPORT.
  2. For Header,Detail,Footer… types that cannot clone to WINDOW by return “_Type_FEQ_#
  3. If blank FEQ Name returned by ClaFieldNameRTL() then return "_RptFEQ_#
  4. Open Dummy Window will change Target() so restore SetTarget(Report)
RptControlFEQName PROCEDURE(LONG ControlFEQ, REPORT ReportRef)!,STRING   !works passing REPORT 
DummyWindow WINDOW,AT(-10,-10,1,1)
            END
CloneFEQ  LONG,AUTO
TargetWas LONG,AUTO     !Restore a SetTarget(Report) after Open/Close Window
NameFEQ   CSTRING(128),AUTO
  CODE
  CASE ReportRef $ ControlFEQ{PROP:Type}
  OF CREATE:Window ; NameFEQ='_Window' &'_FEQ_'& ControlFEQ &'_' !Passed (0,Window)
  OF CREATE:Report ; NameFEQ='_Report' &'_FEQ_'& ControlFEQ &'_' !Passed (0,Report)
  OF CREATE:Header ; NameFEQ='_Header' &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Footer ; NameFEQ='_Footer' &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Break  ; NameFEQ='_Break'  &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Form   ; NameFEQ='_Form'   &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Detail ; NameFEQ='_Detail' &'_FEQ_'& ControlFEQ &'_'
  ELSE
     TargetWas = SYSTEM{PROP:Target}
     OPEN(DummyWindow)
     CloneFEQ = CLONE(0,ControlFEQ,,,ReportRef) !Clone Rpt Control to Window
     NameFEQ = ClaFieldNameRTL(CloneFEQ)        !Can get FEQ Name from Window
     IF NameFEQ <= ' ' THEN                     !If returned Blank / low ASCII 
        NameFEQ = '_RptFEQ_'&  ControlFEQ &'_'  !   Then tell caller FEQ#
     END
     CLOSE(DummyWindow)
     IF TargetWas = ADDRESS(ReportRef) THEN SETTARGET(ReportRef).
  END
  RETURN NameFEQ

!======================= Global Map =======================
    MAP
RptControlFEQName   PROCEDURE(LONG ControlFEQ, REPORT ReportRef),STRING
      MODULE('RTL')     !This must be declared in the Global Map
        ClaFieldNameRTL(LONG pFEQ),CSTRING,RAW,NAME('Cla$FIELDNAME'),DLL(dll_mode)
      END      
    END

Below example of it working:
FeqNameReport_Example.zip (3.0 KB)

  PROGRAM
  MAP
TestMain            PROCEDURE()  !Test in procedure so data is not Global
RptControlFEQName   PROCEDURE(LONG ControlFEQ, REPORT ReportRef),STRING   !works fine passing REPORT 
      MODULE('RTL')     !This must be declared in the Global Map
        ClaFieldNameRTL(LONG pFEQ),CSTRING,RAW,NAME('Cla$FIELDNAME'),DLL(dll_mode)
      END      
      MODULE('WinAPI')
        OutputDebugString(*cstring Msg),PASCAL,RAW,NAME('OutputDebugStringA'),DLL(1)
      END  
ClaControlTypeName  PROCEDURE(LONG CtrlPropType),STRING
DB                  PROCEDURE(STRING DebugText)  !Debug Output
    END 
    CODE
    TestMain()
!============================================
TestMain    PROCEDURE()
String1     STRING(40)
EndOfReport BYTE
Report REPORT('FEQName'),AT(1000,2000,6000,7000),FONT('Arial',10),PRE(RPT),THOUS
        HEADER,AT(1000,1000,6000,1000),USE(?HEADER1)
            STRING('Report Test FEQ Name'),AT(1740,94,2500),USE(?HeadStr1),TRN,CENTER,FONT(,,,FONT:bold)
            STRING('(Clone to Window)'),AT(1740,292,2500),USE(?SubHeadStr1),TRN,CENTER,FONT(,,,FONT:bold)
            BOX,AT(219,583,5573,219),USE(?BOX1),COLOR(COLOR:Black),FILL(COLOR:White),LINEWIDTH(1)
        END
BreakEOR BREAK(EndOfReport),USE(?Break_EndOfReport)
DetailSKip  DETAIL,AT(0,0,6000,542),USE(?DetailSKip)
                STRING(@s40),AT(167,146),USE(String1)
                STRING(@s40),AT(3167,146), USE(String1,, ?String1:skip),SKIP
                LINE,AT(198,396,5500),USE(?LineDetail1)
            END
        END
        FOOTER,AT(1000,9000,6000,250),USE(?FOOTER1)
        END
        FORM,AT(1000,1000,6000,9000),USE(?FORM1)
        END
    END
NextFEQ     LONG 
Dbg1        PSTRING(256)
DbgAll      ANY
    CODE
    OPEN(Report)    
    DB('=== TOP == Enumerate Report Controls === '& Command('0') )
    SetTarget(Report)   !Safer to do this every LOOP, but FEQ Name has a SetTarget() fixup
    NextFEQ = 0
    LOOP
        NextFEQ = Report{PROP:NextField,NextFEQ}
        IF ~NextFEQ THEN BREAK. 
        Dbg1 = 'FEQ#=' & NextFEQ & |
               '<9>Type='& NextFEQ{PROP:Type} & |
                     ' '& ClaControlTypeName(NextFEQ{PROP:Type}) & |
               ' <9> FEQ Name=' & RptControlFEQName(NextFEQ,REPORT)
        DB(Dbg1)
        DbgAll = DbgAll & Dbg1 & '<13,10>'
    END
    DB('=== END ===')
    Message(DbgAll,'RptControlFEQName() Example',Icon:Print1,,,MSGMODE:FIXEDFONT)
    RETURN 
!============================================================================
DB   PROCEDURE(STRING xMessage)
Prfx EQUATE('FeqNameRpt: ')   !All output gets this
sz   CSTRING(SIZE(Prfx)+SIZE(xMessage)+3),AUTO
  CODE
  sz  = Prfx & CLIP(xMessage) & '<13,10>'
  OutputDebugString( sz )
  RETURN
!============================================================================
ClaControlTypeName PROCEDURE(LONG CtrlPropType)!,STRING  !Pass FEQ{PROP:Type} to get name e.g. Button
TypeName    STRING(24)
    CODE        
!Edit: This was returning 'Window' if Zero is passed as Type. That is Wrong. Changed to Type?0
    TypeName=CHOOSE(BAND(CtrlPropType,0FFh)+1,'Type?0', | 
        'SString','String','Image','Region','Line','Box','Ellipse','Entry','Button','Prompt',|          !1-10
        'Option','Check','Group','List','Combo','Spin','Text','Custom','Menu','Item',|                  !11-20
        'Radio','MenuBar','Create23','Application','Window','Report','Header','Footer','Break','Form',| !21-30
        'Detail','Ole','Droplist','Dropcombo','Progress','Slider','Sheet','Tab','Panel','TextRtf',|     !31-40
        'Text_SingleLine','Check3','Type?' & CtrlPropType)                                              !41-42
    CASE CtrlPropType
    OF CREATE:ToolBar   ;  TypeName='ToolBar'  !ToolBar is 128
    OF CREATE:SubList   ;  TypeName='SubList-' & TypeName     !DropList is 270=10Eh CREATE:sublist  EQUATE(CREATE:list + 0100H) 
    OF CREATE:SubList+1 ;  TypeName='ButtonDrop-' & TypeName  !DropButto  is 271=10Fh CREATE:sublist  EQUATE(CREATE:list + 0100H) 
    OF 100h TO 100h+42   !CREATE:sublist  EQUATE(CREATE:list + 0100H)
       TypeName='SubList-' & TypeName    
    END 
    RETURN CLIP(TypeName) 

!============================================================================
! Changes to RptControlFEQName:
! 1. Prototype change WINDOW to REPORT. Works the same, more obvious to pass REPORT.
! 2. For Header,Detail,Footer... types that cannot clone to WINDOW by return "`_Type_FEQ_#`"
! 3. If blank FEQ Name returned by ClaFieldNameRTL() then return "`_RptFEQ_#`'
! 4. Open(DummyWindow) will change Target() so restore SetTarget(Report)
!============================================================================
RptControlFEQName PROCEDURE(LONG ControlFEQ, REPORT ReportRef)!,STRING   !works passing REPORT 
!To get a Report Control USE(FeqName) clone it to a Window
DummyWindow WINDOW,AT(-10,-10,1,1)
            END
CloneFEQ  LONG,AUTO
TargetWas LONG,AUTO     !Restore a SetTarget(Report) after Open/Close Window
NameFEQ   CSTRING(128),AUTO
  CODE
  CASE ReportRef $ ControlFEQ{PROP:Type}
  OF CREATE:Window ; NameFEQ='_Window' &'_FEQ_'& ControlFEQ &'_' !Passed (0,Window)
  OF CREATE:Report ; NameFEQ='_Report' &'_FEQ_'& ControlFEQ &'_' !Passed (0,Report)
  OF CREATE:Header ; NameFEQ='_Header' &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Footer ; NameFEQ='_Footer' &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Break  ; NameFEQ='_Break'  &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Form   ; NameFEQ='_Form'   &'_FEQ_'& ControlFEQ &'_'
  OF CREATE:Detail ; NameFEQ='_Detail' &'_FEQ_'& ControlFEQ &'_'
  ELSE
     TargetWas = SYSTEM{PROP:Target}
     OPEN(DummyWindow)
     CloneFEQ = CLONE(0,ControlFEQ,,,ReportRef) !Clone Rpt Control to Window
     NameFEQ = ClaFieldNameRTL(CloneFEQ)        !Can get FEQ Name from Window
     IF NameFEQ <= ' ' THEN                     !If returned Blank / low ASCII 
        NameFEQ = '_RptFEQ_'&  ControlFEQ &'_'  !   Then tell caller FEQ#
     END
     CLOSE(DummyWindow)
     IF TargetWas = ADDRESS(ReportRef) THEN SETTARGET(ReportRef).
  END
  RETURN NameFEQ
3 Likes