#pragma	title("Status Bar Control  --  Version 1.0 -- (StatBar.C)")
#pragma	subtitle("  Status Bar Control DLL - Interface Definitions")

#pragma	info(noext)

#define	INCL_GPI		   /* Include OS/2 PM GPI Interface	*/
#define	INCL_WIN		   /* Include OS/2 PM Windows Interface	*/
#define	INCL_NLS		   /* Include OS/2 PM NLS Support	*/

#include <os2.h>
#include <string.h>

#include <pmcx.h>

#include "statbar.h"

/* This	module contains	an example installable control that can	be used	*/
/* within applications where additional	facilities are provided	that	*/
/* are not found within	the default controls of	OS/2 PM.		*/
/*									*/
/* For complete	details	regarding the PM Control Extensions (PMCX)	*/
/* consult the User's Guide.                                            */
/*									*/
/* The DLL is created using the	following command line invocation:	*/
/*									*/
/*     Icc -C -G3e -O+ -Sm -W3 StatBar.C				*/

/* Filename:   StatBar.C						*/

/*  Version:   1.0							*/
/*  Created:   1993-03-05						*/
/*  Revised:   1994-06-26						*/

/* Routines:   BOOL EXPENTRY StatBarRegister(HAB hAB);			*/
/*	       BOOL EXPENTRY StatBarQuery(PUSERINFO pControlInfo);	*/
/*	       static VOID SizeStatus(HWND hWnd, LONG x, LONG y,	*/
/*				      LONG cx, LONG cy);		*/
/*	       LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG	ulID2,	*/
/*				  LONG lDefault);			*/
/*	       MRESULT EXPENTRY	StatBarWndProc(HWND hWnd, ULONG	msg,	*/
/*					       MPARAM mp1, MPARAM mp2);	*/
/*	       MRESULT EXPENTRY	StatBarStyles(HWND hWnd, ULONG msg,	*/
/*					      MPARAM mp1, MPARAM mp2);	*/


/* Copyright ¸ 1989-1994  Prominare Inc.  All Rights Reserved.		*/

/* --------------------------------------------------------------------	*/

/************************************************************************/
/************************************************************************/
/*		       DISCLAIMER OF WARRANTIES.			*/
/************************************************************************/
/************************************************************************/
/*     The following [enclosed]	code is	library	code created by		*/
/*     Prominare Inc.  This library code 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.  Prominare	Inc. shall not be liable	*/
/*     for any damages arising out of your use of the library code,	*/
/*     even if they have been advised of the possibility of such	*/
/*     damages.								*/
/************************************************************************/
/************************************************************************/

/* --- Window Information Structures ----------------------------------	*/

typedef	struct _STATUS		   /* status */
   {
   ULONG    id;			   /* ID Value				*/
   LONG	    cTotal;		   /* Total Count			*/
   LONG	    cCurrent;		   /* Current count			*/
   BOOL	    fNoText;		   /* No Text Flag			*/
   RECTL    rcl;		   /* Window Rectangle			*/
   RECTL    rclBar;		   /* Window Rectangle			*/
   POINTL   aptlShadow[5];	   /* Shadow Polyline Array		*/
   POINTL   aptlInterior[2];	   /* Shadow Polyline Array		*/
   LONG	    xWidth;		   /* Width				*/
   HWND	    hwndOwner;		   /* Owner Window Handle		*/
   HWND	    hwndParent;		   /* Parent Window Handle		*/
   HWND	    hwndText;		   /* Text Window Handle		*/
   HWND	    ahwnd[11];		   /* %	Text Window Handle		*/
   HPOINTER hptrArrow;		   /* Arrow Pointer			*/
   LONG	    lClrBar;		   /* Status Bar Colour			*/
   LONG	    aClr[7];		   /* Presentation Colours Array	*/
   } STATUS ;

typedef	STATUS *PSTATUS;

/* --- Status Bar Support ---------------------------------------------	*/

typedef	struct _STATUSCDATA
   {
   LONG	   cb;			   /* Size of Structure			*/
   LONG	   cTotal;		   /* Total Element Count		*/
   LONG	   cCurrent;		   /* Current Element Count		*/
   } STATUSCDATA ;

typedef	STATUSCDATA *PSTATUSCDATA;

#define	WM_SETRANGE	   (WM_USER + 256)
#define	WM_UPDATESTATUSBAR (WM_USER + 257)
#define	WM_SETCOLOUR	   (WM_USER + 258)
#define	WM_CLRRANGE	   (WM_USER + 259)

