Checking for open dialogbox in ABL using the widget tree?

Posted by MBeynon on 07-Jan-2019 16:02

Is it possible to walk the widget tree in ABL and determine if there is an open diolog box?

I can get the type of NEXT-SIBLING but it always seems to be "WINDOW".

Thanks.

All Replies

Posted by James Palmer on 07-Jan-2019 16:09

You need to check FIRST-CHILD as well IIRC. A Dialog is a Child of a Window.

Posted by Patrick Tingen on 07-Jan-2019 18:00

See if there are attributes that are different between dialogs and normal windows. Afaik a dialog is a frame widget, so my first guess would be to check if there is a child (or grandchild) of the widget you are examining that is of type 'frame'. I suspect that a normal window will have such a child and a dialog not.

Posted by Matt Gilarde on 07-Jan-2019 18:56

The TYPE attribute of a dialog-box frame returns "DIALOG-BOX".

Posted by MBeynon on 08-Jan-2019 08:38

Thanks for the help.

I got a working solution...quite simple really by just passing in the current window;

PROCEDURE WalkTheTree:
    /*------------------------------------------------------------------------------
            Purpose:                                                                        
            Notes:                                                                        
    ------------------------------------------------------------------------------*/

  DEFINE INPUT PARAMETER LV_WIDGET_HANDLE AS HANDLE.
 
  DEFINE VARIABLE lvhChild        AS HANDLE NO-UNDO.
 
  lvhChild = LV_WIDGET_HANDLE:FIRST-CHILD.
  DO WHILE lvhChild <> ?:
 
    IF VALID-HANDLE(lvhChild) THEN
      IF lvhChild:TYPE = "DIALOG-BOX" THEN
        RETURN ERROR.

    lvhChild = lvhChild:NEXT-SIBLING.
  END.

END PROCEDURE.

Posted by Patrick Tingen on 08-Jan-2019 10:40

Not meant offensive, but I find style and naming used in the example not so simple; why do you return an error and why is your procedure called 'WalkTheTree'. Surely it does something more than just walk the tree.

Keep in mind that someone else will eventually read this code too. This person might be yourself in a few years. You should give as much clue as possible to the future reader to what this code is actually doing.

Personally, I find something like the below more readable:

FUNCTION getWindowType RETURNS CHARACTER
  (phWidget AS HANDLE):
  
  phWidget = phWidget:FIRST-CHILD.

  DO WHILE VALID-HANDLE(phWidget):
    IF phWidget:TYPE = "DIALOG-BOX" THEN RETURN "DIALOG-BOX".
    phWidget = phWidget:NEXT-SIBLING.
  END.

  RETURN "WINDOW".
END FUNCTION. /* getWindowType */

Although one could argue that it would be even better to create an ENUM for window types and return that.

Posted by Stefan Drissen on 08-Jan-2019 11:18

And I don't mean to be offensive ( ;-) ), but why are you changing the function input parameters? To save a variable?

Function parameters do /not/, nor can they be NO-UNDO.

Besides the "performance" loss, I dislike inputs being mangled while debugging.

function foo returns logical (
   i_ibar as integer
):

   def var ibar_original as int no-undo.
   
   ibar_original = i_ibar.

   do transaction:
   
      i_ibar = i_ibar + 1.
      
      undo.
      
   end.

   return i_ibar = ibar_original.

end function.

message foo( 1 ) view-as alert-box.

Posted by Patrick Tingen on 08-Jan-2019 12:33

I generally do not change input parameters since I dislike it as well, but for small functions I sometimes don't follow that rule. The 'clutter' of an extra variable in those cases outweigh the dislike of changing an input parameter. In larger or more complex functions I don't do these things.

I regularly abuse my own rules (more political correct would be to say that my rules are flexible). For example: in assign statements I normally use multiple lines, except when it is only one var or field. Same with commands like SUBSTITUTE and RUN. If they are large or complex, I use multiple lines, otherwise they go on one line. I always try to keep readability in mind. However, that remains in the eye of the beholder.

Posted by Stefan Drissen on 08-Jan-2019 13:05

Sorry - I had always wondered about the undo'ness of function parameters - so created the small example above. The example actually demonstrates that they /are/ no-undo, sorry for the confusion.

Posted by Peter Judge on 08-Jan-2019 13:59

> Although one could argue that it would be even better to create an ENUM for window types and return that.

+1 this idea.  

FWIW in $DLC/[src|tty\gui]/OpenEdge.Core.pl there are a number of (native ABL) enums for a variety of things (IO modes, etc). Not all (and not these widget types) but they are there if needed.

You can use them to get to the name aspect via the enum's ToString() method or simply using the ABL's STRING() function.

This thread is closed