/*****************************************************************************/
/*                                                                           */
/*  File Name   : SKETSAMP.C                                                 */
/*                                                                           */
/*  Description : Sample Program for SKETCH Controls                         */
/*                A Sketch Control is created in the client window.          */
/*                                                                           */
/*                A SKETCH Control Message will be executed when the user    */
/*                presses the "Select Control" pushbutton and highlights an  */
/*                item from the list box then presses OK.                    */
/*                The user can get HELP for a particular message by          */
/*                highlighting a Message in the list box and pressing HELP.  */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/*  Copyright (C) 1993 IBM Corporation                                       */
/*                                                                           */
/*      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is          */
/*      sample code created by IBM Corporation. This sample code is not      */
/*      part of any standard or IBM product and is provided to you solely    */
/*      for  the purpose of assisting you in the development of your         */
/*      applications.  The code is provided "AS IS", without                 */
/*      warranty of any kind.  IBM shall not be liable for any damages       */
/*      arising out of your use of the sample code, even if they have been   */
/*      advised of the possibility of such damages.                          */
/*                                                                           */
/*****************************************************************************/

#define INCL_GPI
#define INCL_DOS
#define INCL_WIN
#define INCL_PM
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <os2.h>
#include <penpm.h>

#include "sketsamp.h"
int main()
{

  HMQ     hmq;
  QMSG    qmsg;
  HWND    hwndClient;

  CHAR      szClientClass [] = "SKETCH Controls Sample Program";

  ULONG ulCreateFlags =  FCF_STANDARD         /* Frame creation flags        */
                      & ~(FCF_SHELLPOSITION   /* Don't let shell position    */
                      | FCF_ACCELTABLE        /* No accelerator table        */
                      | FCF_MENU );           /* No application menu bar     */


  /*************************************************************************/
  /* Initialize PM for this program and create its PM message queue.       */
  /*************************************************************************/
  hab = WinInitialize( (ULONG)NULL );
  hmq = WinCreateMsgQueue( hab, 0L );

  /*************************************************************************/
  /* Register "ClientWndProc" as the handling procedure for the            */
  /* "Sketch Sample" class window.                                         */
  /*************************************************************************/
  WinRegisterClass( hab,
                    szClientClass,
                    (PFNWP)ClientWndProc,
                    (LONG) CS_SIZEREDRAW,     /* Class flags            */
                    0UL );

  /*************************************************************************/
  /* Tell PM that we want the standard frame window.  This frame window    */
  /* will surround a "Sketch Sample" class client window.                  */
  /*************************************************************************/
  hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
                                  WS_VISIBLE,
                                  (PULONG)&ulCreateFlags,
                                  szClientClass,
                                  szClientClass,
                                  0L,
                                  (HMODULE)NULL,
                                  ID_MAIN,
                                  (PHWND)&hwndClient );


  InitHelp();

  WinSetWindowPos(hwndFrame, HWND_TOP,
                  100, 100, 450, 280,
                  SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW );

  /*************************************************************************/
  /* This while loop waits for messages from PM.  If not a WM_CLOSE msg,   */
  /* then we dispatch the message to our client window procedure.          */
  /*************************************************************************/
  while( WinGetMsg( hab, &qmsg, (HWND) NULL, 0, 0 ) )
  {
    WinDispatchMsg( hab, &qmsg );
  }

  /*************************************************************************/
  /* We will drop out of the while loop if the program receives a WM_CLOSE */
  /* message.  We must destroy our PM resources and return to the          */
  /* invoking procedure.                                                   */
  /*************************************************************************/
  WinDestroyHelpInstance( hwndHelp );
  WinDestroyWindow( hwndFrame );
  WinDestroyMsgQueue( hmq );
  WinTerminate( hab );
  return( 0 );
}


/****************************************************************************/
/*  Name : ClientWndProc                                                    */
/*                                                                          */
/*  Description :                                                           */
/*                                                                          */
/* Parameters   : hwnd - Window handle to which message is addressed        */
/*                msg - Message type                                        */
/*                mp1 - First message parameter                             */
/*                mp2 - Second message parameter                            */
/*                                                                          */
/****************************************************************************/
MRESULT EXPENTRY ClientWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
        HPS       hpsClient;
        RECTL     rclClient;
