diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c index 25bafe1c7607c728413558eaf2df593ef550c92f..2702d77be99b8555c0513eb77d0ef64ba013ef8d 100644 --- a/dlls/comctl32/animate.c +++ b/dlls/comctl32/animate.c @@ -10,10 +10,9 @@ * Eric <ekohl@abo.rhein-zeitung.de> * * TODO: + * - correct RLE4 decompression * - check for the 'rec ' list in some AVI files - * - implement some missing flags (ACS_TRANSPARENT) - * - protection between service thread and wndproc messages handling - * concurrent access to infoPtr + * - concurrent access to infoPtr */ @@ -62,19 +61,21 @@ typedef struct LPVOID outdata; /* data for the background mechanism */ CRITICAL_SECTION cs; - HANDLE hService; + HANDLE hThread; UINT uTimer; /* data for playing the file */ int nFromFrame; int nToFrame; int nLoop; int currFrame; - /* Background frame info*/ - HBITMAP bkgFrameb; - LPDWORD bkColor; + /* tranparency info*/ + COLORREF transparentColor; + HBRUSH hbrushBG; + } ANIMATE_INFO; #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0)) +#define ANIMATE_COLOR_NONE 0xffffffff HMODULE hModWinmm; @@ -114,8 +115,6 @@ static BOOL ANIMATE_LoadResA(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPSTR lpNam return FALSE; } - infoPtr->bkgFrameb=(HBITMAP)NULL; - return TRUE; } @@ -137,9 +136,11 @@ static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr) EnterCriticalSection(&infoPtr->cs); /* should stop playing */ - if (infoPtr->hService) { - SERVICE_Delete(infoPtr->hService); - infoPtr->hService = 0; + if (infoPtr->hThread) + { + if (!TerminateThread(infoPtr->hThread,0)) + WARN("could not destroy animation thread!\n"); + infoPtr->hThread = 0; } if (infoPtr->uTimer) { KillTimer(infoPtr->hWnd, infoPtr->uTimer); @@ -159,11 +160,6 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr) if (infoPtr->hMMio) { ANIMATE_DoStop(infoPtr); infoPtr->fnmmioClose(infoPtr->hMMio, 0); - if (infoPtr->bkgFrameb) { - DeleteObject(infoPtr->bkgFrameb); - infoPtr->bkgFrameb=(HBITMAP)NULL; - infoPtr->bkColor=NULL; - } if (infoPtr->hRes) { FreeResource(infoPtr->hRes); infoPtr->hRes = 0; @@ -184,141 +180,277 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr) HeapFree(GetProcessHeap(), 0, infoPtr->outbih); infoPtr->outbih = NULL; } + if( infoPtr->indata ) + { HeapFree(GetProcessHeap(), 0, infoPtr->indata); + infoPtr->indata = NULL; + } + if( infoPtr->outdata ) + { HeapFree(GetProcessHeap(), 0, infoPtr->outdata); + infoPtr->outdata = NULL; + } infoPtr->indata = infoPtr->outdata = NULL; infoPtr->hWnd = 0; infoPtr->hMMio = 0; + memset(&infoPtr->mah, 0, sizeof(infoPtr->mah)); memset(&infoPtr->ash, 0, sizeof(infoPtr->ash)); infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0; } + infoPtr->transparentColor = ANIMATE_COLOR_NONE; } +/*********************************************************************** + * ANIMATE_Expand_RLE8 + * + * Decompresses an 8-bit compressed frame over previous frame + * + */ -static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) +enum Rle8_EscapeCodes { - if (!hDC || !infoPtr->inbih) - return TRUE; - if (infoPtr->hic){ - if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT){ - FIXME("TRANSPARENCY NOT SUPPORTED(NOT TESTED) FOR COMPRESSED IMAGE\n"); + RleEol = 0, /* End of line */ + RleEnd = 1, /* End of bitmap */ + RleDelta = 2 /* Delta */ +}; + +static LRESULT ANIMATE_Expand_RLE8(BYTE* pDest, int nWidth, int nHeight, BYTE* pSource) +{ + int x; /* X-positon on each line. Increases. */ + int line; /* Line #. Increases */ + BYTE *pOut; /* current position in destination buffer */ + BYTE length; /* The length of a run */ + BYTE color_index; /* index for current pixel */ + BYTE escape_code; /* See enum Rle8_EscapeCodes.*/ + int bEndOfBitmap=0; + /* image width including byte padding */ + int nStride = ((( nWidth - 1 ) >> 2) + 1 ) << 2; + + if (nHeight < 1 || nWidth < 1 || nStride < 1 || !pSource || !pDest) + return FALSE; + + x = 0; + line = 0; + pOut = pDest; + do + { + length = *pSource++; + /* + * If the length byte is not zero (which is the escape value), + * We have a run of length pixels all the same colour. The color + * index is stored next. + * + * If the length byte is zero, we need to read the next byte to + * know what to do. + */ + if (length != 0) + { + /* + * [Run-Length] Encoded mode + */ + color_index = (*pSource++); /* Get the color index. */ + + while (length-- && x < nWidth) + { + *pOut++=color_index; + x++; } - StretchDIBits(hDC, 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight, - 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight, - infoPtr->outdata, (LPBITMAPINFO)infoPtr->outbih, DIB_RGB_COLORS, - SRCCOPY); + } else + { + /* + * Escape codes or absolute sequence + */ + escape_code = (*pSource++); + switch (escape_code) + { + case RleEol: /* =0, end of line */ + { + x = 0; + line++; + pOut = pDest + nStride * line; + break; } - else{ - if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT){ - HBITMAP hbmMem, hbmMem2,hbmMem3; - HDC hdcSrc, hdcMask, hdcMem; - - hdcSrc = CreateCompatibleDC(hDC); - hdcMask = CreateCompatibleDC(hDC); - hdcMem = CreateCompatibleDC(hDC); - - /* create a Black and white bitmap */ - hbmMem = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight); - hbmMem2 = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1, 1, NULL); - hbmMem3 = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight); - - SelectObject( hdcSrc, hbmMem); - - StretchDIBits(hdcSrc, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, - 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, - infoPtr->indata, (LPBITMAPINFO)infoPtr->inbih, DIB_RGB_COLORS, - SRCCOPY); - - if (infoPtr->bkgFrameb==(HBITMAP)NULL) + case RleEnd: /* =1, end of bitmap */ { - infoPtr->bkgFrameb = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight); - SelectObject( hdcMem, infoPtr->bkgFrameb); - BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hDC, 0, 0, SRCCOPY); - /* Get the transparent color from the first frame*/ - switch (infoPtr->inbih->biBitCount) { - case 1: - case 4: - /*FIXME: Not supported Yet.*/ + bEndOfBitmap=TRUE; + line=nHeight; /* exit from loop. */ break; - case 8: - infoPtr->bkColor = (LPVOID)((LPSTR)infoPtr->inbih + (WORD)(((LPBITMAPINFO)infoPtr->inbih)->bmiHeader.biSize)); + } + case RleDelta: /* =2, a delta */ + { + x += (*pSource++); + line += (*pSource++); + if (line >= nHeight || x >= nWidth) + { + WARN("Delta out of bounds\n"); + line = nHeight; + } + pOut = pDest + (line * nStride) + x; break; - case 16: - case 24: - case 32: - infoPtr->bkColor = (LPVOID)GetPixel(hdcSrc, 0, 0); - /*FIXME:Has not been test with more than 8bpp, errors are possible*/ + } + default: /* >2, absolute mode */ + { + length = escape_code; + while (length--) + { + color_index = (*pSource++); + if (x < nWidth) + { + *pOut++=color_index; + x++; + } + } + if (escape_code & 1) + pSource++; /* Throw away the pad byte. */ break; } + } /* switch (escape_code) */ + } /* process either an encoded sequence or an escape sequence */ + /* We expect to come here more than once per line. */ + } while (line < nHeight); /* Do this until the bitmap is filled */ + + if ( !bEndOfBitmap ) + { + TRACE("Reached end of bitmap without a EndOfBitmap code\n"); } - /* Need the copy of the original destination HDC*/ - SelectObject( hdcSrc, infoPtr->bkgFrameb); - SelectObject( hdcMem, hbmMem3); - BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCCOPY); - - SelectObject( hdcSrc, hbmMem); - SelectObject( hdcMask, hbmMem2); - - /*Windows converts a color source into monochrome when the destination is - monochrome. In this situation, all pixels in the color bitmap that are the same color - as the background color become 1s, and all the other pixels are converted to 0s. */ - - /* Set the transparent color from the first frame*/ - switch (infoPtr->inbih->biBitCount) { - case 1: - case 4: - /*FIXME: Not supported Yet.*/ - break; - case 8: - SetBkColor(hdcSrc, infoPtr->bkColor[(((BYTE*)infoPtr->indata)[0])]); - break; - case 16: - case 24: - case 32: - SetBkColor(hdcSrc, (COLORREF)infoPtr->bkColor); - break; + return TRUE; } - BitBlt(hdcMask, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCCOPY); +static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource) +{ + HDC hdcMask; + HBITMAP hbmMask; + HBITMAP hbmOld; + + /* create a transparency mask */ + hdcMask = CreateCompatibleDC(hdcDest); + hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL); + hbmOld = SelectObject(hdcMask, hbmMask); + + SetBkColor(hdcSource,infoPtr->transparentColor); + BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY); + + /* mask the source bitmap */ + SetBkColor(hdcSource, RGB(0,0,0)); + SetTextColor(hdcSource, RGB(255,255,255)); + BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + + /* mask the destination bitmap */ + SetBkColor(hdcDest, RGB(255,255,255)); + SetTextColor(hdcDest, RGB(0,0,0)); + BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + + /* combine source and destination */ + BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT); + + SelectObject(hdcMask, hbmOld); + DeleteObject(hbmMask); + DeleteDC(hdcMask); +} + +static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) +{ + void* pBitmapData = NULL; + LPBITMAPINFO pBitmapInfo = NULL; + + HDC hdcMem; + HBITMAP hbmNew; + HBITMAP hbmOld; - /*During a blt operation with a color destination, a monochrome source bitmap - (and/or a brush when applicable) is converted to color on the fly before the - actual ROP is carried out on the bits. The 0 (black) pixels in the monochrome - bitmap are converted to the destination's text (foreground) color, and the 1 - (white) pixels are converted to the background color. */ + int nOffsetX = 0; + int nOffsetY = 0; - SetBkColor(hdcSrc, RGB(0,0,0)); /* 1s --> black (0x000000)*/ - SetTextColor(hdcSrc, RGB(255,255,255)); /* 0s --> white (0xFFFFFF)*/ + int nWidth; + int nHeight; - BitBlt(hdcSrc, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + if (!hDC || !infoPtr->inbih) + return TRUE; - SetBkColor(hdcMem, RGB(255,255,255)); /* 0s --> white (0xFFFFFF) */ - SetTextColor(hdcMem, RGB(0,0,0)); /* 1s --> black (0x000000) */ + if (infoPtr->hic || + /* put this once correct RLE4 decompression is implemented */ + /* infoPtr->inbih->biCompression == BI_RLE4 || */ + infoPtr->inbih->biCompression == BI_RLE8 ) + { + pBitmapData = infoPtr->outdata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih; - BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + nWidth = infoPtr->outbih->biWidth; + nHeight = infoPtr->outbih->biHeight; + } + else + { + pBitmapData = infoPtr->indata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih; - BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCPAINT); + nWidth = infoPtr->inbih->biWidth; + nHeight = infoPtr->inbih->biHeight; + } - BitBlt(hDC, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMem, 0, 0, SRCCOPY); + if (infoPtr->inbih->biCompression == BI_RLE8) + ANIMATE_Expand_RLE8(pBitmapData, nWidth, nHeight, infoPtr->indata); - DeleteDC(hdcMem); - DeleteDC(hdcSrc); - DeleteDC(hdcMask); - DeleteObject(hbmMem); - DeleteObject(hbmMem2); - DeleteObject(hbmMem3); + if (infoPtr->inbih->biCompression == BI_RLE4) + FIXME("correct RLE4 decompression not implemented yet (no samples available)\n"); + + hdcMem = CreateCompatibleDC(hDC); + hbmNew = CreateCompatibleBitmap(hDC,nWidth, nHeight); + hbmOld = SelectObject(hdcMem, hbmNew); - } - else{ - StretchDIBits(hDC, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, + StretchDIBits(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, - infoPtr->indata, (LPBITMAPINFO)infoPtr->inbih, DIB_RGB_COLORS, + pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); + + /* + * we need to get the transparent color even without ACS_TRANSPARENT, + * because the style can be changed later on and the color should always + * be obtained in the first frame + */ + if(infoPtr->transparentColor == ANIMATE_COLOR_NONE) + { + infoPtr->transparentColor = GetPixel(hdcMem,0,0); + } + + if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + HDC hdcFinal = CreateCompatibleDC(hDC); + HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight); + HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal); + RECT rect; + + rect.left = 0; + rect.top = 0; + rect.right = nWidth; + rect.bottom = nHeight; + + if(!infoPtr->hbrushBG) + infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH); + + FillRect(hdcFinal, &rect, infoPtr->hbrushBG); + ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem); + + SelectObject(hdcFinal, hbmOld2); + SelectObject(hdcMem, hbmFinal); + DeleteDC(hdcFinal); + DeleteObject(hbmNew); + hbmNew=hbmFinal; } + + if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_CENTER) + { + RECT rect; + + GetWindowRect(infoPtr->hWnd, &rect); + nOffsetX = ((rect.right - rect.left) - nWidth)/2; + nOffsetY = ((rect.bottom - rect.top) - nHeight)/2; } + BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); + DeleteObject(hbmNew); return TRUE; } @@ -359,13 +491,34 @@ static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr) return TRUE; } -static void CALLBACK ANIMATE_ServiceCallback(ULONG_PTR ptr_) +static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_) { ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_; + HDC hDC; + + if(!infoPtr) + { + WARN("animation structure undefined!\n"); + return FALSE; + } + while(1) + { + if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + hDC = GetDC(infoPtr->hWnd); + infoPtr->hbrushBG = SendMessageA(GetParent(infoPtr->hWnd),WM_CTLCOLORSTATIC,hDC, infoPtr->hWnd); + ReleaseDC(infoPtr->hWnd,hDC); + } + EnterCriticalSection(&infoPtr->cs); ANIMATE_DrawFrame(infoPtr); LeaveCriticalSection(&infoPtr->cs); + + /* time is in microseconds, we should convert it to milliseconds */ + Sleep((infoPtr->mah.dwMicroSecPerFrame+500)/1000); +} + return TRUE; } static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) @@ -376,7 +529,7 @@ static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) if (!infoPtr->hMMio) return FALSE; - if (infoPtr->hService || infoPtr->uTimer) { + if (infoPtr->hThread || infoPtr->uTimer) { FIXME("Already playing ? what should I do ??\n"); ANIMATE_DoStop(infoPtr); } @@ -402,10 +555,16 @@ static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) /* create a timer to display AVI */ infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL); } else { - TRACE("Using the service thread\n"); - /* time is in 盜 */ - infoPtr->hService = SERVICE_AddTimer(infoPtr->mah.dwMicroSecPerFrame / 1000, - ANIMATE_ServiceCallback, (DWORD)infoPtr); + DWORD threadID; + + TRACE("Using an animation thread\n"); + infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr,0,0 &threadID); + if(!infoPtr->hThread) + { + ERR("Could not create animation thread!\n"); + return FALSE; + } + } ANIMATE_Notify(infoPtr, ACN_START); @@ -586,11 +745,52 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr) DWORD outSize; /* check uncompressed AVI */ - if (infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ') || - infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) { + if (infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) { infoPtr->hic = 0; return TRUE; } + else if (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) + { + int nStride = 0; + int frameBufferSize; + int sizebih=sizeof(BITMAPINFOHEADER) + infoPtr->inbih->biClrUsed *sizeof(RGBQUAD); + + if(infoPtr->inbih->biCompression == BI_RLE8) + nStride = (((( infoPtr->inbih->biWidth - 1 ) >> 2) + 1 ) << 2); + else if(infoPtr->inbih->biCompression == BI_RLE4) + nStride = (((( infoPtr->inbih->biWidth - 1 ) >> 3) + 1 ) << 2); + else + { + ERR("Image compression format unknown\n"); + return FALSE; + } + + frameBufferSize = infoPtr->inbih->biHeight * nStride; + + infoPtr->hic = 0; + infoPtr->outbih = HeapAlloc(GetProcessHeap(),0, sizebih); + if(!infoPtr->outbih) + { + ERR("out of memory!\n"); + return FALSE; + } + + infoPtr->outdata = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, frameBufferSize); + if(!infoPtr->outdata) + { + HeapFree(GetProcessHeap(),0,infoPtr->outbih); + infoPtr->outbih = 0; + ERR("out of memory!\n"); + return FALSE; + } + + /* create a BITMAPINFO header for the uncompressed bitmap */ + memcpy(infoPtr->outbih, infoPtr->inbih, sizebih); + infoPtr->outbih->biCompression = BI_RGB; + infoPtr->outbih->biSizeImage = frameBufferSize; + + return TRUE; + } /* try to get a decompressor for that type */ infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO, @@ -633,23 +833,6 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr) return TRUE; } -static void ANIMATE_Center(ANIMATE_INFO *infoPtr) -{ - int x,y,dx,dy; - RECT Rect; - HWND hWnd=infoPtr->hWnd; - HWND hWndParent=GetWindowLongA(hWnd, GWL_HWNDPARENT); - - if (!hWndParent || !GetWindowRect(hWndParent, &Rect)) return; - - dx=Rect.right-Rect.left+1; - dy=Rect.bottom-Rect.top+1; - x=infoPtr->mah.dwWidth < dx ? (dx-infoPtr->mah.dwWidth) >> 1 : 0; - y=infoPtr->mah.dwHeight < dy ? (dy-infoPtr->mah.dwHeight) >> 1 : 0; - - MoveWindow(hWnd, x, y, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, TRUE); -} - static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam) { ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); @@ -697,20 +880,11 @@ static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam) return FALSE; } - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { - - ANIMATE_Center(infoPtr); - - } else { - /* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/ + if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); } - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) { - FIXME("ACS_TRANSPARENT: NIY\n"); - } - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) { return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1)); } @@ -760,7 +934,7 @@ static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam) /* store crossref hWnd <-> info structure */ SetWindowLongA(hWnd, 0, (DWORD)infoPtr); infoPtr->hWnd = hWnd; - + infoPtr->transparentColor = ANIMATE_COLOR_NONE; hModWinmm = LoadLibraryA("WINMM"); infoPtr->fnmmioOpenA = (void*)GetProcAddress(hModWinmm, "mmioOpenA"); @@ -796,29 +970,22 @@ static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam) { RECT rect; + HBRUSH hBrush = 0; + + if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + hBrush = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd); + } GetClientRect(hWnd, &rect); -#if 0 - HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk); + FillRect((HDC)wParam, &rect, hBrush ? hBrush : GetCurrentObject((HDC)wParam, OBJ_BRUSH)); - FillRect((HDC)wParam, &rect, hBrush); - DeleteObject(hBrush); -#else - FillRect((HDC)wParam, &rect, GetSysColorBrush(COLOR_WINDOW)); -#endif return TRUE; } static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam) { - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { - if (infoPtr->hMMio) { - /* centers the animation in the control, invalidates the control - */ - ANIMATE_Center(infoPtr); - } InvalidateRect(hWnd, NULL, TRUE); } return TRUE; @@ -861,6 +1028,11 @@ static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP /* case WM_STYLECHANGED: FIXME shall we do something ?? */ case WM_TIMER: + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); + infoPtr->hbrushBG = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd); + } return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd)); case WM_CLOSE: @@ -868,14 +1040,35 @@ static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP return TRUE; case WM_PAINT: - if (wParam) { - ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), (HDC)wParam); - } else { + { + ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); + + /* the animation isn't playing, don't paint */ + if(!infoPtr->uTimer && !infoPtr->hThread) + break; + + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + infoPtr->hbrushBG = SendMessageA(GetParent(hWnd), WM_CTLCOLORSTATIC, + (HDC)wParam, hWnd); + + if (wParam) + { + EnterCriticalSection(&infoPtr->cs); + ANIMATE_PaintFrame(infoPtr, (HDC)wParam); + LeaveCriticalSection(&infoPtr->cs); + } + else + { PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); - ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), hDC); + + EnterCriticalSection(&infoPtr->cs); + ANIMATE_PaintFrame(infoPtr, hDC); + LeaveCriticalSection(&infoPtr->cs); + EndPaint(hWnd, &ps); } + } break; case WM_SIZE: