MFC耗时操作增加模态旋转等待对话框

简介:

  http操作下,有时会碰到请求过程中,界面卡死问题,多点几次后导致程序崩溃问题。这严重影响到软件的稳定性和降低客户体验感。这些一般是因为http请求时SendRequest()阻塞导致的,所以针对http阻塞问题可以将业务与界面分离开,单独创建一个线程给业务,也可以增加模态等待对话框,在http操作完成后再去关闭对话框即可。

操作步骤:

步骤一:

  在VS资源视图中右键插入Dialog:
在这里插入图片描述
  设置无边框:
在这里插入图片描述
  增加Picture Control控件:
在这里插入图片描述
  右键对话框添加类(例如DlgExec):
在这里插入图片描述

步骤二:

  在自己工程中添加以下两个文件:
  PictureEx.h

#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(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));
 BOOL Load(LPCTSTR szResourceName,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_)

  PictureEx.cpp

#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(LPCTSTR szResourceName, LPCTSTR szResourceType)
{
 ASSERT(szResourceName);
 ASSERT(szResourceType);
 
 HRSRC hPicture = FindResource(AfxGetResourceHandle(),szResourceName,szResourceType);
 HGLOBAL hResData;
 if (!hPicture || !(hResData = LoadResource(AfxGetResourceHandle(),hPicture)))
 {
  TRACE(_T("Load (resource): Error loading resource %s\n"),szResourceName);
  return FALSE;
 };
 DWORD dwSize = SizeofResource(AfxGetResourceHandle(),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
	m_clrBackground = RGB(255,255,255);
 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);
}


  对话框类文件代码:
  DlgExec.h

#pragma once

#include "PictureEx.h"

// CDlgExec 对话框
class CDlgExec : public CDialogEx
{
	DECLARE_DYNAMIC(CDlgExec)

public:
	CDlgExec(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CDlgExec();

    void setIsStop(bool bStop);
// 对话框数据
	enum { IDD = IDD_EXEC };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
private:
    CPictureEx m_PictureEx;

    bool m_bClose;

public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    virtual BOOL OnInitDialog();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnClose();
};

  DlgExec.cpp

// DlgExec.cpp : 实现文件
//
#include "stdafx.h"
#include "ProductTool.h"
#include "DlgExec.h"
#include "afxdialogex.h"

// CDlgExec 对话框
IMPLEMENT_DYNAMIC(CDlgExec, CDialogEx)

CDlgExec::CDlgExec(CWnd* pParent /*=NULL*/)
	: CDialogEx(CDlgExec::IDD, pParent)
{
    m_bClose = false;
}

CDlgExec::~CDlgExec()
{
}

void CDlgExec::setIsStop(bool bStop)
{
    m_bClose = bStop;
}

void CDlgExec::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_GIFSTATIC, m_PictureEx);
}

BEGIN_MESSAGE_MAP(CDlgExec, CDialogEx)
    ON_WM_ERASEBKGND()
    ON_WM_TIMER()
    ON_WM_CLOSE()
END_MESSAGE_MAP()

BOOL CDlgExec::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_KEYDOWN&&pMsg->wParam==VK_RETURN)
	{
		return FALSE;
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

BOOL CDlgExec::OnInitDialog()
{
    OutputDebugStringA("yibin test OnInitDialog 000");
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	MoveWindow(0,0,108,114);
	CenterWindow();
	COLORREF maskColor = RGB(255,255,255);   //掩码颜色  
	SetWindowLong(this->GetSafeHwnd(),  GWL_EXSTYLE,   GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)| 0x80000);  //设定窗体使用扩展模式   
	SetLayeredWindowAttributes(maskColor,0,LWA_COLORKEY);
	m_PictureEx.MoveWindow(0,0,108,114);

	m_PictureEx.Load(_T("Image/waitimage.gif"));
	m_PictureEx.Draw();
    
	//m_ThreadManager.Start();
	SetTimer(0,100,NULL);
	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

BOOL CDlgExec::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return CDialogEx::OnEraseBkgnd(pDC);
}

void CDlgExec::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nIDEvent == 0)
	{
		if (m_bClose)
		{
			SendMessage(WM_CLOSE);
		}
	}
	CDialogEx::OnTimer(nIDEvent);
}