static  CHAR      szListItem[MESSAGE_MAX];    /* Control Message             */

        ULONG     ulStrokeNumber;    /* notify of Stroke to clear, undo, add */

        COLOR     lColorChangedTo;   /* notify of color changed to           */
        ULONG     ulWidthChangedTo;  /* notify of width changed to           */

        ULONG     ulDX, ulDY, ulY;
        CHAR      szTempString[40];    /* temporary string buffer                    */

        USHORT fsKeyFlags;


  switch( msg )
  {

    case WM_CREATE:
     bWindowsCreated = FALSE;  /* Control, buttons not yet created.          */
     /*********************************************************************/
     /* Check to make sure Pen for OS/2 is up before we do anything else. */
     /*********************************************************************/
     if( WrtWaitActive( WRT_IMMEDIATE_RETURN ) )
     {
       /******************************************************************/
       /* If Pen for OS/2 is NOT active then put up a message box and    */
       /* terminate the program.                                         */
       /******************************************************************/
       ShowMessageBox(hwnd, IDMSG_NO_PEN_RUNNING, NULL);
       WinSendMsg( hwnd, WM_CLOSE, NULL, NULL );
       return( 0 );
     }


     CreateControls(hwnd);        /* Create Select, Cancel, and Help button  */
                                  /* and SKETCH window.                      */

     /***********************************/
     /* Load the PEN Pointer            */
     /***********************************/
     hptrt1 = WinLoadPointer(HWND_DESKTOP, 0L, PTR_PEN);

     strcpy(szListItem, "SKM_DELETE_ALL_STROKES"); /* Highlight listbox item     */

     /***********************************/
     /* Save the Default Sketch Pointer */
     /***********************************/
     hpDefault = (LONG) WinSendMsg(hSKETCHControl, SKM_QUERY_CTL_DRAW_POINTER,
                                NULL, NULL);

     bLookAtNotification = FALSE; /* Don't display notification messages     */
                                  /* unless selected from example selection  */

     /*****************************************/
     /* Create the SELECT Dialog ListBox.     */
     /*****************************************/
     hwndSelectDlg = WinLoadDlg( HWND_DESKTOP, hwnd,  (PFNWP) ChooseControlProc,
                       0L, IDD_SELECTCONTROL, szListItem);


    break;

    case WM_SIZE:              /* Check for a changed pos/size of the window */
    {

      ulDX = SHORT1FROMMP(mp2) - 10;
      ulDY = SHORT2FROMMP(mp2)
           - 30L                                      /* DY of buttons       */
           - 5L                                       /* offset of buttons   */
           - 5L                                       /* space below sketch  */
           - 5L;                                      /* space above sketch  */

      ulY  = SHORT2FROMMP(mp2) - ulDY - 5L;
      WinSetWindowPos( WinWindowFromID(hwnd, IDC_SKETCH),
                       (HWND) NULL,
                       5,                                  /* x              */
                       ulY,                                /* y              */
                       ulDX,                               /* dx             */
                       ulDY,                               /* dy             */
                       SWP_SIZE | SWP_MOVE );              /* Operation      */
    }
    break;

    case WM_CLOSE:
    {

      if (bWindowsCreated)
        {
          WinDestroyWindow( hwndSelectDlg);
          WinDestroyWindow( hSELECTButton );
          WinDestroyWindow( hCANCELButton );
          WinDestroyWindow( hSKETCHControl);
        }
      WinDestroyWindow( hHELPButton );
      WinPostMsg(hwnd, WM_QUIT, MPVOID, MPVOID ); /* Force termination       */
    }
    break;


    case WM_PAINT:
    {
      /*********************************************************************/
      /* If we get a paint message then just clear the client window.      */
      /*********************************************************************/
      hpsClient = WinBeginPaint( hwnd, (HPS)NULL, &rclClient );
      WinFillRect( hpsClient, &rclClient, CLR_PALEGRAY );
      WinEndPaint( hpsClient );
      return( (MRESULT)FALSE );
    }

    case WM_CHAR:
       fsKeyFlags = (USHORT)SHORT1FROMMP(mp1);
       if (fsKeyFlags & KC_VIRTUALKEY)
         {
           switch (SHORT2FROMMP(mp2) )
           {
             case VK_ENTER:
             case VK_NEWLINE:
               WinSendMsg( hwnd,
                           WM_COMMAND,
                           MPFROMSHORT(IDC_SELECT),
                           MPFROM2SHORT(CMDSRC_PUSHBUTTON, FALSE) );
           }
         }
       return( (MRESULT)FALSE );

    case WM_COMMAND:
    {
      switch(SHORT1FROMMP(mp1))
      {
        case IDC_CANCEL:
          WinSendMsg(hwnd, WM_CLOSE, NULL, NULL);
          break;

        case IDC_SELECT:
        /***************************************************/
        /* Show the SELECT Dialog.                         */
        /***************************************************/
        WinSetWindowPos(hwndSelectDlg,
                        HWND_TOP,
                        100,
                        250,
                        0,
                        0,
                        SWP_MOVE | SWP_SHOW | SWP_ACTIVATE);
        break;
      }
      break;


    }

    case WM_CONTROL:
      switch(SHORT2FROMMP(mp1))
      {

       /*************************************************/
       /* Notification messages from the SKETCH Control */
       /*************************************************/

        case SKN_STROKE_ADD:
          /****************************************************************/
          /* Tell user stroke is about to be added - if Cancel, don't add */
          /****************************************************************/
          if (bLookAtNotification)      /* if SKN_STROKE_ADD was selected    */
            {
              bLookAtNotification = FALSE;
              ulStrokeNumber = LONGFROMMP(mp2);
              sprintf(szTempString, "%ld", ulStrokeNumber);
              if (MBID_OK != ShowMessageBox(hwnd, IDMSG_STROKE_ADD, szTempString) )
                 return((MRESULT) TRUE);   /* Don't add the stroke           */
              else
                 return((MRESULT) FALSE);  /* Add the stroke                 */

            }
          break;

        case SKN_STROKE_UNDO:
          /******************************************************************/
          /* Tell user stroke is about to be deleted - if Cancel, don't DEL */
          /******************************************************************/
          if (bLookAtNotification)
            {
              bLookAtNotification = FALSE;
              ulStrokeNumber = LONGFROMMP(mp2);
              sprintf(szTempString, "%ld", ulStrokeNumber);
              if (MBID_OK != ShowMessageBox(hwnd, IDMSG_STROKE_UNDO, szTempString) )
                 return((MRESULT) TRUE);   /* Don't undo the stroke          */
              else
                 return((MRESULT) FALSE);  /* Delete the stroke              */
            }
          break;

        case SKN_CONTROL_CLEARED:
          /**********************************************************************/
          /* Tell user database is about to be cleared - if Cancel, don't CLEAR */
          /**********************************************************************/
          if (bLookAtNotification)
            {
              bLookAtNotification = FALSE;
              ulStrokeNumber = LONGFROMMP(mp2);
              sprintf(szTempString, "%ld", ulStrokeNumber);
              if (MBID_OK != ShowMessageBox(hwnd, IDMSG_STROKE_CLEAR, szTempString) )
                 return((MRESULT) TRUE);        /* Don't delete the strokes  */
              else
                 return((MRESULT) FALSE);       /* delete all strokes        */
            }
          break;


        case SKN_INK_COLOR_CHANGE:
          if (bLookAtNotification)
            {
              lColorChangedTo = LONGFROMMP(mp2);
              GetColorString(lColorChangedTo, (PSZ) &szTempString);   /* get color string*/
              ShowMessageBox(hwnd, IDMSG_INK_COLOR_CHANGE, szTempString);
              bLookAtNotification = FALSE;    /* turn off notification flag  */
            }
          break;

        case SKN_INK_WIDTH_CHANGE:
          if (bLookAtNotification)
            {
              ulWidthChangedTo = LONGFROMMP(mp2);
              sprintf(szTempString, "%ld", ulWidthChangedTo);
              ShowMessageBox(hwnd, IDMSG_INK_WIDTH_CHANGE, szTempString);
              bLookAtNotification = FALSE;    /* turn off notification flag  */
            }
          break;

        default:
          return( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
      }
    break;

    default:
      return( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
  }
  return((MRESULT) FALSE);
}


/*************************************************************************/
/*  Name : ChooseControlProc                                             */
/*                                                                       */
/*  Description : List Box to select which SKETCH Control to execute.    */
/*                                                                       */
/*  Parameters  : hwnd - Window handle to which message is addressed     */
/*                msg - Message type                                     */
/*                mp1 - First message parameter                          */
/*                mp2 - Second message parameter                         */
/*                                                                       */
/*************************************************************************/
MRESULT EXPENTRY ChooseControlProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

       PSZ      pszTemp;         /* temporary string pointer                 */
       USHORT   i;               /* temporary loop counter                   */
       SHORT    sIndex;          /* Control index                            */
       SHORT    sSelection;      /* selected Control Message Index           */


static HWND    hwndControlList;    /* Listbox window handle                  */
static PSZ     pszControl;         /* Current Control String                 */

LONG   MessageHelpPanel; /* Help panels for Control Messages                 */


  switch ( msg )
  {
    case WM_INITDLG:
       /****************************************************/
       /* Retrieve a pointer to the current Control string */
       /* to highlight it.                                 */
       /****************************************************/
       pszControl = PVOIDFROMMP(mp2);

       /****************************************************/
       /* Retrieve the window handle of the list box.      */
       /****************************************************/
       hwndControlList = WinWindowFromID(hwndDlg, IDC_SELECTBOX);

       /****************************************************/
       /* Add all of the Control strings to the list box.  */
       /****************************************************/
       for ( pszTemp = MessageList[0].pszMessageName, i = 1;
             pszTemp != NULL; i++ )
         {
           WinSendMsg (hwndControlList,
                       LM_INSERTITEM,
                       MPFROMSHORT(LIT_END),
                       MPFROMP(pszTemp) );
           pszTemp = MessageList[i].pszMessageName;
         }

       /****************************************************/
       /* Find the index of the current Control string.    */
       /****************************************************/
       sIndex = (SHORT)  WinSendMsg( hwndControlList,
                                     LM_SEARCHSTRING,
                                     MPFROM2SHORT(LSS_CASESENSITIVE, LIT_FIRST),
                                     MPFROMP( pszControl) );

       /*********************************************************/
       /* Highlight the current Control string in the list box. */
       /*********************************************************/
       if (sIndex != LIT_NONE)
         {
           WinSendMsg( hwndControlList,
                       LM_SELECTITEM,
                       MPFROMSHORT(sIndex),
                       MPFROMSHORT(TRUE) );
         }

       /***********************************************************/
       /* Set the Help Panel to match highlighted Control Message */
       /***********************************************************/
       MessageHelpPanel = MessageList[sIndex].ulMessageHelpValue;

       break;

    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          WinSetFocus(HWND_DESKTOP, hwndControlList );   /* Re-start with focus in listbox */
          WinSendMsg (WinWindowFromID(hwndDlg, DID_OK),  /* Re-start to show OK OK as default ENTER */
                                      BM_SETDEFAULT,
                                      MPFROMSHORT(TRUE), 0L);
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
        break;


        case DID_OK:
           /***************************************/
           /*  Get Message selected from list box */
           /***************************************/
           sSelection = (SHORT)WinSendMsg( hwndControlList,
                                            LM_QUERYSELECTION, 0, 0);

           /***********************************/
           /*  If slection was made set text  */
           /***********************************/
           if (sSelection != LIT_NONE)
             {
               WinSendMsg(WinWindowFromID( hwndDlg, IDC_SELECTBOX),
                          LM_QUERYITEMTEXT,
                          MPFROM2SHORT(sSelection, MESSAGE_MAX),
                          MPFROMP(pszControl)  );


               ExecuteControlMessage(MessageList[sSelection].lMessageValue,  /* Message Value */
                                     pszControl,  /* Message String          */
                                     hwndDlg);
             }
          break;

        case IDC_MESSAGE_HELP:
           /*****************************************/
           /*  Get Message selected from list box.  */
           /*****************************************/
           sSelection = (SHORT)WinSendMsg( hwndControlList,
                                            LM_QUERYSELECTION, 0, 0);

           /***********************************/
           /*  If slection was made set text  */
           /***********************************/
           if (sSelection != LIT_NONE)
             {
               WinSendMsg(WinWindowFromID( hwndDlg, IDC_SELECTBOX),
                          LM_QUERYITEMTEXT,
                          MPFROM2SHORT(sSelection, MESSAGE_MAX),
                          MPFROMP(pszControl)  );

               /***********************************************************/
               /* Set the Help Panel to match highlighted Control Message */
               /***********************************************************/
               MessageHelpPanel = MessageList[sSelection].ulMessageHelpValue;


               /********************************************************/
               /* Display the Help panel for highlited Control Message */
               /********************************************************/
               WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
                                    MPFROM2SHORT(MessageHelpPanel,  NULL),
                                    MPFROMSHORT(HM_RESOURCEID) );
             }
        break;
      }
      break;

    case WM_CONTROL:
      switch( SHORT2FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case LN_SELECT:          /* Item in listbox was selected        */
           /*****************************************************/
           /* A selection was made - show the OK button as      */
           /* the default action for when ENTER Key is pressed. */
           /*****************************************************/
           WinSendMsg (WinWindowFromID(hwndDlg, DID_OK),
                                       BM_SETDEFAULT,
                                       MPFROMSHORT(TRUE), 0L);
        break;

       case LN_ENTER:
         {
           /*****************************************************/
           /* If user double-clicked on an item, react the same */
           /* as if the user pressed OK pushbutton              */
           /*****************************************************/

           /***************************************************************/
           /* The Default state must be removed from the pushbuttons or   */
           /* they will also get executed.                                */
           /***************************************************************/
           WinSendMsg (WinWindowFromID(hwndDlg, DID_OK),
                                       BM_SETDEFAULT, FALSE, 0L);
           WinSendMsg (WinWindowFromID(hwndDlg, DID_CANCEL),
                                       BM_SETDEFAULT, FALSE, 0L);
           WinSendMsg (WinWindowFromID(hwndDlg, IDC_MESSAGE_HELP),
                                       BM_SETDEFAULT, FALSE, 0L);

           WinSendMsg( hwndDlg,
                       WM_COMMAND,
                       MPFROMSHORT(DID_OK),
                       MPFROM2SHORT(CMDSRC_PUSHBUTTON, TRUE) );

           WinSetFocus(HWND_DESKTOP, hwndControlList );      /* focus to listbox items */
         }
        break;
      }
      break;

    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;

}


/*****************************************************************************/
/*                                                                           */
/*  ExecuteControlMessage(LONG lMessageValue, PSZ pszChosenItem, HWND hwnd)  */
/*                                                                           */
/*  Notes:                                                                   */
/*                                                                           */
/*                                                                           */
/*  Attributes:                                                              */
/*                                                                           */
/*  Returns: void                                                            */
/*                                                                           */
/*  Change History:                                                          */
/*                                                                           */
/*  04-01-93 - Creation                                CPS                   */
/*                                                                           */
/*****************************************************************************/

void ExecuteControlMessage(LONG lMessageValue, PSZ pszChosenItem, HWND hwnd)
{
BOOL      rc;                 /* Return Code                                 */

HPOINTER  DrawPointer;        /* Draw Pointer returned from query            */
HPOINTER  OldDrawPointer;     /* Draw Pointer before new setting             */
CHAR      szDrawPointer[10];  /* Draw Pointer in string format               */

USHORT    usResult;
CHAR      szTempString[40];    /* temporary string buffer                    */

ULONG     ulWidth;             /* Drawing Width in pels                      */
ULONG     ulWidthCompare;

COLOR     lColorReturn;        /* Return from query of color                 */
COLOR     lColorCompare;


USHORT    usInvisible;         /* TRUE if invisible                          */


ULONG     ulStrokeCount;       /* Return from GET_STROKE_COUNT               */

ULONG     ulStrokeNumber;               /* Stroke number selected to change  */
CHAR      szStrokeColor[25];            /* Stroke color selected to change to*/

ULONG     ulAuxData;                    /* retrieve ADF_ALL or zero          */
USHORT    usAuxReturn;

HBITMAP   hBitmap;                      /* handle returned from GET_BITMAP   */


ULONG     ulBitmapSize;        /* Return from query of bitmap_size           */
SHORT     sSizeX;              /* Size in pixels of bitmap in X direction    */
SHORT     sSizeY;              /* Size in pixels of bitmap in Y direction    */

ULONG     ulStrokeLength;      /* Return from QUERY_STROKE_LENGTH            */

 switch( lMessageValue )                     /* Execute the Control Message  */
 {

   case SKM_DELETE_ALL_STROKES:         /* Execute SKM_DELETE_ALL_STROKES    */
     rc = (BOOL) WinSendMsg(hSKETCHControl,
                            SKM_DELETE_ALL_STROKES,
                            NULL, NULL);

     if( rc == FALSE )
       ShowMessageBox(hwnd, IDMSG_NOTHING_CLEAR, NULL);
     else
       ShowMessageBox(hwnd, IDMSG_ALL_STROKES_CLEARED, NULL);
     break;


   case SKM_UNDO_LAST_STROKE:           /* Execute SKM_UNDO_LAST_STROKE      */
     rc = (BOOL) WinSendMsg(hSKETCHControl,
                            SKM_UNDO_LAST_STROKE,
                            NULL, NULL);
     if( rc == FALSE )
       ShowMessageBox(hwnd, IDMSG_NOTHING_UNDO, NULL);
     else
       ShowMessageBox(hwnd, IDMSG_LAST_STROKE_CLEARED, NULL);
     break;

   case SKM_QUERY_CTL_DRAW_POINTER:    /* Execute SKM_QUERY_CTL_DRAW_POINTER */
    DrawPointer = (LONG) WinSendMsg(hSKETCHControl,
                                    SKM_QUERY_CTL_DRAW_POINTER,
                                    NULL, NULL);


    if (DrawPointer == hptrt1)
      strcpy(szTempString, "PEN");
    else
      if (DrawPointer == hpDefault)
        strcpy(szTempString, "DEFAULT");
      else
        strcpy(szTempString, "UNKNOWN");

    ShowMessageBox(hwnd, IDMSG_DRAWPOINTER_QUERY, szTempString);
    break;

   case SKM_QUERY_CTL_INK_WIDTH:         /* Execute SKM_QUERY_CTL_INK_WIDTH  */
     ulWidth = (ULONG) WinSendMsg(hSKETCHControl,
                                   SKM_QUERY_CTL_INK_WIDTH,
                                   NULL, NULL);
     if (ulWidth)
       {
         sprintf(szTempString, "%ld", ulWidth); /* put width in a string */
         ShowMessageBox(hwnd, IDMSG_INK_WIDTH_QUERY, szTempString); /* show width */
       }
     else
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
     break;

   case SKM_QUERY_CTL_INK_COLOR:         /* Execute SKM_QUERY_CTL_INK_COLOR  */
     lColorReturn =  (COLOR) WinSendMsg(hSKETCHControl,
                                       SKM_QUERY_CTL_INK_COLOR,
                                       NULL, NULL);
     if (lColorReturn == CLR_ERROR)
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
     else
       {
         GetColorString(lColorReturn, (PSZ) &szTempString);   /* get color string*/
         ShowMessageBox(hwnd, IDMSG_INK_COLOR_QUERY, szTempString); /* show color str  */
       }
     break;

   case SKM_QUERY_CTL_INVISIBLE_MODE:/* Execute SKM_QUERY_CTL_INVISIBLE_MODE */
     usInvisible =   (USHORT) WinSendMsg(hSKETCHControl,
                                         SKM_QUERY_CTL_INVISIBLE_MODE,
                                         NULL, NULL);
     if ( usInvisible == TRUE)
       strcpy(szTempString, "\"INVISIBLE\"");
     else
       strcpy(szTempString, "\"VISIBLE\"");
     ShowMessageBox(hwnd, IDMSG_DISPLAY_MODE, szTempString);
     break;

   case SKM_SET_CTL_DRAW_POINTER:        /* Execute SKM_SET_CTL_DRAW_POINTER */
    /****************************************/
    /* First, What is it set to now?        */
    /* If it is the Default, change to PEN; */
    /* if it is the PEN, change to Default. */
    /****************************************/
    DrawPointer = (LONG) WinSendMsg(hSKETCHControl,
                                    SKM_QUERY_CTL_DRAW_POINTER,
                                    NULL, NULL);

    /****************************************/
    /* Drawing pointer is currently set     */
    /* to default Sketch input pointer,     */
    /* change it the the PEN pointer.       */
    /****************************************/
    if (DrawPointer == hpDefault)
      {
        OldDrawPointer = (HPOINTER)WinSendMsg(hSKETCHControl,
                                              SKM_SET_CTL_DRAW_POINTER,
                                              MPFROMLONG(hptrt1), NULL);
        if (OldDrawPointer == hptrt1)
          strcpy(szDrawPointer, "PEN");
        else
          if (OldDrawPointer == hpDefault)
            strcpy(szDrawPointer, "Default");
          else
            strcpy(szDrawPointer, "UNKNOWN");

        sprintf(szTempString, "\nPrevious = %s.\nNew = PEN.",
                               szDrawPointer);
        ShowMessageBox(hwnd, IDMSG_DRAWPOINTER_SET, szTempString);

      }
    else
      /****************************************/
      /* Drawing pointer is currently set     */
      /* to PEN pointer, change back to       */
      /* default Sketch input pointer.        */
      /****************************************/
      {
        OldDrawPointer = (HPOINTER)WinSendMsg(hSKETCHControl,
                                              SKM_SET_CTL_DRAW_POINTER,
                                              MPFROMLONG(hpDefault), NULL);
        if (OldDrawPointer == hptrt1)
          strcpy(szDrawPointer, "PEN");
        else
          if (OldDrawPointer == hpDefault)
            strcpy(szDrawPointer, "Default");
          else
            strcpy(szDrawPointer, "UNKNOWN");

        sprintf(szTempString, "\nPrevious = %s.\nNew = DEFAULT.",
                               szDrawPointer);
        ShowMessageBox(hwnd, IDMSG_DRAWPOINTER_SET, szTempString);

      }

     break;

   case SKM_SET_CTL_INK_WIDTH:           /* Execute SKM_SET_CTL_INK_WIDTH    */
    /********************************/
    /*  Get desired width from user */
    /********************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) WidthDlgProc,   /* Address of width procedure   */
                     0L,                     /* Module handle                */
                     IDD_GETWIDTH,           /* Dialog identifier in resource*/
                     &ulWidth);              /* Return the width             */

     if (usResult == DID_OK)
       {
         rc = (BOOL) WinSendMsg(hSKETCHControl, SKM_SET_CTL_INK_WIDTH,
                                MPFROMLONG(ulWidth), NULL);

         sprintf(szTempString, "%ld", ulWidth);
         if (rc)
           ShowMessageBox(hwnd, IDMSG_INK_WIDTH_SET, szTempString);
         else
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
       }


     break;

   case SKM_SET_CTL_INK_COLOR:           /* Execute SKM_SET_CTL_INK_COLOR    */
     /*************************************************/
     /* First, Query the current color to init color  */
     /* selection button to current color             */
     /*************************************************/
     lColorReturn = (COLOR) WinSendMsg(hSKETCHControl,
                           SKM_QUERY_CTL_INK_COLOR,
                           NULL, NULL);
     if (lColorReturn == CLR_ERROR)
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
     else
     {
     /***************************************/
     /* Prompt User for color to change to. */
     /***************************************/
     usResult =  WinDlgBox(HWND_DESKTOP,         /* place anywhere on desktop     */
                           hwnd,                 /* owned by frame                */
                           (PFNWP) ColorDlgProc, /* Address of color procedure    */
                           0L,                   /* Module handle                 */
                           IDD_COLORSELECTION,   /* Dialog identifier in resource */
                           &lColorReturn);       /* create parms                  */

     /***************************************/
     /* Change to selected color.           */
     /***************************************/
     if (usResult == DID_OK)
       {
         rc = (BOOL) WinSendMsg(hSKETCHControl,
                                SKM_SET_CTL_INK_COLOR,
                                MPFROMLONG(lColorReturn), NULL);
         if (rc)
           {
             GetColorString(lColorReturn, (PSZ) &szStrokeColor);/* get color strng*/
             ShowMessageBox(hwnd, IDMSG_INK_COLOR_SET, szStrokeColor);
           }
         else
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
       }
     }
     break;

   case SKM_SET_CTL_INVISIBLE_MODE:    /* Execute SKM_SET_CTL_INVISIBLE_MODE */
     /***************************************/
     /* First, is ink invisible or visible? */
     /***************************************/
     usInvisible =   (USHORT) WinSendMsg(hSKETCHControl,
                                         SKM_QUERY_CTL_INVISIBLE_MODE,
                                         NULL, NULL);

     /****************************************/
     /* Prompt User for visible or invisible */
     /****************************************/
     usResult =  WinDlgBox(HWND_DESKTOP,          /* place anywhere on desktop     */
                           hwnd,                  /* owned by frame                */
                           (PFNWP) VisibleDlgProc,/* Address of visible procedure  */
                           0L,                    /* Module handle                 */
                           IDD_VISIBLE,           /* Dialog identifier in resource */
                           &usInvisible);           /* create parms                  */


     /***************************************/
     /* Change to visible or invisible.     */
     /***************************************/
     if (usResult == DID_OK)
       {
         rc =  (BOOL) WinSendMsg(hSKETCHControl,
                                 SKM_SET_CTL_INVISIBLE_MODE,
                                 MPFROMSHORT(usInvisible), NULL);
         if (rc == FALSE)
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
       }
     break;

   case SKM_RENDER_TO_CLIPBOARD:             /* Execute SKM_RENDER_TO_CLIPBOARD */
     rc = (BOOL) WinSendMsg(hSKETCHControl,
                            SKM_RENDER_TO_CLIPBOARD,
                            NULL, NULL);
     if( rc == FALSE )
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
     break;

   case SKM_QUERY_CTL_STROKE_COUNT:
     ulStrokeCount =  (ULONG) WinSendMsg(hSKETCHControl,
                                       SKM_QUERY_CTL_STROKE_COUNT,
                                       NULL, NULL);
     sprintf(szTempString, "%ld", ulStrokeCount);/* put stroke count in string*/
     ShowMessageBox(hwnd, IDMSG_STROKE_COUNT, szTempString); /* show stroke count */
     break;


   case SKM_SET_STROKE_INK_COLOR:
    /************************************/
    /*  Ask user what stroke to change. */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,                /* place anywhere on desktop    */
                          hwnd,                        /* owned by frame               */
                          (PFNWP) GetStrokeNumberProc, /* Address of procedure         */
                          0L,                          /* Module handle                */
                          IDD_GETSTROKENUMBER,         /* Dialog identifier in resource*/
                          &ulStrokeNumber);            /* Return Stroke chosen         */

     if (usResult == DID_OK)
       {

         /************************/
         /* Color Selection Init */
         /************************/
         lColorReturn = (COLOR) WinSendMsg(hSKETCHControl,
                                          SKM_QUERY_STROKE_INK_COLOR,
                                          MPFROMLONG(ulStrokeNumber), /* stroke number  */
                                          NULL);
         if (lColorReturn == CLR_ERROR)
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
         else
           {
           usResult =  WinDlgBox(HWND_DESKTOP,         /* place anywhere on desktop     */
                                 hwnd,                 /* owned by frame                */
                                 (PFNWP) ColorDlgProc, /* Address of Color procedure    */
                                 0L,                   /* Module handle                 */
                                 IDD_COLORSELECTION,   /* Dialog identifier in resource */
                                 &lColorReturn);       /* create parms                  */

           if (usResult == DID_OK)
             {

               /************************/
               /* Set Stroke Color.    */
               /************************/
               rc = (BOOL) WinSendMsg(hSKETCHControl,
                                      SKM_SET_STROKE_INK_COLOR,
                                      MPFROMLONG(ulStrokeNumber), /* stroke number */
                                      MPFROMP(lColorReturn) );    /* color         */
               if (rc)
                 {
                   GetColorString(lColorReturn, (PSZ) &szStrokeColor);/* get color strng*/
                   sprintf(szTempString, "\nStroke #%ld = %s", ulStrokeNumber, szStrokeColor);
                   ShowMessageBox(hwnd, IDMSG_STROKE_COLOR_SET, szTempString);
                 }
               else
                 ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
             } /* end color chosen    */
           }
       } /* end chose Stroke            */
     break;

   case SKM_SET_STROKE_INK_WIDTH:
    /************************************/
    /*  Ask user what stroke to change. */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) GetStrokeNumberProc,   /* Address of procedure  */
                     0L,                     /* Module handle                */
                     IDD_GETSTROKENUMBER,    /* Dialog identifier in resource*/
                     &ulStrokeNumber);       /* Return stroke number         */

     if (usResult == DID_OK)
       {
         /***************************************/
         /*  Ask user what to set the width to. */
         /***************************************/
         usResult =  WinDlgBox(HWND_DESKTOP,           /* place anywhere on desktop               */
                                     hwnd,                       /* owned by frame                */
                                      (PFNWP) WidthDlgProc,      /* Address of width procedure    */
                                        0L,                      /* Module handle                 */
                                          IDD_GETWIDTH,          /* Dialog identifier in resource */
                                            &ulWidth);

         if (usResult == DID_OK)
           {
             /****************************/
             /*  Set the stroke width.   */
             /****************************/
             rc = (BOOL) WinSendMsg(hSKETCHControl,
                                    SKM_SET_STROKE_INK_WIDTH,
                                    MPFROMLONG(ulStrokeNumber), /* stroke number  */
                                    MPFROMLONG(ulWidth) );     /* width          */
             if (rc)
               {
                 sprintf(szTempString, "\nStroke #%ld = %ld", ulStrokeNumber, ulWidth);
                 ShowMessageBox(hwnd, IDMSG_STROKE_WIDTH_SET, szTempString);
               }
             else
               ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
           } /* end width chosen    */
       } /* end chose Stroke            */
     break;

   case SKM_GET_BITMAP:
     /************************************************************/
     /* First, Query the bitmap handle.                          */
     /* Next, display the handle and tell user to press OK to    */
     /* save the bitmpap to a file using this handle.            */
     /************************************************************/
     hBitmap = (HBITMAP)WinSendMsg(hSKETCHControl, SKM_GET_BITMAP, NULL, NULL);
     sprintf(szTempString, "%ld.\n", hBitmap);      /* put handle in string  */
     if (MBID_OK == ShowMessageBox(hwnd, IDMSG_BITMAP_HANDLE_SAVE,
                                    szTempString) )
       {
         SaveBmpInFile(hwnd, hBitmap);
       }
   break;

   case SKM_QUERY_BITMAP_SIZE:
     ulBitmapSize = (ULONG) WinSendMsg(hSKETCHControl,
                                       SKM_QUERY_BITMAP_SIZE, NULL, NULL);

     if (ulBitmapSize)
       {

         sSizeX = LOUSHORT(ulBitmapSize);  /* size in pixels of X direction  */
         sSizeY = HIUSHORT(ulBitmapSize);  /* size in pixels of Y direction  */
         sprintf(szTempString, "\nX direction = %d\nY direction = %d", sSizeX, sSizeY);
         ShowMessageBox(hwnd, IDMSG_BITMAP_SIZE_QUERY, szTempString);

       }
     else
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);

   break;

   case SKM_QUERY_STROKE_LENGTH:
    /************************************/
    /*  Ask user what stroke to query.  */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) GetStrokeNumberProc,   /* Address of procedure  */
                     0L,                     /* Module handle                */
                     IDD_GETSTROKENUMBER,    /* Dialog identifier in resource*/
                     &ulStrokeNumber);       /* Return stroke number         */

     if (usResult == DID_OK)
       {
         /******************************/
         /* Query the stroke's length. */
         /******************************/
         ulStrokeLength = (ULONG) WinSendMsg(hSKETCHControl,
                                             SKM_QUERY_STROKE_LENGTH,
                                             MPFROMLONG(ulStrokeNumber),
                                             NULL);

         sprintf(szTempString, "\nStroke #%ld = %ld", ulStrokeNumber, ulStrokeLength);
         ShowMessageBox(hwnd, IDMSG_STROKE_LENGTH_QUERY, szTempString);
       }

   break;

   case SKM_QUERY_STROKE_DATA:
    /************************************/
    /*  Ask user what stroke to query.  */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) GetStrokeNumberProc,   /* Address of procedure  */
                     0L,                     /* Module handle                */
                     IDD_GETSTROKENUMBER,    /* Dialog identifier in resource*/
                     &ulStrokeNumber);       /* Return stroke number         */

     if (usResult == DID_OK)
       {
         /*******************************/
         /*  Query the stroke's length. */
         /*******************************/
         ulStrokeLength = (LONG) WinSendMsg(hSKETCHControl,
                                            SKM_QUERY_STROKE_LENGTH,
                                            MPFROMLONG(ulStrokeNumber),
                                            NULL);

         /*******************************************************/
         /* Allocate a buffer (non-shared) based on that size.  */
         /*******************************************************/
         pStrokeData = malloc(ulStrokeLength);
         if (!pStrokeData)
           {
            sprintf(szTempString, "%ld", ulStrokeNumber);/* current stroke num */
            ShowMessageBox(hwnd, IDMSG_MEMORY_FAIL_GETSTROKE, szTempString);
           }
         else
           {

             /*******************************/
             /* Get the Stroke information. */
             /*******************************/
             rc = (BOOL) WinSendMsg(hSKETCHControl,
                                    SKM_QUERY_STROKE_DATA,
                                    MPFROMLONG(ulStrokeNumber),
                                    MPFROMP(pStrokeData) );

             if( rc )
               {
                 /******************************************/
                 /* Display some of the Stroke Information */
                 /******************************************/
                 WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                           hwnd,              /* owned by frame               */
                           (PFNWP) DisplayStrokeInfoDlgProc,  /* Proc Address */
                           0L,                /* Module handle                */
                           IDD_STROKE_INFO,   /* Dialog identifier in resource*/
                           &ulStrokeNumber);  /* Initialization data          */

               }
             else
               ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);

             free(pStrokeData);
           }
       }
   break;

   case SKM_QUERY_STROKE_INK_COLOR:
    /************************************/
    /*  Ask user what stroke to query.  */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) GetStrokeNumberProc,   /* Address of procedure  */
                     0L,                     /* Module handle                */
                     IDD_GETSTROKENUMBER,    /* Dialog identifier in resource*/
                     &ulStrokeNumber);       /* Return stroke number         */

     if (usResult == DID_OK)
       {
         /****************************/
         /*  Query the stroke color. */
         /****************************/
         lColorReturn = (LONG) WinSendMsg(hSKETCHControl,
                               SKM_QUERY_STROKE_INK_COLOR,
                               MPFROMLONG(ulStrokeNumber), /* stroke number  */
                               NULL );

         GetColorString(lColorReturn,(PSZ) &szStrokeColor);/* get color strng*/
         sprintf(szTempString, "\nStroke #%ld = %s", ulStrokeNumber, szStrokeColor);
         ShowMessageBox(hwnd, IDMSG_STROKE_COLOR_QUERY, szTempString);
       } /* end Stroke Number chosen    */
   break;

   case SKM_QUERY_STROKE_INK_WIDTH:
    /************************************/
    /*  Ask user what stroke to query.  */
    /************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) GetStrokeNumberProc,   /* Address of procedure  */
                     0L,                     /* Module handle                */
                     IDD_GETSTROKENUMBER,    /* Dialog identifier in resource*/
                     &ulStrokeNumber);       /* Return Stroke Number         */

     if (usResult == DID_OK)
       {
         /************************************/
         /* Query the stroke ink width.      */
         /************************************/
         ulWidth = (ULONG) WinSendMsg(hSKETCHControl,
                           SKM_QUERY_STROKE_INK_WIDTH,
                           MPFROMLONG(ulStrokeNumber), /* stroke number  */
                           NULL);
         if (ulWidth)
           {
             sprintf(szTempString, "\nStroke #%ld = %ld", ulStrokeNumber, ulWidth);
             ShowMessageBox(hwnd, IDMSG_STROKE_WIDTH_QUERY, szTempString);
           }
         else
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
       } /* end choose Stroke Number    */
   break;



   case SKM_SET_CTL_AUXDATA_MODE:
     /****************************************/
     /* Prompt User for all aux data or none */
     /****************************************/
     usResult =  WinDlgBox(HWND_DESKTOP,          /* place anywhere on desktop     */
                           hwnd,                  /* owned by frame                */
                           (PFNWP) AllNoneAuxDlgProc,/* Address of proc            */
                           0L,                    /* Module handle                 */
                           IDD_AUX,               /* Dialog identifier in resource */
                           &usAuxReturn);         /* create parms     */


     /***************************************/
     /* Change to visible or invisible.     */
     /***************************************/
     if (usResult == DID_OK)
       {
         usAux = usAuxReturn;  /* set or change aux flag only if OK pressed. */
        /**********************************************************/
        /* Send so subsequent strokes will retrieve all the aux   */
        /* data or none of the aux data.                          */
        /**********************************************************/
        if (usAux)
          ulAuxData = ADF_ALL;
        else
          ulAuxData = 0;
        rc = (BOOL) WinSendMsg(hSKETCHControl,
                               SKM_SET_CTL_AUXDATA_MODE,
                               MPFROMLONG(ulAuxData),
                               NULL);
        if (rc)
          {
            if (usAux)
              ShowMessageBox(hwnd, IDMSG_AUX_ALL_SET, NULL);
            else
              ShowMessageBox(hwnd, IDMSG_AUX_NONE_SET, NULL);
          }
        else
           ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
       } /* end if aux all or none selection was made. */

   break;

   case SKN_INK_COLOR_CHANGE:
     /*******************************************************************/
     /* Change color to user selection to cause an SKN_COLOR_CHANGE     */
     /* notification to be sent.                                        */
     /*******************************************************************/
     lColorReturn = (COLOR) WinSendMsg(hSKETCHControl, SKM_QUERY_CTL_INK_COLOR,
                                     NULL, NULL); /* get current color       */
     if (lColorReturn == CLR_ERROR)
       ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
     else
     {
     usResult =  WinDlgBox(HWND_DESKTOP,           /* place anywhere on desktop */
                       hwnd,                       /* owned by frame            */
                        (PFNWP) ColorDlgProc,      /* Address of Color procedure */
                          0L,                      /* Module handle              */
                            IDD_COLORSELECTION,    /* Dialog identifier in resource */
                             &lColorReturn);        /* create parms               */
     if (usResult == DID_OK)
       {

         /******************************************************/
         /* Query the Color, if different from selected        */
         /* color, show the notification sent from the Control */
         /******************************************************/
         lColorCompare = (COLOR) WinSendMsg(hSKETCHControl,
                                           SKM_QUERY_CTL_INK_COLOR,
                                           NULL, NULL);

         if (lColorCompare!= lColorReturn)
           {

             bLookAtNotification = TRUE;    /* Display the notification message  */
             rc = (BOOL) WinSendMsg(hSKETCHControl, SKM_SET_CTL_INK_COLOR,
                                    MPFROMLONG(lColorReturn), NULL);
             if (rc == FALSE )
               {
                 ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
                 bLookAtNotification = FALSE;
               }
           }
       }
     }
     break;

   case SKN_INK_WIDTH_CHANGE:
     /*******************************************************************/
     /* Change width to user selection to cause an SKN_WIDTH_CHANGE     */
     /* notification to be sent.                                        */
     /*******************************************************************/
     usResult = WinDlgBox(HWND_DESKTOP,      /* place anywhere on desktop    */
                     hwnd,                   /* owned by frame               */
                     (PFNWP) WidthDlgProc,   /* Address of width procedure   */
                     0L,                     /* Module handle                */
                     IDD_GETWIDTH,           /* Dialog identifier in resource*/
                     &ulWidth);              /* Return Width                 */

     if (usResult == DID_OK)
       {
         /******************************************************/
         /* Query the Width, if different from selected        */
         /* width, show the notification sent from the Control */
         /******************************************************/
         ulWidthCompare = (ULONG) WinSendMsg(hSKETCHControl,
                                             SKM_QUERY_CTL_INK_WIDTH,
                                             NULL, NULL);
         if (ulWidthCompare != ulWidth)
           {

             bLookAtNotification = TRUE;    /* Display notification message  */
             rc = (BOOL) WinSendMsg(hSKETCHControl,
                                    SKM_SET_CTL_INK_WIDTH,
                                    MPFROMLONG(ulWidth), NULL);
             if (rc == FALSE )
               {
                 ShowMessageBox(hwnd, IDMSG_MESSAGE_FAIL, pszChosenItem);
                 bLookAtNotification = FALSE;
               }
           }
       }
     break;

   case SKN_STROKE_ADD:
     /*******************************************************************/
     /* When user makes a stroke, prompt will ask if really want to add */
     /*******************************************************************/
     bLookAtNotification = TRUE;
     break;

   case SKN_STROKE_UNDO:
     /*******************************************************************/
     /* Issue an SKM_UNDO_STROKE if there is a stroke to undo.          */
     /*******************************************************************/
     ulStrokeCount =  (ULONG) WinSendMsg(hSKETCHControl,
                                         SKM_QUERY_CTL_STROKE_COUNT,
                                         NULL, NULL);
     if( ulStrokeCount)
       {
         bLookAtNotification = TRUE;
         WinSendMsg(hSKETCHControl,
                    SKM_UNDO_LAST_STROKE,
                    NULL, NULL);
       }
     else
       ShowMessageBox(hwnd, IDMSG_NOTHING_UNDO, NULL);
     break;

   case SKN_CONTROL_CLEARED:
     /*******************************************************************/
     /* Issue an SKM_DELETE_ALL_STROKES if there is a stroke to clear.  */
     /*******************************************************************/
     ulStrokeCount =  (LONG) WinSendMsg(hSKETCHControl,
                                        SKM_QUERY_CTL_STROKE_COUNT,
                                        NULL, NULL);

     if( ulStrokeCount)
       {
         bLookAtNotification = TRUE;
         WinSendMsg(hSKETCHControl,
                    SKM_DELETE_ALL_STROKES,
                    NULL, NULL);
       }
     else
       ShowMessageBox(hwnd, IDMSG_NOTHING_CLEAR, NULL);
     break;


 } /* end switch */

}

