Fixed hash function.
[wine/dcerpc.git] / dlls / comctl32 / animate.c
blobca5f342c22d3c10ed8f42f4604b146caa9887fb3
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3 * Animation control
5 * Copyright 1998, 1999 Eric Kohl
6 * 1999 Eric Pouech
8 * NOTES
9 * I will only improve this control once in a while.
10 * Eric <ekohl@abo.rhein-zeitung.de>
12 * TODO:
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
20 #include "winbase.h"
21 #include "commctrl.h"
22 #include "driver.h"
23 #include "animate.h"
24 #include "mmsystem.h"
25 #include "services.h"
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)
41 HRSRC hrsrc;
42 MMIOINFO mminfo;
43 LPVOID lpAvi;
45 hrsrc = FindResourceA(hInst, lpName, "AVI");
46 if (!hrsrc)
47 return FALSE;
49 infoPtr->hRes = LoadResource(hInst, hrsrc);
50 if (!infoPtr->hRes)
51 return FALSE;
53 lpAvi = LockResource(infoPtr->hRes);
54 if (!lpAvi)
55 return FALSE;
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);
65 return FALSE;
68 return TRUE;
72 static BOOL ANIMATE_LoadFileA(ANIMATE_INFO *infoPtr, LPSTR lpName)
74 infoPtr->hMMio = mmioOpenA((LPSTR)lpName, NULL,
75 MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
77 if (!infoPtr->hMMio)
78 return FALSE;
80 return TRUE;
84 static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
86 if (infoPtr->hMMio) {
87 mmioClose(infoPtr->hMMio, 0);
88 if (infoPtr->hRes) {
89 FreeResource(infoPtr->hRes);
90 infoPtr->hRes = 0;
92 if (infoPtr->lpIndex) {
93 HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex);
94 infoPtr->lpIndex = NULL;
96 if (infoPtr->hic) {
97 (infoPtr->fnICClose)(infoPtr->hic);
98 infoPtr->hic = 0;
100 if (infoPtr->inbih) {
101 HeapFree(GetProcessHeap(), 0, infoPtr->inbih);
102 infoPtr->inbih = NULL;
104 if (infoPtr->outbih) {
105 HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
106 infoPtr->outbih = NULL;
108 HeapFree(GetProcessHeap(), 0, infoPtr->indata);
109 HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
110 infoPtr->indata = infoPtr->outdata = NULL;
111 infoPtr->hWnd = 0;
112 infoPtr->hMMio = 0;
113 memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
114 memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
115 infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
120 static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr)
122 /* should stop playing */
123 if (infoPtr->hService) {
124 SERVICE_Delete(infoPtr->hService);
125 infoPtr->hService = 0;
127 if (infoPtr->uTimer) {
128 KillTimer(infoPtr->hWnd, infoPtr->uTimer);
129 infoPtr->uTimer = 0;
132 ANIMATE_Notify(infoPtr, ACN_STOP);
134 return TRUE;
137 static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC)
139 if (hDC) {
140 StretchDIBits(hDC, 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
141 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
142 infoPtr->outdata, (LPBITMAPINFO)infoPtr->outbih, DIB_RGB_COLORS,
143 SRCCOPY);
145 return TRUE;
148 static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr)
150 HDC hDC;
152 TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop);
154 EnterCriticalSection(&infoPtr->cs);
156 mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
157 mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
159 if ((infoPtr->fnICDecompress)(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
160 infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
161 LeaveCriticalSection(&infoPtr->cs);
162 WARN("Decompression error\n");
163 return FALSE;
166 if ((hDC = GetDC(infoPtr->hWnd)) != 0) {
167 ANIMATE_PaintFrame(infoPtr, hDC);
168 ReleaseDC(infoPtr->hWnd, hDC);
171 if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
172 infoPtr->currFrame = infoPtr->nFromFrame;
173 if (infoPtr->nLoop != -1) {
174 if (--infoPtr->nLoop == 0) {
175 ANIMATE_DoStop(infoPtr);
179 LeaveCriticalSection(&infoPtr->cs);
181 return TRUE;
184 static void CALLBACK ANIMATE_ServiceCallback(ULONG_PTR ptr_)
186 ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_;
188 EnterCriticalSection(&infoPtr->cs);
189 ANIMATE_DrawFrame(infoPtr);
190 LeaveCriticalSection(&infoPtr->cs);
193 static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
195 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
197 /* nothing opened */
198 if (!infoPtr->hMMio)
199 return FALSE;
201 if (infoPtr->hService || infoPtr->uTimer) {
202 FIXME("Already playing ? what should I do ??\n");
203 ANIMATE_DoStop(infoPtr);
206 infoPtr->nFromFrame = (INT)LOWORD(lParam);
207 infoPtr->nToFrame = (INT)HIWORD(lParam);
208 infoPtr->nLoop = (INT)wParam;
210 if (infoPtr->nToFrame == 0xFFFF)
211 infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
213 TRACE("(repeat=%d from=%d to=%d);\n",
214 infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
216 if (infoPtr->nFromFrame >= infoPtr->nToFrame ||
217 infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
218 return FALSE;
220 infoPtr->currFrame = infoPtr->nFromFrame;
222 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) {
223 TRACE("Using a timer\n");
224 /* create a timer to display AVI */
225 infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
226 } else {
227 TRACE("Using the service thread\n");
228 /* time is in µs */
229 infoPtr->hService = SERVICE_AddTimer(infoPtr->mah.dwMicroSecPerFrame,
230 ANIMATE_ServiceCallback, (DWORD)infoPtr);
233 ANIMATE_Notify(infoPtr, ACN_START);
235 return TRUE;
239 static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr)
241 MMCKINFO ckMainRIFF;
242 MMCKINFO mmckHead;
243 MMCKINFO mmckList;
244 MMCKINFO mmckInfo;
245 DWORD numFrame;
246 DWORD insize;
248 if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
249 WARN("Can't find 'RIFF' chunk\n");
250 return FALSE;
253 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
254 (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
255 WARN("Can't find 'AVI ' chunk\n");
256 return FALSE;
259 mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l');
260 if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
261 WARN("Can't find 'hdrl' list\n");
262 return FALSE;
265 mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
266 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
267 WARN("Can't find 'avih' chunk\n");
268 return FALSE;
271 mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
272 TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr->mah.dwMicroSecPerFrame);
273 TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr->mah.dwMaxBytesPerSec);
274 TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr->mah.dwPaddingGranularity);
275 TRACE("mah.dwFlags=%ld\n", infoPtr->mah.dwFlags);
276 TRACE("mah.dwTotalFrames=%ld\n", infoPtr->mah.dwTotalFrames);
277 TRACE("mah.dwInitialFrames=%ld\n", infoPtr->mah.dwInitialFrames);
278 TRACE("mah.dwStreams=%ld\n", infoPtr->mah.dwStreams);
279 TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr->mah.dwSuggestedBufferSize);
280 TRACE("mah.dwWidth=%ld\n", infoPtr->mah.dwWidth);
281 TRACE("mah.dwHeight=%ld\n", infoPtr->mah.dwHeight);
282 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
284 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
285 if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
286 WARN("Can't find 'strl' list\n");
287 return FALSE;
290 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
291 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
292 WARN("Can't find 'strh' chunk\n");
293 return FALSE;
296 mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
297 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)),
298 HIBYTE(LOWORD(infoPtr->ash.fccType)),
299 LOBYTE(HIWORD(infoPtr->ash.fccType)),
300 HIBYTE(HIWORD(infoPtr->ash.fccType)));
301 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
302 HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
303 LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
304 HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
305 TRACE("ash.dwFlags=%ld\n", infoPtr->ash.dwFlags);
306 TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority);
307 TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage);
308 TRACE("ash.dwInitialFrames=%ld\n", infoPtr->ash.dwInitialFrames);
309 TRACE("ash.dwScale=%ld\n", infoPtr->ash.dwScale);
310 TRACE("ash.dwRate=%ld\n", infoPtr->ash.dwRate);
311 TRACE("ash.dwStart=%ld\n", infoPtr->ash.dwStart);
312 TRACE("ash.dwLength=%ld\n", infoPtr->ash.dwLength);
313 TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr->ash.dwSuggestedBufferSize);
314 TRACE("ash.dwQuality=%ld\n", infoPtr->ash.dwQuality);
315 TRACE("ash.dwSampleSize=%ld\n", infoPtr->ash.dwSampleSize);
316 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
317 infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
318 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
320 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
321 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
322 WARN("Can't find 'strh' chunk\n");
323 return FALSE;
326 infoPtr->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
327 if (!infoPtr->inbih) {
328 WARN("Can't alloc input BIH\n");
329 return FALSE;
332 mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
333 TRACE("bih.biSize=%ld\n", infoPtr->inbih->biSize);
334 TRACE("bih.biWidth=%ld\n", infoPtr->inbih->biWidth);
335 TRACE("bih.biHeight=%ld\n", infoPtr->inbih->biHeight);
336 TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes);
337 TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount);
338 TRACE("bih.biCompression=%ld\n", infoPtr->inbih->biCompression);
339 TRACE("bih.biSizeImage=%ld\n", infoPtr->inbih->biSizeImage);
340 TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr->inbih->biXPelsPerMeter);
341 TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr->inbih->biYPelsPerMeter);
342 TRACE("bih.biClrUsed=%ld\n", infoPtr->inbih->biClrUsed);
343 TRACE("bih.biClrImportant=%ld\n", infoPtr->inbih->biClrImportant);
344 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
346 mmioAscend(infoPtr->hMMio, &mmckList, 0);
348 #if 0
349 /* an AVI has 0 or 1 video stream, and to be animated should not contain
350 * an audio stream, so only one strl is allowed
352 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
353 if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
354 WARN("There should be a single 'strl' list\n");
355 return FALSE;
357 #endif
359 mmioAscend(infoPtr->hMMio, &mmckHead, 0);
361 /* no need to read optional JUNK chunk */
363 mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
364 if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
365 WARN("Can't find 'movi' list\n");
366 return FALSE;
369 /* FIXME: should handle the 'rec ' LIST when present */
371 infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
372 infoPtr->mah.dwTotalFrames * sizeof(DWORD));
373 if (!infoPtr->lpIndex) {
374 WARN("Can't alloc index array\n");
375 return FALSE;
378 numFrame = insize = 0;
379 while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
380 numFrame < infoPtr->mah.dwTotalFrames) {
381 infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
382 if (insize < mmckInfo.cksize)
383 insize = mmckInfo.cksize;
384 numFrame++;
385 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
387 if (numFrame != infoPtr->mah.dwTotalFrames) {
388 WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames);
389 return FALSE;
391 if (insize > infoPtr->ash.dwSuggestedBufferSize) {
392 WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize);
393 infoPtr->ash.dwSuggestedBufferSize = insize;
396 infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize);
397 if (!infoPtr->indata) {
398 WARN("Can't alloc input buffer\n");
399 return FALSE;
402 return TRUE;
406 static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
408 DWORD outSize;
410 infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO,
411 infoPtr->ash.fccHandler,
412 ICMODE_DECOMPRESS);
413 if (!infoPtr->hic) {
414 WARN("Can't load codec for the file\n");
415 return FALSE;
418 outSize = (infoPtr->fnICSendMessage)(infoPtr->hic,
419 ICM_DECOMPRESS_GET_FORMAT,
420 (DWORD)infoPtr->inbih, 0L);
421 infoPtr->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
422 if (!infoPtr->outbih) {
423 WARN("Can't alloc output BIH\n");
424 return FALSE;
427 if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
428 (DWORD)infoPtr->inbih,
429 (DWORD)infoPtr->outbih) != ICERR_OK) {
430 WARN("Can't get output BIH\n");
431 return FALSE;
434 infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage);
435 if (!infoPtr->outdata) {
436 WARN("Can't alloc output buffer\n");
437 return FALSE;
440 if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
441 (DWORD)infoPtr->inbih,
442 (DWORD)infoPtr->outbih) != ICERR_OK) {
443 WARN("Can't begin decompression\n");
444 return FALSE;
447 return TRUE;
450 static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam)
452 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
453 HINSTANCE hInstance = (HINSTANCE)wParam;
455 ANIMATE_Free(infoPtr);
457 if (!lParam) {
458 TRACE("Closing avi!\n");
459 return TRUE;
462 if (!hInstance)
463 hInstance = GetWindowLongA(hWnd, GWL_HINSTANCE);
465 if (HIWORD(lParam)) {
466 TRACE("(\"%s\");\n", (LPSTR)lParam);
468 if (!ANIMATE_LoadResA(infoPtr, hInstance, (LPSTR)lParam)) {
469 TRACE("No AVI resource found!\n");
470 if (!ANIMATE_LoadFileA(infoPtr, (LPSTR)lParam)) {
471 WARN("No AVI file found!\n");
472 return FALSE;
475 } else {
476 TRACE("(%u);\n", (WORD)LOWORD(lParam));
478 if (!ANIMATE_LoadResA(infoPtr, hInstance,
479 MAKEINTRESOURCEA((INT)lParam))) {
480 WARN("No AVI resource found!\n");
481 return FALSE;
485 if (!ANIMATE_GetAviInfo(infoPtr)) {
486 WARN("Can't get AVI information\n");
487 ANIMATE_Free(infoPtr);
488 return FALSE;
491 if (!ANIMATE_GetAviCodec(infoPtr)) {
492 WARN("Can't get AVI Codec\n");
493 ANIMATE_Free(infoPtr);
494 return FALSE;
497 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
498 FIXME("ACS_CENTER: NIY\n");
499 } else {
500 /* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/
501 SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
502 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
505 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) {
506 FIXME("ACS_TRANSPARENT: NIY\n");
509 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) {
510 return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
513 return TRUE;
517 /* << ANIMATE_Open32W >> */
519 static LRESULT ANIMATE_Stop(HWND hWnd, WPARAM wParam, LPARAM lParam)
521 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
523 /* nothing opened */
524 if (!infoPtr->hMMio)
525 return FALSE;
527 ANIMATE_DoStop(infoPtr);
528 return TRUE;
533 static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam)
535 ANIMATE_INFO* infoPtr;
536 HMODULE hModule = LoadLibraryA("msvfw32.dll");
538 if (!hModule)
539 return FALSE;
541 /* allocate memory for info structure */
542 infoPtr = (ANIMATE_INFO *)COMCTL32_Alloc(sizeof(ANIMATE_INFO));
543 if (!infoPtr) {
544 ERR("could not allocate info memory!\n");
545 return 0;
548 /* Temporary hack until we get dllglue up and running */
549 infoPtr->fnICOpen = (void*)GetProcAddress(hModule, "ICOpen");
550 infoPtr->fnICClose = (void*)GetProcAddress(hModule, "ICClose");
551 infoPtr->fnICSendMessage = (void*)GetProcAddress(hModule, "ICSendMessage");
552 infoPtr->fnICDecompress = (void*)GetProcAddress(hModule, "ICDecompress");
554 TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd, GWL_STYLE), (DWORD)GetParent(hWnd));
556 /* store crossref hWnd <-> info structure */
557 SetWindowLongA(hWnd, 0, (DWORD)infoPtr);
558 infoPtr->hWnd = hWnd;
560 InitializeCriticalSection(&infoPtr->cs);
562 return 0;
566 static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
568 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
571 /* free avi data */
572 ANIMATE_Free(infoPtr);
574 /* free animate info data */
575 COMCTL32_Free(infoPtr);
577 return 0;
581 static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam)
583 RECT rect;
585 GetClientRect(hWnd, &rect);
586 #if 0
587 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
589 FillRect((HDC)wParam, &rect, hBrush);
590 DeleteObject(hBrush);
591 #else
592 FillRect((HDC)wParam, &rect, GetSysColorBrush(COLOR_WINDOW));
593 #endif
594 return TRUE;
597 static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam)
599 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
601 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
602 FIXME("NIY\n");
603 if (infoPtr->hMMio) {
604 /* centers the animation in the control, invalidates the control
607 InvalidateRect(hWnd, NULL, TRUE);
609 return TRUE;
612 static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
614 switch (uMsg)
616 case ACM_OPENA:
617 return ANIMATE_OpenA(hWnd, wParam, lParam);
619 /* case ACM_OPEN32W: FIXME!! */
620 /* return ANIMATE_Open32W(hWnd, wParam, lParam); */
622 case ACM_PLAY:
623 return ANIMATE_Play(hWnd, wParam, lParam);
625 case ACM_STOP:
626 return ANIMATE_Stop(hWnd, wParam, lParam);
628 case WM_NCCREATE:
629 ANIMATE_Create(hWnd, wParam, lParam);
630 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
632 case WM_NCHITTEST:
633 return HTTRANSPARENT;
635 case WM_DESTROY:
636 ANIMATE_Destroy(hWnd, wParam, lParam);
637 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
639 case WM_ERASEBKGND:
640 ANIMATE_EraseBackground(hWnd, wParam, lParam);
641 break;
643 /* case WM_STYLECHANGED: FIXME shall we do something ?? */
645 case WM_TIMER:
646 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
648 case WM_CLOSE:
649 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd));
650 return TRUE;
652 case WM_PAINT:
653 if (wParam) {
654 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), (HDC)wParam);
655 } else {
656 PAINTSTRUCT ps;
657 HDC hDC = BeginPaint(hWnd, &ps);
658 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), hDC);
659 EndPaint(hWnd, &ps);
661 break;
663 case WM_SIZE:
664 ANIMATE_Size(hWnd, wParam, lParam);
665 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
667 default:
668 if (uMsg >= WM_USER)
669 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
671 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
673 return 0;
677 void ANIMATE_Register(void)
679 WNDCLASSA wndClass;
681 if (GlobalFindAtomA(ANIMATE_CLASSA)) return;
683 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
684 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
685 wndClass.lpfnWndProc = (WNDPROC)ANIMATE_WindowProc;
686 wndClass.cbClsExtra = 0;
687 wndClass.cbWndExtra = sizeof(ANIMATE_INFO *);
688 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
689 wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
690 wndClass.lpszClassName = ANIMATE_CLASSA;
692 RegisterClassA(&wndClass);
696 void ANIMATE_Unregister(void)
698 if (GlobalFindAtomA(ANIMATE_CLASSA))
699 UnregisterClassA(ANIMATE_CLASSA, (HINSTANCE)NULL);