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.
You need to check FIRST-CHILD as well IIRC. A Dialog is a Child of a Window.
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.
The TYPE attribute of a dialog-box frame returns "DIALOG-BOX".
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.
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.
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.
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.
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.
> 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.