The container application includes the following files:

The following sample illustrates the container application code:

================CONTAIN.C
================

#define  INCL_WIN
#define  INCL_GPI

#include <os2.h>
#include <stdio.h>
#include <string.h>
#include "contain.h"
#include "phones.h"

/***********************************************************************/
/*  Program Overview:                                                  */
/*                                                                     */
/*  This program creates a frame window as a parent, then creates      */
/*  a container window as a child.  The frame window sizes the         */
/*  container to fill its client area.                                 */
/*                                                                     */
/*  After the windows are created successfully, the container          */
/*  window is populated.  First, the container is sent a message to    */
/*  allocate memory for each of the records which will be inserted.    */
/*  After the memory is allocated, we set the values for each record.  */
/*  (This sample program reads data from a static array - you could    */
/*  also load values from a file.) Then, the container is sent a       */
/*  message to insert the records (which makes them visible).          */
/*                                                                     */
/*  This container is read-only, which means the end user cannot       */
/*  change the title text.  It supports single selection.              */
/*                                                                     */
/*  In the message loop, we must check for WM_CONTROL messages,        */
/*  which are generated from the container control.  This sample       */
/*  processes CN_ENTER messages, when an item in the container is      */
/*  selected (either with the mouse or the keyboard), and              */
/*  CN_CONTEXTMENU messages, when a context menu is requested.  The    */
/*  context menu allows the user to change the display mode of the     */
/*  container.  Our container supports Icon, Text, and Name views.     */
/*                                                                     */
/*  When a CN_ENTER message is received, we loop through the array     */
/*  of names until we find a match.  On a match, we pop up a message   */
/*  box which contains the nickname, name, and number of the person    */
/*  selected.                                                          */
/*                                                                     */
/***********************************************************************/

#pragma linkage (main,optlink)
INT main(VOID);
VOID LoadDatabase(HWND);

/***********************************************************************/
/*  Main() - program entry point.                                      */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc(HWND, ULONG, MPARAM, MPARAM);

HAB     hab;
HWND    hPopupMenu;
HWND    hFrameWnd, hCnrWnd;
PFNWP   SysWndProc;

INT main (VOID)
{
   HMQ         hmq;
   FRAMECDATA  fcd;
   QMSG        qmsg;

   if (!(hab = WinInitialize(0)))
     return FALSE;

   if (!(hmq = WinCreateMsgQueue(hab, 0)))
     return FALSE;

/***********************************************************************/
/*  Set up the frame control data for the frame window.                */
/***********************************************************************/
   fcd.cb = sizeof(FRAMECDATA);
   fcd.flCreateFlags = FCF_TITLEBAR |
                       FCF_SYSMENU |
                       FCF_SIZEBORDER |
                       FCF_SHELLPOSITION |
                       FCF_MINMAX |
                       FCF_TASKLIST;
   fcd.hmodResources = NULLHANDLE;
   fcd.idResources = 0;

/***********************************************************************/
/*  Create the frame to hold the container control.                    */
/***********************************************************************/
   hFrameWnd = WinCreateWindow(HWND_DESKTOP,
                               WC_FRAME,
                               "Phone Book",
                               0, 0, 0, 0, 0,
                               NULLHANDLE,
                               HWND_TOP,
                               0,
                               &fcd,
                               NULL);

/***********************************************************************/
/*  Verify that the frame was created; otherwise, stop.                */
/***********************************************************************/
   if (!hFrameWnd)
     return FALSE;

/***********************************************************************/
/*  Set an icon for the frame window.                                  */
/***********************************************************************/
   WinSendMsg(hFrameWnd,
              WM_SETICON,
              (MPARAM)WinQuerySysPointer(HWND_DESKTOP,
                                         SPTR_FOLDER,
                                         FALSE),
               NULL);

/***********************************************************************/
/*  Create the container.                                              */
/***********************************************************************/
   hCnrWnd = WinCreateWindow(hFrameWnd,
                             WC_CONTAINER,
                             NULL,
                             CCS_AUTOPOSITION |
                             CCS_READONLY |
                             CCS_SINGLESEL,
                             0, 0, 0, 0,
                             hFrameWnd,
                             HWND_BOTTOM,
                             FID_CLIENT,
                             NULL,
                             NULL);

/***********************************************************************/
/*  If we got it, fill it up.                                          */
/***********************************************************************/
   if (hCnrWnd)
     LoadDatabase(hCnrWnd);

/***********************************************************************/
/*  We must intercept the frame window's messages                      */
/*  (to capture any input from the container control).                 */
/*  We save the return value (the current WndProc),                    */
/*  so we can pass it all the other                                    */
/*  messages the frame gets.                                           */
/***********************************************************************/
   SysWndProc = WinSubclassWindow(hFrameWnd, (PFNWP)LocalWndProc);

/***********************************************************************/
/*  Load the popup menu from the resources                             */
/*  and show the frame window.                                         */
/***********************************************************************/
   hPopupMenu = WinLoadMenu(HWND_OBJECT, NULLHANDLE, IDM_DISPLAY);

   WinShowWindow(hFrameWnd, TRUE);

/***********************************************************************/
/*  Standard PM message loop - get it, dispatch it.                    */
/***********************************************************************/
   while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
   {
      WinDispatchMsg(hab, &qmsg);
   }

/***********************************************************************/
/*  Clean up on the way out.                                           */
/***********************************************************************/
   WinDestroyMsgQueue(hmq);
   WinTerminate(hab);

   return TRUE;
}

