home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windoware
/
WINDOWARE_1_6.iso
/
screen
/
winlava
/
lava.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-10
|
42KB
|
1,347 lines
/*----------------------------------------------------------------------------*\
| Lava.c - A Lava Flow Simulator for Windows application |
| |
| |
\*----------------------------------------------------------------------------*/
/*
(C) Copyright Microsoft Corp. 1991. All rights reserved.
You have a royalty-free right to use, modify, reproduce and
distribute the Sample Files (and/or any modified version) in
any way you find useful, provided that you agree that
Microsoft has no warranty obligations or liability for any
Sample Application Files which are modified.
*/
#define PUBLIC far pascal
#define PRIVATE near pascal
#include <windows.h>
#define WinAssert(x)
#include <math.h>
#include "lava.h"
#define PC_NOCOLLAPSE 0x04 // non-collapsing flag
#define rgbBlack RGB(0,0,0)
#define rgbWhite RGB(255,255,255)
//#define rgbRed RGB(255,0,0)
//#define rgbGreen RGB(0,255,0)
//#define rgbBlue RGB(0,0,255)
#define rgbMenu GetSysColor(COLOR_MENU)
#define rgbMenuText GetSysColor(COLOR_MENUTEXT)
#define MAXCOLORS 256
#define wDibUsage (fPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS)
typedef struct CHARGE
{
POINT pt;
int value;
}CHARGE;
/*----------------------------------------------------------------------------*\
| |
| g l o b a l v a r i a b l e s |
| |
\*----------------------------------------------------------------------------*/
static char szAppName[]="LavaFlow";
static HANDLE hInstApp;
static HWND hwndApp;
/*----------------------------------------------------------------------------*\
| |
| f u n c t i o n d e f i n i t i o n s |
| |
\*----------------------------------------------------------------------------*/
LONG FAR PASCAL AppWndProc (HWND hwnd, unsigned uiMessage, WORD wParam, LONG lParam);
int ErrMsg (LPSTR sz,...);
BOOL fDialog(int id,HWND hwnd,FARPROC fpfn);
HMENU hmenuPopup;
BOOL fSetDIBits = TRUE;
BOOL fPalColors = TRUE;
BOOL fPalette;
BOOL fFastCycle;
short fSinPalette=FALSE;
short fCrossFade=FALSE;
short fColorCycle=TRUE;
short fNoCollapse=FALSE;
short paletteval[MAXCOLORS];
//
// A brush for every color in the palette, for use on non palette devices.
//
HBRUSH hbrPalette[MAXCOLORS];
HPALETTE hpalLava;
LOGPALETTE *pLogPal;
int nColors = 128;
int NumCenters = 4;
int nBandScale = 1;
short nColorPhase = 0;
RGBQUAD rgbLava = {0,0,255};
//
// TRUE if a Lava computation is in progress
//
BOOL fLavaSem;
//
// if set to a non zero value will cause lava calculation to abort
//
BOOL fStopLava;
#define F_LAVAOK 0
#define F_LAVASTOP 1
#define F_LAVADIE 2
HBITMAP hbmLava;
BITMAP bmLava;
BYTE abScanLine[2048];
BITMAPINFOHEADER *pbiLava;
LONG PRIVATE AppOwnerDraw(HWND hwnd, WORD msg, WORD wParam, LONG lParam);
LONG PRIVATE AppCommand(HWND hwnd, unsigned msg, WORD wParam, LONG lParam);
HBITMAP CopyBitmap (HBITMAP hbm);
HPALETTE CopyPalette(HPALETTE hpal);
HANDLE CreateLogicalDib(HBITMAP hbm, HPALETTE hpal);
extern LONG LavaFlowXY386(int nCenter, CHARGE *aptCenter, int x, int y);
void LavaFlow(HDC hdc, int nCenter, CHARGE aptCenter[], PRECT prc);
void CyclePalette(HDC hdc);
void InitPalette();
void SetPalette(PALETTEENTRY * pPal, int nPhase, RGBQUAD rgb);
#define MAXI (16*1024)
/*----------------------------------------------------------------------------*\
| |
| Random functions |
| |
\*----------------------------------------------------------------------------*/
#define RAND(x) (rand() % (x))
DWORD dwRand = 1L;
void PASCAL srand(DWORD dwSeed)
{
dwRand = dwSeed;
}
WORD PASCAL rand(void)
{
dwRand = dwRand * 214013L + 2531011L;
return (WORD)((dwRand >> 16) & 0xffff);
}
POINT PASCAL PtRand(int x, int y)
{
POINT pt;
pt.x = RAND(x);
pt.y = RAND(y);
return pt;
}
VOID WinYield()
{
MSG msg;
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/*----------------------------------------------------------------------------*\
| AppAbout( hDlg, uiMessage, wParam, lParam ) |
| |
| Description: |
| This function handles messages belonging to the "About" dialog box. |
| The only message that it looks for is WM_COMMAND, indicating the use |
| has pressed the "OK" button. When this happens, it takes down |
| the dialog box. |
| |
| Arguments: |
| hDlg window handle of about dialog window |
| uiMessage message number |
| wParam message-dependent |
| lParam message-dependent |
| |
| Returns: |
| TRUE if message has been processed, else FALSE |
| |
\*----------------------------------------------------------------------------*/
BOOL FAR PASCAL AppAbout( hDlg, uiMessage, wParam, lParam )
HWND hDlg;
unsigned uiMessage;
WORD wParam;
long lParam;
{
switch (uiMessage) {
case WM_COMMAND:
if (wParam == IDOK)
EndDialog(hDlg,TRUE);
break;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
VOID SetupPalette()
{
int i;
WORD *pw;
RGBQUAD *prgb;
PALETTEENTRY *ppe;
if (hpalLava)
{
DeleteObject(hpalLava);
hpalLava = NULL;
}
//hpalLava = CreateWashPalette(rgbBlue,rgbBlack,-nColors);
if(pLogPal == NULL)
{
pLogPal = (VOID *)LocalAlloc(LPTR,sizeof(LOGPALETTE) + MAXCOLORS * sizeof(PALETTEENTRY));
}
WinAssert(pLogPal);
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = nColors;
SetPalette(pLogPal->palPalEntry,nColorPhase,rgbLava);
if (!fPalette)
{
for(i=0,ppe=pLogPal->palPalEntry;i<nColors;i++,ppe++)
{
if (hbrPalette[i])
DeleteObject(hbrPalette[i]);
hbrPalette[i] = CreateSolidBrush(RGB(ppe->peRed,ppe->peGreen,ppe->peBlue));
}
}
hpalLava = CreatePalette(pLogPal);
if (pbiLava == NULL)
{
pbiLava = (VOID *)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER) + MAXCOLORS * sizeof(RGBQUAD));
pbiLava->biSize = sizeof(BITMAPINFOHEADER);
pbiLava->biWidth = 0;
pbiLava->biHeight = 0;
pbiLava->biPlanes = 1;
pbiLava->biBitCount = 8;
pbiLava->biCompression = BI_RGB;
pbiLava->biSizeImage = 0;
pbiLava->biXPelsPerMeter = 0;
pbiLava->biYPelsPerMeter = 0;
pbiLava->biClrUsed = nColors;
pbiLava->biClrImportant = 0;
}
WinAssert(pbiLava);
if (fPalColors)
{
pw = (WORD*)((BYTE*)pbiLava+pbiLava->biSize);
for (i=0; i<nColors; i++)
{
*pw++ = i;
}
}
else
{
prgb = (RGBQUAD*)((BYTE*)pbiLava+pbiLava->biSize);
for (i=0; i<nColors; i++)
{
prgb[i].rgbRed = pLogPal->palPalEntry[i].peRed;
prgb[i].rgbGreen = pLogPal->palPalEntry[i].peGreen;
prgb[i].rgbBlue = pLogPal->palPalEntry[i].peBlue;
prgb[i].rgbReserved = 0;
}
}
}
/*----------------------------------------------------------------------------*\
| AppExit() |
| |
| Description: |
| This is called when the application is removed from memory |
| It free all global objects and other things |
| |
| Returns: |
| Exit code to be returned to KERNEL |
| |
\*----------------------------------------------------------------------------*/
WORD AppExit()
{
int i;
for (i=0; i<nColors; i++)
{
if (hbrPalette[i])
DeleteObject(hbrPalette[i]);
}
if (hbmLava)
DeleteObject(hbmLava);
if (hpalLava)
DeleteObject(hpalLava);
//if (hmenuPopup)
// DeleteMenu(hmenuPopup);
return 0;
}
/*----------------------------------------------------------------------------*\
| AppInit( hInst, hPrev) |
| |
| Description: |
| This is called when the application is first loaded into |
| memory. It performs all initialization that doesn't need to be done |
| once per instance. |
| |
| Arguments: |
| hInstance instance handle of current instance |
| hPrev instance handle of previous instance |
| |
| Returns: |
| TRUE if successful, FALSE if not |
| |
\*----------------------------------------------------------------------------*/
BOOL AppInit(hInst,hPrev,sw,szCmd)
HANDLE hInst;
HANDLE hPrev;
WORD sw;
LPSTR szCmd;
{
WNDCLASS rClass;
int dx,dy;
char ach[80];
HMENU hmenu;
HPALETTE hpal;
HDC hdc;
if (LOWORD(GetWinFlags()) & (WF_CPU086|WF_CPU186|WF_CPU286))
{
MessageBox(NULL,"Lava requires a 386 or better","Lava",MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
return FALSE;
}
/* Save instance handle for DialogBoxs */
hInstApp = hInst;
if (!hPrev) {
/*
* Register a class for the main application window
*/
rClass.hCursor = LoadCursor(NULL,IDC_ARROW);
rClass.hIcon = LoadIcon(hInst,"AppIcon");
rClass.lpszMenuName = NULL;
rClass.lpszClassName = szAppName;
rClass.hbrBackground = (HBRUSH)COLOR_WINDOW + 1;
rClass.hInstance = hInst;
rClass.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
rClass.lpfnWndProc = AppWndProc;
rClass.cbWndExtra = 0;
rClass.cbClsExtra = 0;
if (!RegisterClass(&rClass))
return FALSE;
}
dx = GetSystemMetrics (SM_CXSCREEN);
dy = GetSystemMetrics (SM_CYSCREEN);
hwndApp = CreateWindow (szAppName,szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,dx/2,dy/2,
(HWND)NULL, /* no parent */
(HMENU)NULL, /* use class menu */
(HANDLE)hInst, /* handle to window instance */
(LPSTR)NULL /* no params to pass on */
);
WinAssert(hwndApp);
ShowWindow (hwndApp,sw);
hmenu = LoadMenu(hInst,"AppMenu");
WinAssert(hmenu);
hmenuPopup = GetSubMenu(hmenu, 0);
WinAssert(hmenuPopup);
CheckMenuItem(hmenuPopup,MENU_NUMCENTERS+NumCenters,MF_CHECKED);
CheckMenuItem(hmenuPopup,MENU_NUMCOLORS+nColors,MF_CHECKED);
CheckMenuItem(hmenuPopup,MENU_BANDSCALE+nBandScale,MF_CHECKED);
InitPalette();
SetupPalette();
SetTimer(hwndApp,1,10,NULL);
srand(GetCurrentTime());
hdc = GetDC(NULL);
fPalette = fSetDIBits = (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE);
ReleaseDC(NULL,hdc);
return TRUE;
}
/*----------------------------------------------------------------------------*\
| WinMain( hInst, hPrev, lpszCmdLine, cmdShow ) |
| |
| Description: |
| The main procedure for the App. After initializing, it just goes |
| into a message-processing loop until it gets a WM_QUIT message |
| (meaning the app was closed). |
| |
| Arguments: |
| hInst instance handle of this instance of the app |
| hPrev instance handle of previous instance, NULL if first |
| lpszCmdLine ->null-terminated command line |
| cmdShow specifies how the window is initially displayed |
| |
| Returns: |
| The exit code as specified in the WM_QUIT message. |
| |
\*----------------------------------------------------------------------------*/
int PASCAL WinMain( hInst, hPrev, fpcCmdLine, iCmdShow )
HANDLE hInst, hPrev;
LPSTR fpcCmdLine;
int iCmdShow;
{
MSG msg;
/* Call initialization procedure */
if (!AppInit(hInst,hPrev,iCmdShow,fpcCmdLine))
return FALSE;
for (;;)
{
/* Polling messages from event queue */
while (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
goto exit;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (fFastCycle)
SendMessage(hwndApp,WM_TIMER,0,0L);
else
WaitMessage();
}
exit:
return AppExit();
}
/*----------------------------------------------------------------------------*\
| AppPaint(hwnd, hdc) |
| |
| Description: |
| The paint function. Right now this does nothing. |
| |
| Arguments: |
| hwnd window painting into |
| hdc display context to paint to |
| |
| Returns: |
| nothing |
| |
\*----------------------------------------------------------------------------*/
AppPaint (HWND hwnd, HDC hdc)
{
RECT rc;
HBITMAP hbmT;
HDC hdcBits;
if (hbmLava == NULL)
return FALSE;
if (hpalLava)
{
SelectPalette(hdc,hpalLava,FALSE);
RealizePalette(hdc);
}
hdcBits = CreateCompatibleDC(hdc);
GetClientRect(hwnd,&rc);
hbmT = SelectObject(hdcBits,hbmLava);
BitBlt(hdc,0,0,bmLava.bmWidth,bmLava.bmHeight,hdcBits,0,0,SRCCOPY);
SelectObject(hdcBits,hbmT);
DeleteDC(hdcBits);
return TRUE;
}
/*----------------------------------------------------------------------------*\
| |
| w i n d o w p r o c s |
| |
\*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*\
| AppWndProc( hwnd, uiMessage, wParam, lParam ) |
| |
| Description: |
| The window proc for the app's main (tiled) window. This processes all |
| of the parent window's messages. |
| |
| Arguments: |
| hwnd window handle for the window |
| uiMessage message number |
| wParam message-dependent |
| lParam message-dependent |
| |
| Returns: |
| 0 if processed, nonzero if ignored |
| |
\*----------------------------------------------------------------------------*/
LONG FAR PASCAL AppWndProc(hwnd, msg, wParam, lParam)
HWND hwnd;
unsigned msg;
WORD wParam;
long lParam;
{
PAINTSTRUCT ps;
BOOL f;
HDC hdc;
RECT rc;
switch (msg) {
case WM_CREATE:
break;
case WM_QUERYNEWPALETTE:
if (hpalLava)
{
hdc = GetDC(hwnd);
SelectPalette(hdc,hpalLava,FALSE);
f = RealizePalette(hdc);
ReleaseDC(hwnd,hdc);
return (LONG)f;
}
return FALSE;
case WM_PALETTECHANGED:
if (wParam != hwnd && hpalLava)
InvalidateRect(hwnd,NULL,TRUE);
break;
case WM_LBUTTONDOWN:
ClientToScreen(hwnd, (LPPOINT)&lParam);
TrackPopupMenu(hmenuPopup, 0, LOWORD(lParam)-30, HIWORD(lParam)+4, 0, hwnd, NULL);
break;
case WM_DRAWITEM:
case WM_MEASUREITEM:
case WM_DELETEITEM:
return AppOwnerDraw(hwnd,msg,wParam,lParam);
case WM_INITMENU:
EnableMenuItem(wParam,MENU_GO,
fLavaSem ? MF_GRAYED : MF_ENABLED);
EnableMenuItem(wParam,MENU_STOP,
!fLavaSem ? MF_GRAYED : MF_ENABLED);
EnableMenuItem(wParam,MENU_PASTE,
IsClipboardFormatAvailable(CF_BITMAP) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam,MENU_COPY,
hbmLava ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam,MENU_PALCOLORS,
fSetDIBits ? MF_ENABLED : MF_GRAYED);
CheckMenuItem(wParam,MENU_PALETTE,
fPalette ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_SATIN,
fSinPalette ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_CROSSFADE,
fCrossFade ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_SETDIBITS,
fSetDIBits ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_PALCOLORS,
(fPalColors && fSetDIBits)? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_FASTCYCLE,
fFastCycle ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_COLORCYCLE,
fColorCycle ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(wParam,MENU_NOCOLLAPSE,
fNoCollapse ? MF_CHECKED : MF_UNCHECKED);
break;
case WM_COMMAND:
return AppCommand(hwnd,msg,wParam,lParam);
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
//
// if a lava calculation is under way stop it before closing
//
if (fLavaSem)
{
fStopLava = F_LAVADIE;
return 0L;
}
break;
case WM_TIMER:
if (fPalette && hpalLava)
{
hdc = GetDC(hwnd);
SelectPalette(hdc,hpalLava,FALSE);
RealizePalette(hdc);
CyclePalette(hdc);
ReleaseDC(hwnd,hdc);
}
break;
case WM_PAINT:
BeginPaint(hwnd,&ps);
AppPaint (hwnd,ps.hdc);
EndPaint(hwnd,&ps);
return 0L;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
/*----------------------------------------------------------------------------*\
| ErrMsg - Opens a Message box with a error message in it. The user can |
| select the OK button to continue or the CANCEL button to kill |
| the parent application. |
\*----------------------------------------------------------------------------*/
int ErrMsg (LPSTR sz,...)
{
char ach[128];
wsprintf (ach,sz,(LPSTR)(&sz+1)); /* Format the string */
MessageBox(NULL,ach,NULL,MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2|MB_SYSTEMMODAL);
return FALSE;
}
/*----------------------------------------------------------------------------*\
| fDialog(id,hwnd,fpfn) |
| |
| Description: |
| This function displays a dialog box and returns the exit code. |
| the function passed will have a proc instance made for it. |
| |
| Arguments: |
| id resource id of dialog to display |
| hwnd parent window of dialog |
| fpfn dialog message function |
| |
| Returns: |
| exit code of dialog (what was passed to EndDialog) |
| |
\*----------------------------------------------------------------------------*/
BOOL fDialog(int id,HWND hwnd,FARPROC fpfn)
{
BOOL f;
HANDLE hInst;
hInst = GetWindowWord(hwnd,GWW_HINSTANCE);
fpfn = MakeProcInstance(fpfn,hInst);
f = DialogBox(hInst,MAKEINTRESOURCE(id),hwnd,fpfn);
FreeProcInstance (fpfn);
return f;
}
void PRIVATE WinSetCursor(HWND hwnd, HCURSOR hcur)
{
SetCursor(hcur);
SetClassWord(hwnd,GCW_HCURSOR,(WORD)hcur);
}
LONG PRIVATE AppCommand (hwnd, msg, wParam, lParam)
HWND hwnd;
unsigned msg;
WORD wParam;
long lParam;
{
switch(wParam)
{
case MENU_COPY:
if (!OpenClipboard(hwnd))
break;
EmptyClipboard();
rgbLava.rgbRed = rgbLava.rgbGreen = rgbLava.rgbBlue = 255;
SetPalette(pLogPal->palPalEntry,0,rgbLava);
SetPaletteEntries(hpalLava,0,nColors,pLogPal->palPalEntry);
if (hbmLava)
SetClipboardData(CF_BITMAP,CopyBitmap(hbmLava));
if (hpalLava)
SetClipboardData(CF_PALETTE,CopyPalette(hpalLava));
if (hbmLava)
SetClipboardData(CF_DIB,CreateLogicalDib(hbmLava,hpalLava));
CloseClipboard();
break;
case MENU_ABOUT:
fDialog(ABOUTBOX,hwnd,AppAbout);
break;
case MENU_EXIT:
PostMessage(hwnd,WM_CLOSE,0,0L);
break;
case MENU_SATIN:
fSinPalette = !fSinPalette;
InitPalette();
SetupPalette();
break;
case MENU_CROSSFADE:
fCrossFade = !fCrossFade;
break;
case MENU_SETDIBITS:
fSetDIBits = !fSetDIBits;
break;
case MENU_COLORCYCLE:
fColorCycle = !fColorCycle;
break;
case MENU_PALCOLORS:
fPalColors = !fPalColors;
SetupPalette();
break;
case MENU_FASTCYCLE:
fFastCycle = !fFastCycle;
KillTimer(hwndApp,1);
if (!fFastCycle)
SetTimer(hwndApp,1,10,NULL);
break;
case MENU_NOCOLLAPSE:
fNoCollapse = !fNoCollapse;
SetupPalette();
break;
case MENU_PALETTE:
fPalette = !fPalette;
SetupPalette();
break;
case MENU_STOP:
if (fLavaSem)
fStopLava = F_LAVASTOP;
break;
case MENU_GO:
if (!fLavaSem)
{
HDC hdc;
CHARGE apt[40];
RECT rc;
int i;
//
// Change the GO menu item to stop
//
ChangeMenu(hmenuPopup,MENU_GO,"Stop!",MENU_STOP,MF_CHANGE|MF_BYCOMMAND);
WinSetCursor(hwnd,LoadCursor(NULL,IDC_WAIT));
fLavaSem++;
fStopLava = F_LAVAOK;
hdc = GetDC(hwnd);
SelectPalette(hdc,hpalLava,FALSE);
RealizePalette(hdc);
//
// Hack, if the window is maximized generate a SCREEN size
// bitmap
//
if (IsZoomed(hwnd))
SetRect(&rc,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
else
GetClientRect(hwnd,&rc);
//
// Pick random charge centers and weights
//
for (i=0; i<NumCenters; i++)
{
apt[i].pt = PtRand(rc.right,rc.bottom);
do
apt[i].value = RAND(9)-4;
while (apt[i].value == 0);
}
LavaFlow(hdc, NumCenters, apt, &rc);
fLavaSem--;
ReleaseDC(hwnd,hdc);
WinSetCursor(hwnd,LoadCursor(NULL,IDC_ARROW));
//
// Change the STOP menu item back to go
//
ChangeMenu(hmenuPopup,MENU_STOP,"Go!",MENU_GO,MF_CHANGE|MF_BYCOMMAND);
//
// If the user tried to close the app while we were working
// do it now
//
if (fStopLava == F_LAVADIE)
PostMessage(hwnd,WM_CLOSE,0,0L);
}
break;
default:
switch (wParam & 0xFF00)
{
int n;
case MENU_NUMCENTERS:
n = wParam & 0xFF;
CheckMenuItem(hmenuPopup,MENU_NUMCENTERS+NumCenters,MF_UNCHECKED);
CheckMenuItem(hmenuPopup,MENU_NUMCENTERS+n,MF_CHECKED);
NumCenters = n;
break;
case MENU_NUMCOLORS:
n = wParam & 0xFF;
CheckMenuItem(hmenuPopup,MENU_NUMCOLORS+nColors,MF_UNCHECKED);
CheckMenuItem(hmenuPopup,MENU_NUMCOLORS+n,MF_CHECKED);
nColors = n;
SetupPalette();
break;
case MENU_BANDSCALE:
n = wParam & 0xFF;
CheckMenuItem(hmenuPopup,MENU_BANDSCALE+nBandScale,MF_UNCHECKED);
CheckMenuItem(hmenuPopup,MENU_BANDSCALE+n,MF_CHECKED);
nBandScale = n;
break;
}
break;
}
return 0L;
}
LONG PRIVATE AppOwnerDraw(HWND hwnd, WORD msg, WORD wParam, LONG lParam)
{
#define lpMIS ((LPMEASUREITEMSTRUCT)lParam)
#define lpDIS ((LPDRAWITEMSTRUCT)lParam)
switch (msg)
{
case WM_MEASUREITEM:
lpMIS->itemHeight = 10;
lpMIS->itemWidth = 10;
return TRUE;
case WM_DRAWITEM:
return TRUE;
case WM_DELETEITEM:
return TRUE;
}
return TRUE;
}
void InitPalette()
{
int i;
int j;
j = 0;
for(i=0;i<nColors;i++)
{
if (fSinPalette)
paletteval[i] = (int)(MAXI-sin(i*3.14/(nColors-1))*MAXI);
else
paletteval[i] = (int)((1-pow(2.0*i/(nColors-1)-1,2.0))*MAXI);
}
}
/*
* llSetPixel(hdc,x,y,n)
*
* Sets a pixel in a HDC, will use dither patterns if fPalette not set
*
*/
void llSetPixel(HDC hdc, int x, int y, int n)
{
HBRUSH hbrT;
if (fPalette)
{
SetPixel(hdc,x,y,PALETTEINDEX(n));
}
else
{
hbrT = SelectObject(hdc,hbrPalette[n]);
PatBlt(hdc,x,y,1,1,PATCOPY);
SelectObject(hdc,hbrT);
}
}
/*
* LavaFlow()
*
* calulates the "Lava Lamp" equation for each point in the passed
* rectangle. The Lava equation at any point is defined as the sum
* of the distance squared from each center point
*
*/
void LavaFlow(HDC hdc, int nCenter, CHARGE aptCenter[], PRECT prc)
{
int x,y,i,a1;
static short a = 0;
int dx,dy;
HDC hdcBits;
HBITMAP hbmT;
HPALETTE hpalT;
hdcBits = CreateCompatibleDC(hdc);
dx = prc->right - prc->left;
dy = prc->bottom - prc->top;
a1 = a;
if (!hbmLava || bmLava.bmWidth != dx || bmLava.bmHeight != dy)
{
if (hbmLava)
DeleteObject(hbmLava);
hbmLava = CreateCompatibleBitmap(hdc,dx,dy);
if (!hbmLava)
return;
GetObject(hbmLava,sizeof(bmLava),(LPSTR)&bmLava);
pbiLava->biWidth = dx;
pbiLava->biHeight = dy;
pbiLava->biPlanes = 1;
pbiLava->biBitCount = 8;
pbiLava->biClrUsed = nColors;
pbiLava->biClrImportant = 0;
hbmT = SelectObject(hdcBits,hbmLava);
PatBlt(hdcBits,0,0,dx,dy,BLACKNESS);
SelectObject(hdcBits,hbmT);
}
for (y=prc->top; y<prc->bottom; y++)
{
if (fCrossFade)
{
hbmT = SelectObject(hdcBits,hbmLava);
hpalT = SelectPalette(hdcBits,hpalLava,FALSE);
RealizePalette(hdcBits);
a = !a;
for (x=prc->left+a; x<prc->right; x+=2)
{
i = LavaFlowXY386(nCenter,aptCenter,x,y) / nBandScale % nColors;
llSetPixel(hdc,x,y,i);
llSetPixel(hdcBits,x,y,i);
}
SelectObject(hdcBits,hbmT);
SelectPalette(hdcBits,hpalT,FALSE);
}
else
{
for (x=prc->left; x<prc->right; x++)
{
i = LavaFlowXY386(nCenter,aptCenter,x,y) / nBandScale % nColors;
abScanLine[x] = (BYTE)i;
}
if (fSetDIBits)
{
SetDIBits(hdc,hbmLava,dy-1-y,1,abScanLine,(LPBITMAPINFO)pbiLava,wDibUsage);
hbmT = SelectObject(hdcBits,hbmLava);
hpalT = SelectPalette(hdcBits,hpalLava,FALSE);
RealizePalette(hdcBits);
BitBlt(hdc,0,y,dx,1,hdcBits,0,y,SRCCOPY);
SelectObject(hdcBits,hbmT);
SelectPalette(hdcBits,hpalT,FALSE);
}
else
{
hbmT = SelectObject(hdcBits,hbmLava);
hpalT = SelectPalette(hdcBits,hpalLava,FALSE);
RealizePalette(hdcBits);
for (x=prc->left; x<prc->right; x++)
{
i = abScanLine[x];
llSetPixel(hdc,x,y,i);
llSetPixel(hdcBits,x,y,i);
}
SelectObject(hdcBits,hbmT);
SelectPalette(hdcBits,hpalT,FALSE);
}
}
if (fPalette)
CyclePalette(hdc);
WinYield();
//
// See if we should abort early
//
if (fStopLava != F_LAVAOK)
break;
}
a = !a1;
DeleteDC(hdcBits);
}
void SetPalette(PALETTEENTRY * pPal, int nPhase, RGBQUAD rgb)
{
int i,n;
for(i=0;i<nColors;i++)
{
n = paletteval[(nPhase + i) % nColors];
pPal[i].peRed = (BYTE)((long)rgb.rgbRed * n / MAXI);
pPal[i].peGreen = (BYTE)((long)rgb.rgbGreen* n / MAXI);
pPal[i].peBlue = (BYTE)((long)rgb.rgbBlue * n / MAXI);
if (fNoCollapse)
pPal[i].peFlags = (BYTE)PC_NOCOLLAPSE;
else
pPal[i].peFlags = (BYTE)PC_RESERVED;
}
}
void CyclePalette(HDC hdc)
{
int i;
PALETTEENTRY peT;
static short nLenColorCycle = 0;
static RGBQUAD rgbLavaOrg;
static short dr,dg,db;
if (fColorCycle)
{
if (nColorPhase >= nLenColorCycle)
{
nLenColorCycle = (RAND(4) + 1) * nColors;
nColorPhase = 0;
rgbLavaOrg = rgbLava;
dr = RAND(256) - (int)rgbLava.rgbRed;
dg = RAND(256) - (int)rgbLava.rgbGreen;
db = RAND(256) - (int)rgbLava.rgbBlue;
}
rgbLava.rgbRed = (int)rgbLavaOrg.rgbRed + (long)dr * nColorPhase / nLenColorCycle;
rgbLava.rgbGreen = (int)rgbLavaOrg.rgbGreen + (long)dg * nColorPhase / nLenColorCycle;
rgbLava.rgbBlue = (int)rgbLavaOrg.rgbBlue + (long)db * nColorPhase / nLenColorCycle;
nColorPhase++;
SetPalette(pLogPal->palPalEntry,nColorPhase,rgbLava);
}
else
{
peT = pLogPal->palPalEntry[0];
for (i = 0; i < (pLogPal->palNumEntries - 1); i++)
pLogPal->palPalEntry[i] = pLogPal->palPalEntry[i+1];
pLogPal->palPalEntry[i] = peT;
}
if (fNoCollapse)
{
SetPaletteEntries(hpalLava, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
RealizePalette(hdc);
}
else
{
AnimatePalette(hpalLava, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
}
}
#define WIDTHBYTES(i) ((i+31)/32*4) /* ULONG aligned ! */
#define MAKEP(sel,off) ((VOID FAR *)MAKELONG(off,sel))
#define PaletteSize(lpbi) (sizeof(RGBQUAD)*DibNumColors(lpbi))
WORD DibNumColors(LPBITMAPINFOHEADER lpbi)
{
if (lpbi->biClrUsed != 0 || lpbi->biBitCount == 24)
return (WORD)lpbi->biClrUsed;
else
return 1<<lpbi->biBitCount;
}
/*
* CreateLogicalDib
*
* Given a DDB and a HPALETTE create a "logical" DIB
*
* if the HBITMAP is NULL create a DIB from the system "stock" bitmap
* This is used to save a logical palette to a disk file as a DIB
*
* if the HPALETTE is NULL use the system "stock" palette (ie the
* system palette)
*
* a "logical" DIB is a DIB where the DIB color table *exactly* matches
* the passed logical palette. There will be no system colors in the DIB
* block, and a pixel value of <n> in the DIB will correspond to logical
* palette index <n>.
*
* This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
* option then converting the palindexes returned in the color table
* from palette indexes to logical RGB values. The entire passed logical
* palette is always copied to the DIB color table.
*
* The DIB color table will have exactly the same number of entries as
* the logical palette. Normaly GetDIBits() will always set biClrUsed to
* the maximum colors supported by the device regardless of the number of
* colors in the logical palette
*
* Why would you want to do this? The major reason for a "logical" DIB
* is so when the DIB is written to a disk file then reloaded the logical
* palette created from the DIB color table will be the same as one used
* originaly to create the bitmap. It also will prevent GDI from doing
* nearest color matching on PC_RESERVED palettes.
*
* ** What do we do if the logical palette has more than 256 entries!!!!!
* ** GetDIBits() may return logical palette index's that are greater than
* ** 256, we cant represent these colors in the "logical" DIB
* **
* ** for now hose the caller?????
*
*/
HANDLE CreateLogicalDib(HBITMAP hbm, HPALETTE hpal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpDib; // pointer to DIB
LPBITMAPINFOHEADER lpbi; // temp pointer to BITMAPINFO
DWORD dwLen;
DWORD dw;
int n;
int nColors;
HANDLE hdib;
HDC hdc;
BYTE FAR * lpBits;
WORD FAR * lpCT;
RGBQUAD FAR * lpRgb;
PALETTEENTRY peT;
HPALETTE hpalT;
WORD biBits;
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
if (hbm == NULL)
hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
biBits = nColors > 16 ? 8 : 4;
if (nColors > 256) // ACK!
; // How do we handle this????
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = BI_RGB;
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nColors;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
if (!hdib)
return NULL;
lpbi = MAKEP(GlobalAlloc(GMEM_FIXED,bi.biSize + 256 * sizeof(RGBQUAD)),0);
if (!lpbi)
{
GlobalFree(hdib);
return NULL;
}
hdc = GetDC(NULL);
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
lpDib = (VOID FAR *)GlobalLock(hdib);
*lpbi = bi;
*lpDib = bi;
lpCT = (WORD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
lpRgb = (RGBQUAD FAR *)((LPSTR)lpDib + (WORD)lpDib->biSize);
lpBits = (LPSTR)lpDib + (WORD)lpDib->biSize + PaletteSize(lpDib);
/*
* call GetDIBits to get the DIB bits and fill the color table with
* logical palette index's
*/
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
/*
* Now convert the DIB bits into "real" logical palette index's
*
* lpCT points to the DIB color table wich is a WORD array of
* logical palette index's
*
* lpBits points to the DIB bits, each DIB pixel is a index into
* the DIB color table.
*
*/
if (biBits == 8)
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
*lpBits = (BYTE)lpCT[*lpBits];
}
else // biBits == 4
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
*lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
}
/*
* Now copy the RGBs in the logical palette to the dib color table
*/
for (n=0; n<nColors; n++,lpRgb++)
{
GetPaletteEntries(hpal,n,1,&peT);
lpRgb->rgbRed = peT.peRed;
lpRgb->rgbGreen = peT.peGreen;
lpRgb->rgbBlue = peT.peBlue;
lpRgb->rgbReserved = (BYTE)0;
}
GlobalUnlock(hdib);
GlobalFree(HIWORD((DWORD)lpbi));
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/*----------------------------------------------------------------------------
CopyBitmap (hbm) - Returns a copy of the passed bitmap
----------------------------------------------------------------------------*/
HBITMAP CopyBitmap (HBITMAP hbm)
{
HDC hMemDCsrc;
HDC hMemDCdst;
HDC hdc;
HBITMAP hNewBm;
BITMAP bm;
if (!hbm)
return NULL;
hdc = GetDC(NULL);
hMemDCsrc = CreateCompatibleDC(hdc);
hMemDCdst = CreateCompatibleDC(hdc);
GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
hNewBm = CreateBitmap(bm.bmWidth,bm.bmHeight,bm.bmPlanes,bm.bmBitsPixel,NULL);
if (hNewBm)
{
SelectObject (hMemDCsrc,hbm);
SelectObject (hMemDCdst,hNewBm);
BitBlt (hMemDCdst,0,0,bm.bmWidth,bm.bmHeight,hMemDCsrc,0,0,SRCCOPY);
}
ReleaseDC(NULL,hdc);
DeleteDC(hMemDCsrc);
DeleteDC(hMemDCdst);
return hNewBm;
}
/*
* CopyPalette, makes a copy of a GDI logical palette
*/
HPALETTE CopyPalette(HPALETTE hpal)
{
PLOGPALETTE ppal;
int nNumEntries;
if (!hpal)
return NULL;
GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
if (nNumEntries == 0)
return NULL;
ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
nNumEntries * sizeof(PALETTEENTRY));
if (!ppal)
return NULL;
ppal->palVersion = 0x300;
ppal->palNumEntries = nNumEntries;
GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
hpal = CreatePalette(ppal);
LocalFree((HANDLE)ppal);
return hpal;
}