home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 17
/
CD_ASCQ_17_101194.iso
/
vrac_os2
/
blankr42.zip
/
BSSDEV.ZIP
/
bounce.c
< prev
next >
Wrap
Text File
|
1994-08-17
|
8KB
|
283 lines
/***************************************************************************\
* BOUNCE.C - An example Desktop Screen Saver extension by John Ridges
* Converted to a 32-Bit Screen Blanker module by Peter Wansch
\***************************************************************************/
#define MAXBITMAPS 25 /* How many happy faces can be on the screen */
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#define INCL_GPIBITMAPS
#define INCL_WINBUTTONS
#define INCL_WINDIALOGS
#define INCL_WINENTRYFIELDS
#define INCL_WININPUT
#define INCL_WINMESSAGEMGR
#define INCL_WINTIMER
#define INCL_WINWINDOWMGR
#define INCL_WINSHELLDATA
#include <os2.h>
typedef struct {
HAB habBlanker;
HWND hwndScreen;
RECTL rclScreen;
BOOL fClose;
HMODULE hmodBlanker;
} BLANKERBLOCK;
typedef BLANKERBLOCK *PBLANKERBLOCK;
int rand();
void srand(unsigned int seed);
PCHAR pchStatus(PBLANKERBLOCK, PBOOL);
MRESULT EXPENTRY dpBlanker(HWND, ULONG, MPARAM, MPARAM);
VOID vdBlankerThread(VOID);
static PBLANKERBLOCK pBlankerBlock;
/*
This is the record that describes the position and velocity of
a happy face
*/
typedef struct {
FIXED xvelocity,yvelocity;
FIXED xposition,yposition;
} BITMAPREC;
/*
This is the record that contains the options of the screen saver.
These options are kept in the OS2.INI profile file.
*/
typedef struct {
BOOL enabled; /* The screen saver enabled status */
int numbitmaps; /* The number of happy faces on the screen */
} PROFILEREC;
static char name[] = "Bounce"; /* The name of this screen saver */
static BOOL gotprofile = FALSE; /* Indicates that we've read the profile */
static PROFILEREC profile = {TRUE, 4}; /* Default values */
static unsigned int __rand = 1;
int rand()
{
__rand = __rand * 69069 + 5;
return ((__rand >> 16) & 0x7fff);
}
void srand(unsigned int seed)
{
__rand = seed;
}
PCHAR pchStatus(PBLANKERBLOCK initptr, PBOOL enabledptr)
{
ULONG i;
/* Save the SAVERBLOCK address locally */
pBlankerBlock = initptr;
/* Read the profile (but only once!) */
if (!gotprofile) {
i = sizeof(PROFILEREC);
PrfQueryProfileData(HINI_PROFILE,"Blanker",name,&profile,&i);
gotprofile = TRUE;
}
/* Return the enabled status */
*enabledptr = profile.enabled;
/* Return the screen saver name */
return name;
}
MRESULT EXPENTRY dpBlanker(HWND hwnd, ULONG message, MPARAM mp1, MPARAM mp2)
{
SHORT i;
switch(message) {
case WM_INITDLG:
/* Check the enabled button if enabled */
if (profile.enabled)
WinSendDlgItemMsg(hwnd,3,BM_SETCHECK,MPFROMSHORT(1),0);
/* Set the Quantity field */
WinSetDlgItemShort(hwnd,4,profile.numbitmaps,TRUE);
/* Bring up the dialog */
WinShowWindow(hwnd,TRUE);
return FALSE;
case WM_COMMAND:
/* If OK is pushed */
if (SHORT1FROMMP(mp1) == 1) {
/* Get the value of the Quantity field */
WinQueryDlgItemShort(hwnd,4,&i,TRUE);
/* Check to see if the Quantity is in bounds */
if (i < 1 || i > MAXBITMAPS) {
/* Bring up an error message box */
WinMessageBox(HWND_DESKTOP,hwnd,"The number of happy faces must "
"be between 1 and 25",NULL,0,MB_OK|MB_ICONHAND);
/* Hilight the Quantity field */
WinSendDlgItemMsg(hwnd,4,EM_SETSEL,MPFROM2SHORT(0,
WinQueryDlgItemTextLength(hwnd,4)),0);
/* Give the Quantity field the focus */
WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,4));
/* Don't exit the dialog */
return FALSE;
}
/* Save the number of happy faces */
profile.numbitmaps = i;
/* Get the enabled status */
profile.enabled =
SHORT1FROMMR(WinSendDlgItemMsg(hwnd,3,BM_QUERYCHECK,0,0));
/* Write the profile data */
PrfWriteProfileData(HINI_PROFILE,"Blanker",name,&profile,
sizeof(PROFILEREC));
}
}
return WinDefDlgProc(hwnd,message,mp1,mp2);
}
VOID vdBlankerThread(VOID)
{
HAB hab;
HPS hps;
int i;
FIXED tempx,tempy;
ULONG sqrt;
POINTL aptl[4];
BITMAPREC *bitmaps;
HBITMAP hbmp;
/* Get an HAB for this thread (since we make PM calls) */
hab = WinInitialize(0);
/* Get an HPS of the screen */
hps = WinGetPS(pBlankerBlock->hwndScreen);
/* Paint the screen black */
WinFillRect(hps,&pBlankerBlock->rclScreen,CLR_BLACK);
/* Get memory for the array of BITMAPRECs */
bitmaps = NULL;
DosAllocMem((PPVOID)&bitmaps, sizeof(BITMAPREC)*profile.numbitmaps, PAG_READ | PAG_WRITE | PAG_COMMIT);
/* Flag all the happy faces as 'position unknown' */
for (i = 0; i < profile.numbitmaps; i++)
bitmaps[i].xposition = -1L;
/* Get the handle to the happy face and its dimensions */
hbmp = GpiLoadBitmap(hps,pBlankerBlock->hmodBlanker,1,0L,0L);
aptl[2].x = aptl[2].y = 0;
aptl[3].x = aptl[3].y = 34;
/* Randomize RAND using the time */
srand((unsigned int)WinGetCurrentTime(hab));
/* Loop until Screen Blanker tells us to stop */
while (!pBlankerBlock->fClose)
/* Process for each happy face */
for (i = 0; i < profile.numbitmaps; i++) {
/* If the happy face's position is unknown, initialize it */
if (bitmaps[i].xposition < 0) {
/* Pick a random x velocity between -1 and 1 (fixed) */
tempx = (long)rand()<<1;
bitmaps[i].xvelocity = rand()&1 ? tempx : -tempx;
/*
Make the total velocity 1 by computing:
yvelocity = sqrt(1 - xvelocity * xvelocity)
*/
tempy = MAKEFIXED(0,65535)-((ULONG)tempx*(ULONG)tempx>>16);
/* Cheesy sqrt routine to avoid linking in floating point */
sqrt = 0;
tempx = 1L<<15;
do {
sqrt ^= tempx;
if (sqrt*sqrt>>16 > (ULONG)tempy) sqrt ^= tempx;
tempx >>= 1;
} while (tempx);
/* Randomly set y velocity sign */
bitmaps[i].yvelocity = rand()&1 ? sqrt : -sqrt;
/* Randomly choose the x and y position of the happy face */
tempx = MAKEFIXED(pBlankerBlock->rclScreen.xLeft,0)+(rand()*
(pBlankerBlock->rclScreen.xRight-pBlankerBlock->rclScreen.xLeft-32)<<1);
tempy = MAKEFIXED(pBlankerBlock->rclScreen.yBottom,0)+(rand()*
(pBlankerBlock->rclScreen.yTop-pBlankerBlock->rclScreen.yBottom-32)<<1);
}
else {
/* Find the new position of the happy face */
tempx = bitmaps[i].xposition+bitmaps[i].xvelocity;
tempy = bitmaps[i].yposition+bitmaps[i].yvelocity;
/* See if the happy face has hit an edge of the screen */
if (FIXEDINT(tempx) < (int)pBlankerBlock->rclScreen.xLeft) {
/* Bounced off the left edge */
tempx = (pBlankerBlock->rclScreen.xLeft<<17)-tempx;
bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
}
else if (FIXEDINT(tempx) >= (int)pBlankerBlock->rclScreen.xRight-32) {
/* Bounced off the right edge */
tempx = (pBlankerBlock->rclScreen.xRight-32<<17)-tempx;
bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
}
if (FIXEDINT(tempy) < (int)pBlankerBlock->rclScreen.yBottom) {
/* Bounced off the bottom edge */
tempy = (pBlankerBlock->rclScreen.yBottom<<17)-tempy;
bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
}
else if (FIXEDINT(tempy) >= (int)pBlankerBlock->rclScreen.yTop-32) {
/* Bounced off the top edge */
tempy = (pBlankerBlock->rclScreen.yTop-32<<17)-tempy;
bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
}
}
/* Draw the happy face in the new position */
aptl[0].x = FIXEDINT(tempx)-1;
aptl[0].y = FIXEDINT(tempy)-1;
aptl[1].x = FIXEDINT(tempx)+32;
aptl[1].y = FIXEDINT(tempy)+32;
GpiWCBitBlt(hps,hbmp,4L,aptl,ROP_SRCCOPY,BBO_IGNORE);
/* Save the position of the happy face */
bitmaps[i].xposition = tempx;
bitmaps[i].yposition = tempy;
}
/* Release the happy face bitmap */
GpiDeleteBitmap(hbmp);
/* Release the memory for the array of BITMAPRECs */
DosFreeMem(bitmaps);
/* Release the HPS of the screen */
WinReleasePS(hps);
/* Get rid of the HAB */
WinTerminate(hab);
/* Make sure the stack doesn't vanish before we're completely gone */
DosEnterCritSec();
/* Tell Screen Blanker that we're gone */
pBlankerBlock->fClose = FALSE;
}