Programming AmigaOS in C

11. Opening a Window

The next stage is to open a Window, you can open windows on a Public Screen such as Workbench or a custom screen you created earlier. You can have as many windows as you like and place them where you like. Every Window can have basic system gadgets such as Close Window, Expand/Collapse window, Move Window to Back/Front or Resize Window and there is a room for a Windows title at the top. When a user clicks on a window or a gadget in a window, it will generate an event or message which can be processed by your program.

There are two commands available to open a Window:

OpenWindow() - Open a window using the NewWindow structure
OpenWindowTagList()
- Open a window using a Tag list
OpenWindowTags() - Open a window using a Tag structure

12. Opening a Window using OpenWindow()

To open a Window, you can use the OpenWindow() function which will use information from the NewWindow structure as below:

struct NewWindow
   {
   WORD LeftEdge, TopEdge; 	/* screen dimensions of window */
   WORD Width, Height; 		/* screen dimensions of window */
   UBYTE DetailPen, BlockPen;  /* for bar/border/gadget rendering */
   ULONG IDCMPFlags; 			/* User-selected IDCMP flags */
   ULONG Flags; 				/* see Window struct for defines */
   struct Gadget *FirstGadget; /* Pointer to linked list of user-defined Gadgets    */ 
   struct Image *CheckMark; 	/* Pointer to imagery for check marked menu items */
   UBYTE *Title; 				/* the title text for this window */
   struct Screen *Screen; 		/* Pointer to a custom screen */
   struct BitMap *BitMap; 		/* Pointer to a super bitmap, can be null otherwise */
   WORD MinWidth, MinHeight; 	/* minimums */
   UWORD MaxWidth, MaxHeight;  /* maximums */
   UWORD Type; 				/* CustomScreen or WBenchScreen */
};

As you can see there are many items to define for a Window. See the intuition/intuition.h header file for a little bit more information on a Window. So, to define a particular window you need to define the size and position of the window using LeftEdge, TopEdge and Width and Height values. Next you can define the colour pens used for the Window's title bar, borders and gadgets. IDCMP Flags are important to define as these determine what events your program wants to look for. For example, you probably want to check if any Gadgets are pressed, whether the Window is moved or resized or even closed. These flags are values defined in intuition.h, typical IDCMP flags are:

IDCMP_CLOSEWINDOW - Check if the Window Close button has been pressed. If so, then close down program properly.
IDCMP_GADGETUP - Check to see if a Gadget has been pressed AND released.
IDCMP_GADGETDOWN - Check to see if a Gadget has been pressed (but not released yet). Not used as often as GadgetIp.
IDCMP_MENUPICK - Check to see if a menu item has been selected.
IDCMP_DISKINSERTED - Check to see if a floppy disk has been inserted, probably ready for saving to.
IDCMP_ACTIVEWINDOW - Check to see if Window has been activated (clicked on title bar).
IDCMP_VANILLAKEY - Check to see if a key on keyboard has been pressed.
IDCMP_MOUSEMOVE - Check if mouse moves (useful to keep track of x,y position)
IDCMP_NEWSIZE - Check to see if window has been resized.

See the Rom Kernal Manuals: Libraries 9 Intuition Input and Output methods for more features of Windows and IDCMP messages. The other Window features is the Flags which define the format and layout of a Window such as whether it has a title bar or which gadgets to display (Close, Size, Drag and Depth), and whether its active or not, borderless, bitmapped, new look menus, backdrop etc. These are defined in intuition.h and start with WFLG (Window Flag), for example:

WFLG_SIZEGADGET - Use a size gadget in window
WFLG_DRAGBAR - Use a drag bar in window
WFLG_DEPTHGADGET - Use a depth gadget in window
WFLG_CLOSEGADGET - Use a close gadget in Window
WFLG_BORDERLESS - Use a borderless window
WFLG_ACTIVATE - Activate window when displayed
WFLG_NEWLOOKMENUS - Use new style menus (if defined)

If defining gadgets then they must be defined before the window, gadgets can be linked list, in which the address of the previous gadget is specified in the Gadget structure, the last item can be null. The Title contains the title of the window and is a normal character string. If defining a Custom Screen then supply address of the screen defined earlier. A Bitmap can be defined if you want to use a SuperBitmap (you need to define WFLG_GIMMEZEROZERO if you do, for inner x,y co-ords).
Once a Window is defined and a OpenWindow() is called, it will return a pointer to a Window structure which contains more information about the screen including pointers to other useful information such as the RastPort which is used to render graphics in a window, a pointer to a Layer structure and a pointer to Font information and so on. See intuition.h header for more information.

#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/intuition.h>
int main() {
   struct Window *myWindow;
   struct NewWindow winlayout = {
      20, 20,
      200, 150,
      0,1, 
      IDCMP_CLOSEWINDOW,
      WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET |    WFLG_CLOSEGADGET | WFLG_ACTIVATE,
      NULL, NULL,
      "My Window",
      NULL,NULL,
      0,0,
      600,400,
      WBENCHSCREEN
   };
   myWindow = OpenWindow(&winlayout);
   Delay(200);
   if (myWindow) CloseWindow(myWindow);
   return(0);
   }
