883 lines
31 KiB
C
883 lines
31 KiB
C
|
/* MYSTIFY.C
|
||
|
**
|
||
|
** Copyright (C) Microsoft, 1991, All Rights Reserved.
|
||
|
**
|
||
|
** Screensaver Control Panel Applet. This type creates one or two polygons
|
||
|
** which bounce around the screen.
|
||
|
**
|
||
|
** History:
|
||
|
** 6/17/91 stevecat ported to NT Windows
|
||
|
** 2/10/92 stevecat snapped to latest ported to NT Windows
|
||
|
*/
|
||
|
|
||
|
#define OEMRESOURCE
|
||
|
#include <windows.h>
|
||
|
#include <commctrl.h>
|
||
|
#include <scrnsave.h>
|
||
|
#include "mystify.dlg"
|
||
|
#include "strings.h"
|
||
|
#include "uniconv.h"
|
||
|
|
||
|
|
||
|
// void SetFields (HWND, WORD);
|
||
|
|
||
|
DWORD AdjustColor (DWORD dwSrc, DWORD dwDest, int nInc, int nCnt);
|
||
|
LONG AppOwnerDraw (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
WORD AtoI (LPTSTR lpszConvert);
|
||
|
BOOL DrawBitmap (HDC hdc, int x, int y, HBITMAP hbm, DWORD rop);
|
||
|
VOID DrawPolygon (HDC hDC, HPEN hPen, WORD wPolygon, WORD wLine);
|
||
|
VOID FillR (HDC hdc, LPRECT prc, DWORD rgb);
|
||
|
VOID FrameR (HDC hdc, LPRECT prc, DWORD rgb, int iFrame);
|
||
|
DWORD GenerateColor (VOID);
|
||
|
WORD GenerateVelocity (VOID);
|
||
|
VOID GetFields (VOID);
|
||
|
DWORD GetProfileRgb (LPTSTR szApp, LPTSTR szItem, DWORD rgb);
|
||
|
VOID PatB (HDC hdc, int x, int y, int dx, int dy, DWORD rgb);
|
||
|
WORD rand (VOID);
|
||
|
VOID ShadeWindows (HWND hDlg, WORD wPoly, WORD wPolygon);
|
||
|
VOID srand (DWORD dwSeed);
|
||
|
|
||
|
#define RAND(x) ((rand () % (x))+1)
|
||
|
#define ZRAND(x) (rand () % (x))
|
||
|
|
||
|
#define rgbBlack RGB (0,0,0)
|
||
|
#define rgbWhite RGB (255,255,255)
|
||
|
#define rgbGrey RGB (128,128,128)
|
||
|
#define rgbMenu GetSysColor (COLOR_MENU)
|
||
|
#define rgbMenuText GetSysColor (COLOR_MENUTEXT)
|
||
|
|
||
|
#define BUFFER_SIZE 20
|
||
|
#define BUFFER2_SIZE 20
|
||
|
|
||
|
#define NUMBER_POLYGONS 2
|
||
|
#define MAXXVEL 12
|
||
|
#define MAXYVEL 12
|
||
|
#define MAXLINES 15
|
||
|
#define NUMLINES 8
|
||
|
|
||
|
TCHAR szClearName[] = TEXT("Clear Screen"); // ClearScreen .INI key
|
||
|
|
||
|
DWORD dwRand = 1L; // current Random seed
|
||
|
|
||
|
TCHAR szBuffer[BUFFER_SIZE]; // temp buffer
|
||
|
|
||
|
TCHAR szBuffer2[BUFFER2_SIZE]; // temp buffer
|
||
|
|
||
|
BOOL fOn[NUMBER_POLYGONS]; // flag for Active status of polygon
|
||
|
|
||
|
BOOL fWalk[NUMBER_POLYGONS]; // color usage for each polygon
|
||
|
|
||
|
WORD wLines[NUMBER_POLYGONS]; // number of lines for each polygon
|
||
|
|
||
|
WORD wNumDisplay[2];
|
||
|
WORD wFreeEntry[NUMBER_POLYGONS]; // colors for each polygon
|
||
|
|
||
|
DWORD dwStartColor[NUMBER_POLYGONS];
|
||
|
DWORD dwEndColor[NUMBER_POLYGONS];
|
||
|
DWORD dwCurrentColor[NUMBER_POLYGONS];
|
||
|
DWORD dwDestColor[NUMBER_POLYGONS];
|
||
|
DWORD dwSrcColor[NUMBER_POLYGONS];
|
||
|
WORD wIncColor[NUMBER_POLYGONS];
|
||
|
WORD wCurInc[NUMBER_POLYGONS];
|
||
|
TCHAR cblogpalPal[(MAXLINES*NUMBER_POLYGONS+1)
|
||
|
*sizeof (PALETTEENTRY)+sizeof (LOGPALETTE)];
|
||
|
POINT ptBox[MAXLINES*NUMBER_POLYGONS][4]; // array for points used in polygons
|
||
|
|
||
|
LPLOGPALETTE lplogpalPal;
|
||
|
LPPALETTEENTRY lppePal;
|
||
|
HPALETTE hPalette;
|
||
|
BOOL fClearScreen; // Global flag for ClearScreen state
|
||
|
|
||
|
//
|
||
|
// Help IDs
|
||
|
//
|
||
|
DWORD aMystDlgHelpIds[] = {
|
||
|
((DWORD) -1),((DWORD) -1),
|
||
|
ID_SHAPE_LABEL, IDH_DISPLAY_SCREENSAVER_MYSTIFY_SHAPE,
|
||
|
ID_SHAPE, IDH_DISPLAY_SCREENSAVER_MYSTIFY_SHAPE,
|
||
|
ID_ACTIVE, IDH_DISPLAY_SCREENSAVER_MYSTIFY_ACTIVE,
|
||
|
ID_LINES_LABEL, IDH_DISPLAY_SCREENSAVER_MYSTIFY_LINES,
|
||
|
ID_LINES, IDH_DISPLAY_SCREENSAVER_MYSTIFY_LINES,
|
||
|
ID_LINESARROW, IDH_DISPLAY_SCREENSAVER_MYSTIFY_LINES,
|
||
|
ID_COLORGROUP, ((DWORD) -1),
|
||
|
ID_2COLORS, IDH_DISPLAY_SCREENSAVER_MYSTIFY_TWO_COLORS,
|
||
|
ID_COLOR1, IDH_DISPLAY_SCREENSAVER_MYSTIFY_TWO_COLORS,
|
||
|
ID_COLOR2, IDH_DISPLAY_SCREENSAVER_MYSTIFY_TWO_COLORS,
|
||
|
ID_RANDOMCOLORS, IDH_DISPLAY_SCREENSAVER_MYSTIFY_RANDOM_COLORS,
|
||
|
ID_CLEARSCREEN, IDH_DISPLAY_SCREENSAVER_MYSTIFY_CLEAR_SCREEN,
|
||
|
0,0
|
||
|
};
|
||
|
|
||
|
LRESULT ScreenSaverProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
static POINT ptChange[MAXLINES*NUMBER_POLYGONS][4];
|
||
|
static UINT_PTR wTimer;
|
||
|
WORD wLoop1;
|
||
|
WORD wLoop2;
|
||
|
WORD wMainLoop;
|
||
|
static WORD wScreenX;
|
||
|
static WORD wScreenY;
|
||
|
HPEN hPen;
|
||
|
static HPEN hErasePen;
|
||
|
HDC hDC;
|
||
|
HPALETTE hOldPal;
|
||
|
|
||
|
switch (message)
|
||
|
{
|
||
|
// Things to do while setting up the window...
|
||
|
case WM_CREATE:
|
||
|
GetFields ();
|
||
|
wTimer = SetTimer (hWnd, 1, 10, NULL);
|
||
|
|
||
|
// Make sure we use the entire virtual desktop size for multiple
|
||
|
// displays
|
||
|
wScreenX = (WORD) ((LPCREATESTRUCT)lParam)->cx;
|
||
|
wScreenY = (WORD) ((LPCREATESTRUCT)lParam)->cy;
|
||
|
|
||
|
srand (GetCurrentTime ());
|
||
|
for (wMainLoop = 0; wMainLoop < NUMBER_POLYGONS; wMainLoop++)
|
||
|
{
|
||
|
if (fOn[wMainLoop])
|
||
|
{
|
||
|
for (wLoop1 = 0; wLoop1 < 4; wLoop1++)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].x = RAND (wScreenX) - 1;
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].y = RAND (wScreenY) - 1;
|
||
|
if ((ptChange[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
RAND (MAXXVEL * 2)) > MAXXVEL)
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
-(ptChange[wMainLoop*MAXLINES][wLoop1].x
|
||
|
-MAXXVEL);
|
||
|
if ((ptChange[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
RAND (MAXYVEL * 2)) > MAXYVEL)
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
-(ptChange[wMainLoop*MAXLINES][wLoop1].y
|
||
|
-MAXYVEL);
|
||
|
}
|
||
|
wNumDisplay[wMainLoop] = 1;
|
||
|
wFreeEntry[wMainLoop] = 0;
|
||
|
wCurInc[wMainLoop] = 0;
|
||
|
wIncColor[wMainLoop] = 0;
|
||
|
if (fWalk[wMainLoop])
|
||
|
dwDestColor[wMainLoop] = GenerateColor ();
|
||
|
else
|
||
|
dwDestColor[wMainLoop] = dwStartColor[wMainLoop];
|
||
|
}
|
||
|
}
|
||
|
lppePal = (LPPALETTEENTRY)(cblogpalPal + 4);
|
||
|
lplogpalPal = (LPLOGPALETTE)cblogpalPal;
|
||
|
lplogpalPal->palVersion = 0x300;
|
||
|
lplogpalPal->palNumEntries = MAXLINES * NUMBER_POLYGONS + 1;
|
||
|
for (wLoop1 = 0; wLoop1 <= MAXLINES * NUMBER_POLYGONS; wLoop1++)
|
||
|
{
|
||
|
lplogpalPal->palPalEntry[wLoop1].peRed = 0;
|
||
|
lplogpalPal->palPalEntry[wLoop1].peGreen = 0;
|
||
|
lplogpalPal->palPalEntry[wLoop1].peBlue = 0;
|
||
|
lplogpalPal->palPalEntry[wLoop1].peFlags = PC_RESERVED;
|
||
|
}
|
||
|
hErasePen = CreatePen (PS_SOLID, 1,
|
||
|
PALETTEINDEX (MAXLINES * NUMBER_POLYGONS));
|
||
|
hPalette = CreatePalette (lplogpalPal);
|
||
|
break;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
wScreenX = LOWORD(lParam);
|
||
|
wScreenY = HIWORD(lParam);
|
||
|
break;
|
||
|
|
||
|
|
||
|
|
||
|
case WM_ERASEBKGND:
|
||
|
if (fClearScreen)
|
||
|
break;
|
||
|
return 0l;
|
||
|
|
||
|
case WM_TIMER:
|
||
|
// Get the display context...
|
||
|
hDC = GetDC (hWnd);
|
||
|
if (hDC != NULL)
|
||
|
{
|
||
|
// Now that we have changed the palette, make sure that it
|
||
|
// gets updated by first unrealizing, and then realizing...
|
||
|
hOldPal = SelectPalette (hDC, hPalette, 0);
|
||
|
RealizePalette (hDC);
|
||
|
|
||
|
for (wMainLoop = 0; wMainLoop < NUMBER_POLYGONS; wMainLoop++)
|
||
|
{
|
||
|
// Check to see if the current loop is on...
|
||
|
if (fOn[wMainLoop])
|
||
|
{
|
||
|
// If our current count is the same as the final count,
|
||
|
// generate a new count...
|
||
|
if (wCurInc[wMainLoop] == wIncColor[wMainLoop])
|
||
|
{
|
||
|
// Set the count to zero...
|
||
|
wCurInc[wMainLoop] = 0;
|
||
|
|
||
|
// Set an new variant...
|
||
|
wIncColor[wMainLoop] = GenerateVelocity ();
|
||
|
|
||
|
// Set up the cycling colors...
|
||
|
dwSrcColor[wMainLoop] = dwDestColor[wMainLoop];
|
||
|
|
||
|
if (fWalk[wMainLoop])
|
||
|
dwDestColor[wMainLoop] = GenerateColor ();
|
||
|
else if (dwSrcColor[wMainLoop] == dwEndColor[wMainLoop])
|
||
|
dwDestColor[wMainLoop] = dwStartColor[wMainLoop];
|
||
|
else
|
||
|
dwDestColor[wMainLoop] = dwEndColor[wMainLoop];
|
||
|
}
|
||
|
else
|
||
|
wCurInc[wMainLoop]++;
|
||
|
|
||
|
// Now adjust the color between the starting and the
|
||
|
// ending values...
|
||
|
dwCurrentColor[wMainLoop] = AdjustColor (dwSrcColor
|
||
|
[wMainLoop], dwDestColor[wMainLoop], wIncColor
|
||
|
[wMainLoop], wCurInc[wMainLoop]);
|
||
|
wLoop2 = wFreeEntry[wMainLoop] + wMainLoop * MAXLINES;
|
||
|
|
||
|
lplogpalPal->palPalEntry[wLoop2].peRed =
|
||
|
GetRValue (dwCurrentColor[wMainLoop]);
|
||
|
lplogpalPal->palPalEntry[wLoop2].peGreen =
|
||
|
GetGValue (dwCurrentColor[wMainLoop]);
|
||
|
lplogpalPal->palPalEntry[wLoop2].peBlue =
|
||
|
GetBValue (dwCurrentColor[wMainLoop]);
|
||
|
lplogpalPal->palPalEntry[wLoop2].peFlags = PC_RESERVED;
|
||
|
|
||
|
// Adjust the palette...
|
||
|
AnimatePalette (hPalette, wLoop2, 1,
|
||
|
&lplogpalPal->palPalEntry[wLoop2]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now cycle through again...
|
||
|
for (wMainLoop = 0; wMainLoop < NUMBER_POLYGONS; wMainLoop++)
|
||
|
{
|
||
|
if (fOn[wMainLoop])
|
||
|
{
|
||
|
/* If we are currently displaying all of the lines, then
|
||
|
delete the last line... */
|
||
|
if (wNumDisplay[wMainLoop] == wLines[wMainLoop])
|
||
|
/* Erase the last line... */
|
||
|
DrawPolygon (hDC, hErasePen, wMainLoop,
|
||
|
(WORD) (wNumDisplay[wMainLoop] - 1));
|
||
|
|
||
|
/* Starting with the last entry, make it equal to the
|
||
|
entry before it... until we reach the first
|
||
|
entry... */
|
||
|
for (wLoop1 = (wNumDisplay[wMainLoop] - 1); wLoop1; wLoop1--)
|
||
|
{
|
||
|
/* Copy the points in the polygon over... */
|
||
|
for (wLoop2 = 0; wLoop2 < 4; wLoop2++)
|
||
|
{
|
||
|
ptBox[wLoop1+wMainLoop*MAXLINES][wLoop2].x =
|
||
|
ptBox[wLoop1-1+wMainLoop*MAXLINES][wLoop2].x;
|
||
|
ptBox[wLoop1+wMainLoop*MAXLINES][wLoop2].y =
|
||
|
ptBox[wLoop1-1+wMainLoop*MAXLINES][wLoop2].y;
|
||
|
ptChange[wLoop1+wMainLoop*MAXLINES][wLoop2].x =
|
||
|
ptChange[wLoop1-1+wMainLoop*MAXLINES]
|
||
|
[wLoop2].x;
|
||
|
ptChange[wLoop1+wMainLoop*MAXLINES][wLoop2].y =
|
||
|
ptChange[wLoop1-1+wMainLoop*MAXLINES]
|
||
|
[wLoop2].y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Seeing as we now have entry 0 the same as entry 1,
|
||
|
generate a new entry 0... */
|
||
|
for (wLoop1 = 0; wLoop1 < 4; wLoop1++)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].x +=
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].x;
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].y +=
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].y;
|
||
|
if (ptBox[wMainLoop*MAXLINES][wLoop1].x >=
|
||
|
(int)wScreenX)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].x
|
||
|
-2 * (ptBox[wMainLoop*MAXLINES][wLoop1].x
|
||
|
-wScreenX + 1);
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
-RAND (MAXXVEL);
|
||
|
}
|
||
|
if ((int)ptBox[wMainLoop*MAXLINES][wLoop1].x < 0)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
-ptBox[wMainLoop*MAXLINES][wLoop1].x;
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].x =
|
||
|
RAND (MAXXVEL);
|
||
|
}
|
||
|
if (ptBox[wMainLoop*MAXLINES][wLoop1].y >=
|
||
|
(int)wScreenY)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].y - 2 *
|
||
|
(ptBox[wMainLoop*MAXLINES][wLoop1].y
|
||
|
-wScreenY + 1);
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
-RAND (MAXYVEL);
|
||
|
}
|
||
|
if ((int)ptBox[wMainLoop*MAXLINES][wLoop1].y < 0)
|
||
|
{
|
||
|
ptBox[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
-ptBox[wMainLoop*MAXLINES][wLoop1].y;
|
||
|
ptChange[wMainLoop*MAXLINES][wLoop1].y =
|
||
|
RAND (MAXYVEL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Now redraw the new line... */
|
||
|
wLoop2 = wFreeEntry[wMainLoop] + wMainLoop * MAXLINES;
|
||
|
hPen = CreatePen (PS_SOLID, 1, PALETTEINDEX (wLoop2));
|
||
|
DrawPolygon (hDC, hPen, wMainLoop, 0);
|
||
|
if (hPen)
|
||
|
DeleteObject (hPen);
|
||
|
|
||
|
/* Now, as we are finished with the entry in the
|
||
|
palette, increment it such that the next time
|
||
|
around, it points at the next position... */
|
||
|
if ((++wFreeEntry[wMainLoop]) == wLines[wMainLoop])
|
||
|
wFreeEntry[wMainLoop] = 0;
|
||
|
|
||
|
/* Now, if we are not at the maximum number of lines,
|
||
|
then increment towards there... */
|
||
|
if (wNumDisplay[wMainLoop] < wLines[wMainLoop])
|
||
|
wNumDisplay[wMainLoop]++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Reselect the old palette... */
|
||
|
if (hOldPal)
|
||
|
SelectPalette (hDC, hOldPal, FALSE);
|
||
|
|
||
|
/* Release the display context... */
|
||
|
ReleaseDC (hWnd, hDC);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
if (wTimer)
|
||
|
KillTimer (hWnd, 1);
|
||
|
if (hPalette)
|
||
|
DeleteObject (hPalette);
|
||
|
if (hErasePen)
|
||
|
DeleteObject (hErasePen);
|
||
|
break;
|
||
|
}
|
||
|
return (DefScreenSaverProc (hWnd, message, wParam, lParam));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID srand (DWORD dwSeed)
|
||
|
{
|
||
|
dwRand = dwSeed;
|
||
|
}
|
||
|
|
||
|
WORD rand (VOID)
|
||
|
{
|
||
|
dwRand = dwRand * 214013L + 2531011L;
|
||
|
return (WORD)((dwRand >> 16) & 0xffff);
|
||
|
}
|
||
|
|
||
|
BOOL RegisterDialogClasses (HANDLE hInst)
|
||
|
{
|
||
|
/* Register the custom controls.. */
|
||
|
InitCommonControls();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
|
||
|
BOOL ScreenSaverConfigureDialog (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
WORD nPal;
|
||
|
DWORD dwTemp = 0;
|
||
|
HPALETTE hPal;
|
||
|
WORD wLoop, wTemp;
|
||
|
BOOL fError;
|
||
|
BYTE byR, byG, byB;
|
||
|
RECT rDlgBox;
|
||
|
TCHAR szTemp[80];
|
||
|
static HWND hIDOK;
|
||
|
static WORD wPolygon;
|
||
|
|
||
|
switch (message)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
GetFields (); // Read fields from CONTROL.INI
|
||
|
|
||
|
GetWindowRect (hDlg, (LPRECT) & rDlgBox);
|
||
|
hIDOK = GetDlgItem (hDlg, IDOK);
|
||
|
|
||
|
// Set the global clear state...
|
||
|
CheckDlgButton (hDlg, ID_CLEARSCREEN, fClearScreen);
|
||
|
|
||
|
// Fill the boxes...
|
||
|
for (wLoop = 0; wLoop < NUMBER_POLYGONS; wLoop++)
|
||
|
{
|
||
|
TCHAR szBuffer[20];
|
||
|
WORD wTemp;
|
||
|
|
||
|
LoadString (hMainInstance, idsPolygon, szTemp, CharSizeOf(szTemp));
|
||
|
wsprintf (szBuffer, szTemp, wLoop + 1);
|
||
|
wTemp = (WORD)SendDlgItemMessage (hDlg, ID_SHAPE, CB_ADDSTRING, 0,
|
||
|
(LPARAM)szBuffer);
|
||
|
SendDlgItemMessage (hDlg, ID_SHAPE, CB_SETITEMDATA, wTemp, wLoop);
|
||
|
}
|
||
|
|
||
|
hPal = GetStockObject (DEFAULT_PALETTE);
|
||
|
GetObject (hPal, sizeof (WORD), (LPTSTR) &nPal);
|
||
|
for (wTemp = 0; wTemp < nPal; wTemp++)
|
||
|
{
|
||
|
SendDlgItemMessage (hDlg, ID_COLOR1, CB_ADDSTRING, 0, (LPARAM)(LPSTR)"a");
|
||
|
SendDlgItemMessage (hDlg, ID_COLOR2, CB_ADDSTRING, 0, (LPARAM)(LPSTR)"a");
|
||
|
}
|
||
|
|
||
|
// Start at the first polygon and let'r rip...
|
||
|
SendDlgItemMessage (hDlg, ID_LINES, EM_LIMITTEXT, 2, 0l);
|
||
|
SendDlgItemMessage( hDlg, ID_LINESARROW, UDM_SETRANGE, 0, MAKELONG(MAXLINES, 1));
|
||
|
SendDlgItemMessage (hDlg, ID_SHAPE, CB_SETCURSEL, (wPolygon = 0), 0l);
|
||
|
SendMessage (hDlg, WM_COMMAND, MAKELONG (ID_SHAPE, CBN_SELCHANGE), 0);
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
switch (LOWORD(wParam))
|
||
|
{
|
||
|
// If we switch polygons, then update all of the info...
|
||
|
case ID_SHAPE:
|
||
|
if (HIWORD (wParam) == CBN_SELCHANGE)
|
||
|
{
|
||
|
WORD wTemp;
|
||
|
|
||
|
wTemp = (WORD)SendDlgItemMessage (hDlg, ID_SHAPE,
|
||
|
CB_GETCURSEL, 0, 0l);
|
||
|
wPolygon = (WORD)SendDlgItemMessage (hDlg, ID_SHAPE,
|
||
|
CB_GETITEMDATA, wTemp, 0l);
|
||
|
CheckDlgButton (hDlg, ID_ACTIVE, fOn[wPolygon]);
|
||
|
SetDlgItemInt (hDlg, ID_LINES, wLines[wPolygon], FALSE);
|
||
|
hPal = GetStockObject (DEFAULT_PALETTE);
|
||
|
GetObject (hPal, sizeof (WORD), (LPTSTR) &nPal);
|
||
|
if (SendDlgItemMessage (hDlg, ID_COLOR1, CB_SETCURSEL,
|
||
|
GetNearestPaletteIndex (hPal, dwStartColor[wPolygon]),
|
||
|
0l) == CB_ERR)
|
||
|
SendDlgItemMessage (hDlg, ID_COLOR1, CB_SETCURSEL, 0, 0l);
|
||
|
if (SendDlgItemMessage (hDlg, ID_COLOR2, CB_SETCURSEL,
|
||
|
GetNearestPaletteIndex (hPal, dwEndColor[wPolygon]),
|
||
|
0l) == CB_ERR)
|
||
|
SendDlgItemMessage (hDlg, ID_COLOR2, CB_SETCURSEL, 0, 0l);
|
||
|
|
||
|
// Set the walk state...
|
||
|
CheckRadioButton (hDlg, ID_2COLORS, ID_RANDOMCOLORS, ID_2COLORS +
|
||
|
fWalk[wPolygon]);
|
||
|
|
||
|
// Enable/disbale windows...
|
||
|
ShadeWindows (hDlg, wPolygon, wPolygon);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Toggle the actiavtion state...
|
||
|
case ID_ACTIVE:
|
||
|
fOn[wPolygon] ^= 1;
|
||
|
CheckDlgButton (hDlg, LOWORD(wParam), fOn[wPolygon]);
|
||
|
ShadeWindows (hDlg, wPolygon, wPolygon);
|
||
|
break;
|
||
|
|
||
|
case ID_CLEARSCREEN:
|
||
|
fClearScreen ^= 1;
|
||
|
CheckDlgButton (hDlg, LOWORD(wParam), fClearScreen);
|
||
|
break;
|
||
|
|
||
|
case ID_COLOR1:
|
||
|
case ID_COLOR2:
|
||
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
||
|
{
|
||
|
wTemp = (WORD)SendDlgItemMessage (hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0l);
|
||
|
hPal = GetStockObject (DEFAULT_PALETTE);
|
||
|
GetPaletteEntries (hPal, wTemp, 1, (LPPALETTEENTRY)(LPDWORD) & dwTemp);
|
||
|
if ( LOWORD(wParam) == ID_COLOR1 )
|
||
|
dwStartColor[wPolygon] = dwTemp & 0xffffffL;
|
||
|
else
|
||
|
dwEndColor[wPolygon] = dwTemp & 0xffffffL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Toggle the walk state...
|
||
|
case ID_2COLORS:
|
||
|
case ID_RANDOMCOLORS:
|
||
|
fWalk[wPolygon] = LOWORD(wParam) - ID_2COLORS;
|
||
|
CheckRadioButton (hDlg, ID_2COLORS, ID_RANDOMCOLORS, LOWORD(wParam));
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_COLOR1), !fWalk[wPolygon]);
|
||
|
InvalidateRect (GetDlgItem (hDlg, ID_COLOR1), NULL, TRUE);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_COLOR2), !fWalk[wPolygon]);
|
||
|
InvalidateRect (GetDlgItem (hDlg, ID_COLOR2), NULL, TRUE);
|
||
|
break;
|
||
|
|
||
|
// Check to see if the edit texts have lost their focus. If so
|
||
|
// update...
|
||
|
case ID_LINES:
|
||
|
if (HIWORD(wParam) == EN_UPDATE)
|
||
|
{
|
||
|
wLoop = (WORD) GetDlgItemInt (hDlg, LOWORD(wParam), &fError, FALSE);
|
||
|
fError = fError && (wLoop >= 1 && wLoop <= MAXLINES);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_LINESARROW), fError);
|
||
|
EnableWindow (GetDlgItem (hDlg, IDOK), fError);
|
||
|
if (fError)
|
||
|
wLines[wPolygon] = wLoop;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Save the current parameters...
|
||
|
case IDOK:
|
||
|
wLines[wPolygon] = (WORD) GetDlgItemInt (hDlg, ID_LINES, &fError, FALSE);
|
||
|
|
||
|
// Write the activation state of clearing the screen...
|
||
|
wsprintf (szBuffer, TEXT("%d"), fClearScreen);
|
||
|
WritePrivateProfileString (szAppName, szClearName, szBuffer, szIniFile);
|
||
|
|
||
|
/* Write the updated versions of everything here... */
|
||
|
for (wLoop = 0; wLoop < NUMBER_POLYGONS; wLoop++)
|
||
|
{
|
||
|
/* Set the activation state... */
|
||
|
wsprintf (szBuffer, TEXT("Active%d"), wLoop + 1);
|
||
|
wsprintf (szBuffer2, TEXT("%d"), fOn[wLoop]);
|
||
|
WritePrivateProfileString (szAppName, szBuffer, szBuffer2, szIniFile);
|
||
|
|
||
|
/* Set the walk state... */
|
||
|
wsprintf (szBuffer, TEXT("WalkRandom%d"), wLoop + 1);
|
||
|
wsprintf (szBuffer2, TEXT("%d"), fWalk[wLoop]);
|
||
|
WritePrivateProfileString (szAppName, szBuffer, szBuffer2, szIniFile);
|
||
|
|
||
|
/* Get the number of lines for the current polygon... */
|
||
|
wsprintf (szBuffer, TEXT("Lines%d"), wLoop + 1);
|
||
|
wsprintf (szBuffer2, TEXT("%d"), wLines[wLoop]);
|
||
|
WritePrivateProfileString (szAppName, szBuffer, szBuffer2, szIniFile);
|
||
|
|
||
|
/* Set the start color... */
|
||
|
wsprintf (szBuffer, TEXT("StartColor%d"), wLoop + 1);
|
||
|
byR = GetRValue (dwStartColor[wLoop]);
|
||
|
byG = GetGValue (dwStartColor[wLoop]);
|
||
|
byB = GetBValue (dwStartColor[wLoop]);
|
||
|
wsprintf (szBuffer2, TEXT("%d %d %d"), byR, byG, byB);
|
||
|
WritePrivateProfileString (szAppName, szBuffer, szBuffer2, szIniFile);
|
||
|
|
||
|
/* Set the end color... */
|
||
|
wsprintf (szBuffer, TEXT("EndColor%d"), wLoop + 1);
|
||
|
byR = GetRValue (dwEndColor[wLoop]);
|
||
|
byG = GetGValue (dwEndColor[wLoop]);
|
||
|
byB = GetBValue (dwEndColor[wLoop]);
|
||
|
wsprintf (szBuffer2, TEXT("%d %d %d"), byR, byG, byB);
|
||
|
WritePrivateProfileString (szAppName, szBuffer, szBuffer2, szIniFile);
|
||
|
}
|
||
|
|
||
|
/* Bail out... */
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog (hDlg, LOWORD(wParam) == IDOK);
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_DRAWITEM:
|
||
|
return (BOOL)AppOwnerDraw (hDlg, message, wParam, lParam);
|
||
|
|
||
|
case WM_MEASUREITEM:
|
||
|
return (BOOL)AppOwnerDraw (hDlg, message, wParam, lParam);
|
||
|
|
||
|
case WM_DELETEITEM:
|
||
|
return (BOOL)AppOwnerDraw (hDlg, message, wParam, lParam);
|
||
|
|
||
|
case WM_HELP: // F1
|
||
|
WinHelp(
|
||
|
(HWND) ((LPHELPINFO) lParam)->hItemHandle,
|
||
|
szHelpFile,
|
||
|
HELP_WM_HELP,
|
||
|
(ULONG_PTR) (LPSTR) aMystDlgHelpIds
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU: // right mouse click
|
||
|
WinHelp(
|
||
|
(HWND) wParam,
|
||
|
szHelpFile,
|
||
|
HELP_CONTEXTMENU,
|
||
|
(ULONG_PTR) (LPSTR) aMystDlgHelpIds
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID GetFields (VOID)
|
||
|
{
|
||
|
WORD wLoop;
|
||
|
//Load Global Strings from stringtable
|
||
|
LoadString (hMainInstance, idsName, szName, CharSizeOf(szName));
|
||
|
LoadString (hMainInstance, idsAppName, szAppName, CharSizeOf(szAppName));
|
||
|
|
||
|
//Load Common Strings from stringtable...
|
||
|
LoadString (hMainInstance, idsIniFile, szIniFile, CharSizeOf(szIniFile));
|
||
|
LoadString (hMainInstance, idsScreenSaver, szScreenSaver, CharSizeOf(szScreenSaver));
|
||
|
LoadString (hMainInstance, idsHelpFile, szHelpFile, CharSizeOf(szHelpFile));
|
||
|
LoadString (hMainInstance, idsNoHelpMemory, szNoHelpMemory, CharSizeOf(szNoHelpMemory));
|
||
|
|
||
|
/* Do we clear the screen when we start... */
|
||
|
if ((fClearScreen = GetPrivateProfileInt (szAppName, szClearName, 1, szIniFile)) != 0)
|
||
|
fClearScreen = 1;
|
||
|
|
||
|
/* Loop through and get all of the field information... */
|
||
|
for (wLoop = 0; wLoop < NUMBER_POLYGONS; wLoop++)
|
||
|
{
|
||
|
/* Get the activation state... */
|
||
|
wsprintf (szBuffer, TEXT("Active%d"), wLoop + 1);
|
||
|
if ((fOn[wLoop] = GetPrivateProfileInt (szAppName, szBuffer, 1, szIniFile)) != 0)
|
||
|
fOn[wLoop] = 1;
|
||
|
|
||
|
/* Get the walk state... */
|
||
|
wsprintf (szBuffer, TEXT("WalkRandom%d"), wLoop + 1);
|
||
|
if ((fWalk[wLoop] = GetPrivateProfileInt (szAppName, szBuffer, 1, szIniFile)) != 0)
|
||
|
fWalk[wLoop] = 1;
|
||
|
|
||
|
/* Get the number of lines for the current polygon... */
|
||
|
wsprintf (szBuffer, TEXT("Lines%d"), wLoop + 1);
|
||
|
wLines[wLoop] = (WORD) GetPrivateProfileInt (szAppName, szBuffer, 5, szIniFile);
|
||
|
if ((int)wLines[wLoop] < 1)
|
||
|
wLines[wLoop] = 1;
|
||
|
if (wLines[wLoop] > MAXLINES)
|
||
|
wLines[wLoop] = MAXLINES;
|
||
|
|
||
|
/* Get the starting and ending colors (stored in DWORD format)... */
|
||
|
wsprintf (szBuffer, TEXT("StartColor%d"), wLoop + 1);
|
||
|
dwStartColor[wLoop] = GetProfileRgb (szAppName, szBuffer, RGB (0, 0, 0));
|
||
|
wsprintf (szBuffer, TEXT("EndColor%d"), wLoop + 1);
|
||
|
dwEndColor[wLoop] = GetProfileRgb (szAppName, szBuffer, RGB (255, 255, 255));
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID DrawPolygon (HDC hDC, HPEN hPen, WORD wPolygon, WORD wLine)
|
||
|
{
|
||
|
HANDLE hOldPen;
|
||
|
WORD wLoop1;
|
||
|
|
||
|
hOldPen = SelectObject (hDC, hPen);
|
||
|
MoveToEx (hDC, ptBox[wPolygon*MAXLINES+wLine][0].x,
|
||
|
ptBox[wPolygon*MAXLINES+wLine][0].y, NULL);
|
||
|
for (wLoop1 = 0; wLoop1 < 4; wLoop1++)
|
||
|
LineTo (hDC, ptBox[wPolygon*MAXLINES+wLine][(wLoop1+1)%4].x,
|
||
|
ptBox[wPolygon*MAXLINES+wLine][(wLoop1+1)%4].y);
|
||
|
if (hOldPen)
|
||
|
SelectObject (hDC, hOldPen);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Adjust each of the rgb components according to the four input variables...*/
|
||
|
|
||
|
DWORD AdjustColor (DWORD dwSrc, DWORD dwDest, int nInc, int nCnt)
|
||
|
{
|
||
|
DWORD dwTemp;
|
||
|
WORD wLoop;
|
||
|
int nSrc, nDst, nTmp;
|
||
|
int n1, n2, n3, n4, n5;
|
||
|
|
||
|
/* Nullify the end value... */
|
||
|
dwTemp = 0;
|
||
|
|
||
|
/* Cycle through and compute the difference on each byte... */
|
||
|
for (wLoop = 0; wLoop < 3; wLoop++)
|
||
|
{
|
||
|
nSrc = (int)((dwSrc >> (wLoop * 8)) % 256);
|
||
|
nDst = (int)((dwDest >> (wLoop * 8)) % 256);
|
||
|
n1 = nDst - nSrc;
|
||
|
n2 = n1 * 10;
|
||
|
n3 = n2 / nInc;
|
||
|
n4 = n3 * nCnt;
|
||
|
n5 = n4 / 10;
|
||
|
nTmp = nSrc + n5;
|
||
|
dwTemp += ((DWORD)nTmp) << (wLoop * 8);
|
||
|
}
|
||
|
return dwTemp;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Compute a random color that is within the accepted norms... */
|
||
|
|
||
|
DWORD GenerateColor (VOID)
|
||
|
{
|
||
|
return (((DWORD)ZRAND (256)) + (((DWORD)ZRAND (256)) << 8) +
|
||
|
(((DWORD)ZRAND (256)) << 16));
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Compute a random velocity that is within the accepted norms... */
|
||
|
|
||
|
WORD GenerateVelocity (VOID)
|
||
|
{
|
||
|
return 255;
|
||
|
return (RAND (30) + 20);
|
||
|
}
|
||
|
|
||
|
|
||
|
LONG AppOwnerDraw (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
RECT rc;
|
||
|
DWORD rgbBg;
|
||
|
static HBITMAP hbmCheck = NULL;
|
||
|
LPMEASUREITEMSTRUCT lpMIS = ((LPMEASUREITEMSTRUCT)lParam);
|
||
|
LPDRAWITEMSTRUCT lpDIS = ((LPDRAWITEMSTRUCT)lParam);
|
||
|
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_MEASUREITEM:
|
||
|
lpMIS->itemHeight = 15;
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_DRAWITEM:
|
||
|
rc = lpDIS->rcItem;
|
||
|
rgbBg = PALETTEINDEX (lpDIS->itemID);
|
||
|
|
||
|
if (lpDIS->itemState & ODS_SELECTED)
|
||
|
{
|
||
|
FrameR (lpDIS->hDC, &rc, rgbBlack, 2);
|
||
|
InflateRect (&rc, -1, -1);
|
||
|
FrameR (lpDIS->hDC, &rc, rgbWhite, 2);
|
||
|
InflateRect (&rc, -1, -1);
|
||
|
}
|
||
|
if (lpDIS->itemState & ODS_DISABLED)
|
||
|
FillR (lpDIS->hDC, &rc, rgbGrey);
|
||
|
else
|
||
|
FillR (lpDIS->hDC, &rc, rgbBg);
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_DELETEITEM:
|
||
|
return TRUE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID PatB (HDC hdc, int x, int y, int dx, int dy, DWORD rgb)
|
||
|
{
|
||
|
RECT rc;
|
||
|
|
||
|
SetBkColor (hdc, rgb);
|
||
|
rc.left = x;
|
||
|
rc.top = y;
|
||
|
rc.right = x + dx;
|
||
|
rc.bottom = y + dy;
|
||
|
|
||
|
ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID FillR (HDC hdc, LPRECT prc, DWORD rgb)
|
||
|
{
|
||
|
SetBkColor (hdc, rgb);
|
||
|
ExtTextOut (hdc, 0, 0, ETO_OPAQUE, prc, NULL, 0, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID FrameR (HDC hdc, LPRECT prc, DWORD rgb, int iFrame)
|
||
|
{
|
||
|
// RECT rc;
|
||
|
int dx, dy;
|
||
|
|
||
|
dx = prc->right - prc->left;
|
||
|
dy = prc->bottom - prc->top - 2 * iFrame;
|
||
|
|
||
|
PatB (hdc, prc->left, prc->top, dx, iFrame, rgb);
|
||
|
PatB (hdc, prc->left, prc->bottom - iFrame, dx, iFrame, rgb);
|
||
|
|
||
|
PatB (hdc, prc->left, prc->top + iFrame, iFrame, dy, rgb);
|
||
|
PatB (hdc, prc->right - iFrame, prc->top + iFrame, iFrame, dy, rgb);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DrawBitmap (HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
|
||
|
{
|
||
|
HDC hdcBits;
|
||
|
BITMAP bm;
|
||
|
// HPALETTE hpalT;
|
||
|
HBITMAP oldbm;
|
||
|
BOOL f;
|
||
|
|
||
|
if (!hdc || !hbm)
|
||
|
return FALSE;
|
||
|
|
||
|
hdcBits = CreateCompatibleDC (hdc);
|
||
|
GetObject (hbm, sizeof (BITMAP), (LPTSTR) & bm);
|
||
|
oldbm = SelectObject (hdcBits, hbm);
|
||
|
f = BitBlt (hdc, x, y, bm.bmWidth, bm.bmHeight, hdcBits, 0, 0, rop);
|
||
|
if (oldbm)
|
||
|
SelectObject (hdcBits, oldbm);
|
||
|
DeleteDC (hdcBits);
|
||
|
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD GetProfileRgb (LPTSTR szApp, LPTSTR szItem, DWORD rgb)
|
||
|
{
|
||
|
TCHAR buf[80];
|
||
|
LPTSTR pch;
|
||
|
WORD r, g, b;
|
||
|
|
||
|
GetPrivateProfileString (szApp, szItem, TEXT(""), buf, CharSizeOf(buf), szIniFile);
|
||
|
|
||
|
if (*buf)
|
||
|
{
|
||
|
pch = buf;
|
||
|
r = AtoI (pch);
|
||
|
while (*pch && *pch != TEXT(' '))
|
||
|
pch++;
|
||
|
while (*pch && *pch == TEXT(' '))
|
||
|
pch++;
|
||
|
g = AtoI (pch);
|
||
|
while (*pch && *pch != TEXT(' '))
|
||
|
pch++;
|
||
|
while (*pch && *pch == TEXT(' '))
|
||
|
pch++;
|
||
|
b = AtoI (pch);
|
||
|
|
||
|
return RGB (r, g, b);
|
||
|
}
|
||
|
else
|
||
|
return rgb;
|
||
|
}
|
||
|
|
||
|
|
||
|
WORD AtoI (LPTSTR lpszConvert)
|
||
|
{
|
||
|
WORD wReturn = 0;
|
||
|
|
||
|
while (*lpszConvert >= TEXT('0') && *lpszConvert <= TEXT('9'))
|
||
|
{
|
||
|
wReturn = wReturn * 10 + (WORD)(*lpszConvert - TEXT('0'));
|
||
|
lpszConvert++;
|
||
|
}
|
||
|
return wReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID ShadeWindows (HWND hDlg, WORD wPoly, WORD wPolygon)
|
||
|
{
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_COLORGROUP), fOn[wPolygon]);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_2COLORS), fOn[wPolygon]);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_RANDOMCOLORS), fOn[wPolygon]);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_LINES), fOn[wPolygon]);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_LINESARROW), fOn[wPolygon]);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_COLOR1), !fWalk[wPolygon] && fOn[wPolygon]);
|
||
|
InvalidateRect (GetDlgItem (hDlg, ID_COLOR1), NULL, TRUE);
|
||
|
EnableWindow (GetDlgItem (hDlg, ID_COLOR2), !fWalk[wPolygon] && fOn[wPolygon]);
|
||
|
InvalidateRect (GetDlgItem (hDlg, ID_COLOR2), NULL, TRUE);
|
||
|
}
|