/****************************************************************************/
/*  Name:   GetColorString                                                  */
/*                                                                          */
/*  Description : Match the color to it's coordinating color string.        */
/*                                                                          */
/*  Parameters :  LONG      - number of the color                           */
/*                char *    - string to return the actual color string in   */
/*                                                                          */
/*  1/93 CPS                                                                */
/****************************************************************************/
VOID GetColorString(LONG ColNum, PSZ szColor)
{

  switch (ColNum)
    {
    case CLR_WHITE:
      strcpy(szColor, "WHITE");
      break;
    case CLR_BLUE:
      strcpy(szColor, "BLUE");
      break;
    case CLR_RED:
      strcpy(szColor, "RED");
      break;
    case CLR_PINK:
      strcpy(szColor, "PINK");
      break;
    case CLR_GREEN:
      strcpy(szColor, "GREEN");
      break;
    case CLR_CYAN:
      strcpy(szColor, "CYAN");
      break;
    case CLR_YELLOW:
      strcpy(szColor, "YELLOW");
      break;
    case CLR_BLACK:
      strcpy(szColor, "BLACK");
      break;
    case CLR_DARKGRAY:
      strcpy(szColor, "DARK GRAY");
      break;
    case CLR_DARKBLUE:
      strcpy(szColor, "DARK BLUE");
      break;
    case CLR_DARKRED:
      strcpy(szColor, "DARK RED");
      break;
    case CLR_DARKPINK:
      strcpy(szColor, "DARK PINK");
      break;
    case CLR_DARKGREEN:
      strcpy(szColor, "DARK GREEN");
      break;
    case CLR_DARKCYAN:
      strcpy(szColor, "DARK CYAN");
      break;
    case CLR_BROWN:
      strcpy(szColor, "BROWN");
      break;
    case CLR_PALEGRAY:
      strcpy(szColor, "PALE GRAY");
      break;
    default:
      strcpy(szColor, "UNKNOWN");

    }
}  /* end proc */

/***************************************************************************/
/*  Name : ColorDlgProc                                                    */
/*                                                                         */
/*  Description : Get desired color from the user.                         */
/*                                                                         */
/* Parameters   : hwnd - Window handle to which message is addressed       */
/*                msg - Message type                                       */
/*                mp1 - First message parameter                            */
/*                mp2 - Second message parameter                           */
/*                                                                         */
/*                                                                         */
/***************************************************************************/
MRESULT EXPENTRY ColorDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

HWND hwndButton;                 /* handle of current button                */
static PLONG plColorSelection;   /* pointer to actual color variable        */
static LONG lColorTemp;          /* temporary color                         */


  switch ( msg )
  {

    case WM_INITDLG:                /* Get pointer to actual color variable */
      plColorSelection = PVOIDFROMMP(mp2);

      switch ( *plColorSelection)      /* find the handle of the current choice */
      {
         case CLR_WHITE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_WHITE);
           break;

         case CLR_BLUE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_BLUE);
           break;

         case CLR_RED:
           hwndButton = WinWindowFromID(hwndDlg, IDC_RED);
           break;

         case CLR_PINK:
           hwndButton = WinWindowFromID(hwndDlg, IDC_PINK);
           break;

         case CLR_GREEN:
           hwndButton = WinWindowFromID(hwndDlg, IDC_GREEN);
           break;

         case CLR_CYAN:
           hwndButton = WinWindowFromID(hwndDlg, IDC_CYAN);
           break;

         case CLR_YELLOW:
           hwndButton = WinWindowFromID(hwndDlg, IDC_YELLOW);
           break;

         case CLR_BLACK:
           hwndButton = WinWindowFromID(hwndDlg, IDC_BLACK);
           break;

         case CLR_DARKGRAY:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKGRAY);
           break;

         case CLR_DARKBLUE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKBLUE);
           break;

         case CLR_DARKRED:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKRED);
           break;

         case CLR_DARKPINK:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKPINK);
           break;

         case CLR_DARKGREEN:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKGREEN);
           break;

         case CLR_DARKCYAN:
           hwndButton = WinWindowFromID(hwndDlg, IDC_DARKCYAN);
           break;

         case CLR_BROWN:
           hwndButton = WinWindowFromID(hwndDlg, IDC_BROWN);
           break;

         case CLR_PALEGRAY:
           hwndButton = WinWindowFromID(hwndDlg, IDC_PALEGRAY);
           break;

      } /* end switch */
      WinSendMsg (hwndButton, BM_CLICK, 0L, 0L); /* turn on current choice */
      return ( (MRESULT) TRUE);  /* to indicate we changed focus */

    case WM_CONTROL:
      if (SHORT2FROMMP (mp1) == BN_CLICKED)
      {
      /* track the currently selected button */
        switch (SHORT1FROMMP(mp1) )
        {

         case IDC_WHITE:
           lColorTemp = CLR_WHITE;
           break;

         case IDC_BLUE:
           lColorTemp = CLR_BLUE;
           break;

         case IDC_RED:
           lColorTemp = CLR_RED;
           break;

         case IDC_PINK:
           lColorTemp = CLR_PINK;
           break;

         case IDC_GREEN:
           lColorTemp = CLR_GREEN;
           break;

         case IDC_CYAN:
           lColorTemp = CLR_CYAN;
           break;

         case IDC_YELLOW:
           lColorTemp = CLR_YELLOW;
           break;

         case IDC_BLACK:
           lColorTemp = CLR_BLACK;
           break;

         case IDC_DARKGRAY:
           lColorTemp = CLR_DARKGRAY;
           break;

         case IDC_DARKBLUE:
           lColorTemp = CLR_DARKBLUE;
           break;

         case IDC_DARKRED:
           lColorTemp = CLR_DARKRED;
           break;

         case IDC_DARKPINK:
           lColorTemp = CLR_DARKPINK;
           break;

         case IDC_DARKGREEN:
           lColorTemp = CLR_DARKGREEN;
           break;

         case IDC_DARKCYAN:
           lColorTemp = CLR_DARKCYAN;
           break;

         case IDC_BROWN:
           lColorTemp = CLR_BROWN;
           break;

         case IDC_PALEGRAY:
           lColorTemp = CLR_PALEGRAY;
           break;


        } /* end switch */
      } /* end if */
      return (MRESULT)0;

    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_OK:
          *plColorSelection = lColorTemp;  /* update the actual color var */

          WinDismissDlg(hwndDlg, DID_OK);
          break;

        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          WinDismissDlg( hwndDlg, DID_CANCEL );  /* Removes the dialog box    */
          break;
      }
      return(MRESULT)0;

  default:
    return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  }
 return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
}
/********************** End of dialog procedure  ************************/

