How to get Button Control USE name or Any Window Control

I saw this post out in DiscussSV Clarion 11 and thought it had some useful content that was not on the Hub.

Oggy posted:

How to get button(s) use variable name?
for example:

  Loop k# = FIRSTFIELD() to LASTFIELD()
      IF k#{prop:type} =  Create:Button
          stop(k#&' , '&k#{PROP:use}) ! I need to get used name of button control
      END
  END

Jeff replied with a perfect example of using the undocumented RTL function Cla$FIELDNAME:

  PROGRAM
  MAP
    MODULE('')
      FEQtoFieldName (SIGNED pFeq), *CSTRING, RAW, NAME('Cla$FIELDNAME')
    END
  END

Window      WINDOW('Caption'),AT(,,395,224),GRAY,FONT('Segoe UI',9)
              BUTTON('&OK'),AT(291,201,41,14),USE(?OkButton),DEFAULT
              BUTTON('&Cancel'),AT(340,201,42,14),USE(?CancelButton)
            END
  CODE
  OPEN(Window)
  MESSAGE('?OkButton  FEQ='& ?OkButton & |
         '|FEQ to Field Name='& FEQtoFieldName(?OkButton)) 

Above I enhanced the original MESSAGE(FEQtoFieldName(?OkButton))

2 Likes

I normally wrap calls to the Cla$FIELDNAME function to catch some problems. If there is no USE(), or the FEQ is invalid, then the FieldName returns blank so this returns __Feq_####__ to have an idea of what control it was. When FEQ=0 it returns 'Window' … I know of no way to get the Window Label at runtime.

  MAP
ClaFeqName          PROCEDURE(LONG Feq),STRING,PRIVATE    
      MODULE('RTL')
ClaFieldNameRTL     PROCEDURE(LONG pFEQ),CSTRING,RAW,NAME('Cla$FIELDNAME'),DLL(dll_mode)
      END
  END

ClaFeqName PROCEDURE(LONG F)!,STRING
n CSTRING(128)
  CODE
  if ~F then return 'Window'. 
  n=ClaFieldNameRTL(F)
  if n <= ' ' then 
     n = '__Feq_'& F &'__'  !No USE(?xx) so return __Feq_#__
  end
  return n

A related post is this that gets the FEQ for a Report control

One other detail is FIRSTFIELD() and LASTFIELD() are somewhat deprecated as they can return control numbers that do not exist due to gaps. The better way is to use PROP:NextField:

FldNo LONG
    CODE 
    FldNo = 0
    LOOP 
        FldNo = 0{PROP:NextField, FldNo}    !instead of First / LastField()
        IF FldNo = 0 THEN BREAK.
        IF FldNo{prop:Type} =  Create:Button
           stop('FEQ='& FldNo &' , Use='& ClaFeqName(FldNo) ) 
        END        
    END 
2 Likes