/***********************************************************************/
/*  LocalWndProc() - window procedure for the frame window.            */
/*  Called by PM whenever a message is sent to the frame.              */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
   char                szBuffer[80];
   CNRINFO             cnrInfo;
   PNOTIFYRECORDENTER  Selected;
   POINTL              pt;
   int                 x;

   switch(msg)
   {
      case WM_CONTROL:
      switch (SHORT2FROMMP(mp1))
      {

/***********************************************************************/
/*  Context menu - usually right mouse button clicked                  */
/*  on window. Popup a menu to allow the user to                       */
/*  select a new view of the container.                                */
/***********************************************************************/
         case CN_CONTEXTMENU:
            WinQueryPointerPos(HWND_DESKTOP, &pt);
            WinPopupMenu(HWND_DESKTOP,
                         hwnd,
                         hPopupMenu,
                         (SHORT)pt.x,
                         (SHORT)pt.y,
                         IDM_ICON,
                         PU_NONE |
                         PU_MOUSEBUTTON1 |
                         PU_KEYBOARD |
                         PU_SELECTITEM);
            break;

         case CN_ENTER:

/***********************************************************************/
/*  User selected an item - we take the icon text                      */
/*  and spin through the array of Friends, looking for                 */
/*  a match - on match, print out the phone number                     */
/***********************************************************************/
         Selected = (PNOTIFYRECORDENTER)mp2;
         for (x = 0; x < MAXFRIENDS; x++)
         {
            if (!strcmpi(Friends[x].NickName,
              Selected->pRecord->pszIcon))
            {

               sprintf(szBuffer,
                       "'%s' (%s) %s",
                       Friends[x].NickName,
                       Friends[x].FullName,
                       Friends[x].Phone);
                       WinMessageBox(HWND_DESKTOP,
                                     HWND_DESKTOP,
                                     szBuffer,
                                     "Phone",
                                     0,
                                     MB_OK);
            }
         }
         break;
      }
      break;

      case WM_COMMAND:
         switch (SHORT1FROMMP(mp1))
         {
            case IDM_ICON:
               cnrInfo.flWindowAttr = CV_ICON;
               break;
            case IDM_NAME:
               cnrInfo.flWindowAttr = CV_NAME;
               break;
            case IDM_TEXT:
               cnrInfo.flWindowAttr = CV_TEXT;
               break;
            default:
               return (*SysWndProc)(hwnd, msg, mp1, mp2);
               break;
         }

         WinSendMsg(hCnrWnd,
                    CM_SETCNRINFO,
                    &cnrInfo,
                    MPFROMLONG(CMA_FLWINDOWATTR));
         break;

/***********************************************************************/
/*  Send the message to the usual WC_FRAME WndProc.                    */
/***********************************************************************/
         default:
            return (*SysWndProc)(hwnd, msg, mp1, mp2);
            break;
   }
   return (*SysWndProc)(hwnd, msg, mp1, mp2);
}