/*****************************************************************************/
/*  Name:   ShowMessageBox                                                   */
/*                                                                           */
/*  Description : Display Message to the user                                */
/*                                                                           */
/*  Concepts : Displays the Info/warning/error message box with the message  */
/*             given in idMsg retrived from the message table                */
/*             Called whever a Info/warning/error occurs and a message wishes*/
/*             to be displayed to the user.                                  */
/*                                                                           */
/*  API's : WinLoadMessage                                                   */
/*          WinAlarm                                                         */
/*          WinMessageBox                                                    */
/*                                                                           */
/*  Parameters :  hwnd      - window handle of the owner of the              */
/*                            message box                                    */
/*                idMsg     - id of message to be retrieved from             */
/*                            resource file                                  */
/*                                                                           */
/*                szExtendedMessage - extended message                       */
/*  Returns: USHORT                                                          */
/*                                                                           */
/*****************************************************************************/
USHORT ShowMessageBox(HWND hwnd, USHORT idMsg, PSZ szExtendedMessage)
{
  CHAR    szText[MAXTEXTLEN];
  CHAR    szTitle[240];
  USHORT  ulAlarm;
  USHORT  ulStyle;

  if (idMsg > IDMSG_SHOWERROR)
    {
    WinLoadMessage(hab, 0L, IDMSG_SHOWERROR, 240, (PSZ) szTitle);
    ulAlarm = WA_ERROR;
    ulStyle = MB_OK | MB_ERROR | MB_MOVEABLE;
    }
  else
  if (idMsg > IDMSG_SHOWWARNING)
    {
    WinLoadMessage(hab, 0L, IDMSG_SHOWWARNING, 240, (PSZ) szTitle);
    ulAlarm = WA_WARNING;
    ulStyle = MB_OKCANCEL | MB_ICONEXCLAMATION | MB_MOVEABLE;
    }
  else
    {  /* Information message */
    WinLoadMessage(hab, 0L, IDMSG_SHOWINFO, 240, (PSZ) szTitle);
    ulAlarm = WA_NOTE;
    ulStyle = MB_OK | MB_INFORMATION | MB_MOVEABLE;
    }

  WinLoadMessage(hab, 0L, idMsg, MAXTEXTLEN, (PSZ) szText);
  WinAlarm(HWND_DESKTOP, ulAlarm);

  sprintf(szMessageBoxString, szText, szExtendedMessage);

  return(WinMessageBox(HWND_DESKTOP,
                       hwnd,
                       szMessageBoxString,
                       szTitle,
                       IDD_MSGBOX,
                       ulStyle));
}

/***************************************************************************/
/*  Name : VisibleDlgProc                                                  */
/*                                                                         */
/*  Description : Get Invisible or Visible Mode selection.                 */
/*                                                                         */
/* Parameters   : hwnd - Window handle to which message is addressed       */
/*                msg - Message type                                       */
/*                mp1 - First message parameter                            */
/*                mp2 - Second message parameter                           */
/*                                                                         */
/*                                                                         */
/***************************************************************************/
MRESULT EXPENTRY VisibleDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

HWND hwndButton;                 /* handle of current button                */
static PSHORT pModeSelection;    /* pointer to actual mode variable         */
static USHORT usModeTemp;        /* temporary mode                          */


  switch ( msg )
  {

    case WM_INITDLG:                /* Get pointer to actual mode variable   */
      pModeSelection =  PVOIDFROMMP(mp2);

      switch ( *pModeSelection)     /* set button to whatever is active.     */
      {
         case TRUE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_INVISIBLE);
           break;

         case FALSE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_VISIBLE);
           break;


      } /* end switch */
      WinSendMsg (hwndButton, BM_CLICK, 0L, 0L); /* turn on current choice */
      return ( (MRESULT) TRUE);  /* to indicate we changed focus */

    case WM_CONTROL:
      if (SHORT2FROMMP (mp1) == BN_CLICKED)
      {
      /* track the currently selected button */
        switch (SHORT1FROMMP(mp1) )
        {

         case IDC_INVISIBLE:
           usModeTemp = TRUE;
           break;

         case IDC_VISIBLE:
           usModeTemp = FALSE;
           break;

        } /* end switch */
      } /* end if */
      return (MRESULT)0;

    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_OK:
          *pModeSelection = usModeTemp;    /* update the actual mode var     */

          WinDismissDlg(hwndDlg, DID_OK);
          break;

        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          WinDismissDlg( hwndDlg, DID_CANCEL );  /* Removes the dialog box    */
          break;
      }
      return(MRESULT)0;

  default:
    return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  }
return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
}
/********************** End of dialog procedure  ************************/


/*****************************************************************************/
/*  Name : GetStrokeNumberProc                                               */
/*                                                                           */
/*  Description : Get stroke to be changed from the user.                    */
/*                                                                           */
/* Parameters   : hwnd - Window handle to which message is addressed         */
/*                msg - Message type                                         */
/*                mp1 - First message parameter                              */
/*                mp2 - Second message parameter                             */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
MRESULT EXPENTRY GetStrokeNumberProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

       CHAR      szStroke[6];          /* Select stroke number               */
static PULONG    pulStroke;            /* Stroke                             */
static ULONG     ulStrokeTemp;
       ULONG     ulStrokeCount;        /* Check if stroke is valid stroke    */

  switch ( msg )
  {

    case WM_INITDLG:

       pulStroke = PVOIDFROMMP(mp2);         /* Stroke Number parm           */

       /****************************/
       /*  Set field length limit. */
       /****************************/
       WinSendMsg( WinWindowFromID( hwndDlg, IDC_STROKEINPUT),
                   EM_SETTEXTLIMIT, (MPARAM)5, (MPARAM)0);
       break;


    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_OK:                    /* The Enter pushbutton or key. */
                                        /* WinQueryWindowText copies the*/
                                        /* contents of the entry field  */
                                        /* into szStroke                */
        WinQueryWindowText( WinWindowFromID( hwndDlg, IDC_STROKEINPUT),
                              6,
                              szStroke);

        ulStrokeTemp = atol(szStroke);

        /*******************************************/
        /*  Check that it is a valid stroke number */
        /*******************************************/
        ulStrokeCount =  (ULONG) WinSendMsg(hSKETCHControl,
                                            SKM_QUERY_CTL_STROKE_COUNT,
                                            NULL, NULL);


        if ( (ulStrokeTemp <= ulStrokeCount) && (ulStrokeTemp > 0 ) )
          {
            *pulStroke = ulStrokeTemp;       /* Return chosen stroke number */
             WinDismissDlg(hwndDlg, DID_OK);
          }
        else
          {
            ShowMessageBox(hwndDlg, IDMSG_STROKE_INVALID, szStroke);
            WinSetDlgItemText(hwndDlg, IDC_STROKEINPUT, "");
            WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwndDlg, IDC_STROKEINPUT) );
          }
        break;

        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          break;
      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}