/* --- Function	Prototypes --------------------------------------------	*/

BOOL	EXPENTRY StatBarRegister(HAB hAB);
BOOL	EXPENTRY StatBarQueryInfo(PUSERINFO pUserInfo);
MRESULT	EXPENTRY StatBarStyles(HWND hWnd, ULONG	msg, MPARAM mp1, MPARAM	mp2);

/* --- Module Prototype	Definitions -----------------------------------	*/

static VOID SizeStatus(HWND hWnd, LONG x, LONG y, LONG cx, LONG	cy);
LONG lGetPresParam(HWND	hWnd, ULONG ulID1, ULONG ulID2,	LONG lDefault);
MRESULT	EXPENTRY StatusBarWndProc(HWND hWnd, ULONG msg,	MPARAM mp1, MPARAM mp2);

static PSZ apszPercent[11] = {	"0",  "10", "20", "30",	"40", "50", "60",
				"70", "80", "90", "100"	};

#pragma	subtitle("   Status Bar - Control Initialization Function")
#pragma	page ( )

/* --- StatBarRegister --------------------------------- [ Public ] ---	*/
/*									*/
/*     This function is	used to	register the installable control class	*/
/*     with OS/2 Presentation Manager.	The registration must use the	*/
/*     USER_CWINDOWWORDS to reserve memory for the control to allow for	*/
/*     proper usage by Resource	Editor and for use by the control	*/
/*     dialog and window procedures.  The information for the control	*/
/*     containing the style, presentation parameters and control data	*/
/*     is pointed to by	a pointer that can be referenced by the		*/
/*     control's dialog and window procedure as required.  The memory   */
/*     for the structure is allocated and controlled through Resource	*/
/*     Editor.	 The control can reserve more memory for its use	*/
/*     by adding the memory required to	that of	the USER_CWINDOWWORDS	*/
/*     constant.							*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HAB hAB;	= Application Anchor Block Handle			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     StatBarRegister =  TRUE : Class Registration Successful		*/
/*		       = FALSE : Class Registration Failed		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY StatBarRegister(HAB hAB)

{
		       /* Register the control class with OS/2		*/
		       /* Presentation Manager and return registration	*/
		       /* result					*/

return(WinRegisterClass(hAB, "StatusBar", (PFNWP)StatusBarWndProc,
			CS_SYNCPAINT | CS_HITTEST | CS_PARENTCLIP | CS_SIZEREDRAW,
			USER_CWINDOWWORDS));

}
#pragma	subtitle("   Status Bar - Query Control Information Function")
#pragma	page ( )

/* --- StatBarQuery ------------------------------------ [ Public ] ---	*/
/*									*/
/*     This function is	used to	return to the caller information	*/
/*     regarding the installable control and its capabilities.	The	*/
/*     function	should return a	true value otherwise Resource		*/
/*     Editor will not register	the control as being usable.		*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     PUSERINFO pUserInfo; = User Information Pointer			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     StatBarQuery =  TRUE : User Information Being Returned		*/
/*		    = FALSE : No User Information Available		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY StatBarQuery(PUSERINFO pUserInfo)

{
		       /* Complete the User Information	structure	*/
		       /* passed to the	function by Resource Editor  */

		       /* Complete the version and number of control	*/
		       /* types.  In Version 1.00 of CCLS, only	one	*/
		       /* control type is used.				*/
pUserInfo->ulMajor = 3UL;
pUserInfo->ulMinor = 0UL;
		       /* Complete the author and control classname	*/

memcpy(pUserInfo->szAuthor,    "Prominare Inc.", 15);
memcpy(pUserInfo->szClassname, "StatusBar", 10);
memcpy(pUserInfo->szName,      "StatBar", 8);

		       /* Complete the default size and	style of the	*/
		       /* first	user control type			*/

pUserInfo->utDefined[0].cx	   = 40L;
pUserInfo->utDefined[0].cy	   =  4L;
pUserInfo->utDefined[0].flStyle	   = WS_VISIBLE	| SBRS_NOTEXT;

		       /* Set the maximum amount of text control can	*/
		       /* accept including NULL	termination byte	*/

pUserInfo->utDefined[0].cMaxText     = 0;

		       /* Save the style's dialogue ID, type, control   */
		       /* data size and	count of style masks		*/

pUserInfo->utDefined[0].idDlg	     = DLG_CTRLUSER;
pUserInfo->utDefined[0].ulType	     = UTYPE_PRIVATE;
pUserInfo->utDefined[0].cCtlData     = sizeof(STATUSCDATA);
pUserInfo->utDefined[0].cMasks	     = 2UL;
pUserInfo->utDefined[0].flStyleType  = STYLETYPE_BITFLAGS;
pUserInfo->utDefined[0].flOptions    = PMCXOPT_REFRESH;
pUserInfo->utDefined[0].stMasks[0].flStyleMask = SBRS_TEXT;
pUserInfo->utDefined[0].stMasks[0].idStyle     = IDS_SBRS_TEXT;
pUserInfo->utDefined[0].stMasks[1].flStyleMask = SBRS_NOTEXT;
pUserInfo->utDefined[0].stMasks[1].idStyle     = IDS_SBRS_NOTEXT;

		       /* Save the description of the control		*/

memcpy(pUserInfo->utDefined[0].szDescription, "Status Bar", 11);

		       /* Return the success flag back to Resource	*/
		       /* Editor					*/
return(TRUE);
}
#pragma	subtitle("   Status Bar Control - Control Sizing Procedure")
#pragma	page( )

/* --- SizeStatus -------------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	calculate various elements of that	*/
/*     make up the button.						*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND hWnd; = Window Handle					*/
/*     LONG x;	  = x Starting Point					*/
/*     LONG y;	  = y Starting Point					*/
/*     LONG cx;	  = Button Width					*/
/*     LONG cy;	  = Button Height					*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     Nothing								*/
/*									*/
/* --------------------------------------------------------------------	*/

static VOID SizeStatus(HWND hWnd, LONG x, LONG y, LONG cx, LONG	cy)

{
PSTATUS	pstatus;		   /* Status Bar Structure Pointer	*/
RECTL	rcl;			   /* Rectangle	Holder			*/
register INT i;			   /* Loop Counter			*/

		       /* Get the address of the private control data	*/
		       /* structure					*/

pstatus	= (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Save the bounding rectangle of the control	*/

pstatus->rcl.xRight = (pstatus->rcl.xLeft   = x) + cx;
pstatus->rcl.yTop   = (pstatus->rcl.yBottom = y) + cy;

if ( !pstatus->fNoText )
   {

   WinQueryWindowRect(pstatus->hwndText, &rcl);
   WinSetWindowPos(pstatus->hwndText, HWND_BOTTOM,
		   10L,	cy - 5L	- rcl.yTop - rcl.yBottom, 0L, 0L, SWP_MOVE);

   pstatus->aptlShadow[	1].x = 20L;
   pstatus->aptlShadow[	1].y = cy - 10 - rcl.yTop - rcl.yBottom;
   pstatus->aptlShadow[	2].x = pstatus->rcl.xRight - 20L;
   pstatus->aptlShadow[	2].y = cy - 10 - rcl.yTop - rcl.yBottom;

   WinQueryWindowRect(pstatus->ahwnd[0], &rcl);
   WinSetWindowPos(pstatus->ahwnd[0], HWND_BOTTOM,
		   20L - (rcl.xRight - rcl.xLeft) / 2L,
		   5L, 0L, 0L, SWP_MOVE);

   for ( i = 1;	i < 10;	i++ )
       {
       WinQueryWindowRect(pstatus->ahwnd[i], &rcl);
       WinSetWindowPos(pstatus->ahwnd[i], HWND_BOTTOM,
		       ((cx - 40L) * i / 10L) -	(rcl.xRight - rcl.xLeft) / 2L +	20L,
		       5L, 0L, 0L, SWP_MOVE);
       }

   WinQueryWindowRect(pstatus->ahwnd[10], &rcl);
   WinSetWindowPos(pstatus->ahwnd[10], HWND_BOTTOM,
		   cx -	20L - (rcl.xRight - rcl.xLeft) / 2L,
		   5L, 0L, 0L, SWP_MOVE);

		       /* Calculate the	positions of the beveled	*/
		       /* edges	of the button				*/

   pstatus->aptlShadow[0].x = 20L;
   pstatus->aptlShadow[0].y = (rcl.yTop	- rcl.yBottom) + 10L;
   pstatus->aptlShadow[3].x = pstatus->rcl.xRight - 20L;
   pstatus->aptlShadow[3].y = (rcl.yTop	- rcl.yBottom) + 10L;
   pstatus->aptlShadow[4]   = pstatus->aptlShadow[0];

   pstatus->aptlInterior[0].x =	pstatus->aptlShadow[0].x + 1L;
   pstatus->aptlInterior[0].y =	pstatus->aptlShadow[0].y + 1L;
   pstatus->aptlInterior[1].x =	pstatus->aptlShadow[2].x - 1L;
   pstatus->aptlInterior[1].y =	pstatus->aptlShadow[2].y - 1L;

   pstatus->rclBar.xLeft   = pstatus->aptlInterior[0].x;
   pstatus->rclBar.xRight  = pstatus->aptlInterior[2].x;
   pstatus->rclBar.yBottom = pstatus->aptlInterior[0].y;
   pstatus->rclBar.yTop	   = pstatus->aptlInterior[2].y;

   pstatus->xWidth = pstatus->aptlInterior[2].x	- pstatus->aptlInterior[0].x;
   }
else
   {

   pstatus->aptlShadow[	0].x = x + 1L;
   pstatus->aptlShadow[	0].y = y + 1L;
   pstatus->aptlShadow[	1].x = x + 1L;
   pstatus->aptlShadow[	1].y = cy - 2L;
   pstatus->aptlShadow[	2].x = cx - 2L;
   pstatus->aptlShadow[	2].y = cy - 2L;
   pstatus->aptlShadow[	3].x = cx - 2L;
   pstatus->aptlShadow[	3].y = y + 1L;
   pstatus->aptlShadow[	4].x = x + 1L;
   pstatus->aptlShadow[	4].y = y + 1L;

   pstatus->aptlInterior[0].x =	pstatus->aptlShadow[0].x + 1L;
   pstatus->aptlInterior[0].y =	pstatus->aptlShadow[0].y + 1L;
   pstatus->aptlInterior[1].x =	pstatus->aptlShadow[2].x - 1L;
   pstatus->aptlInterior[1].y =	pstatus->aptlShadow[2].y - 1L;

   pstatus->rclBar.xLeft   = pstatus->aptlShadow[0].x;
   pstatus->rclBar.xRight  = pstatus->aptlShadow[2].x;
   pstatus->rclBar.yBottom = pstatus->aptlShadow[0].y;
   pstatus->rclBar.yTop	   = pstatus->aptlShadow[2].y;

   pstatus->xWidth = pstatus->aptlShadow[2].x -	pstatus->aptlShadow[0].x;
   }
}
#pragma	subtitle("   Status Bar Control - Control Window Procedure")
#pragma	page( )

/* --- lGetPresParam ----------------------------------	[ Private } ---	*/
/*									*/
/*     This function is	used to	retrieve a presentation	parameter	*/
/*     that may	be present.  If	the presentation parameter is not,	*/
/*     the default colour passed to the	function will be used.		*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND  hWnd;     = Window	Handle					*/
/*     ULONG ulID1;    = Presentation Parameter	1 ID			*/
/*     ULONG ulID2;    = Presentation Parameter	2 ID			*/
/*     LONG  lDefault; = Default Colour					*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     lGetPresParam = Colour to Use					*/
/*									*/
/* --------------------------------------------------------------------	*/

LONG lGetPresParam(HWND	hWnd, ULONG ulID1, ULONG ulID2,	LONG lDefault)

{
HPS   hPS;			   /* Presentation Space Handle		*/
LONG  lClr;			   /* Presentation Parameter Colour	*/
ULONG ulID;			   /* Presentation Parameter ID		*/

if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, 4, (PVOID)&lClr,
		       QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) )
   return(lClr);
else
   if (	(lDefault >= SYSCLR_SHADOWHILITEBGND) &&
	(lDefault <= SYSCLR_HELPHILITE)	)
       return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L));
   else
       if ( (lClr = GpiQueryRGBColor(hPS = WinGetPS(hWnd),
				     LCOLOPT_REALIZED, lDefault)) == GPI_ALTERROR )
	   {
	   WinReleasePS(hPS);
	   return(lDefault);
	   }
       else
	   {
	   WinReleasePS(hPS);
	   return(lClr);
	   }
}
#pragma	subtitle("   Status Bar Control - Status Bar Control Procedure")
#pragma	page( )

/* --- StatusBarWndProc	-------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	process	the messages for the error	*/
/*     output window.							*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND   hWnd; = Window Handle					*/
/*     ULONG  msg;  = PM Message					*/
/*     MPARAM mp1;  = Message Parameter	1				*/
/*     MPARAM mp2;  = Message Parameter	2				*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     StatusBarWndProc	= Message Handling Result			*/
/*									*/
/* --------------------------------------------------------------------	*/

MRESULT	EXPENTRY StatusBarWndProc(HWND hWnd, ULONG msg,	MPARAM mp1, MPARAM mp2)

{
HPS	      hPS;		   /* Display Presentation Space	*/
LONG	      lClr;		   /* Colour Holder			*/
PCREATESTRUCT pcrst;		   /* Creation Information Pointer	*/
POINTL	      ptl;		   /* Display Point			*/
PSTATUS	      pstatus;		   /* Status Information Pointer	*/
PSTATUSCDATA  pstatusd;		   /* Status Information Pointer	*/
RECTL	      rcl;		   /* Rectangle	Holder			*/
ULONG	      ulID;		   /* ID Holder				*/
register INT i;			   /* Loop Counter			*/

switch ( msg )
   {
   case	WM_CREATE :
		       /* Create a heap	for the	control	using a		*/
		       /* segment					*/

       DosAllocMem((PPVOID)(PVOID)&pstatus, sizeof(STATUS),
		   PAG_READ | PAG_WRITE	| PAG_COMMIT);

		       /* Save the address of the text string pointer	*/
		       /* in the control's reserved memory to allow it  */
		       /* to be	referenced as required by the control	*/

       WinSetWindowPtr(hWnd, QWW_CDATA,	(PVOID)pstatus);

		       /* Get the control's creation structure address  */
		       /* to copy the default text of the control to	*/
		       /* the memory in	the heap			*/

       pcrst	= (PCREATESTRUCT)PVOIDFROMMP(mp2);

       if ( (pstatusd =	(PSTATUSCDATA)PVOIDFROMMP(mp1))	!= NULL	)
	   {
	   pstatus->cTotal   = pstatusd->cTotal;
	   pstatus->cCurrent = pstatusd->cCurrent;
	   }
       pstatus->hwndOwner  = pcrst->hwndOwner;
       pstatus->hwndParent = pcrst->hwndParent;
       pstatus->id	   = pcrst->id;
       pstatus->hptrArrow  = WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW,
						FALSE);
       if ( pcrst->flStyle & SBRS_NOTEXT )
	   pstatus->fNoText = TRUE;
       else
	   {
	   pstatus->hwndText  =	WinCreateWindow(hWnd, WC_STATIC, pcrst->pszText,
						pcrst->flStyle | WS_VISIBLE,
						0, 0, 0, 0,
						hWnd, HWND_BOTTOM, 0x3412,
						pcrst->pCtlData, pcrst->pPresParams);

	   for ( i = 0,	lClr = CLR_PALEGRAY; i < 11; i++ )
	       {
	       pstatus->ahwnd[i] = WinCreateWindow(hWnd, WC_STATIC, apszPercent[i],
						  SS_AUTOSIZE |	SS_TEXT	| DT_CENTER | DT_VCENTER | WS_VISIBLE,
						  0L, 0L, -1L, -1L,
						  hWnd,	HWND_BOTTOM, (ULONG)(0x3413 + i),
						  NULL,	(PVOID)NULL);
	       WinSetPresParam(pstatus->ahwnd[i], PP_FONTNAMESIZE, 8UL,	(PVOID)"8.Helv");
	       WinSetPresParam(pstatus->ahwnd[i], PP_BACKGROUNDCOLORINDEX, 4UL,	(PVOID)&lClr);
	       }
	   }
		       /* Set up the colours that will be used within	*/
		       /* the painting of the control.	The colour	*/
		       /* indices are:					*/
		       /*						*/
		       /* 0 : Foreground (PP_FOREGROUND*)		*/
		       /* 1 : Background (PP_BACKGROUND*)		*/
		       /* 2 : Hilight Foreground (PP_HILITEFOREGROUND*)	*/
		       /* 3 : Hilight Background (PP_HILITEBACKGROUND*)	*/
		       /* 4 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 5 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 6 : Border (PP_BORDER*)			*/

       pstatus->aClr[0]	= lGetPresParam(hWnd, PP_FOREGROUNDCOLOR,
					PP_FOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT);
       pstatus->aClr[1]	= lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
					PP_BACKGROUNDCOLORINDEX, SYSCLR_BACKGROUND);
       pstatus->aClr[2]	= lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR,
					PP_HILITEFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT);
       pstatus->aClr[3]	= lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR,
					PP_HILITEBACKGROUNDCOLORINDEX, SYSCLR_BACKGROUND);
       pstatus->aClr[4]	= lGetPresParam(hWnd, PP_DISABLEDFOREGROUNDCOLOR,
					PP_DISABLEDFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT);
       pstatus->aClr[5]	= lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
					PP_BACKGROUNDCOLORINDEX, SYSCLR_BACKGROUND);
       pstatus->aClr[6]	= lGetPresParam(hWnd, PP_BORDERCOLOR,
					PP_BORDERCOLORINDEX, SYSCLR_BUTTONDARK);

		       /* Check	to see if the user provided font that	*/
		       /* should override the default font that	would	*/
		       /* be set					*/

       if ( !WinQueryPresParam(hWnd, PP_FONTNAMESIZE, 0L, &ulID, 4,
			       (PVOID)&lClr, QPF_NOINHERIT) )

		       /* System indicates not set since not data was	*/
		       /* returned, therefore set default font for the	*/
		       /* control					*/

	   WinSetPresParam(hWnd, PP_FONTNAMESIZE, 8L, (PVOID)"10.Helv");

       pstatus->lClrBar	= 0x00ff0000L;

       SizeStatus(hWnd,	0, 0, pcrst->cx, pcrst->cy);
       break;
		       /* Set Colour message				*/
   case	WM_SETCOLOUR :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);

       if ( LONGFROMMP(mp2) )
	   pstatus->lClrBar = (LONG)LONGFROMMP(mp1);
       else
	   {
	   pstatus->lClrBar = GpiQueryRGBColor(hPS = WinGetPS(HWND_DESKTOP),
					       LCOLOPT_REALIZED, (LONG)LONGFROMMP(mp1));
	   WinReleasePS(hPS);
	   }
       WinInvalidateRect(hWnd, &pstatus->rclBar, FALSE);
       break;
		       /* Set Clear message				*/
   case	WM_CLRRANGE :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);

       pstatus->cCurrent = pstatus->cTotal = 0L;
       WinInvalidateRect(hWnd, &pstatus->rclBar, FALSE);
       break;
		       /* Set Limits message				*/
   case	WM_SETRANGE :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);

       pstatus->cCurrent = (LONG)LONGFROMMP(mp1);
       pstatus->cTotal	 = (LONG)LONGFROMMP(mp2);
       WinInvalidateRect(hWnd, &pstatus->rclBar, FALSE);
       break;
		       /* Update current count				*/

   case	WM_UPDATESTATUSBAR :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);
       if ( (pstatus->cCurrent += (LONG)LONGFROMMP(mp1)) > pstatus->cTotal )
	   pstatus->cCurrent = pstatus->cTotal;
       WinInvalidateRect(hWnd, &pstatus->rclBar, FALSE);
       break;

   case	WM_SIZE	:
       WinQueryWindowRect(hWnd,	&rcl);

       SizeStatus(hWnd,	rcl.xLeft, rcl.yBottom,
		  (rcl.xRight -	rcl.xLeft),
		  (rcl.yTop   -	rcl.yBottom));
       break;
			/* Since the control is	really a composite,	*/
			/* pass	the message to the text	control		*/
   case	WM_CONTROL :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);
       return((MRESULT)WinSendMsg(pstatus->hwndOwner, msg, mp1,	mp2));

		       /* Process window parameters query		*/

   case	WM_QUERYWINDOWPARAMS :
   case	WM_SETWINDOWPARAMS :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);
       return(WinSendMsg(pstatus->hwndText, msg, mp1, mp2));

		       /* Presentation parameters changed, record the	*/
		       /* change internally				*/

   case	WM_PRESPARAMCHANGED :
       if ( LONGFROMMP(mp1) != PP_FONTNAMESIZE )
	   {
	   pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);
	   if (	WinQueryPresParam(hWnd,	(ULONG)LONGFROMMP(mp1),
				  (ULONG)((LONGFROMMP(mp1) % 2)	? LONGFROMMP(mp1) + 1L : 0L),
				  &ulID, 4UL,
				  (PVOID)&lClr,
				  QPF_NOINHERIT	| QPF_ID1COLORINDEX | QPF_ID2COLORINDEX) )
	       {
	       pstatus->aClr[(LONGFROMMP(mp1) -	1L) / 2L] = lClr;
	       WinSetPresParam(pstatus->hwndText,
			       (ULONG)((LONGFROMMP(mp1)	% 2) ? LONGFROMMP(mp1) + 1L : LONGFROMMP(mp1)),
			       4UL, (PVOID)&lClr);
	       }
	   WinInvalidateRect(hWnd, (PRECTL)NULL, TRUE);
	   }
       break;
		       /* Mouse	being passed over the control, imply	*/
		       /* that the control is transparent to the	*/
		       /* system					*/
   case	WM_HITTEST :
       return(MRFROMLONG(HT_TRANSPARENT));

		       /* Erase	control	background			*/

   case	WM_ERASEBACKGROUND :
       return(MRFROMLONG(TRUE));

		       /* Paint	Window					*/
   case	WM_PAINT :
       pstatus = (PSTATUS)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the presentation space for the control	*/
		       /* and set the colour table to RGB mode		*/

       GpiCreateLogColorTable(hPS = WinBeginPaint(hWnd,	(HPS)NULL, (PRECTL)NULL),
			      0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);

		       /* Get the presentation space			*/

       GpiSetColor(hPS,	0x00ffffffL);
       GpiMove(hPS, &pstatus->aptlShadow[0]);
       GpiPolyLine(hPS,	2L, &pstatus->aptlShadow[1]);
       GpiSetColor(hPS,	pstatus->aClr[6]);
       GpiPolyLine(hPS,	2L, &pstatus->aptlShadow[3]);

       GpiMove(hPS, pstatus->aptlInterior);

       ptl = pstatus->aptlInterior[1];
       if ( pstatus->cCurrent )
	   {
	   ptl.x = pstatus->aptlInterior[0].x +	(pstatus->xWidth * pstatus->cCurrent) /	pstatus->cTotal;
	   GpiSetColor(hPS, pstatus->lClrBar);
	   }
       else
	   GpiSetColor(hPS, pstatus->aClr[1]);
       GpiBox(hPS, DRO_FILL, &ptl, 0L, 0L);

       ptl.y = pstatus->aptlInterior[0].y;
       GpiMove(hPS, &ptl);
       GpiSetColor(hPS,	pstatus->aClr[1]);
       GpiBox(hPS, DRO_FILL, &pstatus->aptlInterior[1],	0L, 0L);

		       /* Release the presentation space		*/
       WinEndPaint(hPS);
       break;
		       /* Control being	destroyed			*/
   case	WM_DESTROY :
		       /* Get the address of the text from the		*/
		       /* control's reserved memory and release the     */
		       /* heap allocated for use by the	control		*/

       DosFreeMem((PVOID)WinQueryWindowPtr(hWnd, QWW_CDATA));
       break;
		       /* Default message processing			*/
   default :
       return(WinDefWindowProc(hWnd, msg, mp1, mp2));
   }
return(0L);
}
#pragma	subtitle("   Status Bar Control - Control Styles Dialogue Procedure")
#pragma	page ( )

/* --- StatBarStyles ----------------------------------- [ Public ] ---	*/
/*									*/
/*     This function is	used for the custom control's styles dialogue   */
/*     box procedure.							*/
/*									*/
/*     When the	dialogue is invoked from Resource Editor, the	     */
/*     address of the user style information is	contained in message	*/
/*     parameter 2.  The dialogue is responsible for saving the		*/
/*     address.	 The best method to do this is to save the pointer	*/
/*     in the dialogue's reserved memory where it can be retrieved as   */
/*     needed.								*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND   hWnd; = Dialog Window Handle				*/
/*     ULONG  msg;  = PM Message					*/
/*     MPARAM mp1;  = Message Parameter	1				*/
/*     MPARAM mp2;  = Message Parameter	2				*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     StatBarStyles = Message Handling	Result				*/
/*									*/
/* --------------------------------------------------------------------	*/

MRESULT	EXPENTRY StatBarStyles(HWND hWnd, ULONG	msg, MPARAM mp1, MPARAM	mp2)

{
PUSERSTYLE   pust;		   /* User Style Pointer		*/
PSTATUSCDATA pstd;		   /* Status Bar Control Data		*/
SWP	     swp;		   /* Screen Window Position Holder	*/

switch ( msg )
   {
		       /* Perform dialogue initialization		*/
   case	WM_INITDLG :
		       /* Save the pointer to user style information	*/
		       /* within the dialog's reserved memory           */

       WinSetWindowPtr(hWnd, QWL_USER, (PVOID)mp2);

		       /* Get the pointer to the user style information	*/

       if ( (pust = (PUSERSTYLE)mp2) !=	NULL )
	   {
		       /* Set the text,	ID symbol and value for	the	*/
		       /* control					*/

	   pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE,	pust);

	   pstd	= (PSTATUSCDATA)pust->abCtlData;
	   WinSetDlgItemShort(hWnd, EF_TOTAL, (USHORT)pstd->cTotal, TRUE);
	   WinSetDlgItemShort(hWnd, EF_CURRENT,	(USHORT)pstd->cCurrent,	TRUE);

		       /* Set Auto Scroll check	box if selected		*/

	   if (	pust->flStyle &	SBRS_NOTEXT )
	       WinSendDlgItemMsg(hWnd, RB_SBRS_NOTEXT, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);
	   else
	       WinSendDlgItemMsg(hWnd, RB_SBRS_TEXT, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_VISIBLE )
	       WinSendDlgItemMsg(hWnd, CB_VISIBLE, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_GROUP )
	       WinSendDlgItemMsg(hWnd, CB_GROUP, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_DISABLED )
	       WinSendDlgItemMsg(hWnd, CB_DISABLED, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_TABSTOP )
	       WinSendDlgItemMsg(hWnd, CB_TABSTOP, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);
	   }
		       /* Centre dialog	on the screen			*/

       WinQueryWindowPos(hWnd, (PSWP)&swp);
       WinSetWindowPos(hWnd, HWND_TOP,
		       ((WinQuerySysValue(HWND_DESKTOP,	SV_CXSCREEN) - swp.cx) / 2),
		       ((WinQuerySysValue(HWND_DESKTOP,	SV_CYSCREEN) - swp.cy) / 2),
		       0L, 0L, SWP_MOVE);
       break;
		       /* Process push button selections		*/
   case	WM_COMMAND :
       switch (	SHORT1FROMMP(mp1) )
	   {
		       /* Presentation push button selected		*/

	   case	DID_FONTCLR :

		       /* Get the pointer to the user style information	*/

	       if ( (pust = PDATAFROMDLG(hWnd))	!= NULL	)

		       /* Get the address of the look up function from	*/
		       /* user style information structure and display	*/
		       /* the dialog.  The value selected within the	*/
		       /* dialog will be automatically placed within	*/
		       /* the required entry fields			*/

		   pust->pfnGetFontClr(hWnd);
	       break;
		       /* Enter	pushbutton selected get	the definitions	*/
		       /* for the control				*/
	   case	DID_OK :

		       /* Get the pointer to the user style information	*/

	       if ( (pust = PDATAFROMDLG(hWnd))	!= NULL	)
		   {

		       /* Get the address of the symbol	validation	*/
		       /* function from	the user style information	*/
		       /* structure.  The function will	validate the	*/
		       /* symbol and will check	for duplications of	*/
		       /* values.  A return value of TRUE from the	*/
		       /* validation function indicates	that the symbol	*/
		       /* and value are	acceptable.  Conversely, a	*/
		       /* FALSE	return value indicates that symbol or	*/
		       /* value	was not	acceptable.  In	this case,	*/
		       /* the dialog should not	be exited from and the	*/
		       /* values within	the entry fields should	not be	*/
		       /* saved.					*/

		   if (	!pust->pfnGetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust) )
		       break;
		   else
		       {
		       pstd = (PSTATUSCDATA)pust->abCtlData;
		       pstd->cb	= sizeof(STATUSCDATA);
		       WinQueryDlgItemShort(hWnd, EF_TOTAL,
					    (PSHORT)(PVOID)&pstd->cTotal, TRUE);
		       WinQueryDlgItemShort(hWnd, EF_CURRENT,
					    (PSHORT)(PVOID)&pstd->cCurrent, TRUE);

		       /* Get horizontal alignment type			*/

		       if ( WinSendDlgItemMsg(hWnd, RB_SBRS_NOTEXT,
					      BM_QUERYCHECK,
					      0L, 0L) )
			   pust->flStyle = SBRS_NOTEXT;
		       else
			   pust->flStyle = SBRS_TEXT;

		       if ( WinSendDlgItemMsg(hWnd, CB_VISIBLE,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_VISIBLE;

		       if ( WinSendDlgItemMsg(hWnd, CB_GROUP,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_GROUP;

		       if ( WinSendDlgItemMsg(hWnd, CB_DISABLED,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_DISABLED;

		       if ( WinSendDlgItemMsg(hWnd, CB_TABSTOP,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_TABSTOP;
		       }
		   }
		       /* Exit the dialogue indicating changes made	*/

	       WinDismissDlg(hWnd, TRUE);
	       break;
		       /* Cancel selected, exit	the dialogue without	*/
		       /* changing anything				*/

	   case	DID_CANCEL :
	       WinDismissDlg(hWnd, FALSE);
	       break;
	   }
       break;
		       /* Close	received, exit dialog			*/
   case	WM_CLOSE :
       WinDismissDlg(hWnd, FALSE);
       break;
		       /* Pass through unhandled messages		*/
   default :
       return(WinDefDlgProc(hWnd, msg, mp1, mp2));
   }
return(0L);

}