NB: For AmigaOS 4, prefix 'IIntuition->' before the OpenWindow and CloseWindow functions.

13. Opening a Window using OpenWindowTags()

Rather than having to specify a NewWindow structure for each new window , you can use the new command OpenWindowTags() and then you can specify which parameters you like in the function itself and leave off un-necessary parameters. Each parameter is specified by the Tag Name and the Value, the last Tag item is always TAG_DONE. Tags for Window parameters start with WA.
The format of the function is:

struct Window* = OpenWindowTags(struct NewWindow *, ULONG tagItem, .... );

or, for AmigaOS 4:

struct Window* = IIntuition->OpenWindowTags(struct NewWindow *, ULONG tagItem, .... );

For example,

#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/intuition.h>
int main() {
   struct Window *myWindow;
  myWindow = OpenWindowTags(NULL,
     WA_Left, 20, WA_Top, 20,
     WA_Width, 200, WA_Height, 150,
     WA_IDCMP, IDCMP_CLOSEWINDOW,
     WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET    | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
     WA_Title, "My Window",
     WA_PubScreenName, "Workbench",
     TAG_DONE );
   Delay(200);
   if (myWindow) CloseWindow(myWindow);
   return(0);
   }

If opening a number of Windows, you may specify a NewWindow structure of a screen, and then specify the tags to override the settings in the NewWindow structure to create a different window, you will still need different pointers to the Window structure of each instance of the window.

14. Opening a Window using OpenWindowTagList()

The final command is OpenWindowTagList() which is similar but subtley different from OpenWindowTags. In this case you still provide Tags but as a pointer to a Tag structure. The format of the command is:

struct Window* = OpenWindowTagList(struct NewWindow *, struct TagItem *Taglist. );

or, for AmigaOS 4:

struct Window* = IIntuition->OpenWindowTagList(struct NewWindow *, struct TagItem *Taglist. );

A variation of the previous program is shown below, with the tags provided before opening the Window.

#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/intuition.h>
int main() {
   struct Window *myWindow;
   struct TagItem wintags[] = {  
     WA_Left, 20, WA_Top, 20,
     WA_Width, 200, WA_Height, 150,
     WA_IDCMP, IDCMP_CLOSEWINDOW,
     WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET    | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
     WA_Title, "My Window",
     WA_PubScreenName, "Workbench",
     TAG_DONE
   };
   myWindow = OpenWindowTagList(NULL, &wintags[0]);
   Delay(200);
   if (myWindow) CloseWindow(myWindow);
   return(0);
   }

15. Processing System Gadgets on a Window

For AmigaOS to process events, it has to send Messages to the operating system that an event has taken place, the OS can then determine what event has taken place and provide data to the user to determine what to do with that Message and do more processing. Note that the IDCMP flags must be defined in the Window structure otherwise they will be ignored! So the following tasks have to take place:

a) Wait for signal from the current Active Window
b) If a signal has been sent, get the Message data structure
c) Reply to the message, so that message is removed from the queue and is being dealt with.
d) Determine the message class (or gadget or event) occured by comparing class value with IDCMP flags
e) Do some user processing with that event.

The following example will close the Window if the Close gadget has been pressed (instead of a delay like previous examples):

#include <proto/intuition.h>
/* Gadtools is needed for GetIMsg and ReplyIMsg */ 
#include <proto/gadtools.h>
/* Exec is needed for Wait function */
#include <proto/exec.h>
#include <proto/dos.h>
#include <intuition/intuition.h>
int main() {
   struct Window *myWindow;
   int closewin = FALSE;       /* Flag used to end program */
   struct IntuiMessage *msg;   /* Structure to store Intuition message data */
   ULONG msgClass;             /* Class value */
   
   myWindow = OpenWindowTags(NULL,
   WA_Left, 20, WA_Top, 20,
   WA_Width, 200, WA_Height, 150,
   WA_IDCMP, IDCMP_CLOSEWINDOW,
   WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET    | WFLG_ACTIVATE,
   WA_Title, "My Window",
   WA_PubScreenName, "Workbench",
   TAG_DONE);
 while (closewin == FALSE) {                       /* Run program until window is closed */
    Wait(1L << myWindow->UserPort->mp_SigBit);     /* Wait for an event! */
    msg = GT_GetIMsg(myWindow->UserPort);          /* Get message data    */ 
    msgClass = msg->Class;                         /* What has been clicked? */
    GT_ReplyIMsg(msg);                             /* Close message */
    if (msgClass == IDCMP_CLOSEWINDOW) {           /* Check here if Close    Window selected */
        CloseWindow(myWindow);                     /* Close window    */ 
        closewin = TRUE;
    }
   }
 return(0);
 }

If there are many types of events to select such as gadgets, mouse movements, keyboard, window changes etc, then a select statement rather than an if would be more appropiate. In fact it would be better to put such code in a seperate function to be called when needed.

Next Page