/***********************************************************************/
/*  LoadDatabase() - utility function                                  */
/*  called after the WC_CONTAINER window is created successfully,      */
/*  allocates and populates container records, and then inserts        */
/*  the records into the container window.                             */
/***********************************************************************/
VOID LoadDatabase (HWND hWnd)
{
   HWND            hIcon;
   PRECORDCORE     Address, FirstRec;
   RECORDINSERT    recsIn;
   ULONG           x;

/***********************************************************************/
/*  The Icon view for each of the records in the                       */
/*  container will use the standard File icon,                         */
/*  so we grab the handle now for reference later.                     */
/***********************************************************************/
   hIcon = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE);

/***********************************************************************/
/*  Allocate MAXFRIENDS records all at once -                          */
/*  CM_ALLOCRECORD returns them in a linked list.                      */
/***********************************************************************/
   Address = (PRECORDCORE)WinSendMsg(hWnd,
                                     CM_ALLOCRECORD,
                                     0,
                                     MPFROMLONG(MAXFRIENDS));

/**********************************************************************/
/*  We will need the first record's address to                        */
/*  insert them into the container.                                   */
/**********************************************************************/
   FirstRec = Address;

/**********************************************************************/
/*  Loop through the address book, loading as we go.                  */
/*  Because the CM_ALLOCRECORD returns a linked list,                 */
/*  the address of the next record is retrieved                       */
/*  from each record as we go (preccNextRecord).                      */
/**********************************************************************/
   for (x = 0; x < MAXFRIENDS; x++)
   {
      Address->cb       = sizeof(RECORDCORE); /* Standard records     */
      Address->hptrIcon = hIcon;              /* File icon            */
      Address->pszIcon  = Friends[x].NickName;
      Address->pszName  = Friends[x].FullName;
      Address->pszText  = Friends[x].FullName;
      Address = Address->preccNextRecord;     /* Next record in list  */
   }

/**********************************************************************/
/*  Set up the insert record structure to place                       */
/*  the records in the container.                                     */
/**********************************************************************/
   recsIn.cb = sizeof(RECORDINSERT);

   /* Put the records in after any others */
   recsIn.pRecordOrder = (PRECORDCORE)CMA_END;

   /* All the records are top level (not children of other records) */
   recsIn.pRecordParent = NULL;

   /* The icons are top level */
   recsIn.zOrder = (USHORT)CMA_TOP;

   /* Redraw the container */
   recsIn.fInvalidateRecord = TRUE;

   /* Set the number of records to insert */
   recsIn.cRecordsInsert = MAXFRIENDS;

/**********************************************************************/
/*  Insert the records into the container.                            */
/**********************************************************************/
   WinSendMsg(hWnd,
              CM_INSERTRECORD,
              (PRECORDCORE)FirstRec,
              &recsIn);
}

================
CONTAIN.RC
================
#include <os2.h>
#include "contain.h"

MENU            IDM_DISPLAY
BEGIN
    MENUITEM    "Icon",     IDM_ICON
    MENUITEM    "Text",     IDM_TEXT
    MENUITEM    "Name",     IDM_NAME
END

================
CONTAIN.H
================
#define DLG_ADDRBOOK     100
#define CNR_ADDRBOOK     101
#define PB_ADD           102
#define PB_DIAL          103
#define PHONEBOOK        256
#define IDM_DISPLAY      400
#define IDM_ICON         401
#define IDM_NAME         402
#define IDM_TEXT         403

================
CONTAIN.LNK
================
contain.obj
contain.exe
contain.map
contain.def

================
PHONES.H
================
#define MAXFRIENDS  9

/***********************************************************************/
/*  This is a simple phone book database.                              */
/***********************************************************************/
typedef struct _Phones
{
   PSZ NickName;
   PSZ FullName;
   PSZ Phone;
}PhoneBook;

/***********************************************************************/
/*  Normal programs would read this data from a file.                  */
/***********************************************************************/
PhoneBook Friends[MAXFRIENDS] =
{
   "Giles",      "Kevin Giles",        "214-555-1212",
   "Bubba",      "Hank Smith",         "713-555-1212",
   "Fred",       "Fred Bicycle",       "817-555-1212",
   "Jack",       "Jack Anjill",        "919-555-1212",
   "John",       "John Richards",      "214-555-1212",
   "Toni",       "Toni Henderson",     "919-555-1212",
   "Babe",       "George Herman Ruth", "212-555-1212",
   "Kevin",      "Kevin Kortrel",      "817-555-1212",
   "Honest Abe", "Abraham Lincoln",    "none"
};


[Back] [Next]