📄 animate.c
字号:
WARN("Can't find 'hdrl' list\n");
return FALSE;
}
mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
WARN("Can't find 'avih' chunk\n");
return FALSE;
}
mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
TRACE("mah.dwMicroSecPerFrame=%d\n", infoPtr->mah.dwMicroSecPerFrame);
TRACE("mah.dwMaxBytesPerSec=%d\n", infoPtr->mah.dwMaxBytesPerSec);
TRACE("mah.dwPaddingGranularity=%d\n", infoPtr->mah.dwPaddingGranularity);
TRACE("mah.dwFlags=%d\n", infoPtr->mah.dwFlags);
TRACE("mah.dwTotalFrames=%d\n", infoPtr->mah.dwTotalFrames);
TRACE("mah.dwInitialFrames=%d\n", infoPtr->mah.dwInitialFrames);
TRACE("mah.dwStreams=%d\n", infoPtr->mah.dwStreams);
TRACE("mah.dwSuggestedBufferSize=%d\n", infoPtr->mah.dwSuggestedBufferSize);
TRACE("mah.dwWidth=%d\n", infoPtr->mah.dwWidth);
TRACE("mah.dwHeight=%d\n", infoPtr->mah.dwHeight);
mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
WARN("Can't find 'strl' list\n");
return FALSE;
}
mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
WARN("Can't find 'strh' chunk\n");
return FALSE;
}
mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)),
HIBYTE(LOWORD(infoPtr->ash.fccType)),
LOBYTE(HIWORD(infoPtr->ash.fccType)),
HIBYTE(HIWORD(infoPtr->ash.fccType)));
TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
TRACE("ash.dwFlags=%d\n", infoPtr->ash.dwFlags);
TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority);
TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage);
TRACE("ash.dwInitialFrames=%d\n", infoPtr->ash.dwInitialFrames);
TRACE("ash.dwScale=%d\n", infoPtr->ash.dwScale);
TRACE("ash.dwRate=%d\n", infoPtr->ash.dwRate);
TRACE("ash.dwStart=%d\n", infoPtr->ash.dwStart);
TRACE("ash.dwLength=%d\n", infoPtr->ash.dwLength);
TRACE("ash.dwSuggestedBufferSize=%d\n", infoPtr->ash.dwSuggestedBufferSize);
TRACE("ash.dwQuality=%d\n", infoPtr->ash.dwQuality);
TRACE("ash.dwSampleSize=%d\n", infoPtr->ash.dwSampleSize);
TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
WARN("Can't find 'strh' chunk\n");
return FALSE;
}
infoPtr->inbih = Alloc(mmckInfo.cksize);
if (!infoPtr->inbih) {
WARN("Can't alloc input BIH\n");
return FALSE;
}
mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
TRACE("bih.biSize=%d\n", infoPtr->inbih->biSize);
TRACE("bih.biWidth=%d\n", infoPtr->inbih->biWidth);
TRACE("bih.biHeight=%d\n", infoPtr->inbih->biHeight);
TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes);
TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount);
TRACE("bih.biCompression=%d\n", infoPtr->inbih->biCompression);
TRACE("bih.biSizeImage=%d\n", infoPtr->inbih->biSizeImage);
TRACE("bih.biXPelsPerMeter=%d\n", infoPtr->inbih->biXPelsPerMeter);
TRACE("bih.biYPelsPerMeter=%d\n", infoPtr->inbih->biYPelsPerMeter);
TRACE("bih.biClrUsed=%d\n", infoPtr->inbih->biClrUsed);
TRACE("bih.biClrImportant=%d\n", infoPtr->inbih->biClrImportant);
mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
mmioAscend(infoPtr->hMMio, &mmckList, 0);
#if 0
/* an AVI has 0 or 1 video stream, and to be animated should not contain
* an audio stream, so only one strl is allowed
*/
mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
WARN("There should be a single 'strl' list\n");
return FALSE;
}
#endif
mmioAscend(infoPtr->hMMio, &mmckHead, 0);
/* no need to read optional JUNK chunk */
mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
WARN("Can't find 'movi' list\n");
return FALSE;
}
/* FIXME: should handle the 'rec ' LIST when present */
infoPtr->lpIndex = Alloc(infoPtr->mah.dwTotalFrames * sizeof(DWORD));
if (!infoPtr->lpIndex)
return FALSE;
numFrame = insize = 0;
while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
numFrame < infoPtr->mah.dwTotalFrames) {
infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
if (insize < mmckInfo.cksize)
insize = mmckInfo.cksize;
numFrame++;
mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
}
if (numFrame != infoPtr->mah.dwTotalFrames) {
WARN("Found %d frames (/%d)\n", numFrame, infoPtr->mah.dwTotalFrames);
return FALSE;
}
if (insize > infoPtr->ash.dwSuggestedBufferSize) {
WARN("insize=%d suggestedSize=%d\n", insize, infoPtr->ash.dwSuggestedBufferSize);
infoPtr->ash.dwSuggestedBufferSize = insize;
}
infoPtr->indata = Alloc(infoPtr->ash.dwSuggestedBufferSize);
if (!infoPtr->indata)
return FALSE;
return TRUE;
}
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', ' ')) ||
(infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0)))
{
infoPtr->hic = 0;
return TRUE;
}
/* try to get a decompressor for that type */
infoPtr->hic = fnIC.fnICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS);
if (!infoPtr->hic) {
WARN("Can't load codec for the file\n");
return FALSE;
}
outSize = fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
(DWORD_PTR)infoPtr->inbih, 0L);
infoPtr->outbih = Alloc(outSize);
if (!infoPtr->outbih)
return FALSE;
if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
(DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK)
{
WARN("Can't get output BIH\n");
return FALSE;
}
infoPtr->outdata = Alloc(infoPtr->outbih->biSizeImage);
if (!infoPtr->outdata)
return FALSE;
if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
(DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK) {
WARN("Can't begin decompression\n");
return FALSE;
}
return TRUE;
}
static BOOL ANIMATE_OpenW(ANIMATE_INFO *infoPtr, HINSTANCE hInstance, LPWSTR lpszName)
{
ANIMATE_Free(infoPtr);
if (!lpszName)
{
TRACE("Closing avi!\n");
/* installer of thebat! v1.62 requires FALSE here */
return (infoPtr->hMMio != 0);
}
if (!hInstance)
hInstance = (HINSTANCE)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_HINSTANCE);
TRACE("(%s)\n", debugstr_w(lpszName));
if (HIWORD(lpszName))
{
if (!ANIMATE_LoadResW(infoPtr, hInstance, lpszName))
{
TRACE("No AVI resource found!\n");
if (!ANIMATE_LoadFileW(infoPtr, lpszName))
{
WARN("No AVI file found!\n");
return FALSE;
}
}
}
else
{
if (!ANIMATE_LoadResW(infoPtr, hInstance, lpszName))
{
WARN("No AVI resource found!\n");
return FALSE;
}
}
if (!ANIMATE_GetAviInfo(infoPtr))
{
WARN("Can't get AVI information\n");
ANIMATE_Free(infoPtr);
return FALSE;
}
if (!ANIMATE_GetAviCodec(infoPtr))
{
WARN("Can't get AVI Codec\n");
ANIMATE_Free(infoPtr);
return FALSE;
}
if (!(infoPtr->dwStyle & ACS_CENTER))
SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
if (infoPtr->dwStyle & ACS_AUTOPLAY)
return ANIMATE_Play(infoPtr, -1, 0, infoPtr->mah.dwTotalFrames - 1);
return TRUE;
}
static BOOL ANIMATE_OpenA(ANIMATE_INFO *infoPtr, HINSTANCE hInstance, LPSTR lpszName)
{
LPWSTR lpwszName;
LRESULT result;
INT len;
if (!HIWORD(lpszName))
return ANIMATE_OpenW(infoPtr, hInstance, (LPWSTR)lpszName);
len = MultiByteToWideChar(CP_ACP, 0, lpszName, -1, NULL, 0);
lpwszName = Alloc(len * sizeof(WCHAR));
if (!lpwszName) return FALSE;
MultiByteToWideChar(CP_ACP, 0, lpszName, -1, lpwszName, len);
result = ANIMATE_OpenW(infoPtr, hInstance, lpwszName);
Free (lpwszName);
return result;
}
static BOOL ANIMATE_Stop(ANIMATE_INFO *infoPtr)
{
/* nothing opened */
if (!infoPtr->hMMio)
return FALSE;
ANIMATE_DoStop(infoPtr);
return TRUE;
}
static BOOL ANIMATE_Create(HWND hWnd, LPCREATESTRUCTW lpcs)
{
static const WCHAR msvfw32W[] = { 'm', 's', 'v', 'f', 'w', '3', '2', '.', 'd', 'l', 'l', 0 };
ANIMATE_INFO *infoPtr;
if (!fnIC.hModule)
{
fnIC.hModule = LoadLibraryW(msvfw32W);
if (!fnIC.hModule) return FALSE;
fnIC.fnICOpen = (void*)GetProcAddress(fnIC.hModule, "ICOpen");
fnIC.fnICClose = (void*)GetProcAddress(fnIC.hModule, "ICClose");
fnIC.fnICSendMessage = (void*)GetProcAddress(fnIC.hModule, "ICSendMessage");
fnIC.fnICDecompress = (void*)GetProcAddress(fnIC.hModule, "ICDecompress");
}
/* allocate memory for info structure */
infoPtr = (ANIMATE_INFO *)Alloc(sizeof(ANIMATE_INFO));
if (!infoPtr) return FALSE;
/* store crossref hWnd <-> info structure */
SetWindowLongPtrW(hWnd, 0, (DWORD_PTR)infoPtr);
infoPtr->hwndSelf = hWnd;
infoPtr->hwndNotify = lpcs->hwndParent;
infoPtr->transparentColor = ANIMATE_COLOR_NONE;
infoPtr->hbmPrevFrame = 0;
infoPtr->dwStyle = lpcs->style;
TRACE("Animate style=0x%08x, parent=%p\n", infoPtr->dwStyle, infoPtr->hwndNotify);
InitializeCriticalSection(&infoPtr->cs);
return TRUE;
}
static LRESULT ANIMATE_Destroy(ANIMATE_INFO *infoPtr)
{
/* free avi data */
ANIMATE_Free(infoPtr);
/* free animate info data */
SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
DeleteCriticalSection(&infoPtr->cs);
Free(infoPtr);
return 0;
}
static BOOL ANIMATE_EraseBackground(ANIMATE_INFO *infoPtr, HDC hdc)
{
RECT rect;
HBRUSH hBrush = 0;
if(infoPtr->dwStyle & ACS_TRANSPARENT)
{
hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLORSTATIC,
(WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
}
GetClientRect(infoPtr->hwndSelf, &rect);
FillRect(hdc, &rect, hBrush ? hBrush : GetCurrentObject(hdc, OBJ_BRUSH));
return TRUE;
}
static LRESULT ANIMATE_StyleChanged(ANIMATE_INFO *infoPtr, WPARAM wStyleType, LPSTYLESTRUCT lpss)
{
TRACE("(styletype=%x, styleOld=0x%08x, styleNew=0x%08x)\n",
wStyleType, lpss->styleOld, lpss->styleNew);
if (wStyleType != GWL_STYLE) return 0;
infoPtr->dwStyle = lpss->styleNew;
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ANIMATE_INFO *infoPtr = (ANIMATE_INFO *)GetWindowLongPtrW(hWnd, 0);
TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam);
if (!infoPtr && (uMsg != WM_NCCREATE))
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case ACM_OPENA:
return ANIMATE_OpenA(infoPtr, (HINSTANCE)wParam, (LPSTR)lParam);
case ACM_OPENW:
return ANIMATE_OpenW(infoPtr, (HINSTANCE)wParam, (LPWSTR)lParam);
case ACM_PLAY:
return ANIMATE_Play(infoPtr, (INT)wParam, LOWORD(lParam), HIWORD(lParam));
case ACM_STOP:
return ANIMATE_Stop(infoPtr);
case WM_CLOSE:
ANIMATE_Free(infoPtr);
return 0;
case WM_NCCREATE:
return ANIMATE_Create(hWnd, (LPCREATESTRUCTW)lParam);
case WM_NCHITTEST:
return HTTRANSPARENT;
case WM_DESTROY:
return ANIMATE_Destroy(infoPtr);
case WM_ERASEBKGND:
return ANIMATE_EraseBackground(infoPtr, (HDC)wParam);
case WM_STYLECHANGED:
return ANIMATE_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
case WM_TIMER:
return ANIMATE_Timer(infoPtr);
case WM_PRINTCLIENT:
case WM_PAINT:
{
/* the animation isn't playing, or has not decompressed
* (and displayed) the first frame yet, don't paint
*/
if ((!infoPtr->uTimer && !infoPtr->hThread) ||
!infoPtr->hbmPrevFrame)
{
/* default paint handling */
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
if (infoPtr->dwStyle & ACS_TRANSPARENT)
infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify,
WM_CTLCOLORSTATIC,
wParam, (LPARAM)infoPtr->hwndSelf);
if (wParam)
{
EnterCriticalSection(&infoPtr->cs);
ANIMATE_PaintFrame(infoPtr, (HDC)wParam);
LeaveCriticalSection(&infoPtr->cs);
}
else
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(infoPtr->hwndSelf, &ps);
EnterCriticalSection(&infoPtr->cs);
ANIMATE_PaintFrame(infoPtr, hDC);
LeaveCriticalSection(&infoPtr->cs);
EndPaint(infoPtr->hwndSelf, &ps);
}
}
break;
case WM_SIZE:
if (infoPtr->dwStyle & ACS_CENTER)
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
default:
if ((uMsg >= WM_USER) && (uMsg < WM_APP))
ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
return 0;
}
void ANIMATE_Register(void)
{
WNDCLASSW wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASSW));
wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
wndClass.lpfnWndProc = ANIMATE_WindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(ANIMATE_INFO *);
wndClass.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndClass.lpszClassName = ANIMATE_CLASSW;
RegisterClassW(&wndClass);
}
void ANIMATE_Unregister(void)
{
UnregisterClassW(ANIMATE_CLASSW, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -