Release 10.1A: OpenEdge Development:
Progress 4GL Handbook

> ## Creating the window

> Now things are going to get a little more interesting. The next part of the generated code, labeled Create Window, has a new type of statement in it that requires a brief explanation of a very basic Progress 4GL concept, that of static versus dynamic objects.

> ##### Static objects

> Your procedure contains several `DEFINE` statements in it for a variable, a browse, and four buttons. These are called static objects because they are fully defined in the 4GL syntax that names them. Because of this, the Progress compiler knows most everything it needs to know about them when it compiles the procedure. This allows the compiler to store a complete structure in the r-code that defines each static object. At run time the interpreter scans the r-code and builds each object based on its definition.

> ##### Dynamic Objects

> The window is a different kind of object—a dynamic object. You use a `CREATE` statement rather than a `DEFINE` statement for it. When you create the object you associate the object with a `HANDLE` variable that must already be defined. It is for this that the `DEFINE VARIABLE CustWin` statement you saw earlier was coded. The handle acts as a pointer to a structure that describes the object, but it’s different from the structure resulting from a `DEFINE` statement in that the structure is only built up at run time, as the program is executing. This allows you to set some or all of the object’s attributes based on program conditions. So, in effect, the `CREATE` statement creates an empty shell to be filled in with the object’s description, and the handle points to that shell. Here’s the `CREATE` statement for your window:

>     CREATE WINDOW CustWin ASSIGN
>              HIDDEN             = YES
>              TITLE              = "Customers and Orders"
>              HEIGHT             = 13.67
>              WIDTH              = 86
>              MAX-HEIGHT         = 16
>              MAX-WIDTH          = 86.2
>              VIRTUAL-HEIGHT     = 16
>              VIRTUAL-WIDTH      = 86.2
>              RESIZE             = yes
>              SCROLL-BARS        = no
>              STATUS-AREA        = no
>              BGCOLOR            = ?
>              FGCOLOR            = ?
>              KEEP-FRAME-Z-ORDER = yes
>              THREE-D            = yes
>              MESSAGE-AREA       = no
>              SENSITIVE          = yes.

> Around this code is an`IF-THEN-ELSE` statement:

>     IF SESSION:DISPLAY-TYPE = "GUI":U THEN
>       CREATE WINDOW CustWin …
>     ELSE {&WINDOW-NAME} = CURRENT-WINDOW.

> This rather cryptic-looking sequence effectively says: “If you’re running in the GUI environment, as opposed to on a character device, then create the new window `CustWin`, which will appear as its own identifiable display space on the desktop. Otherwise use the default (and only) window that’s always there for character environments.”

> This `DISPLAY-TYPE` test is the answer to a question that might have popped into your head:

> Why has the AppBuilder made the window dynamic when everything else is static?

> There is no `DEFINE WINDOW` statement in the 4GL, only the `CREATE WINDOW` statement. And this, in turn, is because Progress 4GL procedures are designed to be compilable for different environments largely without change, including graphical and character environments. There’s only one “window” in a character environment, and that is the entire display device. So your code can never ask a character device to create another window. Thus, to have the same code compile and run in both GUI and character, creating the window the GUI environment requires must be conditional. And that is exactly what dynamic objects are for: to let your procedures decide at run time what objects to create and what attributes to give them.

> To set a dynamic object’s attributes, you normally reference the handle in later program statements. However, in this case the `CREATE WINDOW` statement itself has an `ASSIGN` phrase that sets all the window’s attributes to their proper initial values. In principle, you can define a dynamic object by associating it with a handle, and then set and reset its attributes as needed.

> ##### Setting attributes of dynamic objects

> The next part of the procedure consists of mostly internal comments for the AppBuilder’s benefit, but there’s one executable statement in it, and you’ll look at it to learn one or two more things about dynamic objects:

>     IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(CustWin)
>     THEN CustWin:HIDDEN = no.

> This statement means: “If the session’s Display Type is GUI and the window handle named `CustWin` is valid, then set the window’s `HIDDEN` attribute to no.”

> The `VALID-HANDLE` built-in function tests to see if the structure the handle points to has been properly associated with an object.

> Will the handle be valid? It should be because the procedure created the window that uses it just above this. But in your own procedures, you can use handles long after they’re defined. You must always make sure that they point to valid structures before you use them.

> This language statement demonstrates that in the 4GL you can set the attributes of a dynamic object after the `CREATE` statement by using a reference to the object’s handle, followed by a colon, followed by the attribute name. You can read attributes in the same way, as in:

> ``

>     IF CustWin:HIDDEN = no THEN
>          .
>          .
>          .

> ``

> Using dynamic objects is a very powerful way to write general-purpose procedures that can handle a whole set of variations on any common pattern in your application, whether it is windows with different titles, sizes, and contents, or browses on different queries with different columns displayed. You’ll learn a lot more about these dynamic language constructs in later chapters.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095