日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

vc应用CPictureEx类(重载CStatic类)加载gif动画

發布時間:2025/4/16 c/c++ 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vc应用CPictureEx类(重载CStatic类)加载gif动画 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.PictureEx.h文件:

//
// PictureEx.cpp: implementation of the CPictureEx class.
//
// Picture displaying control with support for the following formats:
// GIF (including animated GIF87a and GIF89a), JPEG, BMP, WMF, ICO, CUR
//
// Written by Oleg Bykov (oleg_bykoff@rsdn.ru)
// Copyright (c) 2001
//
// To use CPictureEx, follow these steps:
//?? - place a static control on your dialog (either a text or a bitmap)
//?? - change its identifier to something else (e.g. IDC_MYPIC)
//?? - associate a CStatic with it using ClassWizard
//?? - in your dialog's header file replace CStatic with CPictureEx
//???? (don't forget to #include "PictureEx.h" and add
//???? PictureEx.h and PictureEx.cpp to your project)
//?? - call one of the overloaded CPictureEx::Load() functions somewhere
//???? (OnInitDialog is a good place to start)
//?? - if the preceding Load() succeeded call Draw()
//?
// You can also add the control by defining a member variable of type
// CPictureEx, calling CPictureEx::Create (derived from CStatic), then
// CPictureEx::Load and CPictureEx::Draw.
//
// By default, the control initializes its background to COLOR_3DFACE
// (see CPictureEx::PrepareDC()). You can change the background by
// calling CPictureEx::SetBkColor(COLORREF) after CPictureEx::Load().
//
// I decided to leave in the class the functions to write separate frames from
// animated GIF to disk. If you want to use them, uncomment #define GIF_TRACING
// and an appropriate section in CPictureEx::Load(HGLOBAL, DWORD). These functions
// won't be compiled and linked to your project unless you uncomment #define GIF_TRACING,
// so you don't have to worry.
//
// Warning: this code hasn't been subject to a heavy testing, so
// use it on your own risk. The author accepts no liability for the
// possible damage caused by this code.
//
// Version 1.0? 7 Aug 2001
//????????????? Initial release
//
// Version 1.1? 6 Sept 2001
//????????????? ATL version of the class
//
// Version 1.2? 14 Oct 2001
//????????????? - Fixed a problem with loading GIFs from resources
//??????????????? in MFC-version of the class for multi-modules apps.
//??????????????? Thanks to Ruben Avila-Carretero for finding this out.
//
//????????????? - Got rid of waitable timer in ThreadAnimation()
//??????????????? Now CPictureEx[Wnd] works in Win95 too.
//??????????????? Thanks to Alex Egiazarov and Wayne King for the idea.
//
//????????????? - Fixed a visual glitch of using SetBkColor.
//??????????????? Thanks to Kwangjin Lee for finding this out.
//
// Version 1.3? 10 Nov 2001
//????????????? - Fixed a DC leak. One DC leaked per each UnLoad()
//??????????????? (forgot to put a ReleaseDC() in the end of
//??????????????? CPictureExWnd::PrepareDC() function).
//
//????????????? - Now it is possible to set a clipping rectangle using
//??????????????? CPictureEx[Wnd]::SetPaintRect(const LPRECT) function.
//??????????????? The LPRECT parameter tells the class what portion of
//??????????????? a picture should it display. If the clipping rect is
//??????????????? not set, the whole picture is shown.
//??????????????? Thanks to Fabrice Rodriguez for the idea.
//
//????????????? - Added support for Stop/Draw. Now you can Stop() an
//??????????????? animated GIF, then Draw() it again, it will continue
//??????????????? animation from the frame it was stopped on. You can
//??????????????? also know if a GIF is currently playing with the
//??????????????? IsPlaying() function.
//????????????
//????????????? - Got rid of math.h and made m_bExitThread volatile.
//??????????????? Thanks to Piotr Sawicki for the suggestion.
//
//

#if !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)
#define AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <vector>
//#define GIF_TRACING? // uncomment it if you want detailed TRACEs

class CPictureEx : public CStatic
{
public:

struct TFrame??? // structure that keeps a single frame info
{
?IPicture *m_pPicture;? // pointer to the interface used for drawing
?SIZE???? m_frameSize;
?SIZE???? m_frameOffset;
?UINT???? m_nDelay;???? // delay (in 1/100s of a second)
?UINT???? m_nDisposal;? // disposal method
};

#pragma pack(1)?? // turn byte alignment on

enum GIFBlockTypes
{
?BLOCK_UNKNOWN,
?BLOCK_APPEXT,
?BLOCK_COMMEXT,
?BLOCK_CONTROLEXT,
?BLOCK_PLAINTEXT,
?BLOCK_IMAGE,
?BLOCK_TRAILER
};

enum ControlExtValues // graphic control extension packed field values
{
?GCX_PACKED_DISPOSAL,? // disposal method
?GCX_PACKED_USERINPUT,
?GCX_PACKED_TRANSPCOLOR
};

enum LSDPackedValues? // logical screen descriptor packed field values
{
?LSD_PACKED_GLOBALCT,
?LSD_PACKED_CRESOLUTION,
?LSD_PACKED_SORT,
?LSD_PACKED_GLOBALCTSIZE
};

enum IDPackedValues?? // image descriptor packed field values
{
?ID_PACKED_LOCALCT,
?ID_PACKED_INTERLACE,
?ID_PACKED_SORT,
?ID_PACKED_LOCALCTSIZE
};

struct TGIFHeader?????? // GIF header?
{
?char m_cSignature[3]; // Signature - Identifies the GIF Data Stream
??????? // This field contains the fixed value 'GIF'
?char m_cVersion[3];?// Version number. May be one of the following:
??????// "87a" or "89a"
};

struct TGIFLSDescriptor // Logical Screen Descriptor
{
?WORD m_wWidth;?// 2 bytes. Logical screen width
?WORD m_wHeight; // 2 bytes. Logical screen height

?unsigned char m_cPacked;????? // packed field?

?unsigned char m_cBkIndex;???? // 1 byte. Background color index
?unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio
?inline int GetPackedValue(enum LSDPackedValues Value);
};

struct TGIFAppExtension // application extension block
{
?unsigned char m_cExtIntroducer; // extension introducer (0x21)
?unsigned char m_cExtLabel; // app. extension label (0xFF)
?unsigned char m_cBlockSize; // fixed value of 11
?char m_cAppIdentifier[8];?? // application identifier
?char m_cAppAuth[3];? // application authentication code
};

struct TGIFControlExt // graphic control extension block
{
?unsigned char m_cExtIntroducer; // extension introducer (0x21)
?unsigned char m_cControlLabel;? // control extension label (0xF9)
?unsigned char m_cBlockSize; // fixed value of 4
?unsigned char m_cPacked;??? // packed field
?WORD m_wDelayTime;?// delay time
?unsigned char m_cTColorIndex; // transparent color index
?unsigned char m_cBlockTerm;?? // block terminator (0x00)
public:
?inline int GetPackedValue(enum ControlExtValues Value);
};

struct TGIFCommentExt? // comment extension block
{
?unsigned char m_cExtIntroducer; // extension introducer (0x21)
?unsigned char m_cCommentLabel;? // comment extension label (0xFE)
};

struct TGIFPlainTextExt // plain text extension block
{
?unsigned char m_cExtIntroducer;? // extension introducer (0x21)
?unsigned char m_cPlainTextLabel; // text extension label (0x01)
?unsigned char m_cBlockSize; // fixed value of 12
?WORD m_wLeftPos;??? // text grid left position
?WORD m_wTopPos;???? // text grid top position
?WORD m_wGridWidth;? // text grid width
?WORD m_wGridHeight; // text grid height
?unsigned char m_cCellWidth;? // character cell width
?unsigned char m_cCellHeight; // character cell height
?unsigned char m_cFgColor; // text foreground color index
?unsigned char m_cBkColor; // text background color index
};

struct TGIFImageDescriptor // image descriptor block
{
?unsigned char m_cImageSeparator; // image separator byte (0x2C)
?WORD m_wLeftPos; // image left position
?WORD m_wTopPos;? // image top position
?WORD m_wWidth;?? // image width
?WORD m_wHeight;? // image height
?unsigned char m_cPacked; // packed field
?inline int GetPackedValue(enum IDPackedValues Value);
};

#pragma pack() // turn byte alignment off

public:
?BOOL GetPaintRect(RECT *lpRect);
?BOOL SetPaintRect(const RECT *lpRect);
?CPictureEx();
?virtual ~CPictureEx();
?void Stop();?? // stops animation
?void UnLoad(); // stops animation plus releases all resources

?BOOL IsGIF() const;
?BOOL IsPlaying() const;
?BOOL IsAnimatedGIF() const;
?SIZE GetSize() const;
?int GetFrameCount() const;
?COLORREF GetBkColor() const;
?void SetBkColor(COLORREF clr);

?// draws the picture (starts an animation thread if needed)
?// if an animation was previously stopped by Stop(),
?// continues it from the last displayed frame
?BOOL Draw();

?// loads a picture from a file
?// i.e. Load(_T("mypic.gif"));
?BOOL Load(LPCTSTR szFileName);

?// loads a picture from a global memory block (allocated by GlobalAlloc)
?// Warning: this function DOES NOT free the global memory, pointed to by hGlobal
?BOOL Load(HGLOBAL hGlobal, DWORD dwSize);

?// loads a picture from a program resource
?// i.e. Load(IDR_MYPIC,_T("GIFTYPE"));
?BOOL Load(UINT nResourceID , LPCTSTR szResourceType);

protected:

#ifdef GIF_TRACING
?void EnumGIFBlocks();
?void WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize);
#endif // GIF_TRACING

?RECT m_PaintRect;
?SIZE m_PictureSize;
?COLORREF m_clrBackground;
?UINT m_nCurrFrame;
?UINT m_nDataSize;
?UINT m_nCurrOffset;
?UINT m_nGlobalCTSize;
?BOOL m_bIsGIF;
?BOOL m_bIsPlaying;
?volatile BOOL m_bExitThread;
?BOOL m_bIsInitialized;
?HDC m_hMemDC;

?HDC m_hDispMemDC;
?HBITMAP m_hDispMemBM;
?HBITMAP m_hDispOldBM;

