|
|
Microsoft OS/2 SDK PM 08-08-1988
/*--------------------------------------------------------*\
SHAPES.C - displays rotating, variable size 3D shapes
\*--------------------------------------------------------*/
#include <stddef.h>
#include <stdlib.h>
#include <os2.h>
#include "shapes.h"
#include "sstruct.h"
#define WM_END_CHILD (WM_USER + 0)
VOID CreateParent ();
VOID CreateChild ();
INT iNextValidWindow (INT);
INT iQueryChild (HWND);
INT iNextFreeChild ();
MRESULT EXPENTRY ParentWndProc (HWND, USHORT, MPARAM, MPARAM);
MRESULT EXPENTRY ChildWndProc (HWND, USHORT, MPARAM, MPARAM);
extern VOID ChangeScale (PSV);
extern VOID ChangeShapePosition (PSV);
extern VOID DrawAndFill (PSV);
extern SHAPE rgshape []; /* table of shape definitions */
extern INT shapeMax; /* max number of different shapes */
INT ishapeParent = 0; /* current shape in parent window */
/*
"rgpsv" is a table of pointers to shape variables. For each open
window there is one instance of these variables. (see SHAPEVARS structure)
*/
PSV rgpsv [MAX_WINDOWS];
INT iMaxChild = 0; /* max child index */
INT iChildCreate; /* index of child being created */
BOOL fCloseParent = FALSE; /* true when parent window is closed */
extern INT yPelAdjust = 1024; /* adjustment for varying pixel shape */
LONG cxScreen, cyScreen; /* size of full screen */
HAB hab;
HWND hwndMenu;
CHAR szClassNameParent[] = "Shapes";
CHAR szClassNameChild[] = "Child";
/*
* Main:
* - main loop which receives/sends messages for the parent and child
* windows
* - when no messages are waiting in the queue, the next shape is redrawn
*/
main()
{
HMQ hmq;
QMSG qmsg;
BOOL fNotDone = TRUE;
INT iWindow = 0;
hab = WinInitialize (NULL);
hmq = WinCreateMsgQueue (hab, 0);
WinRegisterClass (hab, szClassNameParent, ParentWndProc,
CS_SIZEREDRAW,
0 );
WinRegisterClass (hab, szClassNameChild, ChildWndProc,
CS_SIZEREDRAW,
0 );
CreateParent ();
/* receive/send messages until parent window is closed */
while (fNotDone)
{
if (WinPeekMsg (hab, &qmsg, NULL, 0, 0, PM_REMOVE) )
if (qmsg.msg == WM_QUIT && fCloseParent)
fNotDone = FALSE;
else
WinDispatchMsg (hab, &qmsg);
else
{
/* get next window and redraw its shape */
iWindow = iNextValidWindow (iWindow);
if (!rgpsv [iWindow]->fShaded)
ChangeShapePosition (rgpsv [iWindow]);
}
}
/* destroy remaining open windows */
iWindow = 0;
do
{
iWindow = iNextValidWindow (iWindow);
GpiDestroyPS (rgpsv [iWindow]->hpsClient);
WinDestroyWindow (rgpsv [iWindow]->hwndFrame);
}
while (iWindow != 0);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return 0;
}
/*
* CreateParent:
* - allocate storage for shape variables
* - create the parent window
*/
VOID CreateParent()
{
PSV psv;
SHAPE *pshape;
ULONG CtlData;
psv = (PSV) malloc (sizeof (SHAPEVARS));
rgpsv [0] = psv;
pshape = &rgshape [ishapeParent];
psv->iShape = ishapeParent;
psv->rgptOld = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
psv->rgptNew = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
psv->fShaded = FALSE;
psv->fErased = TRUE;
psv->fClipping = (pshape->pobject->rgface != NULL);
psv->fVarySize = FALSE;
psv->fPerspective = TRUE;
psv->pt2LightAng.x = 0;
psv->pt2LightAng.y = 0;
psv->pt3Angle = pshape->pinit->pt3Angle;
psv->pt3AngVel = pshape->pinit->pt3AngVel;
psv->pt3SizeAng = pshape->pinit->pt3SizeAng;
CtlData = FCF_TITLEBAR
| FCF_SIZEBORDER | FCF_MINMAX
| FCF_SYSMENU | FCF_MENU;
psv->hwndFrame = WinCreateStdWindow(
HWND_DESKTOP,
WS_VISIBLE | FS_ICON | FS_ACCELTABLE,
&CtlData,
szClassNameParent,
szClassNameParent,
0L,
NULL,
ID_RESOURCE,
&psv->hwndClient );
hwndMenu = WinWindowFromID (psv->hwndFrame, FID_MENU);
}
/*
* CreateChild:
* - allocate storage for shape variables
* - initialize variables using the parents variables
* - create a child window
*/
VOID CreateChild(
INT iNewChild )
{
PSV psv;
SHAPE *pshape;
ULONG CtlData;
psv = (PSV) malloc (sizeof (SHAPEVARS));
rgpsv [iNewChild] = psv;
pshape = &rgshape [ishapeParent];
psv->iShape = ishapeParent;
psv->rgptOld = (POINTL *) malloc (
pshape->pobject->cPoints * sizeof (POINTL) );
psv->rgptNew = (POINTL *) malloc (
pshape->pobject->cPoints * sizeof (POINTL) );
psv->fShaded = rgpsv[0]->fShaded;
psv->fErased = TRUE;
psv->fClipping = rgpsv[0]->fClipping;
psv->fVarySize = rgpsv[0]->fVarySize;
psv->fPerspective = rgpsv[0]->fPerspective;
psv->pt2LightAng = rgpsv[0]->pt2LightAng;
psv->pt3Angle = rgpsv[0]->pt3Angle;
psv->pt3AngVel = rgpsv[0]->pt3AngVel;
psv->pt3SizeAng = rgpsv[0]->pt3SizeAng;
iChildCreate = iNewChild;
CtlData = FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_SYSMENU;
psv->hwndFrame = WinCreateStdWindow(
HWND_DESKTOP,
WS_VISIBLE,
&CtlData,
szClassNameChild,
pshape->szName,
0L,
NULL,
0,
&psv->hwndClient );
}
/*
* iNextValidWindow:
* - get the window index which is greater than a given index
* - if no indexes are greater then return the index for
* the parent (first) window
*/
INT iNextValidWindow (
INT iWindow )
{
INT i;
for (i = iWindow + 1; i <= iMaxChild; i++)
if (rgpsv [i] != NULL)
return i;
return 0;
}
/*
* iQueryChild:
* - get the window index associated with a window handle
* - return 0 if window handle not found
*/
INT iQueryChild (
HWND hwnd )
{
INT i;
for (i = 1; i <= iMaxChild; i++)
if (rgpsv [i] != NULL && rgpsv [i]->hwndClient == hwnd)
return i;
return 0;
}
/*
* iNextFreeChild:
* - get a window index which is free (not currently used)
* - return 0 if no indexes are free
*/
INT iNextFreeChild ()
{
INT i;
for (i = 1; i < MAX_WINDOWS; i++)
if (rgpsv [i] == NULL)
return i;
return 0;
}
/*
* ArrangeWindows:
* - change position and size of windows so that they fill the screen
*/
void ArrangeWindows ()
{
static SWP rgswp [MAX_WINDOWS];
INT cWnd = 0;
INT iWindow = 0;
static INT rgcWndsWide [MAX_WINDOWS] =
{ 1,2,2,2,3,3,3,3 };
static INT rgcWndsHigh [3 * MAX_WINDOWS] =
{ 1,0,0, 1,1,0, 2,1,0, 2,2,0, 2,1,2, 2,2,2, 2,3,2, 3,2,3 };
INT i;
INT xWndPos, yWndPos;
INT iWide, iHigh;
/* initialize each SWP entry - one entry per window */
do
{
iWindow = iNextValidWindow (iWindow);
rgswp [cWnd].fs = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_ACTIVATE;
rgswp [cWnd].hwndInsertBehind = HWND_TOP;
rgswp [cWnd].hwnd = rgpsv [iWindow]->hwndFrame;
cWnd++;
}
while (iWindow != 0);
/* calculate each window size and position */
iWide = cWnd - 1;
iHigh = (cWnd - 1) * 3;
xWndPos = 0;
yWndPos = rgcWndsHigh [iHigh] - 1;
for (i = 0; i < cWnd; i++)
{
rgswp [i].cx = (INT) (cxScreen / rgcWndsWide [iWide]);
rgswp [i].cy = (INT) (cyScreen / rgcWndsHigh [iHigh + xWndPos]);
rgswp [i].x = rgswp [i].cx * xWndPos;
rgswp [i].y = rgswp [i].cy * yWndPos;
if (yWndPos-- == 0)
{
xWndPos++;
yWndPos = rgcWndsHigh [iHigh + xWndPos] - 1;
}
}
/* reposition all windows */
WinSetMultWindowPos (hab, rgswp, cWnd);
}
/*
* AboutDlgProc:
* - simple 'About' dialog box
*/
MRESULT EXPENTRY AboutDlgProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
switch (msg)
{
case WM_COMMAND:
switch (SHORT1FROMMP (mp1) )
{
case DID_OK:
case DID_CANCEL:
WinDismissDlg (hwnd, TRUE);
break;
default:
break;
}
break;
default:
return WinDefDlgProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
/*
* LightSourceDlgProc:
* - allows the user to change the angle of the light source
*/
MRESULT EXPENTRY LightSourceDlgProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
PSV psv;
INT iNewPosition;
INT cAddToPos;
switch (msg)
{
case WM_INITDLG:
psv = rgpsv [0];
/* Set angle ranges from 0 to 180 */
WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_X, SBM_SETSCROLLBAR,
MPFROMP (psv->pt2LightAng.x + 90),
MPFROM2SHORT (0, 180) );
WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_Y, SBM_SETSCROLLBAR,
MPFROMP (psv->pt2LightAng.y + 90),
MPFROM2SHORT (0, 180) );
break;
case WM_HSCROLL:
switch (SHORT2FROMMP (mp2) )
{
case SB_LINELEFT:
cAddToPos = -5;
break;
case SB_LINERIGHT:
cAddToPos = 5;
break;
case SB_PAGELEFT:
cAddToPos = -30;
break;
case SB_PAGERIGHT:
cAddToPos = 30;
break;
default:
cAddToPos = 0;
break;
}
if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
iNewPosition = SHORT1FROMMP (mp2);
else
iNewPosition =
(INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
SBM_QUERYPOS, 0L, 0L)
+ cAddToPos;
/* Update slider position */
WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
MPFROMP (iNewPosition), NULL);
break;
case WM_COMMAND:
switch (SHORT1FROMMP (mp1) )
{
case DID_OK:
psv = rgpsv [0];
/* Accept new angles (range -90 to 90) */
psv->pt2LightAng.x = (INT) WinSendDlgItemMsg (hwnd,
IDD_LIGHTANG_X, SBM_QUERYPOS, 0L, 0L);
psv->pt2LightAng.x -= 90;
psv->pt2LightAng.y = (INT) WinSendDlgItemMsg (hwnd,
IDD_LIGHTANG_Y, SBM_QUERYPOS, 0L, 0L);
psv->pt2LightAng.y -= 90;
WinDismissDlg (hwnd, TRUE);
break;
case DID_CANCEL:
WinDismissDlg (hwnd, FALSE);
break;
default:
break;
}
break;
default:
return WinDefDlgProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
/*
* RotationDlgProc:
* - allows the user to change the angle and angular velocity of
* a shape in the parent window
*/
MRESULT EXPENTRY RotationDlgProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
PSV psv;
INT iNewPosition;
INT cAddToPos;
INT cLineSize, cPageSize;
switch (msg)
{
case WM_INITDLG:
psv = rgpsv [0];
/* Set angle ranges from 0 to 359 */
WinSendDlgItemMsg (hwnd, IDD_ANGLE_X, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3Angle.x),
MPFROM2SHORT (0, 359) );
WinSendDlgItemMsg (hwnd, IDD_ANGLE_Y, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3Angle.y),
MPFROM2SHORT (0, 359) );
WinSendDlgItemMsg (hwnd, IDD_ANGLE_Z, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3Angle.z),
MPFROM2SHORT (0, 359) );
/* Set angular velocity ranges from 0 to 30 */
WinSendDlgItemMsg (hwnd, IDD_ANGVEL_X, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3AngVel.x),
MPFROM2SHORT (0, 30) );
WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Y, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3AngVel.y),
MPFROM2SHORT (0, 30) );
WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Z, SBM_SETSCROLLBAR,
MPFROMP (psv->pt3AngVel.z),
MPFROM2SHORT (0, 30) );
break;
case WM_HSCROLL:
switch (SHORT1FROMMP (mp1) )
{
case IDD_ANGLE_X:
case IDD_ANGLE_Y:
case IDD_ANGLE_Z:
cLineSize = 1;
cPageSize = 30;
break;
case IDD_ANGVEL_X:
case IDD_ANGVEL_Y:
case IDD_ANGVEL_Z:
cLineSize = 1;
cPageSize = 6;
break;
}
switch (SHORT2FROMMP (mp2) )
{
case SB_LINELEFT:
cAddToPos = -cLineSize;
break;
case SB_LINERIGHT:
cAddToPos = cLineSize;
break;
case SB_PAGELEFT:
cAddToPos = -cPageSize;
break;
case SB_PAGERIGHT:
cAddToPos = cPageSize;
break;
default:
cAddToPos = 0;
break;
}
if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
iNewPosition = SHORT1FROMMP (mp2);
else
iNewPosition =
(INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
SBM_QUERYPOS, 0L, 0L)
+ cAddToPos;
/* Update slider position */
WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
MPFROMP (iNewPosition), NULL);
break;
case WM_COMMAND:
switch (SHORT1FROMMP (mp1) )
{
case DID_OK:
psv = rgpsv [0];
/* Accept new angles */
psv->pt3Angle.x = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGLE_X, SBM_QUERYPOS, 0L, 0L);
psv->pt3Angle.y = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGLE_Y, SBM_QUERYPOS, 0L, 0L);
psv->pt3Angle.z = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGLE_Z, SBM_QUERYPOS, 0L, 0L);
/* Accept new angular velocities */
psv->pt3AngVel.x = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGVEL_X, SBM_QUERYPOS, 0L, 0L);
psv->pt3AngVel.y = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGVEL_Y, SBM_QUERYPOS, 0L, 0L);
psv->pt3AngVel.z = (INT) WinSendDlgItemMsg (hwnd,
IDD_ANGVEL_Z, SBM_QUERYPOS, 0L, 0L);
WinDismissDlg (hwnd, TRUE);
break;
case DID_CANCEL:
WinDismissDlg (hwnd, FALSE);
break;
default:
break;
}
break;
default:
return WinDefDlgProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
/*
* ListDlgProc:
* - allows the user to switch to a new shape in the parent window
*/
MRESULT EXPENTRY ListDlgProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
PSV psv;
INT iShape;
INT iItem;
SHAPE *pshape;
switch (msg)
{
case WM_INITDLG:
WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_DELETEALL, NULL, NULL);
/* Fill list box with shape names */
for (iShape = 0; iShape < shapeMax; iShape++)
{
iItem = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
LM_INSERTITEM,
MPFROM2SHORT (LIT_SORTASCENDING, 0),
MPFROMP (rgshape [iShape].szName));
WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_SETITEMHANDLE,
MPFROMP (iItem),
MPFROMP (iShape));
}
break ;
case WM_COMMAND:
switch (SHORT1FROMMP (mp1) )
{
case DID_OK:
iShape = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
LM_QUERYSELECTION, 0L, 0L);
if (iShape >= 0 && iShape <= shapeMax)
{
/* set parent window to display chosen shape */
ishapeParent = (USHORT) WinSendDlgItemMsg (hwnd,
IDD_NEWSHAPE,
LM_QUERYITEMHANDLE,
MPFROMP (iShape), NULL);
psv = rgpsv [0];
pshape = &rgshape [ishapeParent];
psv->iShape = ishapeParent;
psv->fShaded = FALSE;
psv->fClipping = (pshape->pobject->rgface != NULL);
psv->fVarySize = FALSE;
psv->fPerspective = TRUE;
psv->pt2LightAng.x = 0;
psv->pt2LightAng.y = 0;
psv->pt3Angle = pshape->pinit->pt3Angle;
psv->pt3AngVel = pshape->pinit->pt3AngVel;
psv->pt3SizeAng = pshape->pinit->pt3SizeAng;
/* set scale of shape for size of parent window */
ChangeScale (psv);
WinDismissDlg (hwnd, TRUE);
}
else
WinDismissDlg (hwnd, FALSE);
break;
case DID_CANCEL:
WinDismissDlg (hwnd, FALSE);
break;
default:
break;
}
break;
default:
return WinDefDlgProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
/*
* ParentWndProc:
* - process menu requests
* - start and terminate child windows
* - handle painting and size changes
*/
MRESULT EXPENTRY ParentWndProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
HPS hps;
HDC hdc;
PSV psv = rgpsv [0];
SIZEL sizel;
LONG xPelsPerMeter, yPelsPerMeter;
INT iChild;
static BOOL fChildDisabled = FALSE;
SHAPE *pshape;
BOOL enClipping, enVarySize, enLightSource, enShaded;
/* enable flags for menu items */
switch (msg)
{
case WM_CREATE:
hdc = WinOpenWindowDC (hwnd);
DevQueryCaps (hdc, CAPS_WIDTH, 1L, &cxScreen);
DevQueryCaps (hdc, CAPS_HEIGHT, 1L, &cyScreen);
DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xPelsPerMeter);
DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yPelsPerMeter);
yPelAdjust = (INT) ((yPelsPerMeter << 10) / xPelsPerMeter);
sizel.cx = sizel.cy = 0;
psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
PU_PELS | GPIT_MICRO | GPIA_ASSOC );
GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
GpiSetMix (psv->hpsClient, FM_OVERPAINT);
GpiSetBackColor (psv->hpsClient, CLR_WHITE);
break;
case WM_INITMENU:
switch (SHORT1FROMMP (mp1))
{
case IDM_OPTIONS:
pshape = &rgshape [ishapeParent];
/* disable/enable menu items */
enShaded = pshape->pobject->rgface != NULL;
enClipping = enShaded
&& (pshape->pobject->rgline != NULL)
&& !psv->fShaded;
enLightSource = psv->fShaded;
enVarySize = !psv->fShaded;
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_CLIPPING, TRUE),
MPFROM2SHORT (MIA_DISABLED, enClipping ?
0 : MIA_DISABLED) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_VARYSIZE, TRUE),
MPFROM2SHORT (MIA_DISABLED, enVarySize ?
0 : MIA_DISABLED) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_LIGHTSOURCE, TRUE),
MPFROM2SHORT (MIA_DISABLED, enLightSource ?
0 : MIA_DISABLED) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_SHADED, TRUE),
MPFROM2SHORT (MIA_DISABLED, enShaded ?
0 : MIA_DISABLED) );
/* display check marks */
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_SHADED, TRUE),
MPFROM2SHORT (MIA_CHECKED,
psv->fShaded ? MIA_CHECKED : 0) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_CLIPPING, TRUE),
MPFROM2SHORT (MIA_CHECKED,
psv->fClipping ? MIA_CHECKED : 0) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_VARYSIZE, TRUE),
MPFROM2SHORT (MIA_CHECKED,
psv->fVarySize ? MIA_CHECKED : 0) );
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_PERSPECTIVE, TRUE),
MPFROM2SHORT (MIA_CHECKED,
psv->fPerspective ? MIA_CHECKED : 0) );
break;
default:
break;
}
break;
case WM_COMMAND:
switch (SHORT1FROMMP (mp1))
{
case IDM_LIST:
/* display list dialog box */
WinDlgBox (HWND_DESKTOP, hwnd, ListDlgProc,
NULL, IDD_LIST, NULL);
break;
case IDM_ROTATION:
/* display rotation dialog box */
WinDlgBox (HWND_DESKTOP, hwnd, RotationDlgProc,
NULL, IDD_ROTATION, NULL);
break;
case IDM_LIGHTSOURCE:
/* display light source dialog box */
WinDlgBox (HWND_DESKTOP, hwnd, LightSourceDlgProc,
NULL, IDD_LIGHTSOURCE, NULL);
break;
case IDM_SHADED:
/* toggle shaded */
psv->fShaded = !psv->fShaded;
break;
case IDM_CLIPPING:
/* toggle clipping */
psv->fClipping = !psv->fClipping;
break;
case IDM_VARYSIZE:
/* toggle vary size */
psv->fVarySize = !psv->fVarySize;
break;
case IDM_PERSPECTIVE:
/* toggle perspective */
psv->fPerspective = !psv->fPerspective;
break;
case IDM_ABOUT:
/* display about dialog box */
WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
NULL, IDD_ABOUT, NULL);
break;
case IDM_CHILD:
/* create child window when space exists */
iChild = iNextFreeChild ();
if (iChild != 0)
{
if (iChild > iMaxChild)
iMaxChild = iChild;
CreateChild (iChild);
}
if (iNextFreeChild () == 0)
{
fChildDisabled = TRUE;
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_CHILD, TRUE),
MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED) );
}
break;
case IDM_ARRANGE:
/* arrange the windows to fill the screen */
ArrangeWindows ();
break;
}
/* window is now invalid */
WinInvalidateRect (hwnd, NULL, FALSE);
break;
case WM_END_CHILD:
/* destroy child window and associated variables */
iChild = SHORT1FROMMP (mp1);
psv = rgpsv [iChild];
if (iChild == iMaxChild)
iMaxChild--;
rgpsv [iChild] = NULL;
GpiDestroyPS (psv->hpsClient);
WinDestroyWindow (psv->hwndFrame);
free (psv);
if (fChildDisabled)
{
fChildDisabled = FALSE;
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT (IDM_CHILD, TRUE),
MPFROM2SHORT (MIA_DISABLED, 0) );
}
break;
case WM_SIZE:
/* change the centre and scale of shape for new window size */
psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;
ChangeScale (psv);
break;
case WM_PAINT:
hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
GpiErase (hps);
if (psv->fShaded)
DrawAndFill (psv);
WinEndPaint (hps);
psv->fErased = TRUE;
break;
case WM_CLOSE:
/* set flag so that main loop is terminated */
fCloseParent = TRUE;
return WinDefWindowProc (hwnd, msg, mp1, mp2);
default:
return WinDefWindowProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
/*
* ChildWndProc:
* - generic child procedure (used for all child windows)
* - send message to parent upon termination
* - handle painting and size changes
*/
MRESULT EXPENTRY ChildWndProc(
HWND hwnd,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
HPS hps;
HDC hdc;
PSV psv;
SIZEL sizel;
INT iChild;
switch (msg)
{
case WM_CREATE:
psv = rgpsv [iChildCreate];
hdc = WinOpenWindowDC (hwnd);
sizel.cx = sizel.cy = 0;
psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
PU_PELS | GPIT_MICRO | GPIA_ASSOC );
GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
GpiSetMix (psv->hpsClient, FM_OVERPAINT);
GpiSetBackColor (psv->hpsClient, CLR_WHITE);
break;
case WM_SIZE:
/* change the centre and scale of shape for new window size */
iChild = iQueryChild (hwnd);
psv = rgpsv [iChild];
psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;
ChangeScale (psv);
break;
case WM_PAINT:
iChild = iQueryChild (hwnd);
psv = rgpsv [iChild];
hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
GpiErase (hps);
if (psv->fShaded)
DrawAndFill (psv);
WinEndPaint (hps);
psv->fErased = TRUE;
break;
case WM_CLOSE:
iChild = iQueryChild (hwnd);
/* send termination message to parent */
WinPostMsg (rgpsv [0]->hwndClient, WM_END_CHILD,
MPFROMSHORT (iChild), 0L);
break;
default:
return WinDefWindowProc (hwnd, msg, mp1, mp2);
}
return FALSE;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.