home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
THREADS3.ZIP
/
THREADS3.C
next >
Wrap
Text File
|
1990-03-18
|
11KB
|
335 lines
«RHA«PT2»«LM10»«RM75»ENVIRONMENTS o CHARLES PETZOLD p. «PN» of «FP»
Vol. 9, No. 12
Filename: «VA$FI»
»«PT2»«LM20»«RM50.5»«LS2»«TS22»
«NB»«PT11»«LM0»«RM80»«AL1»«TS8,16,24,32,40»
CODE BOX
THREADS3.C
COMPLETE LISTING
/*---------------------------------------------------------
THREADS3.C -- Demonstrates drawing from a second thread
(c) 1990, Ziff Communications Co.
PC Magazine * Charles Petzold, 2/90
---------------------------------------------------------*/
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
#include <mt\process.h>
#include <mt\stdlib.h>
#define CXIMAGE 150
#define CYIMAGE 150
#define SPLINE 100
#define STACKSIZE (4096 * sizeof (int))
#define SEGNAME 1L
#define PI 3.14159
typedef struct
{
HPS hps ;
BOOL fTerminate ;
ULONG semTriggerDraw ;
ULONG semDoingDraw ;
}
THREADPARAMS ;
MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
VOID FAR SecondThread (THREADPARAMS *) ;
VOID ScaleImageToClient (HPS, SIZEL *) ;
VOID DrawImage (HPS) ;
VOID DrawLetters (HPS) ;
HAB hab ;
int main (void)
{
static CHAR szClientClass [] = "Threads3" ;
static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
FCF_SIZEBORDER | FCF_MINMAX |
FCF_SHELLPOSITION | FCF_TASKLIST ;
HAB hab ;
HMQ hmq ;
HWND hwndFrame, hwndClient ;
QMSG qmsg ;
hab = WinInitialize (0) ;
hmq = WinCreateMsgQueue (hab, 0) ;
WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
&flFrameFlags, szClientClass, NULL,
0L, NULL, 0, &hwndClient) ;
while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
WinDispatchMsg (hab, &qmsg) ;
WinDestroyWindow (hwndFrame) ;
WinDestroyMsgQueue (hmq) ;
WinTerminate (hab) ;
return 0 ;
}
MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
{
static int aiThreadStack [STACKSIZE / sizeof (int)] ;
static THREADPARAMS tp ;
HDC hdc ;
SIZEL sizlPage, sizlClient ;
switch (msg)
{
case WM_CREATE:
// create a presentation space for the window
hdc = WinOpenWindowDC (hwnd) ;
sizlPage.cx = 0 ;
sizlPage.cy = 0 ;
tp.hps = GpiCreatePS (hab, hdc, &sizlPage,
PU_LOENGLISH | GPIF_DEFAULT |
GPIT_NORMAL | GPIA_ASSOC) ;
// start the thread after initialization
tp.fTerminate = FALSE ;
DosSemSet (&tp.semTriggerDraw) ;
DosSemClear (&tp.semDoingDraw) ;
_beginthread (SecondThread, aiThreadStack, STACKSIZE, &tp) ;
// create the segment
GpiSetDrawingMode (tp.hps, DM_RETAIN) ;
GpiOpenSegment (tp.hps, SEGNAME) ;
DrawImage (tp.hps) ;
GpiCloseSegment (tp.hps) ;
return 0 ;
case WM_SIZE:
// stop the thread from drawing
GpiSetStopDraw (tp.hps, SDW_ON) ;
DosSemWait (&tp.semDoingDraw, SEM_INDEFINITE_WAIT) ;
// get new size of client window
sizlClient.cx = SHORT1FROMMP (mp2) ;
sizlClient.cy = SHORT2FROMMP (mp2) ;
// set the new default view matrix
GpiConvert (tp.hps, CVTC_DEVICE, CVTC_PAGE, 1L,
(PPOINTL) &sizlClient) ;
ScaleImageToClient (tp.hps, &sizlClient) ;
return 0 ;
case WM_PAINT:
// stop the thread from drawing
GpiSetStopDraw (tp.hps, SDW_ON) ;
DosSemWait (&tp.semDoingDraw, SEM_INDEFINITE_WAIT) ;
// erase the window
WinBeginPaint (hwnd, tp.hps, NULL) ;
GpiErase (tp.hps) ;
WinEndPaint (tp.hps) ;
// let the thread continue
GpiSetStopDraw (tp.hps, SDW_OFF) ;
DosSemSet (&tp.semDoingDraw) ;
DosSemClear (&tp.semTriggerDraw) ;
return 0 ;
case WM_DESTROY:
// stop the thread
tp.fTerminate = TRUE ;
GpiSetStopDraw (tp.hps, SDW_ON) ;
DosSemWait (&tp.semDoingDraw, SEM_INDEFINITE_WAIT) ;
// clean up
GpiDeleteSegment (tp.hps, SEGNAME) ;
GpiAssociate (tp.hps, NULL) ;
GpiDestroyPS (tp.hps) ;
return 0 ;
}
return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
}
VOID _CDECL FAR SecondThread (THREADPARAMS * ptp)
{
HAB hab ;
hab = WinInitialize (0) ;
while (!ptp->fTerminate)
{
// wait for the semaphore to be cleared
DosSemWait (&ptp->semTriggerDraw, SEM_INDEFINITE_WAIT) ;
// draw the image
GpiSavePS (ptp->hps) ;
GpiDrawSegment (ptp->hps, SEGNAME) ;
GpiRestorePS (ptp->hps, -1L) ;
// set and clear the semaphores
DosSemSet (&ptp->semTriggerDraw) ;
DosSemClear (&ptp->semDoingDraw) ;
}
WinTerminate (hab) ;
_endthread () ;
}
VOID ScaleImageToClient (HPS hps, SIZEL *psizlClient)
{
FIXED afxScale[2] ;
MATRIXLF matlf ;
POINTL ptl ;
afxScale[0] = afxScale[1] = min (65536L * psizlClient->cx / CXIMAGE,
65536L * psizlClient->cy / CYIMAGE) ;
ptl.x = 0 ;
ptl.y = 0 ;
GpiScale (hps, &matlf, TRANSFORM_REPLACE, afxScale, &ptl) ;
ptl.x = (psizlClient->cx - afxScale[0] * CXIMAGE / 65536L) / 2 ;
ptl.y = (psizlClient->cy - afxScale[1] * CYIMAGE / 65536L) / 2 ;
GpiTranslate (hps, &matlf, TRANSFORM_ADD, &ptl) ;
GpiSetDefaultViewMatrix (hps, 9L, &matlf, TRANSFORM_REPLACE) ;
}
VOID DrawImage (HPS hps)
{
MATRIXLF matlf ;
POINTL ptl, aptl[4] ;
SHORT iAngle ;
// Draw outline of letters
DrawLetters (hps) ;
// Use letters outline as clipping path
GpiBeginPath (hps, 1L) ;
DrawLetters (hps) ;
GpiEndPath (hps) ;
GpiSetClipPath (hps, 1L, SCP_AND | SCP_ALTERNATE) ;
for (iAngle = 0 ; iAngle < 360 ; iAngle++)
{
// Find matrix for rotation around origin
ptl.x = 0 ;
ptl.y = 0 ;
GpiRotate (hps, &matlf, TRANSFORM_REPLACE,
MAKEFIXED (iAngle, 0), &ptl) ;
// Append matrix for translation to center of image
ptl.x = CXIMAGE / 2 ;
ptl.y = CYIMAGE / 2 ;
GpiTranslate (hps, &matlf, TRANSFORM_ADD, &ptl) ;
// Set model transform using composite matrix
GpiSetModelTransformMatrix (hps, 9L, &matlf, TRANSFORM_REPLACE) ;
// Draw spline curve
aptl[0].x = 0 ;
aptl[0].y = 0 ;
aptl[1].x = SPLINE / 3 ;
aptl[1].y = SPLINE / 2 ;
aptl[2].x = 2 * SPLINE / 3 ;
aptl[2].y = - SPLINE / 2 ;
aptl[3].x = SPLINE ;
aptl[3].y = 0 ;
GpiMove (hps, aptl) ;
GpiPolySpline (hps, 3L, aptl + 1) ;
}
}
VOID DrawLetters (HPS hps)
{
POINTL ptl, aptl[3] ;
// Outside of 'P'
ptl.x = 4 ; ptl.y = 4 ; GpiMove (hps, &ptl) ;
ptl.x = 4 ; ptl.y = 146 ; GpiLine (hps, &ptl) ;
ptl.x = 45 ; ptl.y = 146 ; GpiLine (hps, &ptl) ;
aptl[0].x = 72 ; aptl[0].y = 146 ;
aptl[1].x = 72 ; aptl[1].y = 119 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 72 ; ptl.y = 85 ; GpiLine (hps, &ptl) ;
aptl[0].x = 72 ; aptl[0].y = 58 ;
aptl[1].x = 45 ; aptl[1].y = 58 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 35 ; ptl.y = 58 ; GpiLine (hps, &ptl) ;
ptl.x = 35 ; ptl.y = 4 ; GpiLine (hps, &ptl) ;
ptl.x = 4 ; ptl.y = 4 ; GpiLine (hps, &ptl) ;
// Inside of 'P'
ptl.x = 35 ; ptl.y = 77 ; GpiMove (hps, &ptl) ;
ptl.x = 35 ; ptl.y = 125 ; GpiLine (hps, &ptl) ;
aptl[0].x = 43 ; aptl[0].y = 125 ;
aptl[1].x = 43 ; aptl[1].y = 117 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 43 ; ptl.y = 85 ; GpiLine (hps, &ptl) ;
aptl[0].x = 43 ; aptl[0].y = 77 ;
aptl[1].x = 35 ; aptl[1].y = 77 ; GpiPolyFillet (hps, 2L, aptl) ;
// Outline of 'C'
ptl.x = 116 ; ptl.y = 63 ; GpiMove (hps, &ptl) ;
ptl.x = 145 ; ptl.y = 63 ; GpiLine (hps, &ptl) ;
ptl.x = 145 ; ptl.y = 31 ; GpiLine (hps, &ptl) ;
aptl[0].x = 145 ; aptl[0].y = 4 ;
aptl[1].x = 118 ; aptl[1].y = 4 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 103 ; ptl.y = 4 ; GpiLine (hps, &ptl) ;
aptl[0].x = 76 ; aptl[0].y = 4 ;
aptl[1].x = 76 ; aptl[1].y = 31 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 76 ; ptl.y = 119 ; GpiLine (hps, &ptl) ;
aptl[0].x = 76 ; aptl[0].y = 146 ;
aptl[1].x = 103 ; aptl[1].y = 146 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 118 ; ptl.y = 146 ; GpiLine (hps, &ptl) ;
aptl[0].x = 145 ; aptl[0].y = 146 ;
aptl[1].x = 145 ; aptl[1].y = 119 ; GpiPolyFillet (hps, 2L, aptl) ;
ptl.x = 145 ; ptl.y = 88 ; GpiLine (hps, &ptl) ;
ptl.x = 116 ; ptl.y = 88 ; GpiLine (hps, &ptl) ;
ptl.x = 116 ; ptl.y = 123 ; GpiLine (hps, &ptl) ;
aptl[0].x = 116 ; aptl[0].y = 127 ;
aptl[1].x = 108 ; aptl[1].y = 127 ;
aptl[2].x = 108 ; aptl[2].y = 123 ; GpiPolyFillet (hps, 3L, aptl) ;
ptl.x = 108 ; ptl.y = 30 ; GpiLine (hps, &ptl) ;
aptl[0].x = 108 ; aptl[0].y = 26 ;
aptl[1].x = 116 ; aptl[1].y = 26 ;
aptl[2].x = 116 ; aptl[2].y = 30 ; GpiPolyFillet (hps, 3L, aptl) ;
ptl.x = 116 ; ptl.y = 63 ; GpiLine (hps, &ptl) ;
}
caption:
«BB»«PT7»«AL0»«LM0»«RM69.6»«LS2»«MDBO»Figure 3:«MDNM» The THREADS3.C source code listing contains several new functions that require OS/2 1.2.