void CDlgExec::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_PictureEx.DestroyWindow();
	CDialogEx::OnClose();
}
// CDlgExec 消息处理程序

步骤三:

将waitimage.gif添加到自己工程目录中:

请添加图片描述

使用:

  可以独立创建一个线程给耗时操作,然后主线程上执行模态阻塞等待,等到线程中的http执行完成后,再关闭模态阻塞对话框,继续执行主线程的代码。

void CDlgAgingTest::OnBtnStart() 
{
	TCHAR tzText[MAX_PATH] = {0};
	UpdateData(TRUE);
	CProductToolDlg *pMainWnd = (CProductToolDlg*)AfxGetMainWnd();
	CString strIPStart, strPwd, strUser;
	m_edIPStart.GetWindowText(strIPStart);
	strIPStart.TrimLeft();
	strIPStart.TrimRight();
	TCHAR tsTempText[256] = {0};
    
	char strStartIP[256] = {0};
	Widechar_2_Multibyte(CP_ACP, strIPStart, strStartIP, sizeof(strStartIP)-1);
	int nIp1=0, nIp2=0, nIp3=0, nIp4=0;
	if((sscanf(strStartIP, "%d.%d.%d.%d", &nIp1, &nIp2, &nIp3, &nIp4) != 4) ||
		(nIp1>255 || nIp2>255 || nIp3>255 || nIp4>255))
    {
		CLanguage::GetPromptString(_T("60048"), tsTempText, 255,
            _T("Please make sure the start IP is correct!"));
		AfxMessageBox(tsTempText);
		return;
	}
        
	if (gTesterRun)
		OnBtnStop();

	if (m_nCountFromEdit > MAX_TEST_IPC_COUNT)
		m_nCountFromEdit = MAX_TEST_IPC_COUNT;
	m_edPwd.GetWindowText(strPwd);
	strPwd.TrimLeft();
	strPwd.TrimRight();
	Widechar_2_Multibyte(CP_ACP, strPwd, CIpcTester::gTestPwd,
        sizeof(CIpcTester::gTestPwd)-1);
	m_edUser.GetWindowText(strUser);
	strUser.TrimLeft();
	strUser.TrimRight();
	Widechar_2_Multibyte(CP_ACP, strUser, CIpcTester::gTestUserName,
        sizeof(CIpcTester::gTestUserName)-1);

    //耗时操作独立创建一个线程
    if(m_ThreadTimer)
    {
        my_thread_join(m_ThreadTimer);
    	my_free(m_ThreadTimer);
    	m_ThreadTimer = NULL;
    }

    if(NULL == m_ThreadTimer)
    {
        m_ThreadTimer = my_thread_create(20000, ThreadCheckUserPwd, this);
    }

    //模态阻塞,直到线程http请求完毕
    m_pWaitDlg = new CDlgExec(this);
    m_pWaitDlg->DoModal();


    if(!m_bCheckpwdSuc)
    {
        ys_print("m_bCheckpwdSuc false");
        return;
    }
	......

}

void* ThreadCheckUserPwd(void* dwUser)
{
	CDlgAgingTest* Dialog = (CDlgAgingTest*)dwUser;
	Dialog->CheckMulUserPwd();
	return NULL;
}

void CDlgAgingTest::CheckMulUserPwd()
{

    ys_print("CheckMulUserPwd m_nCountFromEdit:%d", m_nCountFromEdit);
    CString strIPStart;
	m_edIPStart.GetWindowText(strIPStart);
    bool bCheckSuc = true;
    for (int i = 0; i < m_nCountFromEdit; i++) 
    {

        CString sLanIpStart = AscIpAddr(strIPStart, i);
		char sIP[32] = {0};
		Widechar_2_Multibyte(CP_ACP, sLanIpStart, sIP, 32);

        if(CheckUserPwd(sIP) == -1) 
        {
            bCheckSuc = false;
            break;
        }
    }

    if(bCheckSuc)
        m_bCheckpwdSuc = true;
    else
        m_bCheckpwdSuc = false;

	//http请求完成,关闭模态阻塞对话框,继续执行主线程代码
    if(m_pWaitDlg)
       m_pWaitDlg->setIsStop(true); 
    
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅笑一斤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值