/********************** End of dialog procedure  ************************/

/****************************************************************************/
/*  Name : WidthDlgProc                                                     */
/*                                                                          */
/*  Description : Get desired width from the user.                          */
/*                                                                          */
/* Parameters   : hwnd - Window handle to which message is addressed        */
/*                msg - Message type                                        */
/*                mp1 - First message parameter                             */
/*                mp2 - Second message parameter                            */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
MRESULT EXPENTRY WidthDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{


static PULONG    pulWidth;             /* Width                              */
static ULONG     ulWidthTemp;
       CHAR      szWidth[2];           /* Stroke width selected to change    */

  switch ( msg )
  {

    case WM_INITDLG:

       pulWidth = PVOIDFROMMP(mp2);         /* Width Parm                   */

       /**************************************/
       /*  Set field length limit.           */
       /**************************************/
       WinSendMsg( WinWindowFromID( hwndDlg, IDC_WIDTHINPUT),
                   EM_SETTEXTLIMIT, (MPARAM)1, (MPARAM)0);
       break;

    case WM_COMMAND:                    /* Posted by pushbutton or key       */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value         */
      {
        case DID_OK:                    /* The Enter pushbutton or key.      */
                                        /* WinQueryWindowText copies the     */
                                        /* contents of the entry field       */
                                        /* into szWidth.                     */
          WinQueryWindowText( WinWindowFromID( hwndDlg, IDC_WIDTHINPUT),
                              2,
                              szWidth);

          ulWidthTemp = atol(szWidth);
          if ( (ulWidthTemp < 1) || (ulWidthTemp > 2) )
            {
              ShowMessageBox(hwndDlg, IDMSG_INK_WIDTH_SET_FAIL, NULL);
              WinSetDlgItemText(hwndDlg, IDC_WIDTHINPUT, "");
              WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwndDlg, IDC_WIDTHINPUT) );
            }
          else
            {
              *pulWidth = ulWidthTemp;       /* Return chosen width          */
              WinDismissDlg(hwndDlg, DID_OK);
            }
          break;

        case DID_CANCEL:         /* The Cancel pushbutton or Escape key      */
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          break;
      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}
/********************** End of dialog procedure  ************************/

/*****************************************************************************/
/* InitHelp()                                                                */
/*                                                                           */
/* DESCRIPTION: Help Procedure                                               */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/

VOID    InitHelp(VOID)
{

  HELPINIT      HelpInit;

   HelpInit.pszHelpLibraryName       = "sketsamp.hlp";
   HelpInit.pszHelpWindowTitle       = "Sketch Controls Sample Program Help";
   HelpInit.hmodHelpTableModule      = 0;
   HelpInit.hmodAccelActionBarModule = 0;
   HelpInit.phtHelpTable             = (PHELPTABLE)MAKEULONG( SKETCH_HELPTABLE, 0xffff );

   HelpInit.cb                       = sizeof( HELPINIT );
   HelpInit.ulReturnCode             = 0L;
   HelpInit.pszTutorialName          = (PSZ)NULL;
   HelpInit.idAccelTable             = 0L;
   HelpInit.idActionBar              = 0L;
   HelpInit.fShowPanelId             = CMIC_HIDE_PANEL_ID;

   if ( ! ( hwndHelp = WinCreateHelpInstance( hab, &HelpInit ) ) )
     {

       /***************************/
       /* Help Creation error.    */
       /***************************/
       ShowMessageBox(HWND_DESKTOP, IDMSG_NO_HELP, NULL);


     }
   else
     {
       WinAssociateHelpInstance( hwndHelp, hwndFrame );
     }

}

/****************************************************************************/
/*  Name : AllNoneAuxDlgProc                                                */
/*                                                                          */
/*  Description : Ask user if he wants ALL or NONE Auxilliary data          */
/*                                                                          */
/* Parameters   : hwnd - Window handle to which message is addressed        */
/*                msg - Message type                                        */
/*                mp1 - First message parameter                             */
/*                mp2 - Second message parameter                            */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
MRESULT EXPENTRY AllNoneAuxDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
HWND hwndButton;                 /* handle of current button                */
static USHORT usAuxTemp;         /* temporary Aux Pointer                   */
static PSHORT pAuxSelection;     /* pointer to actual mode variable         */


  switch ( msg )
  {

    case WM_INITDLG:                /* Get pointer to aux var                */
      pAuxSelection =  PVOIDFROMMP(mp2);


      switch ( usAux)               /* set button to whatever is active.     */
      {
         case TRUE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_ALLAUX);
           break;

         case FALSE:
           hwndButton = WinWindowFromID(hwndDlg, IDC_NONEAUX);
           break;


      } /* end switch */
      WinSendMsg (hwndButton, BM_CLICK, 0L, 0L); /* turn on current choice */
      return ( (MRESULT) TRUE);  /* to indicate we changed focus */

    case WM_CONTROL:
      if (SHORT2FROMMP (mp1) == BN_CLICKED)
      {
      /* track the currently selected button */
        switch (SHORT1FROMMP(mp1) )
        {

         case IDC_NONEAUX:
           usAuxTemp = FALSE;
           break;

         case IDC_ALLAUX:
           usAuxTemp = TRUE;
           break;

        } /* end switch */
      } /* end if */
      return (MRESULT)0;

    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_OK:
          *pAuxSelection = usAuxTemp;    /* update the actual return       */

          WinDismissDlg(hwndDlg, DID_OK);
          break;

        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          WinDismissDlg( hwndDlg, DID_CANCEL );  /* Removes the dialog box    */
          break;

        case IDC_AUX_HELP:
               /********************************************************/
               /* Display the Help panel for Auxiliary data choices.   */
               /********************************************************/
               WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
                                    MPFROM2SHORT(PANEL_AUX, NULL),
                                    MPFROMSHORT(HM_RESOURCEID) );
        break;

      }
      return(MRESULT)0;

  default:
    return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  }
return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
}
/********************** End of dialog procedure  ************************/

/****************************************************************************/
/* SaveBmpInFile  -  Save the bitmap to file on disk.                       */
/*                   User select file name.                                 */
/*  Parameters:                                                             */
/*                                                                          */
/*  Return Value:                                                           */
/*                                                                          */
/****************************************************************************/
VOID SaveBmpInFile(HWND hwndDlg, HBITMAP hBitmap)
{
  APIRET rc;                               /* return code                    */

  HFILE             hfBmpFile;

  BITMAPFILEHEADER2 bmpFileHdr2;
  PBYTE             pbBuffer = NULL;
  ULONG             ulRGBTbl;              /* buffer lengths                 */
  ULONG             ulImgData;
  ULONG             ulTotal;
  ULONG             ulBmpFileHdr2;
  PBITMAPINFO2      pbmi = NULL;           /* info structure                 */

  ULONG             ulBytesWritten;        /* Bytes Written to file          */
  ULONG             ulAction;


  HDC      hMemoryDC;
  HPS      hMemoryPS;
  SIZEL    sizeL;


  FILEDLG           SaveFileDlg;           /* Chose name to save bitmap      */
  char pszTitle[40] = "Enter file name to save bitmap.";
  char pszFullFile[CCHMAXPATH] = "?.bmp";
  HDIR         hdir;
  FILEFINDBUF  findbuf;
  ULONG        cFilenames;

  cFilenames = 1;
  hdir = HDIR_SYSTEM;

  /*****************************************************/
  /* First, Get name of file to save as.               */
  /*****************************************************/
  memset(&SaveFileDlg, 0, sizeof(FILEDLG) );
  SaveFileDlg.cbSize = sizeof(FILEDLG);
  SaveFileDlg.fl = FDS_SAVEAS_DIALOG | FDS_CENTER;/* Save File Dialog        */
  SaveFileDlg.pszTitle = pszTitle;                /* Dialog title string     */
  strcpy(SaveFileDlg.szFullFile, pszFullFile);    /* File name               */

  WinFileDlg(HWND_DESKTOP, hwndDlg, &SaveFileDlg);       /* get file name    */

  if (SaveFileDlg.lReturn == DID_CANCEL)
    return;

  /***************************************/
  /* Check if this file already exists.  */
  /* If it does give chance to cancel.   */
  /***************************************/
  rc = DosFindFirst(SaveFileDlg.szFullFile,
                    &hdir,
                    FILE_NORMAL,
                    &findbuf,
                    sizeof(findbuf),
                    &cFilenames,
                    FIL_STANDARD);

  DosFindClose(hdir);

  if (!rc)                     /* requested file name already exists. */

    {
      if (MBID_OK != ShowMessageBox(hwndDlg, IDMSG_BITMAP_REALLY_SAVE,
                                    SaveFileDlg.szFullFile) )

      return;
    }


  if( (hMemoryDC = DevOpenDC(hab, OD_MEMORY, (PSZ) "*", 0L, 0L, 0L)) != NULLHANDLE )
  {
    sizeL.cx = 0L;                               /* 0, when using GPIA_ASSOC */
    sizeL.cy = 0L;

    if( (hMemoryPS = GpiCreatePS( hab, hMemoryDC, &sizeL , PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT)) != NULLHANDLE )
    {
      if( GpiSetBitmap( hMemoryPS, hBitmap) == NULLHANDLE )
      {
        bmpFileHdr2.bmp2.cbFix = sizeof (BITMAPINFOHEADER2);
        GpiQueryBitmapInfoHeader(hBitmap, &bmpFileHdr2.bmp2);


        /************************************************************/
        /* Compute the size of the image_data buffer and the bitmap */
        /* information structure.                                   */
        /************************************************************/
        ulBmpFileHdr2 = sizeof (BITMAPFILEHEADER2);

        ulImgData = (((bmpFileHdr2.bmp2.cBitCount * bmpFileHdr2.bmp2.cx) + 31) / 32)
                       * 4 * bmpFileHdr2.bmp2.cy * bmpFileHdr2.bmp2.cPlanes;

        ulRGBTbl = (sizeof(RGB2) * (1 << bmpFileHdr2.bmp2.cBitCount));

        ulTotal = ulBmpFileHdr2 + ulImgData + ulRGBTbl;

        bmpFileHdr2.usType   = BFT_BMAP;
        bmpFileHdr2.cbSize   = ulTotal;
        bmpFileHdr2.xHotspot = 0;
        bmpFileHdr2.yHotspot = 0;
        bmpFileHdr2.offBits  = ulBmpFileHdr2 + ulRGBTbl;
        /*******************************************************/
        /* Allocate a buffer (non-shared) based on that size.  */
        /*******************************************************/
        pbBuffer = malloc(ulTotal);
        if (pbBuffer)
          {
            memcpy(pbBuffer, &bmpFileHdr2, sizeof(BITMAPFILEHEADER2));
            /*******************************************************/
            /* Allocate a buffer (non-shared) based on that size.  */
            /*******************************************************/
            pbmi = malloc(ulTotal);
            if (pbmi)
              {
                pbmi = (PBITMAPINFO2) (pbBuffer +
                                       (LONG) sizeof(BITMAPFILEHEADER2) -
                                       (LONG) sizeof(BITMAPINFOHEADER2));
                pbmi->cbFix = bmpFileHdr2.bmp2.cbFix;
                pbmi->cPlanes = bmpFileHdr2.bmp2.cPlanes;
                pbmi->cBitCount = bmpFileHdr2.bmp2.cBitCount;
                GpiQueryBitmapBits(hMemoryPS,
                                   0L,
                                   (LONG) bmpFileHdr2.bmp2.cy,
                                   pbBuffer + bmpFileHdr2.offBits,
                                   pbmi);
                /*******************************************************/
                /* Open the file to save the signature.                */
                /*******************************************************/
                rc = DosOpen(SaveFileDlg.szFullFile,
                             &hfBmpFile,
                             &ulAction,
                             ulImgData,
                             FILE_NORMAL,
                             OPEN_ACTION_CREATE_IF_NEW |
                             OPEN_ACTION_REPLACE_IF_EXISTS,
                             OPEN_FLAGS_WRITE_THROUGH |
                             OPEN_FLAGS_NO_CACHE |
                             OPEN_FLAGS_NOINHERIT |
                             OPEN_SHARE_DENYREADWRITE |
                             OPEN_ACCESS_READWRITE ,
                             (PEAOP2)NULL);
                if (!rc)
                  {

                    /*******************************************************/
                    /* Write HEADER AND BITMAP image to file.              */
                    /*******************************************************/
                    DosWrite(hfBmpFile,
                             pbBuffer,
                             ulTotal,
                             &ulBytesWritten);
                    DosClose(hfBmpFile);
                    ShowMessageBox(hwndDlg, IDMSG_BMP_SAVED_OK, SaveFileDlg.szFullFile);
                  }
                else
                  ShowMessageBox(hwndDlg, IDMSG_FILE_ERROR, NULL);
                free(pbBuffer);
                free(pbmi);
              } /* buffer created */
            else
              {
                ShowMessageBox(hwndDlg, IDMSG_MEMORY_ERROR, NULL);
                free(pbBuffer);
              }
          } /* buffer created */
        else
            ShowMessageBox(hwndDlg, IDMSG_MEMORY_ERROR, NULL);
      } /* memory ps */

      GpiAssociate( hMemoryPS, NULLHANDLE );    /* DisAssoc memory bitmap */
      GpiSetBitmap( hMemoryPS, NULLHANDLE );    /* PS no longer has a BMP */
      GpiDestroyPS( hMemoryPS );                /* Destroy the PS         */
    } /* memoryDC created */

    DevCloseDC( hMemoryDC );                    /* Close the DC              */
  }

}
/********************** End of Function *************************************/

/*****************************************************************************/
/*                                                                           */
/*  CreateControls - Create the following controls:  Selection Button        */
/*                                                   Cancel Button           */
/*                                                   Help Button             */
/*                                                   Sketch Window           */
/*                                                                           */
/*****************************************************************************/

void CreateControls(HWND hwnd)
{

  ULONG ulWindowStyle;


ulWindowStyle = WS_VISIBLE | BS_PUSHBUTTON | BS_DEFAULT;

hSELECTButton = WinCreateWindow( hwnd,              /* parent                */
                                 WC_BUTTON,         /* class name            */
                                 "SELECT CONTROL",  /* caption               */
                                  ulWindowStyle,    /* style                 */
                                  5L,               /* x of window position  */
                                  5L,               /* y of window position  */
                                  200L,             /* cx width of window    */
                                  30L,              /* cy length of window   */
                                  hwnd,             /* owner                 */
                                  HWND_BOTTOM,      /* position (nop)        */
                                  IDC_SELECT,       /* id                    */
                                  (PVOID) NULL,     /* parms passed wm_create*/
                                  (PVOID) NULL );   /* presparams            */


  ulWindowStyle = WS_VISIBLE | BS_PUSHBUTTON;

  hCANCELButton = WinCreateWindow( hwnd,              /* parent              */
                                   WC_BUTTON,         /* class name          */
                                   "CANCEL",          /* Cancel Button       */
                                   ulWindowStyle,     /* style               */
                                   210L,              /* x of window position*/
                                   5L,                /* y of window position*/
                                   88L,               /* cx width of window  */
                                   30L,               /* cy length of window */
                                   hwnd,              /* owner               */
                                   HWND_BOTTOM,       /* position (nop)      */
                                   IDC_CANCEL,        /* Control ID          */
                                   (PVOID) NULL,      /* parms passed to wm_c*/
                                   (PVOID) NULL );    /* presparams          */


  ulWindowStyle = WS_VISIBLE | BS_PUSHBUTTON | BS_HELP | BS_NOPOINTERFOCUS;

  hHELPButton = WinCreateWindow( hwnd,                /* parent              */
                                   WC_BUTTON,         /* class name          */
                                   "HELP",            /* Help                */
                                   ulWindowStyle,     /* style               */
                                   300L,              /* x of window position*/
                                   5L,                /* y of window position*/
                                   70L,               /* cx width of window  */
                                   30L,               /* cy length of window */
                                   hwnd,              /* owner               */
                                   HWND_BOTTOM,       /* position (nop)      */
                                   IDC_SKETCH_HELP,   /* Control ID          */
                                   (PVOID) NULL,      /* parms passed to wm_c*/
                                   (PVOID) NULL );    /* presparams          */

  ulWindowStyle = WS_VISIBLE | SKS_BORDER;

  hSKETCHControl  = WinCreateWindow( hwnd,            /* parent              */
                                     WC_SKETCH,       /* class name          */
                                     "",              /* Caption             */
                                     ulWindowStyle,   /* style               */
                                     5L,              /* x  window position  */
                                     40L,             /* y  window position  */
                                     195L,            /* cx width of window  */
                                     90L,             /* cy length of window */
                                     hwnd,            /* owner               */
                                     HWND_BOTTOM,     /* position (nop)      */
                                     IDC_SKETCH,      /* Control ID          */
                                     (PVOID) NULL,    /* parms passed to wm_c*/
                                     (PVOID) NULL );  /* presparams          */

  bWindowsCreated = TRUE;

}
/********************** End of Function *************************************/

/*****************************************************************************/
/*  Name : DisplayStrokeInfoDlgProc                                          */
/*                                                                           */
/*  Description : Display some of the information for a particular stroke.   */
/*                                                                           */
/* Parameters   : hwnd - Window handle to which message is addressed         */
/*                msg - Message type                                         */
/*                mp1 - First message parameter                              */
/*                mp2 - Second message parameter                             */
/*                                                                           */
/*****************************************************************************/
MRESULT EXPENTRY DisplayStrokeInfoDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

CHAR             szTempString[40];     /* temporary string buffer            */
PULONG           pulStrokeNumber;      /* Stroke Number                      */


  switch ( msg )
  {
    case WM_INITDLG:
       pulStrokeNumber =  PVOIDFROMMP(mp2);  /* Stroke Number parm           */

       /**************************************/
       /* Set Stroke Information.            */
       /**************************************/

       /************************/
       /* Stroke Number        */
       /************************/
       sprintf(szTempString, "%ld", *pulStrokeNumber);
       WinSetDlgItemText(hwndDlg, IDC_STROKE_NUMBER_DATA, szTempString);

       /************************/
       /* Stroke Color         */
       /************************/
       GetColorString(pStrokeData->ulStrokeColor, (PSZ) &szTempString); /* get color string*/
       WinSetDlgItemText(hwndDlg, IDC_STROKE_COLOR_DATA, szTempString);

       /************************/
       /* Stroke Width         */
       /************************/
       sprintf(szTempString, "%ld", pStrokeData->ulStrokeWidth);
       WinSetDlgItemText(hwndDlg, IDC_STROKE_WIDTH_DATA, szTempString);

       /************************/
       /* ulTimestamp          */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->ulTimestamp);
       WinSetDlgItemText(hwndDlg, IDC_TIMESTAMP_DATA, szTempString);

       /************************/
       /* cbStructSize         */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->cbStructSize);
       WinSetDlgItemText(hwndDlg, IDC_STRUCT_SIZE_DATA, szTempString);

       /************************/
       /* ulSource             */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->ulSource);
       WinSetDlgItemText(hwndDlg, IDC_SOURCE_DATA, szTempString);

       /************************/
       /* ulResolution         */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->ulResolution);
       WinSetDlgItemText(hwndDlg, IDC_RESOLUTION_DATA, szTempString);

       /************************/
       /* ulSampleRate         */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->ulSampleRate);
       WinSetDlgItemText(hwndDlg, IDC_SAMPLE_RATE_DATA, szTempString);

       /************************/
       /* ulNumPoints          */
       /************************/
       sprintf(szTempString, "%ld",pStrokeData->pStroke->ulNumPoints);
       WinSetDlgItemText(hwndDlg, IDC_NUMPOINTS_DATA, szTempString);


       break;


    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_CANCEL:              /* The Cancel pushbutton or Escape key */
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          return (MRESULT) FALSE;
      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}
/********************** End of Function *************************************/