?HBITMAP m_hBitmap;
?HBITMAP m_hOldBitmap;
?HANDLE m_hThread;
?HANDLE m_hExitEvent;
?IPicture * m_pPicture;
?TGIFHeader * m_pGIFHeader;
?unsigned char * m_pRawData;
?TGIFLSDescriptor * m_pGIFLSDescriptor;
?std::vector<TFrame> m_arrFrames;

?void ThreadAnimation();
?static UINT WINAPI _ThreadAnimation(LPVOID pParam);

?int GetNextBlockLen() const;
?BOOL SkipNextBlock();
?BOOL SkipNextGraphicBlock();
?BOOL PrepareDC(int nWidth, int nHeight);
?void ResetDataPointer();
?enum GIFBlockTypes GetNextBlock() const;
?UINT GetSubBlocksLen(UINT nStartingOffset) const;
?HGLOBAL GetNextGraphicBlock(UINT *pBlockLen, UINT *pDelay,
??SIZE *pBlockSize, SIZE *pBlockOffset, UINT *pDisposal);

?// Generated message map functions
?//{{AFX_MSG(CPictureEx)
?afx_msg void OnDestroy();
?afx_msg void OnPaint();
?//}}AFX_MSG
?
?DECLARE_MESSAGE_MAP()
};

#endif // !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)

?

2.PictureEx.cpp文件:

//
// PictureEx.cpp: implementation of the CPictureEx class.
//
// Picture displaying control with support for the following formats:
// GIF (including animated GIF87a and GIF89a), JPEG, BMP, WMF, ICO, CUR
//
// Written by Oleg Bykov (oleg_bykoff@rsdn.ru)
// Copyright (c) 2001
//
// To use CPictureEx, follow these steps:
//?? - place a static control on your dialog (either a text or a bitmap)
//?? - change its identifier to something else (e.g. IDC_MYPIC)
//?? - associate a CStatic with it using ClassWizard
//?? - in your dialog's header file replace CStatic with CPictureEx
//???? (don't forget to #include "PictureEx.h" and add
//???? PictureEx.h and PictureEx.cpp to your project)
//?? - call one of the overloaded CPictureEx::Load() functions somewhere
//???? (OnInitDialog is a good place to start)
//?? - if the preceding Load() succeeded call Draw()
//?
// You can also add the control by defining a member variable of type
// CPictureEx, calling CPictureEx::Create (derived from CStatic), then
// CPictureEx::Load and CPictureEx::Draw.
//
// By default, the control initializes its background to COLOR_3DFACE
// (see CPictureEx::PrepareDC()). You can change the background by
// calling CPictureEx::SetBkColor(COLORREF) after CPictureEx::Load().
//
// I decided to leave in the class the functions to write separate frames from
// animated GIF to disk. If you want to use them, uncomment #define GIF_TRACING
// and an appropriate section in CPictureEx::Load(HGLOBAL, DWORD). These functions
// won't be compiled and linked to your project unless you uncomment #define GIF_TRACING,
// so you don't have to worry.
//
// Warning: this code hasn't been subject to a heavy testing, so
// use it on your own risk. The author accepts no liability for the
// possible damage caused by this code.
//
// Version 1.0? 7 Aug 2001
//????????????? Initial release
//
// Version 1.1? 6 Sept 2001
//????????????? ATL version of the class
//
// Version 1.2? 14 Oct 2001
//????????????? - Fixed a problem with loading GIFs from resources
//??????????????? in MFC-version of the class for multi-modules apps.
//??????????????? Thanks to Ruben Avila-Carretero for finding this out.
//
//????????????? - Got rid of waitable timer in ThreadAnimation()
//??????????????? Now CPictureEx[Wnd] works in Win95 too.
//??????????????? Thanks to Alex Egiazarov and Wayne King for the idea.
//
//????????????? - Fixed a visual glitch of using SetBkColor.
//??????????????? Thanks to Kwangjin Lee for finding this out.
//
// Version 1.3? 10 Nov 2001
//????????????? - Fixed a DC leak. One DC leaked per each UnLoad()
//??????????????? (forgot to put a ReleaseDC() in the end of
//??????????????? CPictureExWnd::PrepareDC() function).
//
//????????????? - Now it is possible to set a clipping rectangle using
//??????????????? CPictureEx[Wnd]::SetPaintRect(const LPRECT) function.
//??????????????? The LPRECT parameter tells the class what portion of
//??????????????? a picture should it display. If the clipping rect is
//??????????????? not set, the whole picture is shown.
//??????????????? Thanks to Fabrice Rodriguez for the idea.
//
//????????????? - Added support for Stop/Draw. Now you can Stop() an
//??????????????? animated GIF, then Draw() it again, it will continue
//??????????????? animation from the frame it was stopped on. You can
//??????????????? also know if a GIF is currently playing with the
//??????????????? IsPlaying() function.
//????????????
//????????????? - Got rid of math.h and made m_bExitThread volatile.
//??????????????? Thanks to Piotr Sawicki for the suggestion.
//
//

#include "stdafx.h"
#include "PictureEx.h"
#include <process.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//
// Nested structures member functions
//

inline int CPictureEx::TGIFControlExt::GetPackedValue(enum ControlExtValues Value)
{
?int nRet = (int)m_cPacked;
?switch (Value)
?{
?case GCX_PACKED_DISPOSAL:
??nRet = (nRet & 28) >> 2;
??break;

?case GCX_PACKED_USERINPUT:
??nRet = (nRet & 2) >> 1;
??break;

?case GCX_PACKED_TRANSPCOLOR:
??nRet &= 1;
??break;
?};

?return nRet;
}

inline int CPictureEx::TGIFLSDescriptor::GetPackedValue(enum LSDPackedValues Value)
{
?int nRet = (int)m_cPacked;

?switch (Value)
?{
?case LSD_PACKED_GLOBALCT:
??nRet = nRet >> 7;
??break;

?case LSD_PACKED_CRESOLUTION:
??nRet = ((nRet & 0x70) >> 4) + 1;
??break;

?case LSD_PACKED_SORT:
??nRet = (nRet & 8) >> 3;
??break;

?case LSD_PACKED_GLOBALCTSIZE:
??nRet &= 7;
??break;
?};

?return nRet;
}

inline int CPictureEx::TGIFImageDescriptor::GetPackedValue(enum IDPackedValues Value)
{
?int nRet = (int)m_cPacked;

?switch (Value)
?{
?case ID_PACKED_LOCALCT:
??nRet >>= 7;
??break;

?case ID_PACKED_INTERLACE:
??nRet = ((nRet & 0x40) >> 6);
??break;

?case ID_PACKED_SORT:
??nRet = (nRet & 0x20) >> 5;
??break;

?case ID_PACKED_LOCALCTSIZE:
??nRet &= 7;
??break;
?};

?return nRet;
}


//
// Construction/Destruction
//

CPictureEx::CPictureEx()
{
?// check structures size
?ASSERT(sizeof(TGIFImageDescriptor) == 10);
?ASSERT(sizeof(TGIFAppExtension)??? == 14);
?ASSERT(sizeof(TGIFPlainTextExt)??? == 15);
?ASSERT(sizeof(TGIFLSDescriptor)??? ==? 7);
?ASSERT(sizeof(TGIFControlExt)??? ==? 8);
?ASSERT(sizeof(TGIFCommentExt)??? ==? 2);
?ASSERT(sizeof(TGIFHeader)???? ==? 6);

?m_pGIFLSDescriptor = NULL;
?m_pGIFHeader??? = NULL;
?m_pPicture???? = NULL;
?m_pRawData???? = NULL;
?m_hThread???? = NULL;
?m_hBitmap????????? = NULL;
?m_hMemDC???? = NULL;

?m_hDispMemDC?????? = NULL;
?m_hDispMemBM?????? = NULL;
?m_hDispOldBM?????? = NULL;

?m_bIsInitialized?? = FALSE;
?m_bExitThread??? = FALSE;
?m_bIsPlaying?????? = FALSE;
?m_bIsGIF???? = FALSE;
?m_clrBackground??? = RGB(255,255,255); // white by default
?m_nGlobalCTSize??? = 0;
?m_nCurrOffset??? = 0;
?m_nCurrFrame??? = 0;
?m_nDataSize???? = 0;
?m_PictureSize.cx = m_PictureSize.cy = 0;
?SetRect(&m_PaintRect,0,0,0,0);

?m_hExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
}

CPictureEx::~CPictureEx()
{
?UnLoad();
?CloseHandle(m_hExitEvent);
}

BEGIN_MESSAGE_MAP(CPictureEx, CStatic)
?//{{AFX_MSG_MAP(CPictureEx)
?ON_WM_DESTROY()
?ON_WM_PAINT()
?//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CPictureEx::Load(HGLOBAL hGlobal, DWORD dwSize)
{
?IStream *pStream = NULL;
?UnLoad();

?if (!(m_pRawData = reinterpret_cast<unsigned char*> (GlobalLock(hGlobal))) )
?{
??TRACE(_T("Load: Error locking memory\n"));
??return FALSE;
?};

?m_nDataSize = dwSize;
?m_pGIFHeader = reinterpret_cast<TGIFHeader *> (m_pRawData);

?if ((memcmp(&m_pGIFHeader->m_cSignature,"GIF",3) != 0) &&
??((memcmp(&m_pGIFHeader->m_cVersion,"87a",3) != 0) ||
?? (memcmp(&m_pGIFHeader->m_cVersion,"89a",3) != 0)) )
?{
?// it's neither GIF87a nor GIF89a
?// do the default processing

??// clear GIF variables
??m_pRawData = NULL;
??GlobalUnlock(hGlobal);

??// don't delete memory on object's release
??if (CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK)
???return FALSE;

??if (OleLoadPicture(pStream,dwSize,FALSE,IID_IPicture,
???reinterpret_cast<LPVOID *>(&m_pPicture)) != S_OK)
??{
???pStream->Release();
???return FALSE;
??};
??pStream->Release();

??// store picture's size

??long hmWidth;
??long hmHeight;
??m_pPicture->get_Width(&hmWidth);
??m_pPicture->get_Height(&hmHeight);

??HDC hDC = ::GetDC(m_hWnd);
??m_PictureSize.cx = MulDiv(hmWidth, GetDeviceCaps(hDC,LOGPIXELSX), 2540);
??m_PictureSize.cy = MulDiv(hmHeight, GetDeviceCaps(hDC,LOGPIXELSY), 2540);
??::ReleaseDC(m_hWnd,hDC);
?}
?else
?{
??// it's a GIF
??m_bIsGIF = TRUE;
??m_pGIFLSDescriptor = reinterpret_cast<TGIFLSDescriptor *>
???(m_pRawData + sizeof(TGIFHeader));
??if (m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCT) == 1)
??{
???// calculate the globat color table size
???m_nGlobalCTSize = static_cast<int>
????(3* (1 << (m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCTSIZE)+1)));
???// get the background color if GCT is present
???unsigned char *pBkClr = m_pRawData + sizeof(TGIFHeader) +
????sizeof(TGIFLSDescriptor) + 3*m_pGIFLSDescriptor->m_cBkIndex;
???m_clrBackground = RGB(pBkClr[0],pBkClr[1],pBkClr[2]);
??};

??// store the picture's size
??m_PictureSize.cx = m_pGIFLSDescriptor->m_wWidth;
??m_PictureSize.cy = m_pGIFLSDescriptor->m_wHeight;

??// determine frame count for this picture
??UINT nFrameCount=0;
??ResetDataPointer();
??while (SkipNextGraphicBlock())
???nFrameCount++;

#ifdef GIF_TRACING
??TRACE(
???_T(" -= GIF encountered\n"
????? "Logical Screen dimensions = %dx%d\n"
????? "Global color table = %d\n"
????? "Color depth = %d\n"
????? "Sort flag = %d\n"
????? "Size of Global Color Table = %d\n"
????? "Background color index = %d\n"
????? "Pixel aspect ratio = %d\n"
????? "Frame count = %d\n"
????? "Background color = %06Xh\n\n"
???? ),
???m_pGIFLSDescriptor->m_wWidth,
???m_pGIFLSDescriptor->m_wHeight,
???m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCT),
???m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_CRESOLUTION),
???m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_SORT),
???m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCTSIZE),
???m_pGIFLSDescriptor->m_cBkIndex,
???m_pGIFLSDescriptor->m_cPixelAspect,
???nFrameCount,
???m_clrBackground
???);
??EnumGIFBlocks();
#endif

??if (nFrameCount == 0) // it's an empty GIF!
??{
???m_pRawData = NULL;
???GlobalUnlock(hGlobal);
???return FALSE;
??};

??// now check the frame count
??// if there's only one frame, no need to animate this GIF
??// therefore, treat it like any other pic

??if (nFrameCount == 1)
??{
???// clear GIF variables
???m_pRawData = NULL;
???GlobalUnlock(hGlobal);

???// don't delete memory on object's release
???if (CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK)
????return FALSE;

???if (OleLoadPicture(pStream,dwSize,FALSE,IID_IPicture,
????(LPVOID *)&m_pPicture) != S_OK)
???{
????pStream->Release();
????return FALSE;
???};

???pStream->Release();
??}
??else
??{
??// if, on the contrary, there are several frames
??// then store separate frames in an array

???TFrame frame;
???UINT nBlockLen;
???HGLOBAL hFrameData;
???UINT nCurFrame = 0;

???ResetDataPointer();
???while (hFrameData = GetNextGraphicBlock(&nBlockLen,
????&frame.m_nDelay, &frame.m_frameSize,
????&frame.m_frameOffset, &frame.m_nDisposal) )
???{
????#ifdef GIF_TRACING
????//
????// uncomment the following strings if you want
????// to write separate frames on disk
????//
????//?CString szName;
????//?szName.Format(_T("%.4d.gif"),nCurFrame);
????//?WriteDataOnDisk(szName,hFrameData,nBlockLen);
????//?nCurFrame++;
????#endif // GIF_TRACING

????IStream *pStream = NULL;

????// delete memory on object's release
????if (CreateStreamOnHGlobal(hFrameData,TRUE,&pStream) != S_OK)
????{
?????GlobalFree(hFrameData);
?????continue;
????};

????if (OleLoadPicture(pStream,nBlockLen,FALSE,
?????IID_IPicture,
?????reinterpret_cast<LPVOID *>(&frame.m_pPicture)) != S_OK)
????{
?????pStream->Release();
?????continue;
????};
????pStream->Release();
???
????// everything went well, add this frame
????m_arrFrames.push_back(frame);
???};

???// clean after ourselves
???m_pRawData = NULL;
???GlobalUnlock(hGlobal);

???if (m_arrFrames.empty()) // couldn't load any frames
????return FALSE;
??};
?}; // if (!IsGIF...

?return PrepareDC(m_PictureSize.cx,m_PictureSize.cy);
}

void CPictureEx::UnLoad()
{
?Stop();
?if (m_pPicture)
?{
??m_pPicture->Release();
??m_pPicture = NULL;
?};
?
?std::vector<TFrame>::iterator it;
?for (it=m_arrFrames.begin();it<m_arrFrames.end();it++)
??(*it).m_pPicture->Release();
?m_arrFrames.clear();

?if (m_hMemDC)
?{
??SelectObject(m_hMemDC,m_hOldBitmap);
??::DeleteDC(m_hMemDC);
??::DeleteObject(m_hBitmap);
??m_hMemDC? = NULL;
??m_hBitmap = NULL;
?};

?if (m_hDispMemDC)
?{
??SelectObject(m_hDispMemDC,m_hDispOldBM);
??::DeleteDC(m_hDispMemDC);
??::DeleteObject(m_hDispMemBM);
??m_hDispMemDC? = NULL;
??m_hDispMemBM = NULL;
?};

?SetRect(&m_PaintRect,0,0,0,0);
?m_pGIFLSDescriptor = NULL;
?m_pGIFHeader??? = NULL;
?m_pRawData???? = NULL;
?m_hThread???? = NULL;
?m_bIsInitialized?? = FALSE;
?m_bExitThread??? = FALSE;
?m_bIsGIF???? = FALSE;
?m_clrBackground??? = RGB(255,255,255); // white by default
?m_nGlobalCTSize??? = 0;
?m_nCurrOffset??? = 0;
?m_nCurrFrame??? = 0;
?m_nDataSize???? = 0;
}

BOOL CPictureEx::Draw()
{
?if (!m_bIsInitialized)
?{
??TRACE(_T("Call one of the CPictureEx::Load() member functions before calling Draw()\n"));
??return FALSE;
?};

?if (IsAnimatedGIF())
?{
?// the picture needs animation
?// we'll start the thread that will handle it for us
?
??unsigned int nDummy;
??m_hThread = (HANDLE) _beginthreadex(NULL,0,_ThreadAnimation,this,
???CREATE_SUSPENDED,&nDummy);
??if (!m_hThread)
??{
???TRACE(_T("Draw: Couldn't start a GIF animation thread\n"));
???return FALSE;
??}
??else
???ResumeThread(m_hThread);
?}
?else
?{
??if (m_pPicture)
??{
???long hmWidth;
???long hmHeight;
???m_pPicture->get_Width(&hmWidth);
???m_pPicture->get_Height(&hmHeight);
???if (m_pPicture->Render(m_hMemDC, 0, 0, m_PictureSize.cx, m_PictureSize.cy,
????0, hmHeight, hmWidth, -hmHeight, NULL) == S_OK)
???{
????Invalidate(FALSE);
????return TRUE;
???};
??};
?};

?return FALSE;?
}

SIZE CPictureEx::GetSize() const
{
?return m_PictureSize;
}

BOOL CPictureEx::Load(LPCTSTR szFileName)
{
?ASSERT(szFileName);
?
?CFile file;
?HGLOBAL hGlobal;
?DWORD dwSize;

?if (!file.Open(szFileName,
????CFile::modeRead |
????CFile::shareDenyWrite) )
?{
??TRACE(_T("Load (file): Error opening file %s\n"),szFileName);
??return FALSE;
?};

?dwSize = file.GetLength();
?hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
?if (!hGlobal)
?{
??TRACE(_T("Load (file): Error allocating memory\n"));
??return FALSE;
?};
?
?char *pData = reinterpret_cast<char*>(GlobalLock(hGlobal));
?if (!pData)
?{
??TRACE(_T("Load (file): Error locking memory\n"));
??GlobalFree(hGlobal);
??return FALSE;
?};

?TRY
?{
??file.Read(pData,dwSize);
?}
?CATCH(CFileException, e);?????????????????????????????????????????
?{
??TRACE(_T("Load (file): An exception occured while reading the file %s\n"),
???szFileName);
??GlobalFree(hGlobal);
??e->Delete();
??file.Close();
??return FALSE;
?}
?END_CATCH
?GlobalUnlock(hGlobal);
?file.Close();

?BOOL bRetValue = Load(hGlobal,dwSize);
?GlobalFree(hGlobal);
?return bRetValue;
}

BOOL CPictureEx::Load(UINT nResourceID , LPCTSTR szResourceType)
{
?ASSERT(szResourceType);

?HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nResourceID),RT_GROUP_ICON) ;
?
?HRSRC hPicture = NULL ;
?FindResource(hInst,MAKEINTRESOURCE(nResourceID),szResourceType);

?HGLOBAL hResData;
?if (!hPicture || !(hResData = LoadResource(hInst,hPicture)))
?{
??return FALSE;
?};
?DWORD dwSize = SizeofResource(hInst,hPicture);

?// hResData is not the real HGLOBAL (we can't lock it)
?// let's make it real

?HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
?if (!hGlobal)
?{
??TRACE(_T("Load (resource): Error allocating memory\n"));
??FreeResource(hResData);
??return FALSE;
?};
?
?char *pDest = reinterpret_cast<char *> (GlobalLock(hGlobal));
?char *pSrc = reinterpret_cast<char *> (LockResource(hResData));
?if (!pSrc || !pDest)
?{
??TRACE(_T("Load (resource): Error locking memory\n"));
??GlobalFree(hGlobal);
??FreeResource(hResData);
??return FALSE;
?};
?CopyMemory(pDest,pSrc,dwSize);
?FreeResource(hResData);
?GlobalUnlock(hGlobal);

?BOOL bRetValue = Load(hGlobal,dwSize);
?GlobalFree(hGlobal);
?return bRetValue;
}

void CPictureEx::ResetDataPointer()
{
?// skip header and logical screen descriptor
?m_nCurrOffset =
??sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize;
}

BOOL CPictureEx::SkipNextGraphicBlock()
{
?if (!m_pRawData) return FALSE;

?// GIF header + LSDescriptor [+ GCT] [+ Control block] + Data

?enum GIFBlockTypes nBlock;

?nBlock = GetNextBlock();

?while ((nBlock != BLOCK_CONTROLEXT) &&
???? (nBlock != BLOCK_IMAGE) &&
???? (nBlock != BLOCK_PLAINTEXT) &&
???? (nBlock != BLOCK_UNKNOWN) &&
???? (nBlock != BLOCK_TRAILER) )
?{
??if (!SkipNextBlock()) return NULL;
??nBlock = GetNextBlock();
?};

?if ((nBlock == BLOCK_UNKNOWN) ||
??(nBlock == BLOCK_TRAILER))
??return FALSE;

?// it's either a control ext.block, an image or a plain text

?if (GetNextBlockLen() <= 0) return FALSE;

?if (nBlock == BLOCK_CONTROLEXT)
?{
??if (!SkipNextBlock()) return FALSE;
??nBlock = GetNextBlock();

??// skip everything until we meet an image block or a plain-text block
??while ((nBlock != BLOCK_IMAGE) &&
????? (nBlock != BLOCK_PLAINTEXT) &&
????? (nBlock != BLOCK_UNKNOWN) &&
????? (nBlock != BLOCK_TRAILER) )
??{
???if (!SkipNextBlock()) return NULL;
???nBlock = GetNextBlock();
??};

??if ((nBlock == BLOCK_UNKNOWN) ||
???(nBlock == BLOCK_TRAILER))
???return FALSE;
?};

?// skip the found data block (image or plain-text)
?if (!SkipNextBlock()) return FALSE;

?return TRUE;
}

UINT CPictureEx::GetSubBlocksLen(UINT nStartingOffset) const
{
?UINT nRet = 0;
?UINT nCurOffset = nStartingOffset;

?while (m_pRawData[nCurOffset] != 0)
?{
??nRet += m_pRawData[nCurOffset]+1;
??nCurOffset += m_pRawData[nCurOffset]+1;
?};

?return nRet+1;
}

enum CPictureEx::GIFBlockTypes CPictureEx::GetNextBlock() const
{
?switch(m_pRawData[m_nCurrOffset])
?{
?case 0x21:
?// extension block
??switch(m_pRawData[m_nCurrOffset+1])
??{
??case 0x01:
??// plain text extension
???return BLOCK_PLAINTEXT;
???break;

??case 0xF9:
??// graphic control extension
???return BLOCK_CONTROLEXT;
???break;

??case 0xFE:
??// comment extension
???return BLOCK_COMMEXT;
???break;

??case 0xFF:
??// application extension
???return BLOCK_APPEXT;
???break;
??};
??break;
?
?case 0x3B:
?// trailer
??return BLOCK_TRAILER;
??break;

?case 0x2C:
?// image data
??return BLOCK_IMAGE;
??break;
?};

?return BLOCK_UNKNOWN;
}

BOOL CPictureEx::SkipNextBlock()
{
?if (!m_pRawData) return FALSE;

?int nLen = GetNextBlockLen();
?if ((nLen <= 0) || ((m_nCurrOffset+nLen) > m_nDataSize))
??return FALSE;

?m_nCurrOffset += nLen;
?return TRUE;
}

int CPictureEx::GetNextBlockLen() const
{
?GIFBlockTypes nBlock = GetNextBlock();

?int nTmp;

?switch(nBlock)
?{
?case BLOCK_UNKNOWN:
??return -1;
??break;

?case BLOCK_TRAILER:
??return 1;
??break;

?case BLOCK_APPEXT:
??nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFAppExtension));
??if (nTmp > 0)
???return sizeof(TGIFAppExtension)+nTmp;
??break;

?case BLOCK_COMMEXT:
??nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFCommentExt));
??if (nTmp > 0)
???return sizeof(TGIFCommentExt)+nTmp;
??break;

?case BLOCK_CONTROLEXT:
??return sizeof(TGIFControlExt);
??break;

?case BLOCK_PLAINTEXT:
??nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFPlainTextExt));
??if (nTmp > 0)
???return sizeof(TGIFPlainTextExt)+nTmp;
??break;

?case BLOCK_IMAGE:
??TGIFImageDescriptor *pIDescr =
???reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
??int nLCTSize = (int)
???(pIDescr->GetPackedValue(ID_PACKED_LOCALCT)*3*
???(1 << (pIDescr->GetPackedValue(ID_PACKED_LOCALCTSIZE)+1)));

??int nTmp = GetSubBlocksLen(m_nCurrOffset+
???sizeof(TGIFImageDescriptor) + nLCTSize + 1);
??if (nTmp > 0)
???return sizeof(TGIFImageDescriptor) + nLCTSize + 1 + nTmp;
??break;
?};

?return 0;
}

UINT WINAPI CPictureEx::_ThreadAnimation(LPVOID pParam)
{
?ASSERT(pParam);
?CPictureEx *pPic = reinterpret_cast<CPictureEx *> (pParam);

?pPic->m_bIsPlaying = TRUE;
?pPic->ThreadAnimation();
?pPic->m_bIsPlaying = FALSE;

?// this thread has finished its work so we close the handle
?CloseHandle(pPic->m_hThread);
?// and init the handle to zero (so that Stop() doesn't Wait on it)
?pPic->m_hThread = 0;
?return 0;
}

void CPictureEx::ThreadAnimation()
{
?// first, restore background (for stop/draw support)
?// disposal method #2
?if (m_arrFrames[m_nCurrFrame].m_nDisposal == 2)
?{
??HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
??if (hBrush)
??{
???RECT rect = {
????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cx + m_arrFrames[m_nCurrFrame].m_frameSize.cx,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cy + m_arrFrames[m_nCurrFrame].m_frameSize.cy };
???FillRect(m_hMemDC,&rect,hBrush);
???DeleteObject(hBrush);
??};
?}
?else
??// disposal method #3
??if (m_hDispMemDC && (m_arrFrames[m_nCurrFrame].m_nDisposal == 3) )
??{
???// put it back
???BitBlt(m_hMemDC,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
????m_arrFrames[m_nCurrFrame].m_frameSize.cx,
????m_arrFrames[m_nCurrFrame].m_frameSize.cy,
????m_hDispMemDC,0,0, SRCCOPY);
???// init variables
???SelectObject(m_hDispMemDC,m_hDispOldBM);
???DeleteDC(m_hDispMemDC); m_hDispMemDC = NULL;
???DeleteObject(m_hDispMemBM); m_hDispMemBM = NULL;
??};

?while (!m_bExitThread)
?{
??if (m_arrFrames[m_nCurrFrame].m_pPicture)
??{
??///
??// Before rendering a frame we should take care of what's
??// behind that frame. TFrame::m_nDisposal will be our guide:
??//?? 0 - no disposal specified (do nothing)
??//?? 1 - do not dispose (again, do nothing)
??//?? 2 - restore to background color (m_clrBackground)
??//?? 3 - restore to previous

??? disposal method #3
???if (m_arrFrames[m_nCurrFrame].m_nDisposal == 3)
???{
????// prepare a memory DC and store the background in it
????m_hDispMemDC = CreateCompatibleDC(m_hMemDC);
????m_hDispMemBM = CreateCompatibleBitmap(m_hMemDC,
???????m_arrFrames[m_nCurrFrame].m_frameSize.cx,
???????m_arrFrames[m_nCurrFrame].m_frameSize.cy);
????
????if (m_hDispMemDC && m_hDispMemBM)
????{
?????m_hDispOldBM = reinterpret_cast<HBITMAP> (SelectObject(m_hDispMemDC,m_hDispMemBM));
?????BitBlt(m_hDispMemDC,0,0,
??????m_arrFrames[m_nCurrFrame].m_frameSize.cx,
??????m_arrFrames[m_nCurrFrame].m_frameSize.cy,
??????m_hMemDC,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
??????SRCCOPY);
????};
???};
???///

???long hmWidth;
???long hmHeight;
???m_arrFrames[m_nCurrFrame].m_pPicture->get_Width(&hmWidth);
???m_arrFrames[m_nCurrFrame].m_pPicture->get_Height(&hmHeight);

???if (m_arrFrames[m_nCurrFrame].m_pPicture->Render(m_hMemDC,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
????m_arrFrames[m_nCurrFrame].m_frameSize.cx,
????m_arrFrames[m_nCurrFrame].m_frameSize.cy,
????0, hmHeight, hmWidth, -hmHeight, NULL) == S_OK)
???{
????Invalidate(FALSE);
???};
???
???if (m_bExitThread) break;

???// if the delay time is too short (like in old GIFs), wait for 100ms
???if (m_arrFrames[m_nCurrFrame].m_nDelay < 5)
????WaitForSingleObject(m_hExitEvent, 100);
???else
????WaitForSingleObject(m_hExitEvent, 10*m_arrFrames[m_nCurrFrame].m_nDelay);

???if (m_bExitThread) break;

???// disposal method #2
???if (m_arrFrames[m_nCurrFrame].m_nDisposal == 2)
???{
????HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
????if (hBrush)
????{
?????RECT rect = {
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cx + m_arrFrames[m_nCurrFrame].m_frameSize.cx,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cy + m_arrFrames[m_nCurrFrame].m_frameSize.cy };
?????FillRect(m_hMemDC,&rect,hBrush);
?????DeleteObject(hBrush);
????};
???}
???else
????if (m_hDispMemDC && (m_arrFrames[m_nCurrFrame].m_nDisposal == 3) )
????{
?????// put it back
?????BitBlt(m_hMemDC,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
??????m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
??????m_arrFrames[m_nCurrFrame].m_frameSize.cx,
??????m_arrFrames[m_nCurrFrame].m_frameSize.cy,
??????m_hDispMemDC,0,0, SRCCOPY);
?????// init variables
?????SelectObject(m_hDispMemDC,m_hDispOldBM);
?????DeleteDC(m_hDispMemDC); m_hDispMemDC = NULL;
?????DeleteObject(m_hDispMemBM); m_hDispMemBM = NULL;
????};
??};
??m_nCurrFrame++;
??if (m_nCurrFrame == m_arrFrames.size())
??{
???m_nCurrFrame
????= 0;
??// init the screen for the first frame,
???HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
???if (hBrush)
???{
????RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy};
????FillRect(m_hMemDC,&rect,hBrush);
????DeleteObject(hBrush);
???};
??};
?};
}

void CPictureEx::Stop()
{
?m_bIsPlaying = FALSE;
?m_bExitThread = TRUE;
?SetEvent(m_hExitEvent);
?if (m_hThread)
?{
??// we'll wait for 5 seconds then continue execution
??WaitForSingleObject(m_hThread,5000);
??CloseHandle(m_hThread);
??m_hThread = NULL;
?}

?// make it possible to Draw() again
?ResetEvent(m_hExitEvent);
?m_bExitThread = FALSE;
}

HGLOBAL CPictureEx::GetNextGraphicBlock(UINT *pBlockLen,
?UINT *pDelay, SIZE *pBlockSize, SIZE *pBlockOffset,
?UINT *pDisposal)
{
?if (!m_pRawData) return NULL;

?// GIF header + LSDescriptor [+ GCT] [+ Control block] + Data

?*pDisposal = 0;
?enum GIFBlockTypes nBlock;
?nBlock = GetNextBlock();

?while (
??(nBlock != BLOCK_CONTROLEXT) &&
??(nBlock != BLOCK_IMAGE) &&
??(nBlock != BLOCK_PLAINTEXT) &&
??(nBlock != BLOCK_UNKNOWN) &&
??(nBlock != BLOCK_TRAILER)
??)
?{
??if (!SkipNextBlock()) return NULL;
??nBlock = GetNextBlock();
?};

?if ((nBlock == BLOCK_UNKNOWN) ||
??(nBlock == BLOCK_TRAILER))
??return NULL;

?// it's either a control ext.block, an image or a plain text

?int nStart = m_nCurrOffset;
?int nBlockLen = GetNextBlockLen();

?if (nBlockLen <= 0) return NULL;

?if (nBlock == BLOCK_CONTROLEXT)
?{
??// get the following data
??TGIFControlExt *pControl =
???reinterpret_cast<TGIFControlExt *> (&m_pRawData[m_nCurrOffset]);
??// store delay time
??*pDelay = pControl->m_wDelayTime;
??// store disposal method
??*pDisposal = pControl->GetPackedValue(GCX_PACKED_DISPOSAL);

??if (!SkipNextBlock()) return NULL;
??nBlock = GetNextBlock();
??
??// skip everything until we find data to display
??// (image block or plain-text block)
??
??while (
???(nBlock != BLOCK_IMAGE) &&
???(nBlock != BLOCK_PLAINTEXT) &&
???(nBlock != BLOCK_UNKNOWN) &&
???(nBlock != BLOCK_TRAILER)
???)
??{
???if (!SkipNextBlock()) return NULL;
???nBlock = GetNextBlock();
???nBlockLen += GetNextBlockLen();
??};

??if ((nBlock == BLOCK_UNKNOWN) || (nBlock == BLOCK_TRAILER))
???return NULL;
??nBlockLen += GetNextBlockLen();
?}
?else
??*pDelay = -1; // to indicate that there was no delay value

?if (nBlock == BLOCK_IMAGE)
?{
??// store size and offsets
??TGIFImageDescriptor *pImage =
???reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
??pBlockSize->cx = pImage->m_wWidth;
??pBlockSize->cy = pImage->m_wHeight;
??pBlockOffset->cx = pImage->m_wLeftPos;
??pBlockOffset->cy = pImage->m_wTopPos;
?};

?if (!SkipNextBlock()) return NULL;

?HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED,
??sizeof(TGIFHeader) +
??sizeof(TGIFLSDescriptor) +
??m_nGlobalCTSize +
??nBlockLen +
??1);? // for the trailer

?if (!hGlobal) return NULL;

?int nOffset = 0;

?// GMEM_FIXED means we get a pointer
?unsigned char *pGlobal = reinterpret_cast<unsigned char *> (hGlobal);

?CopyMemory(pGlobal,m_pRawData,
??sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize);
?nOffset += sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize;

?CopyMemory(pGlobal + nOffset,&m_pRawData[nStart], nBlockLen);
?nOffset += nBlockLen;

?pGlobal[nOffset] = 0x3B; // trailer
?nOffset++;

?*pBlockLen = nOffset;

?return hGlobal;
}

BOOL CPictureEx::IsGIF() const
{
?return m_bIsGIF;
}

BOOL CPictureEx::IsAnimatedGIF() const
{
?return (m_bIsGIF && (m_arrFrames.size() > 1));
}

BOOL CPictureEx::IsPlaying() const
{
?return m_bIsPlaying;
}

int CPictureEx::GetFrameCount() const
{
?if (!IsAnimatedGIF())
??return 0;

?return m_arrFrames.size();
}

COLORREF CPictureEx::GetBkColor() const
{
?return m_clrBackground;
}

void CPictureEx::OnPaint()
{
?CPaintDC dc(this); // device context for painting

?LONG nPaintWidth = m_PaintRect.right-m_PaintRect.left;

?if (nPaintWidth > 0)
?{
??LONG nPaintHeight = m_PaintRect.bottom - m_PaintRect.top;
??::BitBlt(dc.m_hDC, 0, 0, nPaintWidth, nPaintHeight,?
???m_hMemDC, m_PaintRect.left, m_PaintRect.top, SRCCOPY);
?}
?else
?{
??::BitBlt(dc.m_hDC, 0, 0, m_PictureSize.cx, m_PictureSize.cy,
???m_hMemDC, 0, 0, SRCCOPY);
?};
}

BOOL CPictureEx::PrepareDC(int nWidth, int nHeight)
{
?SetWindowPos(NULL,0,0,nWidth,nHeight,SWP_NOMOVE | SWP_NOZORDER);

?HDC hWinDC = ::GetDC(m_hWnd);
?if (!hWinDC) return FALSE;
?
?m_hMemDC = CreateCompatibleDC(hWinDC);
?if (!m_hMemDC)
?{
??::ReleaseDC(m_hWnd,hWinDC);
??return FALSE;
?};

?m_hBitmap? = CreateCompatibleBitmap(hWinDC,nWidth,nHeight);
?if (!m_hBitmap)
?{
??::ReleaseDC(m_hWnd,hWinDC);
??::DeleteDC(m_hMemDC);
??return FALSE;
?};

?m_hOldBitmap = reinterpret_cast<HBITMAP>
??????(SelectObject(m_hMemDC,m_hBitmap));
?
?// fill the background
?m_clrBackground = GetSysColor(COLOR_3DFACE);
?RECT rect = {0,0,nWidth,nHeight};
?FillRect(m_hMemDC,&rect,(HBRUSH)(COLOR_WINDOW));

?::ReleaseDC(m_hWnd,hWinDC);
?m_bIsInitialized = TRUE;
?return TRUE;
}

void CPictureEx::OnDestroy()
{
?Stop();?
?CStatic::OnDestroy();
}

void CPictureEx::SetBkColor(COLORREF clr)
{
?if (!m_bIsInitialized) return;

?m_clrBackground = clr;

?HBRUSH hBrush = CreateSolidBrush(clr);
?if (hBrush)
?{
??RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy};
??FillRect(m_hMemDC,&rect,hBrush);
??DeleteObject(hBrush);
?};
}

#ifdef GIF_TRACING
void CPictureEx::WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize)
{
?CFile file;

?if (!file.Open(szFileName,
???CFile::modeCreate |
???CFile::modeWrite |
???CFile::shareDenyNone))
?{
??TRACE(_T("WriteData: Error creating file %s\n"),szFileName);
??return;
?};

?char *pData = reinterpret_cast<char *> (GlobalLock(hData));
?if (!pData)
?{
??TRACE(_T("WriteData: Error locking memory\n"));
??return;
?};

?TRY
?{
??file.Write(pData,dwSize);
?}
?CATCH(CFileException, e);?????????????????????????????????????????
?{
??TRACE(_T("WriteData: An exception occured while writing to the file %s\n"),
???szFileName);
??e->Delete();
??GlobalUnlock(hData);
??file.Close();
??return;
?}
?END_CATCH
?
?GlobalUnlock(hData);
?file.Close();
}

void CPictureEx::EnumGIFBlocks()
{
?enum GIFBlockTypes nBlock;

?ResetDataPointer();
?while(m_nCurrOffset < m_nDataSize)
?{
??nBlock = GetNextBlock();
??switch(nBlock)
??{
??case BLOCK_UNKNOWN:
???TRACE(_T("- Unknown block\n"));
???return;
???break;

??case BLOCK_TRAILER:
???TRACE(_T("- Trailer block\n"));
???break;

??case BLOCK_APPEXT:
???TRACE(_T("- Application extension block\n"));
???break;

??case BLOCK_COMMEXT:
???TRACE(_T("- Comment extension block\n"));
???break;

??case BLOCK_CONTROLEXT:
???{
???TGIFControlExt *pControl =
????reinterpret_cast<TGIFControlExt *> (&m_pRawData[m_nCurrOffset]);
???TRACE(_T("- Graphic control extension block (delay %d, disposal %d)\n"),
?????pControl->m_wDelayTime, pControl->GetPackedValue(GCX_PACKED_DISPOSAL));
???};
???break;

??case BLOCK_PLAINTEXT:
???TRACE(_T("- Plain text extension block\n"));
???break;

??case BLOCK_IMAGE:
???TGIFImageDescriptor *pIDescr =
????reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
???TRACE(_T("- Image data block (%dx%d? %d,%d)\n"),
?????pIDescr->m_wWidth,
?????pIDescr->m_wHeight,
?????pIDescr->m_wLeftPos,
?????pIDescr->m_wTopPos);
???break;
??};

??SkipNextBlock();?
?};

?TRACE(_T("\n"));
}
#endif // GIF_TRACING

BOOL CPictureEx::SetPaintRect(const RECT *lpRect)
{
?return CopyRect(&m_PaintRect, lpRect);
}

BOOL CPictureEx::GetPaintRect(RECT *lpRect)
{
?return CopyRect(lpRect, &m_PaintRect);
}

?

3.dlg頭文件定義:CPictureEx *pAutoGif;

?? 要包含#include "PictureEx.h"

4.dlg的cpp文件實現動態加載gif:

void C**Dlg::OnOK()
{
?// TODO: Add extra validation here
?pAutoGif=new CPictureEx();
?pAutoGif->Create(NULL,WS_CHILD | WS_VISIBLE |SS_ENHMETAFILE,CRect(50,50,100,100),this,1234);
??? if(pAutoGif->Load(_T("g1.gif")))
??pAutoGif->Draw();
?//CDialog::OnOK();
}

