## Creating secondary windows and cascading menus.

This example is a very simple demonstration of how to set up a cascading menu in Win32lib, and how to create secondary, or 'child' windows in a program. The parent window will allow you to open one of two secondary windows with slightly different styles. The cascading menu is contained within one of these secondary windows, and actually allows you to exit the whole program from within it's menu.

-- childwin.exw

    -- Wolf/Jan.26/99

    include win32lib.ew
    without warning

    constant
    -- first, create the parent window, and it's menu.
      ParentWin        = create( Window, "Parent window", 0, 0, 0, 320, 110, 0 ),
      List1            = create( List, "", ParentWin, 2, 2, 308, 60, 0 ),

      ParentCloseMenu  = create( Menu, "&Close", ParentWin, 0, 0, 0, 0, 0 ),
      CloseParentMenu  = create( MenuItem, "Parent window", ParentCloseMenu, 0, 0, 0, 0, 0 ),
      ParentCreateMenu = create( Menu, "C&reate", ParentWin, 0, 0, 0, 0, 0 ),
      CreateChildMenu  = create( MenuItem, "&Child Window", ParentCreateMenu, 0, 0, 0, 0, 0 ),
      CreateEntryMenu  = create( MenuItem, "&Entry Window", ParentCreateMenu, 0, 0, 0, 0, 0 ),

    -- then create the first secondary window, and it's menu.
      ChildWin         = create( Window, "Child window", ParentWin, 30, 30, 320, 100, {WS_CAPTION,WS_SYSMENU,WS_THICKFRAME} ),
      ChildCloseMenu   = create( Menu, "&Close", ChildWin, 0, 0, 0, 0, 0 ),
      EitherMenu       = create( Menu, "Either", ChildCloseMenu, 0, 0, 0, 0, 0 ),

    -- here is our menu cascade. Note that they are both 'linked'
    -- to EitherMenu, which is a Menu, NOT a MenuItem.
      CloseChildMenu   = create( MenuItem, "C&hild window,", EitherMenu, 0, 0, 0, 0, 0 ),
      CloseBothMenu    = create( MenuItem, "or &Parent + Child.", EitherMenu, 0, 0, 0, 0, 0 ),

    -- here we create the second 'child', with buttons only.
      EntryWindow      = create( Window, "Entry Window", ChildWin, 30, 30, 402, 85, {#C40000} ),
      Label1           = create( LText, "enter something!", EntryWindow, 1, 4, 110, 20, 0) ,
      Entry1           = create( EditText, "", EntryWindow, 115, 2, 277, 20, 32 ),
      btnAdd           = create( PushButton,"Add to List", EntryWindow, 2, 28, 90, 25, 0 ),
      btnQuit          = create( PushButton, "QUIT", EntryWindow, 302, 28, 90, 25, 0 )

    -- change the color of the second 'child', just to emphasize!
      setWindowBackColor(EntryWindow, rgb(0,255,0))

    -- this quits everything, since shutting down a parent
    -- takes the children away too.
    procedure onMenu_Exit( integer self, integer event, sequence params )
      closeWindow(ParentWin)
    end procedure

    -- kill the first 'child'.
    procedure onMenu_Exit_Child( integer self, integer event, sequence params )
      closeWindow(ChildWindow)
    end procedure

    -- this procedure 'writes' our text to the 'child' window
    -- every time it is 'opened'
    procedure paint_child()
      setPenPos(ChildWindow,0,0)
      wPuts(ChildWindow,"this child is MODAL, without min/max buttons.")
      setPenPos(ChildWindow,0,20)
      wPuts(ChildWindow,"  ..just perfect for entry forms!")
    end procedure

    procedure show_child( integer self, integer event, sequence params)
      openWindow(ChildWindow,Modal)
    -- Modal, here, means you can't get back to the parent,
    -- without closing the child.
      paint_child()
    end procedure

    -- this opens the second child window.
    procedure show_entry_form( integer self, integer event, sequence params)
      openWindow(EntryWindow,Modal)
      setFocus(Entry1)
    end procedure

    -- this adds the item from the entry form window,
    -- to the list in the parent, and clears the entry sle
    -- for new input.
    procedure onClick_btnAdd( integer self, integer event, sequence params)
      if length(getText(Entry1)) != 0 then  -- anything there ?
        addItem(List1,getText(Entry1))      -- if so, add it.
      end if
      setFocus(Entry1)     -- go back to entry sle,
      setText(Entry1,{})   -- and clear it.
    end procedure

    procedure onClick_btnQuit()
      closeWindow(EntryWindow)
      if getCount(List1) > 0 then        -- is anything there ?
        setIndex(List1,getCount(List1))  -- if so, focus on last item.
      end if
      setFocus(List1)
    end procedure

The next three procedures add some keyboard handling routines to three of our 'control' windows. I should mention that most of the 'keyboard' values are now defined in Win32lib, so the numbers, ( 13, and 27 ), are actually equivalent to Win32lib's global constants VK_RETURN and VK_ESCAPE.

    -- let the ENTER key work for all entry window items. !
    procedure onKey_Entry1( integer self, integer event, sequence params)
     integer key = params[1]
     if key=13 then onClick_btnAdd( self, event, params )
     elsif key=27 then onClick_btnQuit( self, event, params )
     end if
    end procedure

    procedure onKey_btnAdd( integer self, integer event, sequence params)
     integer key = params[1]
     if key=13 then onClick_btnAdd( self, event, params ) else end if
    end procedure

    procedure onKey_btnQuit( integer self, integer event, sequence params)
     integer key = params[1]
     if key=13 then onClick_btnQuit( self, event, params ) else end if
    end procedure

    -- all the event handlers
    setHandler( CloseParentMenu, w32HClick, routine_id("onMenu_Exit") )
    setHandler( CreateChildMenu, w32HClick, routine_id("show_child") )
    setHandler( CloseChildMenu, w32HClick, routine_id("onMenu_Exit_Child") )
    setHandler( CloseBothMenu, w32HClick, routine_id("onMenu_Exit") )
    setHandler( CreateEntryMenu, w32HClick, routine_id("show_entry_form") )
    setHandler( btnAdd, w32HClick, routine_id("onClick_btnAdd") )
    setHandler( btnQuit, w32HClick, routine_id("onClick_btnQuit") )
    setHandler( Entry1, w32HKeyDown, routine_id("onKey_Entry1") )
    setHandler( btnAdd, w32HKeyDown, routine_id("onKey_btnAdd") )
    setHandler( btnQuit, w32HKeyDown, routine_id("onKey_btnQuit") )

    WinMain( ParentWin,Normal )
    -- end --

About Window Styles:
The last parameter in create(Window, ... can determine some of the style attributes of the window.
The default style ( 0 ) is already defined by Mr. Cuny in Win32lib.ew,s createWindow() procedure as the following:

      WS_OVERLAPPEDWINDOW =        hex value #CF0000
        or_all({  WS_OVERLAPPED,             #000000
               WS_CAPTION,                   #C00000 -- the title bar
               WS_SYSMENU,                   #080000 -- 'menu' in icon
               WS_THICKFRAME,                #040000 -- a nice border
               WS_MINIMIZEBOX,               #020000 -- minimize button
               WS_MAXIMIZEBOX}),             #010000 -- maximize button

I have changed the default styles in the two secondary windows to show some of the options you can use.
In the first secondary window ( Child ), I have removed the minimize/maximize buttons, since there is obviously no need for them. The hexadecimal value is just the or_all() of the desired options. In this case I have just removed WS_MINIMIZEBOX, and WS_MAXIMIZEBOX, to get the value #CC0000.

In the secondary entry window I have also removed WS_SYSMENU, so there is no program icon in the caption bar, and therefore no active 'x' to exit button. This gave me the #C40000 value.

The *magic* number ( #C40000 ), can, obviously, just be replaced by calling the function:

or_all( {WS_CAPTION, WS_THICKFRAME} ),

as the last 'create' parameter.

You can play around with all the options listed in Win32lib.ew under -- Window Styles, to get whatever you might prefer. Just be careful with WS_DISABLED , as it does what it says ;-)

I should mention that some of these style parameters are not necessarily *individual* style parameters. For example:
... the WS_CAPTION style already includes the WS_BORDER style,
... you cannot combine the WS_CHILD and WS_POPUP styles,
... and, if you want to use WS_SYSMENU, you must use WS_CAPTION as well.

You should also be aware that all these windows are created on startup, but only the primary window is shown at first. Try opening a secondary window, dragging it somewhere else, closing it, and then opening it again! Guess what, it re-appears where you left it, in spite of the 'location' variables in it's create() function.

... my little trick !

The entry window's SLE, of course, does NOT display what you have typed, displaying just asterisks ( *** ), instead, because of it's last create() attribute (ES_PASSWORD). More of these EditText control 'attributes' are described in the last "Addressbook" lesson further on.

... tidbits !

A 'control' is a window that can respond to the user in some fashion.

A 'window caption bar' is also often referred to as a 'titlebar'.

An 'EditText' control is often referred to as an SLE, or 'single-line-entry' window.

..end of lesson.
CONTENTS