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
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(animate
);
29 #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
33 static void ANIMATE_Notify(ANIMATE_INFO
* infoPtr
, UINT notif
)
35 SendMessageA(GetParent(infoPtr
->hWnd
), WM_COMMAND
,
36 MAKEWPARAM(GetDlgCtrlID(infoPtr
->hWnd
), notif
),
37 (LPARAM
)infoPtr
->hWnd
);
40 static BOOL
ANIMATE_LoadResA(ANIMATE_INFO
*infoPtr
, HINSTANCE hInst
, LPSTR lpName
)
46 hrsrc
= FindResourceA(hInst
, lpName
, "AVI");
50 infoPtr
->hRes
= LoadResource(hInst
, hrsrc
);
54 lpAvi
= LockResource(infoPtr
->hRes
);
58 memset(&mminfo
, 0, sizeof(mminfo
));
59 mminfo
.fccIOProc
= FOURCC_MEM
;
60 mminfo
.pchBuffer
= (LPSTR
)lpAvi
;
61 mminfo
.cchBuffer
= SizeofResource(hInst
, hrsrc
);
62 infoPtr
->hMMio
= infoPtr
->fnmmioOpenA(NULL
, &mminfo
, MMIO_READ
);
64 if (!infoPtr
->hMMio
) {
65 GlobalFree((HGLOBAL
)lpAvi
);
73 static BOOL
ANIMATE_LoadFileA(ANIMATE_INFO
*infoPtr
, LPSTR lpName
)
75 infoPtr
->hMMio
= infoPtr
->fnmmioOpenA((LPSTR
)lpName
, NULL
,
76 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
85 static LRESULT
ANIMATE_DoStop(ANIMATE_INFO
*infoPtr
)
87 EnterCriticalSection(&infoPtr
->cs
);
89 /* should stop playing */
90 if (infoPtr
->hService
) {
91 SERVICE_Delete(infoPtr
->hService
);
92 infoPtr
->hService
= 0;
94 if (infoPtr
->uTimer
) {
95 KillTimer(infoPtr
->hWnd
, infoPtr
->uTimer
);
99 LeaveCriticalSection(&infoPtr
->cs
);
101 ANIMATE_Notify(infoPtr
, ACN_STOP
);
107 static void ANIMATE_Free(ANIMATE_INFO
*infoPtr
)
109 if (infoPtr
->hMMio
) {
110 ANIMATE_DoStop(infoPtr
);
111 infoPtr
->fnmmioClose(infoPtr
->hMMio
, 0);
113 FreeResource(infoPtr
->hRes
);
116 if (infoPtr
->lpIndex
) {
117 HeapFree(GetProcessHeap(), 0, infoPtr
->lpIndex
);
118 infoPtr
->lpIndex
= NULL
;
121 (infoPtr
->fnICClose
)(infoPtr
->hic
);
124 if (infoPtr
->inbih
) {
125 HeapFree(GetProcessHeap(), 0, infoPtr
->inbih
);
126 infoPtr
->inbih
= NULL
;
128 if (infoPtr
->outbih
) {
129 HeapFree(GetProcessHeap(), 0, infoPtr
->outbih
);
130 infoPtr
->outbih
= NULL
;
132 HeapFree(GetProcessHeap(), 0, infoPtr
->indata
);
133 HeapFree(GetProcessHeap(), 0, infoPtr
->outdata
);
134 infoPtr
->indata
= infoPtr
->outdata
= NULL
;
137 memset(&infoPtr
->mah
, 0, sizeof(infoPtr
->mah
));
138 memset(&infoPtr
->ash
, 0, sizeof(infoPtr
->ash
));
139 infoPtr
->nFromFrame
= infoPtr
->nToFrame
= infoPtr
->nLoop
= infoPtr
->currFrame
= 0;
144 static LRESULT
ANIMATE_PaintFrame(ANIMATE_INFO
* infoPtr
, HDC hDC
)
146 if (!hDC
|| !infoPtr
->inbih
)
149 StretchDIBits(hDC
, 0, 0, infoPtr
->outbih
->biWidth
, infoPtr
->outbih
->biHeight
,
150 0, 0, infoPtr
->outbih
->biWidth
, infoPtr
->outbih
->biHeight
,
151 infoPtr
->outdata
, (LPBITMAPINFO
)infoPtr
->outbih
, DIB_RGB_COLORS
,
154 StretchDIBits(hDC
, 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,
155 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,
156 infoPtr
->indata
, (LPBITMAPINFO
)infoPtr
->inbih
, DIB_RGB_COLORS
,
162 static LRESULT
ANIMATE_DrawFrame(ANIMATE_INFO
* infoPtr
)
166 TRACE("Drawing frame %d (loop %d)\n", infoPtr
->currFrame
, infoPtr
->nLoop
);
168 EnterCriticalSection(&infoPtr
->cs
);
170 infoPtr
->fnmmioSeek(infoPtr
->hMMio
, infoPtr
->lpIndex
[infoPtr
->currFrame
], SEEK_SET
);
171 infoPtr
->fnmmioRead(infoPtr
->hMMio
, infoPtr
->indata
, infoPtr
->ash
.dwSuggestedBufferSize
);
174 (infoPtr
->fnICDecompress
)(infoPtr
->hic
, 0, infoPtr
->inbih
, infoPtr
->indata
,
175 infoPtr
->outbih
, infoPtr
->outdata
) != ICERR_OK
) {
176 LeaveCriticalSection(&infoPtr
->cs
);
177 WARN("Decompression error\n");
181 if ((hDC
= GetDC(infoPtr
->hWnd
)) != 0) {
182 ANIMATE_PaintFrame(infoPtr
, hDC
);
183 ReleaseDC(infoPtr
->hWnd
, hDC
);
186 if (infoPtr
->currFrame
++ >= infoPtr
->nToFrame
) {
187 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
188 if (infoPtr
->nLoop
!= -1) {
189 if (--infoPtr
->nLoop
== 0) {
190 ANIMATE_DoStop(infoPtr
);
194 LeaveCriticalSection(&infoPtr
->cs
);
199 static void CALLBACK
ANIMATE_ServiceCallback(ULONG_PTR ptr_
)
201 ANIMATE_INFO
* infoPtr
= (ANIMATE_INFO
*)ptr_
;
203 EnterCriticalSection(&infoPtr
->cs
);
204 ANIMATE_DrawFrame(infoPtr
);
205 LeaveCriticalSection(&infoPtr
->cs
);
208 static LRESULT
ANIMATE_Play(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
210 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
216 if (infoPtr
->hService
|| infoPtr
->uTimer
) {
217 FIXME("Already playing ? what should I do ??\n");
218 ANIMATE_DoStop(infoPtr
);
221 infoPtr
->nFromFrame
= (INT
)LOWORD(lParam
);
222 infoPtr
->nToFrame
= (INT
)HIWORD(lParam
);
223 infoPtr
->nLoop
= (INT
)wParam
;
225 if (infoPtr
->nToFrame
== 0xFFFF)
226 infoPtr
->nToFrame
= infoPtr
->mah
.dwTotalFrames
- 1;
228 TRACE("(repeat=%d from=%d to=%d);\n",
229 infoPtr
->nLoop
, infoPtr
->nFromFrame
, infoPtr
->nToFrame
);
231 if (infoPtr
->nFromFrame
>= infoPtr
->nToFrame
||
232 infoPtr
->nToFrame
>= infoPtr
->mah
.dwTotalFrames
)
235 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
237 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TIMER
) {
238 TRACE("Using a timer\n");
239 /* create a timer to display AVI */
240 infoPtr
->uTimer
= SetTimer(hWnd
, 1, infoPtr
->mah
.dwMicroSecPerFrame
/ 1000, NULL
);
242 TRACE("Using the service thread\n");
244 infoPtr
->hService
= SERVICE_AddTimer(infoPtr
->mah
.dwMicroSecPerFrame
/ 1000,
245 ANIMATE_ServiceCallback
, (DWORD
)infoPtr
);
248 ANIMATE_Notify(infoPtr
, ACN_START
);
254 static BOOL
ANIMATE_GetAviInfo(ANIMATE_INFO
*infoPtr
)
263 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &ckMainRIFF
, NULL
, 0) != 0) {
264 WARN("Can't find 'RIFF' chunk\n");
268 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
269 (ckMainRIFF
.fccType
!= mmioFOURCC('A', 'V', 'I', ' '))) {
270 WARN("Can't find 'AVI ' chunk\n");
274 mmckHead
.fccType
= mmioFOURCC('h', 'd', 'r', 'l');
275 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckHead
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
276 WARN("Can't find 'hdrl' list\n");
280 mmckInfo
.ckid
= mmioFOURCC('a', 'v', 'i', 'h');
281 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckHead
, MMIO_FINDCHUNK
) != 0) {
282 WARN("Can't find 'avih' chunk\n");
286 infoPtr
->fnmmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->mah
, sizeof(infoPtr
->mah
));
287 TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr
->mah
.dwMicroSecPerFrame
);
288 TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr
->mah
.dwMaxBytesPerSec
);
289 TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr
->mah
.dwPaddingGranularity
);
290 TRACE("mah.dwFlags=%ld\n", infoPtr
->mah
.dwFlags
);
291 TRACE("mah.dwTotalFrames=%ld\n", infoPtr
->mah
.dwTotalFrames
);
292 TRACE("mah.dwInitialFrames=%ld\n", infoPtr
->mah
.dwInitialFrames
);
293 TRACE("mah.dwStreams=%ld\n", infoPtr
->mah
.dwStreams
);
294 TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr
->mah
.dwSuggestedBufferSize
);
295 TRACE("mah.dwWidth=%ld\n", infoPtr
->mah
.dwWidth
);
296 TRACE("mah.dwHeight=%ld\n", infoPtr
->mah
.dwHeight
);
297 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
299 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
300 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) != 0) {
301 WARN("Can't find 'strl' list\n");
305 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'h');
306 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
307 WARN("Can't find 'strh' chunk\n");
311 infoPtr
->fnmmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->ash
, sizeof(infoPtr
->ash
));
312 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccType
)),
313 HIBYTE(LOWORD(infoPtr
->ash
.fccType
)),
314 LOBYTE(HIWORD(infoPtr
->ash
.fccType
)),
315 HIBYTE(HIWORD(infoPtr
->ash
.fccType
)));
316 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
317 HIBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
318 LOBYTE(HIWORD(infoPtr
->ash
.fccHandler
)),
319 HIBYTE(HIWORD(infoPtr
->ash
.fccHandler
)));
320 TRACE("ash.dwFlags=%ld\n", infoPtr
->ash
.dwFlags
);
321 TRACE("ash.wPriority=%d\n", infoPtr
->ash
.wPriority
);
322 TRACE("ash.wLanguage=%d\n", infoPtr
->ash
.wLanguage
);
323 TRACE("ash.dwInitialFrames=%ld\n", infoPtr
->ash
.dwInitialFrames
);
324 TRACE("ash.dwScale=%ld\n", infoPtr
->ash
.dwScale
);
325 TRACE("ash.dwRate=%ld\n", infoPtr
->ash
.dwRate
);
326 TRACE("ash.dwStart=%ld\n", infoPtr
->ash
.dwStart
);
327 TRACE("ash.dwLength=%ld\n", infoPtr
->ash
.dwLength
);
328 TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr
->ash
.dwSuggestedBufferSize
);
329 TRACE("ash.dwQuality=%ld\n", infoPtr
->ash
.dwQuality
);
330 TRACE("ash.dwSampleSize=%ld\n", infoPtr
->ash
.dwSampleSize
);
331 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr
->ash
.rcFrame
.top
, infoPtr
->ash
.rcFrame
.left
,
332 infoPtr
->ash
.rcFrame
.bottom
, infoPtr
->ash
.rcFrame
.right
);
333 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
335 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'f');
336 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
337 WARN("Can't find 'strh' chunk\n");
341 infoPtr
->inbih
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
342 if (!infoPtr
->inbih
) {
343 WARN("Can't alloc input BIH\n");
347 infoPtr
->fnmmioRead(infoPtr
->hMMio
, (LPSTR
)infoPtr
->inbih
, mmckInfo
.cksize
);
348 TRACE("bih.biSize=%ld\n", infoPtr
->inbih
->biSize
);
349 TRACE("bih.biWidth=%ld\n", infoPtr
->inbih
->biWidth
);
350 TRACE("bih.biHeight=%ld\n", infoPtr
->inbih
->biHeight
);
351 TRACE("bih.biPlanes=%d\n", infoPtr
->inbih
->biPlanes
);
352 TRACE("bih.biBitCount=%d\n", infoPtr
->inbih
->biBitCount
);
353 TRACE("bih.biCompression=%ld\n", infoPtr
->inbih
->biCompression
);
354 TRACE("bih.biSizeImage=%ld\n", infoPtr
->inbih
->biSizeImage
);
355 TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr
->inbih
->biXPelsPerMeter
);
356 TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr
->inbih
->biYPelsPerMeter
);
357 TRACE("bih.biClrUsed=%ld\n", infoPtr
->inbih
->biClrUsed
);
358 TRACE("bih.biClrImportant=%ld\n", infoPtr
->inbih
->biClrImportant
);
359 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
361 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckList
, 0);
364 /* an AVI has 0 or 1 video stream, and to be animated should not contain
365 * an audio stream, so only one strl is allowed
367 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
368 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) == 0) {
369 WARN("There should be a single 'strl' list\n");
374 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckHead
, 0);
376 /* no need to read optional JUNK chunk */
378 mmckList
.fccType
= mmioFOURCC('m', 'o', 'v', 'i');
379 if (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckList
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
380 WARN("Can't find 'movi' list\n");
384 /* FIXME: should handle the 'rec ' LIST when present */
386 infoPtr
->lpIndex
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
387 infoPtr
->mah
.dwTotalFrames
* sizeof(DWORD
));
388 if (!infoPtr
->lpIndex
) {
389 WARN("Can't alloc index array\n");
393 numFrame
= insize
= 0;
394 while (infoPtr
->fnmmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, 0) == 0 &&
395 numFrame
< infoPtr
->mah
.dwTotalFrames
) {
396 infoPtr
->lpIndex
[numFrame
] = mmckInfo
.dwDataOffset
;
397 if (insize
< mmckInfo
.cksize
)
398 insize
= mmckInfo
.cksize
;
400 infoPtr
->fnmmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
402 if (numFrame
!= infoPtr
->mah
.dwTotalFrames
) {
403 WARN("Found %ld frames (/%ld)\n", numFrame
, infoPtr
->mah
.dwTotalFrames
);
406 if (insize
> infoPtr
->ash
.dwSuggestedBufferSize
) {
407 WARN("insize=%ld suggestedSize=%ld\n", insize
, infoPtr
->ash
.dwSuggestedBufferSize
);
408 infoPtr
->ash
.dwSuggestedBufferSize
= insize
;
411 infoPtr
->indata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->ash
.dwSuggestedBufferSize
);
412 if (!infoPtr
->indata
) {
413 WARN("Can't alloc input buffer\n");
421 static BOOL
ANIMATE_GetAviCodec(ANIMATE_INFO
*infoPtr
)
425 /* check uncompressed AVI */
426 if (infoPtr
->ash
.fccHandler
== mmioFOURCC('D', 'I', 'B', ' ') ||
427 infoPtr
->ash
.fccHandler
== mmioFOURCC('R', 'L', 'E', ' ')) {
432 /* try to get a decompressor for that type */
433 infoPtr
->hic
= (infoPtr
->fnICOpen
)(ICTYPE_VIDEO
,
434 infoPtr
->ash
.fccHandler
,
437 WARN("Can't load codec for the file\n");
441 outSize
= (infoPtr
->fnICSendMessage
)(infoPtr
->hic
,
442 ICM_DECOMPRESS_GET_FORMAT
,
443 (DWORD
)infoPtr
->inbih
, 0L);
444 infoPtr
->outbih
= HeapAlloc(GetProcessHeap(), 0, outSize
);
445 if (!infoPtr
->outbih
) {
446 WARN("Can't alloc output BIH\n");
450 if ((infoPtr
->fnICSendMessage
)(infoPtr
->hic
, ICM_DECOMPRESS_GET_FORMAT
,
451 (DWORD
)infoPtr
->inbih
,
452 (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
453 WARN("Can't get output BIH\n");
457 infoPtr
->outdata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->outbih
->biSizeImage
);
458 if (!infoPtr
->outdata
) {
459 WARN("Can't alloc output buffer\n");
463 if ((infoPtr
->fnICSendMessage
)(infoPtr
->hic
, ICM_DECOMPRESS_BEGIN
,
464 (DWORD
)infoPtr
->inbih
,
465 (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
466 WARN("Can't begin decompression\n");
473 static LRESULT
ANIMATE_OpenA(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
475 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
476 HINSTANCE hInstance
= (HINSTANCE
)wParam
;
478 ANIMATE_Free(infoPtr
);
481 TRACE("Closing avi!\n");
486 hInstance
= GetWindowLongA(hWnd
, GWL_HINSTANCE
);
488 if (HIWORD(lParam
)) {
489 TRACE("(\"%s\");\n", (LPSTR
)lParam
);
491 if (!ANIMATE_LoadResA(infoPtr
, hInstance
, (LPSTR
)lParam
)) {
492 TRACE("No AVI resource found!\n");
493 if (!ANIMATE_LoadFileA(infoPtr
, (LPSTR
)lParam
)) {
494 WARN("No AVI file found!\n");
499 TRACE("(%u);\n", (WORD
)LOWORD(lParam
));
501 if (!ANIMATE_LoadResA(infoPtr
, hInstance
,
502 MAKEINTRESOURCEA((INT
)lParam
))) {
503 WARN("No AVI resource found!\n");
508 if (!ANIMATE_GetAviInfo(infoPtr
)) {
509 WARN("Can't get AVI information\n");
510 ANIMATE_Free(infoPtr
);
514 if (!ANIMATE_GetAviCodec(infoPtr
)) {
515 WARN("Can't get AVI Codec\n");
516 ANIMATE_Free(infoPtr
);
520 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
521 FIXME("ACS_CENTER: NIY\n");
523 /* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/
524 SetWindowPos(hWnd
, 0, 0, 0, infoPtr
->mah
.dwWidth
, infoPtr
->mah
.dwHeight
,
525 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
528 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
) {
529 FIXME("ACS_TRANSPARENT: NIY\n");
532 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_AUTOPLAY
) {
533 return ANIMATE_Play(hWnd
, -1, (LPARAM
)MAKELONG(0, infoPtr
->mah
.dwTotalFrames
-1));
540 /* << ANIMATE_Open32W >> */
542 static LRESULT
ANIMATE_Stop(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
544 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
550 ANIMATE_DoStop(infoPtr
);
555 static LRESULT
ANIMATE_Create(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
557 ANIMATE_INFO
* infoPtr
;
558 HMODULE hModule
= LoadLibraryA("msvfw32.dll");
563 /* allocate memory for info structure */
564 infoPtr
= (ANIMATE_INFO
*)COMCTL32_Alloc(sizeof(ANIMATE_INFO
));
566 ERR("could not allocate info memory!\n");
570 /* Temporary hack until we get dllglue up and running */
571 infoPtr
->fnICOpen
= (void*)GetProcAddress(hModule
, "ICOpen");
572 infoPtr
->fnICClose
= (void*)GetProcAddress(hModule
, "ICClose");
573 infoPtr
->fnICSendMessage
= (void*)GetProcAddress(hModule
, "ICSendMessage");
574 infoPtr
->fnICDecompress
= (void*)GetProcAddress(hModule
, "ICDecompress");
576 TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd
, GWL_STYLE
), (DWORD
)GetParent(hWnd
));
578 /* store crossref hWnd <-> info structure */
579 SetWindowLongA(hWnd
, 0, (DWORD
)infoPtr
);
580 infoPtr
->hWnd
= hWnd
;
582 hModWinmm
= LoadLibraryA("WINMM");
584 infoPtr
->fnmmioOpenA
= (void*)GetProcAddress(hModWinmm
, "mmioOpenA");
585 infoPtr
->fnmmioClose
= (void*)GetProcAddress(hModWinmm
, "mmioClose");
586 infoPtr
->fnmmioAscend
= (void*)GetProcAddress(hModWinmm
, "mmioAscend");
587 infoPtr
->fnmmioDescend
= (void*)GetProcAddress(hModWinmm
, "mmioDescend");
588 infoPtr
->fnmmioSeek
= (void*)GetProcAddress(hModWinmm
, "mmioSeek");
589 infoPtr
->fnmmioRead
= (void*)GetProcAddress(hModWinmm
, "mmioRead");
591 InitializeCriticalSection(&infoPtr
->cs
);
597 static LRESULT
ANIMATE_Destroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
599 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
603 ANIMATE_Free(infoPtr
);
605 /* free animate info data */
606 COMCTL32_Free(infoPtr
);
607 SetWindowLongA(hWnd
, 0, 0);
609 FreeLibrary(hModWinmm
);
614 static LRESULT
ANIMATE_EraseBackground(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
618 GetClientRect(hWnd
, &rect
);
620 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
622 FillRect((HDC
)wParam
, &rect
, hBrush
);
623 DeleteObject(hBrush
);
625 FillRect((HDC
)wParam
, &rect
, GetSysColorBrush(COLOR_WINDOW
));
630 static LRESULT WINAPI
ANIMATE_Size(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
632 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
634 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
636 if (infoPtr
->hMMio
) {
637 /* centers the animation in the control, invalidates the control
640 InvalidateRect(hWnd
, NULL
, TRUE
);
645 static LRESULT WINAPI
ANIMATE_WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
647 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hWnd
, uMsg
, wParam
, lParam
);
648 if (!ANIMATE_GetInfoPtr(hWnd
) && (uMsg
!= WM_NCCREATE
))
649 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
653 return ANIMATE_OpenA(hWnd
, wParam
, lParam
);
655 /* case ACM_OPEN32W: FIXME!! */
656 /* return ANIMATE_Open32W(hWnd, wParam, lParam); */
659 return ANIMATE_Play(hWnd
, wParam
, lParam
);
662 return ANIMATE_Stop(hWnd
, wParam
, lParam
);
665 ANIMATE_Create(hWnd
, wParam
, lParam
);
666 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
669 return HTTRANSPARENT
;
672 ANIMATE_Destroy(hWnd
, wParam
, lParam
);
673 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
676 ANIMATE_EraseBackground(hWnd
, wParam
, lParam
);
679 /* case WM_STYLECHANGED: FIXME shall we do something ?? */
682 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd
));
685 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd
));
690 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd
), (HDC
)wParam
);
693 HDC hDC
= BeginPaint(hWnd
, &ps
);
694 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd
), hDC
);
700 ANIMATE_Size(hWnd
, wParam
, lParam
);
701 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
705 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
, lParam
);
707 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
713 void ANIMATE_Register(void)
717 ZeroMemory(&wndClass
, sizeof(WNDCLASSA
));
718 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
719 wndClass
.lpfnWndProc
= (WNDPROC
)ANIMATE_WindowProc
;
720 wndClass
.cbClsExtra
= 0;
721 wndClass
.cbWndExtra
= sizeof(ANIMATE_INFO
*);
722 wndClass
.hCursor
= LoadCursorA(0, IDC_ARROWA
);
723 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
724 wndClass
.lpszClassName
= ANIMATE_CLASSA
;
726 RegisterClassA(&wndClass
);
730 void ANIMATE_Unregister(void)
732 UnregisterClassA(ANIMATE_CLASSA
, (HINSTANCE
)NULL
);