Discussion:
gdi animation
(too old to reply)
steve
2010-12-08 19:45:49 UTC
Permalink
Hello,
I'm completely new to GDI.
I found this simple gdi animation program in a book.
It compiles just fine, however, it does not animate.
It's just static.
It draws colored rectangles, one inside the other and the colors are
supposed to rotate inward,
creating a "tunnel" effect.


// Animate.c
// Palette animation
// Book:Programming Windows 98/NT Unleashed

// link with: gdi32.lib, user32.lib


#include <windows.h>


void Animate(HWND, HPALETTE);
void DrawCircle(HWND, HPALETTE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


struct
{
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[12];

} palPalette =
{
0x300,
12,
{
{0xFF, 0x00, 0x00, PC_RESERVED},
{0xC0, 0x40, 0x00, PC_RESERVED},
{0x80, 0x80, 0x00, PC_RESERVED},
{0x40, 0xC0, 0x00, PC_RESERVED},
{0x00, 0xFF, 0x00, PC_RESERVED},
{0x00, 0xC0, 0x40, PC_RESERVED},
{0x00, 0x80, 0x80, PC_RESERVED},
{0x00, 0x40, 0xC0, PC_RESERVED},
{0x00, 0x00, 0xFF, PC_RESERVED},
{0x40, 0x00, 0xC0, PC_RESERVED},
{0x80, 0x00, 0x80, PC_RESERVED},
{0xC0, 0x00, 0x40, PC_RESERVED}
}

};



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
d3, int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;

if(hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = "HELLO";

if(!RegisterClass(&wndClass))
{
return FALSE;
}
}

hwnd = CreateWindow("HELLO", "HELLO", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

SetTimer(hwnd, 1, 100, NULL);

while(GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}

KillTimer(hwnd, 1);

return msg.wParam;
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
{
static HPALETTE hPalette;

switch(uMsg)
{
case WM_CREATE:
hPalette = CreatePalette((LPLOGPALETTE) &palPalette);
break;
case WM_PAINT:
DrawCircle(hwnd, hPalette);
break;
case WM_TIMER:
Animate(hwnd, hPalette);
break;
case WM_DESTROY:
DeleteObject(hPalette);
hPalette = NULL;
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}



void DrawCircle(HWND hwnd, HPALETTE hPalette)
{
HDC hDC;
PAINTSTRUCT paintStruct;
RECT rect;
HPALETTE hOldPal;
int i;


hDC = BeginPaint(hwnd, &paintStruct);

if(hDC != NULL)
{
hOldPal = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
GetClientRect(hwnd, &rect);
DPtoLP(hDC, (LPPOINT) &rect, 2);

for(i = 0; i < 12; i++)
{
HBRUSH hbr;
HBRUSH hbrOld;
hbr = CreateSolidBrush(PALETTEINDEX(i));
hbrOld = (HBRUSH) SelectObject(hDC, hbr);
Rectangle(hDC, MulDiv(i, rect.right, 24), MulDiv(i,
rect.bottom, 24),
rect.right - MulDiv(i, rect.right, 24),
rect.bottom - MulDiv(i, rect.bottom, 24));

SelectObject(hDC, hbrOld);
DeleteObject(hbr);
}

SelectPalette(hDC, hOldPal, FALSE);
EndPaint(hwnd, &paintStruct);
}
}



void Animate(HWND hwnd, HPALETTE hPalette)
{
HDC hDC;
PALETTEENTRY pe[12];
HPALETTE hOldPal;
static int nIndex;
int i;

for(i = 0; i < 12; i++)
{
pe[i] = palPalette.palPalEntry[(i + nIndex) % 12];
}

hDC = GetDC(hwnd);
hOldPal = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
AnimatePalette(hPalette, 0, 12, pe);
nIndex = (++nIndex) % 12;
SelectPalette(hDC, hOldPal, FALSE);
ReleaseDC(hwnd, hDC);
}


The code is correct. I verified it using two other sources; cd-rom and
online.
From what I can tell, the Timer messages are getting through
correctly.
It just seems that the Animate function isn't animating the color
palette the way it should.
Does someone understand what might be (or not be) happening here ?

Thanks,
Steve
Alfred Venancio
2010-12-08 21:32:28 UTC
Permalink
Hi Steve,

I believe the code is missing an invalidation to the window. I built the code you posted and indeed there is no animation but the timer is firing. After a closer look I noticed there was nothing causing the client area of the window to redraw. Anyway you should use InvalidateRect(). Replace your WM_TIMER case with the snippet below.

-Alfred

case WM_TIMER:
Animate(hwnd, hPalette);
InvalidateRect(hwnd,NULL,FALSE);
break;


Submitted via EggHeadCafe
Microsoft ASP.NET For Beginners
http://www.eggheadcafe.com/training-topic-area/ASP-NET/7/ASP.aspx
steve
2010-12-08 23:19:48 UTC
Permalink
 Animate(hwnd, hPalette);
 InvalidateRect(hwnd,NULL,FALSE);
break;
Hey Alfred,
This is great !!!

I knew it had something to do with redrawing the client area, but,
since I know nothing about GDI I was completely lost.
Thanks a million.
Wow, it works great.

Steve
Love N
2011-01-16 12:37:32 UTC
Permalink
Hi Steve,

I see you already got the app running, but...
It's actually NOT running the way it's supposed to!

AnimatePalette requires a display that actually has palette,
to work properly. It's purpose is to create color animation,
an old technique to animate WITHOUT REDRAWING !

Todays full color displays don't usually have a palette.
That's the reason you had to redraw the screen
in order to see the animation.

To use palette animation on today's advanced graphics
cards you must change the video mode to palette mode.
256 color modes normally have a palette.
You can change video mode programatically
by using the ChangeDisplaySettings function.

A simplified example for you:
(You ought to check the device capabilites bits,
and verify that mode actually as a palette,
but 256 color modes normally do, so :)

DEVMODE dm;
LONG rc;
BOOL displayOk;

// Get current display settings

memset( &dm,0,sizeof(dm) );
dm.dmSize = sizeof(dm);
displayOk = EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm );

// Let's have fun with palette animation ..

if (displayOk)
{
// Set 256 color palette mode
dm.dmBitsPerPel = 8;
dm.dmFields = DM_BITSPERPEL;
rc = ChangeDisplaySettings( &dm,CDS_FULLSCREEN );
displayOk = (rc == DISP_CHANGE_SUCCESSFUL);
if (!displayOk)
MsgBox( hwnd,MB_WARNING,"PolyCycloid",
"Can't set palette mode. Palette animation wont work"
);
}

Best regards
// Love Nystrom

On Wed, 8 Dec 2010 11:45:49 -0800 (PST), steve
Post by steve
Hello,
I'm completely new to GDI.
I found this simple gdi animation program in a book.
It compiles just fine, however, it does not animate.
It's just static.
It draws colored rectangles, one inside the other and the colors are
supposed to rotate inward,
creating a "tunnel" effect.
// Animate.c
// Palette animation
// Book:Programming Windows 98/NT Unleashed
// link with: gdi32.lib, user32.lib
#include <windows.h>
void Animate(HWND, HPALETTE);
void DrawCircle(HWND, HPALETTE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
struct
{
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[12];
} palPalette =
{
0x300,
12,
{
{0xFF, 0x00, 0x00, PC_RESERVED},
{0xC0, 0x40, 0x00, PC_RESERVED},
{0x80, 0x80, 0x00, PC_RESERVED},
{0x40, 0xC0, 0x00, PC_RESERVED},
{0x00, 0xFF, 0x00, PC_RESERVED},
{0x00, 0xC0, 0x40, PC_RESERVED},
{0x00, 0x80, 0x80, PC_RESERVED},
{0x00, 0x40, 0xC0, PC_RESERVED},
{0x00, 0x00, 0xFF, PC_RESERVED},
{0x40, 0x00, 0xC0, PC_RESERVED},
{0x80, 0x00, 0x80, PC_RESERVED},
{0xC0, 0x00, 0x40, PC_RESERVED}
}
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
d3, int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
if(hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = "HELLO";
if(!RegisterClass(&wndClass))
{
return FALSE;
}
}
hwnd = CreateWindow("HELLO", "HELLO", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
SetTimer(hwnd, 1, 100, NULL);
while(GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
KillTimer(hwnd, 1);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
{
static HPALETTE hPalette;
switch(uMsg)
{
hPalette = CreatePalette((LPLOGPALETTE) &palPalette);
break;
DrawCircle(hwnd, hPalette);
break;
Animate(hwnd, hPalette);
break;
DeleteObject(hPalette);
hPalette = NULL;
PostQuitMessage(0);
break;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
void DrawCircle(HWND hwnd, HPALETTE hPalette)
{
HDC hDC;
PAINTSTRUCT paintStruct;
RECT rect;
HPALETTE hOldPal;
int i;
hDC = BeginPaint(hwnd, &paintStruct);
if(hDC != NULL)
{
hOldPal = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
GetClientRect(hwnd, &rect);
DPtoLP(hDC, (LPPOINT) &rect, 2);
for(i = 0; i < 12; i++)
{
HBRUSH hbr;
HBRUSH hbrOld;
hbr = CreateSolidBrush(PALETTEINDEX(i));
hbrOld = (HBRUSH) SelectObject(hDC, hbr);
Rectangle(hDC, MulDiv(i, rect.right, 24), MulDiv(i,
rect.bottom, 24),
rect.right - MulDiv(i, rect.right, 24),
rect.bottom - MulDiv(i, rect.bottom, 24));
SelectObject(hDC, hbrOld);
DeleteObject(hbr);
}
SelectPalette(hDC, hOldPal, FALSE);
EndPaint(hwnd, &paintStruct);
}
}
void Animate(HWND hwnd, HPALETTE hPalette)
{
HDC hDC;
PALETTEENTRY pe[12];
HPALETTE hOldPal;
static int nIndex;
int i;
for(i = 0; i < 12; i++)
{
pe[i] = palPalette.palPalEntry[(i + nIndex) % 12];
}
hDC = GetDC(hwnd);
hOldPal = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
AnimatePalette(hPalette, 0, 12, pe);
nIndex = (++nIndex) % 12;
SelectPalette(hDC, hOldPal, FALSE);
ReleaseDC(hwnd, hDC);
}
The code is correct. I verified it using two other sources; cd-rom and
online.
From what I can tell, the Timer messages are getting through
correctly.
It just seems that the Animate function isn't animating the color
palette the way it should.
Does someone understand what might be (or not be) happening here ?
Thanks,
Steve
steve
2011-01-17 20:35:19 UTC
Permalink
Thanks for the info Love N.
I'll give it a try.

Steve

Continue reading on narkive:
Loading...