1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
5 * Copyright 1998, 1999 Eric Kohl
9 * I will only improve this control once in a while.
10 * Eric <ekohl@abo.rhein-zeitung.de>
13 * - check for the 'rec ' list in some AVI files
14 * - implement some missing flags (ACS_TRANSPARENT and ACS_CENTER)
15 * - protection between service thread and wndproc messages handling
16 * concurrent access to infoPtr
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(animate
)
30 #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
32 static void ANIMATE_Notify(ANIMATE_INFO
* infoPtr
, UINT notif
)
34 SendMessageA(GetParent(infoPtr
->hWnd
), WM_COMMAND
,
35 MAKEWPARAM(GetDlgCtrlID(infoPtr
->hWnd
), notif
),
36 (LPARAM
)infoPtr
->hWnd
);
39 static BOOL
ANIMATE_LoadResA(ANIMATE_INFO
*infoPtr
, HINSTANCE hInst
, LPSTR lpName
)
45 hrsrc
= FindResourceA(hInst
, lpName
, "AVI");
49 infoPtr
->hRes
= LoadResource(hInst
, hrsrc
);
53 lpAvi
= LockResource(infoPtr
->hRes
);
57 memset(&mminfo
, 0, sizeof(mminfo
));
58 mminfo
.fccIOProc
= FOURCC_MEM
;
59 mminfo
.pchBuffer
= (LPSTR
)lpAvi
;
60 mminfo
.cchBuffer
= SizeofResource(hInst
, hrsrc
);
61 infoPtr
->hMMio
= mmioOpenA(NULL
, &mminfo
, MMIO_READ
);
63 if (!infoPtr
->hMMio
) {
64 GlobalFree((HGLOBAL
)lpAvi
);
72 static BOOL
ANIMATE_LoadFileA(ANIMATE_INFO
*infoPtr
, LPSTR lpName
)
74 infoPtr
->hMMio
= mmioOpenA((LPSTR
)lpName
, NULL
,
75 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
84 static LRESULT
ANIMATE_DoStop(ANIMATE_INFO
*infoPtr
)
86 EnterCriticalSection(&infoPtr
->cs
);
88 /* should stop playing */
89 if (infoPtr
->hService
) {
90 SERVICE_Delete(infoPtr
->hService
);
91 infoPtr
->hService
= 0;
93 if (infoPtr
->uTimer
) {
94 KillTimer(infoPtr
->hWnd
, infoPtr
->uTimer
);
98 LeaveCriticalSection(&infoPtr
->cs
);
100 ANIMATE_Notify(infoPtr
, ACN_STOP
);
106 static void ANIMATE_Free(ANIMATE_INFO
*infoPtr
)
108 if (infoPtr
->hMMio
) {
109 ANIMATE_DoStop(infoPtr
);
110 mmioClose(infoPtr
->hMMio
, 0);
112 FreeResource(infoPtr
->hRes
);
115 if (infoPtr
->lpIndex
) {
116 HeapFree(GetProcessHeap(), 0, infoPtr
->lpIndex
);
117 infoPtr
->lpIndex
= NULL
;
120 (infoPtr
->fnICClose
)(infoPtr
->hic
);
123 if (infoPtr
->inbih
) {
124 HeapFree(GetProcessHeap(), 0, infoPtr
->inbih
);
125 infoPtr
->inbih
= NULL
;
127 if (infoPtr
->outbih
) {
128 HeapFree(GetProcessHeap(), 0, infoPtr
->outbih
);
129 infoPtr
->outbih
= NULL
;
131 HeapFree(GetProcessHeap(), 0, infoPtr
->indata
);
132 HeapFree(GetProcessHeap(), 0, infoPtr
->outdata
);
133 infoPtr
->indata
= infoPtr
->outdata
= NULL
;
136 memset(&infoPtr
->mah
, 0, sizeof(infoPtr
->mah
));
137 memset(&infoPtr
->ash
, 0, sizeof(infoPtr
->ash
));
138 infoPtr
->nFromFrame
= infoPtr
->nToFrame
= infoPtr
->nLoop
= infoPtr
->currFrame
= 0;
143 static LRESULT
ANIMATE_PaintFrame(ANIMATE_INFO
* infoPtr
, HDC hDC
)
145 if (!hDC
|| !infoPtr
->inbih
)
148 StretchDIBits(hDC
, 0, 0, infoPtr
->outbih
->biWidth
, infoPtr
->outbih
->biHeight
,
149 0, 0, infoPtr
->outbih
->biWidth
, infoPtr
->outbih
->biHeight
,
150 infoPtr
->outdata
, (LPBITMAPINFO
)infoPtr
->outbih
, DIB_RGB_COLORS
,
153 StretchDIBits(hDC
, 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,
154 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,
155 infoPtr
->indata
, (LPBITMAPINFO
)infoPtr
->inbih
, DIB_RGB_COLORS
,
161 static LRESULT
ANIMATE_DrawFrame(ANIMATE_INFO
* infoPtr
)
165 TRACE("Drawing frame %d (loop %d)\n", infoPtr
->currFrame
, infoPtr
->nLoop
);
167 EnterCriticalSection(&infoPtr
->cs
);
169 mmioSeek(infoPtr
->hMMio
, infoPtr
->lpIndex
[infoPtr
->currFrame
], SEEK_SET
);
170 mmioRead(infoPtr
->hMMio
, infoPtr
->indata
, infoPtr
->ash
.dwSuggestedBufferSize
);
173 (infoPtr
->fnICDecompress
)(infoPtr
->hic
, 0, infoPtr
->inbih
, infoPtr
->indata
,
174 infoPtr
->outbih
, infoPtr
->outdata
) != ICERR_OK
) {
175 LeaveCriticalSection(&infoPtr
->cs
);
176 WARN("Decompression error\n");
180 if ((hDC
= GetDC(infoPtr
->hWnd
)) != 0) {
181 ANIMATE_PaintFrame(infoPtr
, hDC
);
182 ReleaseDC(infoPtr
->hWnd
, hDC
);
185 if (infoPtr
->currFrame
++ >= infoPtr
->nToFrame
) {
186 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
187 if (infoPtr
->nLoop
!= -1) {
188 if (--infoPtr
->nLoop
== 0) {
189 ANIMATE_DoStop(infoPtr
);
193 LeaveCriticalSection(&infoPtr
->cs
);
198 static void CALLBACK
ANIMATE_ServiceCallback(ULONG_PTR ptr_
)
200 ANIMATE_INFO
* infoPtr
= (ANIMATE_INFO
*)ptr_
;
202 EnterCriticalSection(&infoPtr
->cs
);
203 ANIMATE_DrawFrame(infoPtr
);
204 LeaveCriticalSection(&infoPtr
->cs
);
207 static LRESULT
ANIMATE_Play(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
209 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
215 if (infoPtr
->hService
|| infoPtr
->uTimer
) {
216 FIXME("Already playing ? what should I do ??\n");
217 ANIMATE_DoStop(infoPtr
);
220 infoPtr
->nFromFrame
= (INT
)LOWORD(lParam
);
221 infoPtr
->nToFrame
= (INT
)HIWORD(lParam
);
222 infoPtr
->nLoop
= (INT
)wParam
;
224 if (infoPtr
->nToFrame
== 0xFFFF)
225 infoPtr
->nToFrame
= infoPtr
->mah
.dwTotalFrames
- 1;
227 TRACE("(repeat=%d from=%d to=%d);\n",
228 infoPtr
->nLoop
, infoPtr
->nFromFrame
, infoPtr
->nToFrame
);
230 if (infoPtr
->nFromFrame
>= infoPtr
->nToFrame
||
231 infoPtr
->nToFrame
>= infoPtr
->mah
.dwTotalFrames
)
234 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
236 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TIMER
) {
237 TRACE("Using a timer\n");
238 /* create a timer to display AVI */
239 infoPtr
->uTimer
= SetTimer(hWnd
, 1, infoPtr
->mah
.dwMicroSecPerFrame
/ 1000, NULL
);
241 TRACE("Using the service thread\n");
243 infoPtr
->hService
= SERVICE_AddTimer(infoPtr
->mah
.dwMicroSecPerFrame
,
244 ANIMATE_ServiceCallback
, (DWORD
)infoPtr
);
247 ANIMATE_Notify(infoPtr
, ACN_START
);
253 static BOOL
ANIMATE_GetAviInfo(ANIMATE_INFO
*infoPtr
)
262 if (mmioDescend(infoPtr
->hMMio
, &ckMainRIFF
, NULL
, 0) != 0) {
263 WARN("Can't find 'RIFF' chunk\n");
267 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
268 (ckMainRIFF
.fccType
!= mmioFOURCC('A', 'V', 'I', ' '))) {
269 WARN("Can't find 'AVI ' chunk\n");
273 mmckHead
.fccType
= mmioFOURCC('h', 'd', 'r', 'l');
274 if (mmioDescend(infoPtr
->hMMio
, &mmckHead
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
275 WARN("Can't find 'hdrl' list\n");
279 mmckInfo
.ckid
= mmioFOURCC('a', 'v', 'i', 'h');
280 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckHead
, MMIO_FINDCHUNK
) != 0) {
281 WARN("Can't find 'avih' chunk\n");
285 mmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->mah
, sizeof(infoPtr
->mah
));
286 TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr
->mah
.dwMicroSecPerFrame
);
287 TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr
->mah
.dwMaxBytesPerSec
);
288 TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr
->mah
.dwPaddingGranularity
);
289 TRACE("mah.dwFlags=%ld\n", infoPtr
->mah
.dwFlags
);
290 TRACE("mah.dwTotalFrames=%ld\n", infoPtr
->mah
.dwTotalFrames
);
291 TRACE("mah.dwInitialFrames=%ld\n", infoPtr
->mah
.dwInitialFrames
);
292 TRACE("mah.dwStreams=%ld\n", infoPtr
->mah
.dwStreams
);
293 TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr
->mah
.dwSuggestedBufferSize
);
294 TRACE("mah.dwWidth=%ld\n", infoPtr
->mah
.dwWidth
);
295 TRACE("mah.dwHeight=%ld\n", infoPtr
->mah
.dwHeight
);
296 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
298 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
299 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) != 0) {
300 WARN("Can't find 'strl' list\n");
304 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'h');
305 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
306 WARN("Can't find 'strh' chunk\n");
310 mmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->ash
, sizeof(infoPtr
->ash
));
311 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccType
)),
312 HIBYTE(LOWORD(infoPtr
->ash
.fccType
)),
313 LOBYTE(HIWORD(infoPtr
->ash
.fccType
)),
314 HIBYTE(HIWORD(infoPtr
->ash
.fccType
)));
315 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
316 HIBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
317 LOBYTE(HIWORD(infoPtr
->ash
.fccHandler
)),
318 HIBYTE(HIWORD(infoPtr
->ash
.fccHandler
)));
319 TRACE("ash.dwFlags=%ld\n", infoPtr
->ash
.dwFlags
);
320 TRACE("ash.wPriority=%d\n", infoPtr
->ash
.wPriority
);
321 TRACE("ash.wLanguage=%d\n", infoPtr
->ash
.wLanguage
);
322 TRACE("ash.dwInitialFrames=%ld\n", infoPtr
->ash
.dwInitialFrames
);
323 TRACE("ash.dwScale=%ld\n", infoPtr
->ash
.dwScale
);
324 TRACE("ash.dwRate=%ld\n", infoPtr
->ash
.dwRate
);
325 TRACE("ash.dwStart=%ld\n", infoPtr
->ash
.dwStart
);
326 TRACE("ash.dwLength=%ld\n", infoPtr
->ash
.dwLength
);
327 TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr
->ash
.dwSuggestedBufferSize
);
328 TRACE("ash.dwQuality=%ld\n", infoPtr
->ash
.dwQuality
);
329 TRACE("ash.dwSampleSize=%ld\n", infoPtr
->ash
.dwSampleSize
);
330 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr
->ash
.rcFrame
.top
, infoPtr
->ash
.rcFrame
.left
,
331 infoPtr
->ash
.rcFrame
.bottom
, infoPtr
->ash
.rcFrame
.right
);
332 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
334 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'f');
335 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
336 WARN("Can't find 'strh' chunk\n");
340 infoPtr
->inbih
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
341 if (!infoPtr
->inbih
) {
342 WARN("Can't alloc input BIH\n");
346 mmioRead(infoPtr
->hMMio
, (LPSTR
)infoPtr
->inbih
, mmckInfo
.cksize
);
347 TRACE("bih.biSize=%ld\n", infoPtr
->inbih
->biSize
);
348 TRACE("bih.biWidth=%ld\n", infoPtr
->inbih
->biWidth
);
349 TRACE("bih.biHeight=%ld\n", infoPtr
->inbih
->biHeight
);
350 TRACE("bih.biPlanes=%d\n", infoPtr
->inbih
->biPlanes
);
351 TRACE("bih.biBitCount=%d\n", infoPtr
->inbih
->biBitCount
);
352 TRACE("bih.biCompression=%ld\n", infoPtr
->inbih
->biCompression
);
353 TRACE("bih.biSizeImage=%ld\n", infoPtr
->inbih
->biSizeImage
);
354 TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr
->inbih
->biXPelsPerMeter
);
355 TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr
->inbih
->biYPelsPerMeter
);
356 TRACE("bih.biClrUsed=%ld\n", infoPtr
->inbih
->biClrUsed
);
357 TRACE("bih.biClrImportant=%ld\n", infoPtr
->inbih
->biClrImportant
);
358 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
360 mmioAscend(infoPtr
->hMMio
, &mmckList
, 0);
363 /* an AVI has 0 or 1 video stream, and to be animated should not contain
364 * an audio stream, so only one strl is allowed
366 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
367 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) == 0) {
368 WARN("There should be a single 'strl' list\n");
373 mmioAscend(infoPtr
->hMMio
, &mmckHead
, 0);
375 /* no need to read optional JUNK chunk */
377 mmckList
.fccType
= mmioFOURCC('m', 'o', 'v', 'i');
378 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
379 WARN("Can't find 'movi' list\n");
383 /* FIXME: should handle the 'rec ' LIST when present */
385 infoPtr
->lpIndex
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
386 infoPtr
->mah
.dwTotalFrames
* sizeof(DWORD
));
387 if (!infoPtr
->lpIndex
) {
388 WARN("Can't alloc index array\n");
392 numFrame
= insize
= 0;
393 while (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, 0) == 0 &&
394 numFrame
< infoPtr
->mah
.dwTotalFrames
) {
395 infoPtr
->lpIndex
[numFrame
] = mmckInfo
.dwDataOffset
;
396 if (insize
< mmckInfo
.cksize
)
397 insize
= mmckInfo
.cksize
;
399 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
401 if (numFrame
!= infoPtr
->mah
.dwTotalFrames
) {
402 WARN("Found %ld frames (/%ld)\n", numFrame
, infoPtr
->mah
.dwTotalFrames
);
405 if (insize
> infoPtr
->ash
.dwSuggestedBufferSize
) {
406 WARN("insize=%ld suggestedSize=%ld\n", insize
, infoPtr
->ash
.dwSuggestedBufferSize
);
407 infoPtr
->ash
.dwSuggestedBufferSize
= insize
;
410 infoPtr
->indata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->ash
.dwSuggestedBufferSize
);
411 if (!infoPtr
->indata
) {
412 WARN("Can't alloc input buffer\n");
420 static BOOL
ANIMATE_GetAviCodec(ANIMATE_INFO
*infoPtr
)
424 /* check uncompressed AVI */
425 if (infoPtr
->ash
.fccHandler
== mmioFOURCC('D', 'I', 'B', ' ')) {
430 /* try to get a decompressor for that type */
431 infoPtr
->hic
= (infoPtr
->fnICOpen
)(ICTYPE_VIDEO
,
432 infoPtr
->ash
.fccHandler
,
435 WARN("Can't load codec for the file\n");
439 outSize
= (infoPtr
->fnICSendMessage
)(infoPtr
->hic
,
440 ICM_DECOMPRESS_GET_FORMAT
,
441 (DWORD
)infoPtr
->inbih
, 0L);
442 infoPtr
->outbih
= HeapAlloc(GetProcessHeap(), 0, outSize
);
443 if (!infoPtr
->outbih
) {
444 WARN("Can't alloc output BIH\n");
448 if ((infoPtr
->fnICSendMessage
)(infoPtr
->hic
, ICM_DECOMPRESS_GET_FORMAT
,
449 (DWORD
)infoPtr
->inbih
,
450 (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
451 WARN("Can't get output BIH\n");
455 infoPtr
->outdata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->outbih
->biSizeImage
);
456 if (!infoPtr
->outdata
) {
457 WARN("Can't alloc output buffer\n");
461 if ((infoPtr
->fnICSendMessage
)(infoPtr
->hic
, ICM_DECOMPRESS_BEGIN
,
462 (DWORD
)infoPtr
->inbih
,
463 (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
464 WARN("Can't begin decompression\n");
471 static LRESULT
ANIMATE_OpenA(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
473 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
474 HINSTANCE hInstance
= (HINSTANCE
)wParam
;
476 ANIMATE_Free(infoPtr
);
479 TRACE("Closing avi!\n");
484 hInstance
= GetWindowLongA(hWnd
, GWL_HINSTANCE
);
486 if (HIWORD(lParam
)) {
487 TRACE("(\"%s\");\n", (LPSTR
)lParam
);
489 if (!ANIMATE_LoadResA(infoPtr
, hInstance
, (LPSTR
)lParam
)) {
490 TRACE("No AVI resource found!\n");
491 if (!ANIMATE_LoadFileA(infoPtr
, (LPSTR
)lParam
)) {
492 WARN("No AVI file found!\n");
497 TRACE("(%u);\n", (WORD
)LOWORD(lParam
));
499 if (!ANIMATE_LoadResA(infoPtr
, hInstance
,
500 MAKEINTRESOURCEA((INT
)lParam
))) {
501 WARN("No AVI resource found!\n");
506 if (!ANIMATE_GetAviInfo(infoPtr
)) {
507 WARN("Can't get AVI information\n");
508 ANIMATE_Free(infoPtr
);
512 if (!ANIMATE_GetAviCodec(infoPtr
)) {
513 WARN("Can't get AVI Codec\n");
514 ANIMATE_Free(infoPtr
);
518 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
519 FIXME("ACS_CENTER: NIY\n");
521 /* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/
522 SetWindowPos(hWnd
, 0, 0, 0, infoPtr
->mah
.dwWidth
, infoPtr
->mah
.dwHeight
,
523 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
526 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
) {
527 FIXME("ACS_TRANSPARENT: NIY\n");
530 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_AUTOPLAY
) {
531 return ANIMATE_Play(hWnd
, -1, (LPARAM
)MAKELONG(0, infoPtr
->mah
.dwTotalFrames
-1));
538 /* << ANIMATE_Open32W >> */
540 static LRESULT
ANIMATE_Stop(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
542 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
548 ANIMATE_DoStop(infoPtr
);
553 static LRESULT
ANIMATE_Create(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
555 ANIMATE_INFO
* infoPtr
;
556 HMODULE hModule
= LoadLibraryA("msvfw32.dll");
561 /* allocate memory for info structure */
562 infoPtr
= (ANIMATE_INFO
*)COMCTL32_Alloc(sizeof(ANIMATE_INFO
));
564 ERR("could not allocate info memory!\n");
568 /* Temporary hack until we get dllglue up and running */
569 infoPtr
->fnICOpen
= (void*)GetProcAddress(hModule
, "ICOpen");
570 infoPtr
->fnICClose
= (void*)GetProcAddress(hModule
, "ICClose");
571 infoPtr
->fnICSendMessage
= (void*)GetProcAddress(hModule
, "ICSendMessage");
572 infoPtr
->fnICDecompress
= (void*)GetProcAddress(hModule
, "ICDecompress");
574 TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd
, GWL_STYLE
), (DWORD
)GetParent(hWnd
));
576 /* store crossref hWnd <-> info structure */
577 SetWindowLongA(hWnd
, 0, (DWORD
)infoPtr
);
578 infoPtr
->hWnd
= hWnd
;
580 InitializeCriticalSection(&infoPtr
->cs
);
586 static LRESULT
ANIMATE_Destroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
588 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
592 ANIMATE_Free(infoPtr
);
594 /* free animate info data */
595 COMCTL32_Free(infoPtr
);
601 static LRESULT
ANIMATE_EraseBackground(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
605 GetClientRect(hWnd
, &rect
);
607 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
609 FillRect((HDC
)wParam
, &rect
, hBrush
);
610 DeleteObject(hBrush
);
612 FillRect((HDC
)wParam
, &rect
, GetSysColorBrush(COLOR_WINDOW
));
617 static LRESULT WINAPI
ANIMATE_Size(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
619 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
621 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
623 if (infoPtr
->hMMio
) {
624 /* centers the animation in the control, invalidates the control
627 InvalidateRect(hWnd
, NULL
, TRUE
);
632 static LRESULT WINAPI
ANIMATE_WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
637 return ANIMATE_OpenA(hWnd
, wParam
, lParam
);
639 /* case ACM_OPEN32W: FIXME!! */
640 /* return ANIMATE_Open32W(hWnd, wParam, lParam); */
643 return ANIMATE_Play(hWnd
, wParam
, lParam
);
646 return ANIMATE_Stop(hWnd
, wParam
, lParam
);
649 ANIMATE_Create(hWnd
, wParam
, lParam
);
650 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
653 return HTTRANSPARENT
;
656 ANIMATE_Destroy(hWnd
, wParam
, lParam
);
657 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
660 ANIMATE_EraseBackground(hWnd
, wParam
, lParam
);
663 /* case WM_STYLECHANGED: FIXME shall we do something ?? */
666 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd
));
669 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd
));
674 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd
), (HDC
)wParam
);
677 HDC hDC
= BeginPaint(hWnd
, &ps
);
678 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd
), hDC
);
684 ANIMATE_Size(hWnd
, wParam
, lParam
);
685 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
689 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
, lParam
);
691 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
697 void ANIMATE_Register(void)
701 if (GlobalFindAtomA(ANIMATE_CLASSA
)) return;
703 ZeroMemory(&wndClass
, sizeof(WNDCLASSA
));
704 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
705 wndClass
.lpfnWndProc
= (WNDPROC
)ANIMATE_WindowProc
;
706 wndClass
.cbClsExtra
= 0;
707 wndClass
.cbWndExtra
= sizeof(ANIMATE_INFO
*);
708 wndClass
.hCursor
= LoadCursorA(0, IDC_ARROWA
);
709 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
710 wndClass
.lpszClassName
= ANIMATE_CLASSA
;
712 RegisterClassA(&wndClass
);
716 void ANIMATE_Unregister(void)
718 if (GlobalFindAtomA(ANIMATE_CLASSA
))
719 UnregisterClassA(ANIMATE_CLASSA
, (HINSTANCE
)NULL
);