5.靜態加載:可以預先加入圖片控件,在ClassWiard中為圖片控件加入CSatic控制變量m_GifPic,然后將CSatic更改成CPictureEx的變量,當然要加上#include "PictureEx.h",可以將gif預先通過resourceview導入到工程中,之后可以在OnInitDialog()加載:

if (m_GifPic.Load(MAKEINTRESOURCE(IDR_GIF),_T("Gif")))//IDR_GIF導入工程gif的id屬性
m_GifPic.Draw();

6.可以在onpaint()中移動加載gif的圖片控件:

CRect rc =CRect(100,400,150,450);

?m_GifPic.MoveWindow(&rc,true);

?m_GifPic.Draw();

?

總結

以上是生活随笔為你收集整理的vc应用CPictureEx类(重载CStatic类)加载gif动画的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲午夜精品久久久久久久久久久久 | 天天操天天添天天吹 | 日韩 精品 一区 国产 麻豆 | www天天干 | 免费av大全 | 亚洲天天摸日日摸天天欢 | 亚洲成aⅴ人在线观看 | 亚洲精品影视在线观看 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 在线色资源 | 观看免费av | a久久免费视频 | 国产精品男女 | 中文字幕免费观看全部电影 | 热久久精品在线 | 福利一区在线视频 | 国产高清永久免费 | 免费观看国产成人 | 欧美一区二区视频97 | 久久久久久久影院 | 在线中文字母电影观看 | 亚州精品在线视频 | 在线观看成人av | 亚洲男男gⅴgay双龙 | 一区二区欧美在线观看 | 国产a免费 | 九九色综合 | 国产黄色大片免费看 | 国产伦精品一区二区三区免费 | 精品一区欧美 | 在线不卡的av | 正在播放 国产精品 | 天天干天天操av | 激情欧美在线观看 | 天天干天天操天天射 | 欧美精品中文在线免费观看 | 欧美一二三视频 | 97精品超碰一区二区三区 | 国产伦精品一区二区三区照片91 | 欧美精品久久久久久久久久白贞 | 国产最新视频在线 | 99视频在线免费播放 | 国产伦理久久精品久久久久_ | 玖玖爱国产在线 | 国产二级视频 | 91精品国产亚洲 | 天天天色综合 | 久操伊人 | 欧美日韩一区二区三区免费视频 | 丁香六月天婷婷 | 欧美色综合天天久久综合精品 | 91精品网站在线观看 | 欧美日韩在线电影 | 国内精品久久久久影院一蜜桃 | 亚州精品一二三区 | 国产又粗又猛又色又黄视频 | 超碰97国产 | 欧美网址在线观看 | 久久国产香蕉视频 | 黄色一级大片在线免费看国产一 | 天天透天天插 | 亚洲精品视频在线观看视频 | 久久精品中文字幕一区二区三区 | 日韩久久精品一区二区三区下载 | 最近免费中文字幕mv在线视频3 | 亚洲精品在线一区二区 | 在线免费高清视频 | 久久国产日韩 | 久久成人高清视频 | 国产精品视频大全 | 精品视频9999 | 日本不卡久久 | 中文字幕免费成人 | 久操中文字幕在线观看 | 亚洲三级网 | 日韩簧片在线观看 | 精品免费在线视频 | 波多野结衣电影一区二区三区 | 日日爱影视 | 看黄色91 | 日韩欧美黄色网址 | www.天天射| 亚洲1区 在线 | 国产黄大片在线观看 | 久久综合色影院 | 久久黄页| 黄色特级一级片 | 久久艹久久 | 免费亚洲成人 | 国产精品热视频 | 九九视频热 | 久久视奸 | 国产片免费在线观看视频 | 国产成人免费高清 | 国产在线一区观看 | 狠狠色狠狠色综合日日92 | 成人一区二区三区中文字幕 | 超碰官网 | 日韩电影中文字幕在线观看 | 五月婷婷久久丁香 | 亚洲国产中文字幕在线 | 亚洲国产一区av | 99情趣网视频 | 国产成人久久精品一区二区三区 | 国产精品一区专区欧美日韩 | 在线观看v片 | 亚洲黄色三级 | 免费观看的黄色片 | 欧美黄色免费 | 91丨九色丨国产在线观看 | 亚洲黄色激情小说 | 欧美日韩久久久 | 国产精品第2页 | 日韩中文字幕在线不卡 | 久久久久久久网站 | 久久毛片网站 | av电影在线观看完整版一区二区 | 精品播放| av中文字幕av | 国产视频午夜 | 国产午夜影院 | 国产三级视频在线 | 久久成人一区 | 亚洲精品麻豆 | 日韩精品一区二区三区免费观看 | 成人国产精品久久久 | 久久精品视频在线 | 成人午夜免费福利 | 成人欧美一区二区三区黑人麻豆 | 狠狠做深爱婷婷综合一区 | 中文字幕在线观看91 | 丁香五香天综合情 | 婷婷视频| 精品久久免费 | 国产精品日韩久久久久 | 91精品影视 | 丁香在线 | 日本在线观看黄色 | 99这里都是精品 | 综合色伊人 | 国产精品久久久久久久久久东京 | 日日操操 | 色综合久久综合 | 六月丁香伊人 | 国产精品欧美激情在线观看 | 亚洲精品www久久久久久 | 色偷偷网站视频 | 日本精品久久久一区二区三区 | 国产精品2区 | 欧美精品黑人性xxxx | 成人a v视频| 国产又粗又猛又色又黄视频 | 中文字幕你懂的 | 日韩激情视频在线观看 | 婷婷丁香国产 | 久操视频在线免费看 | 久久五月情影视 | 成人在线免费小视频 | 久久久伦理 | 日日爽天天操 | 久二影院 | 欧美日韩伦理一区 | 欧美久久久影院 | 国产一二区免费视频 | 国产精品中文字幕在线播放 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 成人资源在线观看 | 香蕉视频亚洲 | 国产精品视频永久免费播放 | 免费在线看成人av | 亚州视频在线 | 色在线视频网 | 中文字幕免费观看 | 国产成人三级一区二区在线观看一 | 国产精品videossex国产高清 | 精品国产人成亚洲区 | 国产精品免费视频网站 | 国产精品一区久久久久 | 香蕉网在线观看 | 超碰人人做 | 国产成人精品综合 | 成人永久在线 | 国产亚洲精品美女久久 | 欧美一级片在线播放 | 国产高清在线不卡 | 男女靠逼app| 日韩在线视频线视频免费网站 | 国产在线国偷精品产拍免费yy | 欧美成人h版在线观看 | 青青河边草免费观看完整版高清 | 国产精品99久久久 | 中文字幕在线观看资源 | 日韩精品五月天 | 91精品视频免费观看 | 日日躁天天躁 | 9ⅰ精品久久久久久久久中文字幕 | 中文理论片 | 国产精品免费在线播放 | 国产精品不卡在线 | 国产成人精品一区二区三区 | 精品在线播放视频 | 国产小视频在线免费观看 | 亚洲国产高清在线 | 欧美久久久久久久 | 夜色资源站wwwcom | 国产精品影音先锋 | 四虎影视精品永久在线观看 | 香蕉视频免费在线播放 | av不卡网站 | 狠狠色丁香婷婷综合基地 | 婷婷在线免费视频 | 久久久久久久久毛片精品 | 成年人免费观看国产 | 成人资源网 | 激情网站 | 国产精品毛片一区视频播 | 久久伊人热 | 国产va精品免费观看 | 国产精品资源在线观看 | 日韩免费福利 | 国产乱老熟视频网88av | 欧美精品一区二区免费 | 一区二区视频网站 | 久久精品www人人爽人人 | 天天操天天爱天天干 | 国产精品18久久久久vr手机版特色 | 婷婷丁香九月 | 精品亚洲欧美一区 | 色婷久久| 成人黄色中文字幕 | a视频免费| 91亚洲精品视频 | 9999精品免费视频 | 极品嫩模被强到高潮呻吟91 | 国产资源免费 | 国产韩国精品一区二区三区 | 国产亚洲在 | 免费在线国产精品 | 色综合天天综合网国产成人网 | 91插插插网站 | 免费三级影片 | 又黄又刺激的网站 | 国产.精品.日韩.另类.中文.在线.播放 | 国产一区二区网址 | 国产日韩欧美在线影视 | 中国一级片在线 | 国产69精品久久99不卡的观看体验 | 又黄又爽又无遮挡的视频 | 亚洲成色777777在线观看影院 | 黄色成人影视 | 国产最新在线视频 | 欧美黄色特级片 | 成人午夜网址 | 免费精品久久久 | 国产精品电影在线 | 日本中文一级片 | 高清不卡一区二区在线 | 爱色av.com | 亚洲成年人在线播放 | 91视频a | 成人免费在线视频观看 | 色婷婷综合久久久久中文字幕1 | 米奇四色影视 | av先锋中文字幕 | 成年人看片 | 五月色婷 | 天天色天天操天天爽 | 99久久精品免费一区 | 91污视频在线观看 | 亚洲一级二级 | 成年人视频在线免费 | 成年人视频在线免费观看 | 免费在线成人 | 亚洲 欧洲 国产 日本 综合 | 免费高清在线一区 | 中文一区二区三区在线观看 | 国产人免费人成免费视频 | 免费三级黄 | 五月婷婷电影网 | 99产精品成人啪免费网站 | 国产精品成人av在线 | 精品国产自在精品国产精野外直播 | 五月天综合在线 | 亚洲精品视频一二三 | 91视频在线免费下载 | 欧美综合国产 | 国产精品视频免费 | 国产精品视频专区 | 在线亚洲欧美视频 | 蜜臀av一区二区 | 狠狠躁夜夜a产精品视频 | 国产精品一区在线播放 | 欧美激情视频一区二区三区免费 | 2024国产精品视频 | 国内视频在线 | 国产黄色片在线免费观看 | 日韩在线视 | 玖玖玖在线观看 | 日韩中文字幕a | 国产手机视频在线观看 | 日日操天天操狠狠操 | 免费视频 你懂的 | 九九热精品视频在线观看 | 精品国产免费av | 久久99国产综合精品免费 | 亚洲三区在线 | 久久福利电影 | 国产精品美女毛片真酒店 | 日韩理论片中文字幕 | 果冻av在线 | 日韩午夜电影院 | 人成免费网站 | 日韩免费在线观看网站 | av福利在线 | 欧美日韩aaaa | 免费看片黄色 | 九九久久久 | 人人澡人 | 亚洲乱码精品久久久久 | 97人人模人人爽人人少妇 | 国产区久久| 亚州精品天堂中文字幕 | 色多多污污在线观看 | a级片久久久 | 九九视频精品免费 | 国产一二区免费视频 | 亚洲精品在线观看中文字幕 | 日韩欧美精品在线观看 | 日韩av三区 | 亚洲成人av片在线观看 | 亚洲午夜精品在线观看 | 狠狠狠操 | 亚洲精品系列 | 国产福利91精品一区二区三区 | 在线观看免费av网站 | 精品久久久久久国产91 | 日韩精品中文字幕有码 | 狠狠狠狠狠狠狠狠干 | 国产视| 六月色丁香 | 国产在线不卡视频 | 夜夜爱av| 国内精品一区二区 | 亚洲精品777| 毛片视频电影 | av在线免费在线观看 | 欧美精品在线免费 | 久久久综合九色合综国产精品 | 亚洲一区视频在线播放 | 亚洲国产人午在线一二区 | 中文字幕av最新更新 | 91成人精品观看 | 国产在线播放一区二区 | 久久久久福利视频 | 美女视频久久 | 永久免费毛片 | av电影在线观看完整版一区二区 | 五月婷婷视频在线观看 | 国产美女精彩久久 | av解说在线观看 | 91看片淫黄大片一级在线观看 | 国内精品久久久 | 一区二区中文字幕在线 | 狠狠操操操 | 日韩av不卡在线播放 | 免费视频在线观看网站 | 色婷婷国产精品 | 国产精品爽爽久久久久久蜜臀 | 亚洲精品乱码久久久久久久久久 | 国产成在线观看免费视频 | 人人插人人看 | 婷婷国产v亚洲v欧美久久 | 欧美精品中文 | 97精品欧美91久久久久久 | 亚洲日本在线视频观看 | 国产精品精品久久久久久 | 精品福利国产 | 很黄很色很污的网站 | 国产理论在线 | 天无日天天操天天干 | 国产一区二区精品在线 | 精品国产亚洲在线 | 亚洲精品观看 | 91精品国产99久久久久久久 | 国产亚洲精品bv在线观看 | 亚一亚二国产专区 | 久久久福利影院 | 99视频精品在线 | 最新色视频 | 四虎成人免费观看 | 美女黄网站视频免费 | 操操日日 | 午夜精品一区二区三区在线观看 | 西西www444 | 日日摸日日碰 | 国模视频一区二区 | 久久久午夜视频 | 日韩无在线 | 国内揄拍国内精品 | 欧美91精品国产自产 | 91.精品高清在线观看 | 欧美精品在线观看 | 96久久| a级国产乱理论片在线观看 伊人宗合网 | 日韩在线字幕 | 久久精品a| av成人在线看 | 伊人伊成久久人综合网站 | 国产一区二区在线视频观看 | 欧美福利在线播放 | 狠狠干电影 | 96av麻豆蜜桃一区二区 | 日本美女xx | 麻豆视频入口 | 最近中文字幕免费av | 超碰成人免费电影 | 久久久午夜电影 | 成人亚洲欧美 | 免费黄色网址大全 | 日韩欧美精品在线观看视频 | 欧美精品亚洲精品日韩精品 | 在线观看视频你懂 | 欧美另类一二三四区 | av无限看 | 不卡av免费在线观看 | 狠狠干夜夜爽 | 丰满少妇在线观看资源站 | 91精品免费在线 | 国产一级视频在线免费观看 | 久久99亚洲热视 | 亚洲精品女人 | 精品视频一区在线观看 | 麻豆免费观看视频 | 免费av大全 | 欧美地下肉体性派对 | 91视频专区 | 亚洲精品久久激情国产片 | 黄色片软件网站 | 日韩精品一区二区三区免费观看视频 | 免费高清av在线看 | 欧美日韩高清免费 | 久久免费黄色 | 中文字幕韩在线第一页 | 麻豆视频大全 | 一级免费黄色 | 久久少妇免费视频 | 色综合天天综合 | 黄色免费国产 | 亚洲精品一区二区在线观看 | 日韩中文字幕免费 | 国产精品一区二区三区观看 | 亚洲免费永久精品国产 | 欧美天堂影院 | 激情综合五月网 | 婷婷久月 | 国产99久久久精品 | 福利电影久久 | 丝袜少妇在线 | 亚洲成人av在线 | 三级免费黄 | 成人看片 | 久久999久久| 中文字幕高清在线播放 | av电影免费观看 | 免费a级黄色毛片 | 91成人天堂久久成人 | 国产日产精品久久久久快鸭 | 国产一级片免费观看 | 久草在线一免费新视频 | 久久久久一区二区三区四区 | 日韩精品三区四区 | 精品久久久久久久久久久久久久久久 | 国产精品久久99综合免费观看尤物 | 国产日韩欧美精品在线观看 | 国产白浆视频 | 国产精品不卡一区 | 亚洲精品国偷拍自产在线观看蜜桃 | 91麻豆精品国产自产在线 | 黄污网站在线观看 | 亚洲黄色小说网址 | 婷婷久久亚洲 | 色视频成人在线观看免 | 亚洲国产欧美在线人成大黄瓜 | 欧美日本三级 | 亚洲国产日韩欧美在线 | 成人免费在线网 | 中文字幕免费一区 | 亚洲成人蜜桃 | 久久电影日韩 | 麻豆激情电影 | 国产中文字幕在线 | 亚州人成在线播放 | 日本中文在线播放 | 日韩成人免费在线电影 | 美腿丝袜一区二区三区 | 国产成人综合图片 | 99精品区 | 日日摸日日爽 | 国产精品视频免费在线观看 | 久久九九国产视频 | 色婷婷狠狠干 | 亚洲三级在线免费观看 | 日韩在线短视频 | 99热最新精品 | 久久精品免费观看 | 欧美精品久久久久久久久久 | 久久精品国产免费看久久精品 | 国产在线观看一区 | 九九视频精品在线 | 久草在线免费看视频 | 久久露脸国产精品 | av成人亚洲 | 久久久av免费 | 激情网在线视频 | 亚洲五月花 | 亚洲欧美日韩精品久久奇米一区 | 综合久久久久久久 | 五月婷久 | 国产成年人av | 狠狠色丁香婷婷综合基地 | 日韩,中文字幕 | 激情深爱.com| 麻豆精品视频在线观看免费 | 欧美日韩一区二区三区不卡 | 国产一区视频在线 | 久草在线视频精品 | 激情动态 | 午夜电影中文字幕 | 欧美先锋影音 | 成人性生爱a∨ | 九九欧美| 久草网免费 | 四虎永久免费在线观看 | 亚洲无吗视频在线 | 操天天操 | 精品国偷自产在线 | 成人亚洲综合 | 91av视频在线免费观看 | 日韩久久精品一区二区 | 精品国产一区二区三区久久久久久 | 99精品国产99久久久久久福利 | 天天色天天操天天爽 | 日韩四虎| 97av在线视频免费播放 | 天天摸天天舔天天操 | 成人av在线电影 | 欧美精品久久久久性色 | av片在线观看免费 | 九九热在线观看视频 | 激情 亚洲| 免费看黄在线网站 | 日韩在线视频线视频免费网站 | 国产免费久久精品 | 午夜久久久久久久久久久 | 久久人人爽人人片av | 国产破处在线视频 | 久久精品人 | 精品免费视频 | 久久精品男人的天堂 | 久久香蕉国产精品麻豆粉嫩av | 亚洲视频久久久 | 成人在线观看免费视频 | 国产成人综合图片 | 久久精品视频在线观看 | 精品久久久久久电影 | a特级毛片| 日日夜夜天天 | 超碰在线97免费 | 九九欧美| 久久不卡国产精品一区二区 | 免费国产视频 | 国产一二区视频 | 日韩精品视频一二三 | 国产麻豆果冻传媒在线观看 | 亚洲一区二区视频在线 | www.亚洲精品视频 | 久久久婷 | 日韩免费 | 久久免费视频这里只有精品 | 99久久激情视频 | 美女福利视频网 | 91九色最新 | 欧洲在线免费视频 | 亚洲专区 国产精品 | 免费国产在线视频 | 欧美二区三区91 | 六月久久婷婷 | www99精品| 中文在线8新资源库 | 婷婷综合激情 | 亚洲精品动漫成人3d无尽在线 | 99国产成+人+综合+亚洲 欧美 | 精品日韩在线一区 | 久久免费在线视频 | 欧美aa在线观看 | 久久久国产精品一区二区中文 | av大片网址| 99国产精品视频免费观看一公开 | www.大网伊人 | 亚洲精品欧洲精品 | 国产精品久久久久久久电影 | 亚洲人成免费 | 久久久电影网站 | 中文字幕色在线 | 国产精品久久中文字幕 | 亚洲精品国产精品国 | 精品久久久久久久久久久久久久久久久久 | 日韩美在线观看 | 国产无遮挡猛进猛出免费软件 | 三级黄色免费片 | 五月婷婷视频在线 | 91完整版 | 2023国产精品自产拍在线观看 | 天天射天天操天天色 | 久久精品中文 | 久久久国产视频 | 黄色小说免费观看 | 久久精品123| 久久99国产综合精品免费 | 中文字幕高清 | 麻豆国产精品va在线观看不卡 | 又黄又爽的视频在线观看网站 | 99久久综合精品五月天 | 久久男人影院 | 国产成人免费在线 | 国产小视频国产精品 | 国产亚洲精品久久 | 中文字幕高清 | 亚洲免费在线 | 午夜久久电影网 | 2021国产在线视频 | 国产成人在线综合 | 99久久精品免费看 | 丁香六月网 | 亚洲精品在线免费观看视频 | 91九色在线 | 欧美日韩免费在线视频 | 成人亚洲综合 | 亚洲精品成人免费 | 免费网站黄| av中文字幕在线观看网站 | 成人午夜黄色 | 亚洲精品久久久久中文字幕二区 | 人人爱夜夜操 | 青青草华人在线视频 | 天天综合91 | 天天综合导航 | 成年人网站免费观看 | 9999精品视频 | 亚洲日本中文字幕在线观看 | 亚洲爱爱视频 | 精品在线观| 人人插人人草 | 亚洲狠狠婷婷综合久久久 | 亚洲一区二区视频在线 | 久久国产片 | 国产精品久久久久永久免费 | 日本一区二区免费在线观看 | 日韩欧美国产视频 | 在线观看成人小视频 | 91麻豆免费视频 | 99自拍视频在线观看 | 高清中文字幕 | 成人wwwxxx视频 | 精品视频免费久久久看 | 高潮久久久久久久久 | 欧美久久九九 | 一区二区三区高清不卡 | 久久成人精品电影 | 色偷偷av男人天堂 | 成人在线免费视频 | 国产在线播放一区二区三区 | 欧美男同视频网站 | 27xxoo无遮挡动态视频 | 色全色在线资源网 | 午夜在线免费观看视频 | 日本黄色一级电影 | 国产福利资源 | 国产免费国产 | 高清在线一区 | 国产免费a| 91精品天码美女少妇 | 久久美女高清视频 | 97福利在线 | 欧美一级大片在线观看 | 热久久免费国产视频 | 丁香婷婷久久 | 日韩精品三区四区 | 国产精品免费观看久久 | 日韩四虎 | 精精国产xxxx视频在线播放 | 天天操夜夜想 | 全久久久久久久久久久电影 | 亚洲精品国产成人 | 有没有在线观看av | 又污又黄的网站 | 国产麻豆剧果冻传媒视频播放量 | av中文字幕在线免费观看 | 91av视频观看 | 国产黄色精品在线 | 免费看的国产视频网站 | 色婷婷播放 | 国产亚洲精品久久 | 亚洲精品免费在线视频 | 国产精品成人久久久久久久 | 国产精品成人一区二区三区吃奶 | 国产精品 日韩 欧美 | 在线国产视频一区 | 干干日日 | 日韩欧美综合视频 | 成人黄色一级视频 | 亚洲资源视频 | 综合激情网 | 99久久久国产精品免费观看 | 婷婷在线网| 久久久久久久久久久电影 | 精品一区二区精品 | 中文字幕日本在线 | 亚洲视频1 | 在线观看精品 | 国产成人99av超碰超爽 | 91久久爱热色涩涩 | 99久久这里只有精品 | 激情五月婷婷综合网 | 色婷婷激情综合 | 91手机视频在线 | 97视频免费在线 | 精品国产一区二区三区四区vr | 国产精品女同一区二区三区久久夜 | 亚一亚二国产专区 | 91成人精品在线 | 西西444www大胆高清视频 | 日韩区在线观看 | 夜夜躁天天躁很躁波 | 欧美老人xxxx18| 91久久久久久久一区二区 | 91麻豆精品国产91久久久更新时间 | 久久福利国产 | 国产视频导航 | 国产不卡av在线 | 久草在线免费播放 | 亚洲91网站 | 日韩av影视在线观看 | 久久精品福利视频 | 丁香 久久 综合 | 91禁在线看 | 黄色在线免费观看网址 | 婷婷久久丁香 | 国产黄色成人av | 日韩经典一区二区三区 | 中文字幕在线观看日本 | 久久久久久久久久久网 | 免费在线观看国产黄 | 国产精品国产三级国产不产一地 | 久久少妇免费视频 | 高清一区二区三区 | 99性视频 | 国产色女 | 999久久久免费精品国产 | 97色综合 | 人人舔人人干 | 91黄色成人| 日日爽夜夜爽 | 伊人手机在线 | 国产四虎在线 | 97在线免费观看视频 | 99热国产在线 | 超碰在线公开免费 | 天天拍天天色 | 国产涩图 | 欧美日韩aa | 一区二区三区在线免费 | 五月综合网 | 人人澡人人澡人人 | 国产99久久久国产 | 色狠狠久久av五月综合 | 99热这里只有精品在线观看 | av在线免费播放 | 精品福利网 | 中文字幕 国产 一区 | 欧美一级黄色片 | 日韩高清dvd | 最近中文字幕视频网 | 中文字幕一区二区三区在线视频 | 久久国产日韩 | 久久天堂亚洲 | 天天插视频 | 久久99国产精品视频 | 国产精品久久久久久久久久直播 | 国偷自产视频一区二区久 | 欧美日韩一级视频 | 国产色视频网站 | 国产中出在线观看 | 国产精品美女久久久久久网站 | 99在线精品视频观看 | 国产精品久久久久久久久免费看 | 国产不卡在线观看视频 | 国产精品免费视频观看 | 日韩电影一区二区三区在线观看 | 国产手机精品视频 | 亚洲午夜久久久久 | 欧美一区二区精美视频 | 一级黄色片网站 | 日韩在线在线 | av成人免费网站 | 久久久综合九色合综国产精品 | 国产尤物视频在线 | 91精品麻豆 | 精品av在线播放 | 在线观看岛国av | 亚洲精品美女久久久 | 欧美色综合久久 | 欧美91在线| 永久av免费在线观看 | www视频免费在线观看 | 久热电影| 欧美日韩后 | 免费观看日韩 | 国产 欧美 在线 | 草久久久久久 | 很污的网站 | 成人永久在线 | 国产字幕在线看 | www91在线| 国产色啪 | 久久亚洲私人国产精品 | 欧洲av不卡| 五月婷婷丁香色 | 在线观看视频中文字幕 | 中文字幕亚洲在线观看 | 亚洲成av人影院 | 色偷偷88欧美精品久久久 | 精品在线观看一区二区三区 | 黄色a视频免费 | 日韩高清免费无专码区 | 在线精品视频免费播放 | 免费福利片2019潦草影视午夜 | 亚洲国产中文在线观看 | 中文字幕在线免费 | 91成人久久| 国产精品久久久久久久久久妇女 | 国产激情电影综合在线看 | 久久久久久免费网 | 久久久久久久久久久黄色 | 国产精品18久久久久vr手机版特色 | 久热免费在线观看 | 久久久精品国产一区二区电影四季 | 午夜国产成人 | 精品国产乱码久久久久久1区二区 | 久久久免费毛片 | 久久精品官网 | 亚洲精品456在线播放第一页 | 亚洲区二区 | 国产免费三级在线观看 | 国产精品亚 | 久久久精品欧美一区二区免费 | 九九热精品视频在线观看 | 美女视频是黄的免费观看 | 日韩av手机在线观看 | 久久国产精品久久久久 | 久久人视频 | 九九三级毛片 | 911国产| 在线亚洲小视频 | 欧美日韩一区二区三区在线免费观看 | 亚洲成av人片 | 女人18毛片a级毛片一区二区 | www.色午夜,com | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 精品国产乱码一区二区三区在线 | 天天爽天天做 | 午夜久久久精品 | 午夜婷婷网 | 婷婷深爱五月 | 99久久精品国产亚洲 | 在线观看久久久久久 | 中文字幕亚洲欧美日韩2019 | 久久一二三四 | 欧美成人精品欧美一级乱 | 97超碰人人看 | 亚洲精品免费视频 | 在线91精品| 草久在线| 国产日本三级 | 911在线| 国产传媒中文字幕 | 国产麻豆电影 | 热久久最新地址 | 久久免费在线视频 | 91黄视频在线 | 夜夜视频资源 | 99c视频高清免费观看 | www.午夜| 黄色电影网站在线观看 | 99视频免费 | 一级黄色在线视频 | 久久久精品电影 | 亚洲五月六月 | 成人av日韩 | 伊人热| 一区二区三区在线免费播放 | 久久99久久99精品免费看小说 | 高清av免费看 | 成人av电影在线播放 | 波多野结衣一区 | 在线观看中文字幕第一页 | 久亚洲| 欧美一级片在线 | 激情影院在线观看 | 久久超碰免费 | 免费观看性生活大片 | 亚洲视频免费在线观看 | 日韩免费在线观看视频 | 青青五月天 | 欧美精品久久久久久久免费 | 91精品久久久久久综合五月天 | 天天拍天天操 | av免费在线免费观看 | 亚洲精品播放 | 五月婷婷综合激情 | 在线观看你懂的网站 | 久影院 | av东方在线 | 国内精品久久久久久久久久久久 | 亚洲成人高清在线 | 欧美日韩亚洲在线观看 | 99精品福利视频 | 亚洲女欲精品久久久久久久18 | 欧美一二三专区 | 99热超碰| 黄色一级大片在线免费看产 | 日韩成人欧美 | 黄色www免费| 国产日韩欧美自拍 | 三级黄色片在线观看 | 免费在线观看av网站 | 96视频在线 | 亚洲欧美综合精品久久成人 | 久久99深爱久久99精品 | 成人欧美在线 | 日本精品二区 | av综合站| 中文字幕色婷婷在线视频 | 国产精品一区二区三区在线免费观看 | 韩日精品在线 | 日韩av影视在线 | 亚洲精品乱码久久久一二三 | 欧美性黑人 | 亚洲综合色视频在线观看 | 一区二区不卡在线观看 | 婷婷草 | 成人欧美日韩国产 | 夜夜婷婷 | 97超级碰碰碰视频在线观看 | 国产专区在线看 | 中文字幕国产在线 | 婷婷色视频 | 日韩动漫免费观看高清完整版在线观看 | 国产亚洲视频系列 | 手机成人在线电影 | 啪啪动态视频 | 超碰在线日本 | 国产在线观看中文字幕 | av大全在线观看 | 91精品国产亚洲 | 一区二区三区四区精品视频 | 在线观看韩日电影免费 | 日韩精品欧美精品 | 国产精品美女久久久久久久久久久 | 婷婷在线观看视频 | 免费人成网ww44kk44 | 国产又粗又猛又黄又爽视频 | 激情欧美日韩一区二区 | 婷婷在线综合 | 国模精品一区二区三区 | 69久久夜色精品国产69 | 中文字幕亚洲字幕 | av福利在线| 国产国产人免费人成免费视频 | 蜜桃视频成人在线观看 | 精品日本视频 | 四虎www.| 激情av在线播放 | 成人9ⅰ免费影视网站 | 欧洲av不卡 | 成人亚洲欧美 | 久久久亚洲麻豆日韩精品一区三区 | 黄色资源在线 | 久久成人亚洲欧美电影 | 欧美污网站 | 久青草国产在线 | 成人在线观看资源 | 成人va视频 | 99久久99久久精品国产片 | 国产成人精品在线播放 | 欧美一区二区三区免费看 | 91精品国产欧美一区二区 | 欧美高清成人 |