• 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 
     
    //#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 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_)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227

      PictureEx.cpp

    #include "stdafx.h"
    #include "PictureEx.h"
    #include 
     
    #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 (GlobalLock(hGlobal))) )
     {
      TRACE(_T("Load: Error locking memory\n"));
      return FALSE;
     };
     
     m_nDataSize = dwSize;
     m_pGIFHeader = reinterpret_cast (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(&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
       (m_pRawData + sizeof(TGIFHeader));
      if (m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCT) == 1)
      {
       // calculate the globat color table size
       m_nGlobalCTSize = static_cast
        (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(&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::iterator it;
     for (it=m_arrFrames.begin();itRelease();
     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(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 (GlobalLock(hGlobal));
     char *pSrc = reinterpret_cast (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 (&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 (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 (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 (&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 (&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 (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 
          (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 (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 (&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 (&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);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
    • 824
    • 825
    • 826
    • 827
    • 828
    • 829
    • 830
    • 831
    • 832
    • 833
    • 834
    • 835
    • 836
    • 837
    • 838
    • 839
    • 840
    • 841
    • 842
    • 843
    • 844
    • 845
    • 846
    • 847
    • 848
    • 849
    • 850
    • 851
    • 852
    • 853
    • 854
    • 855
    • 856
    • 857
    • 858
    • 859
    • 860
    • 861
    • 862
    • 863
    • 864
    • 865
    • 866
    • 867
    • 868
    • 869
    • 870
    • 871
    • 872
    • 873
    • 874
    • 875
    • 876
    • 877
    • 878
    • 879
    • 880
    • 881
    • 882
    • 883
    • 884
    • 885
    • 886
    • 887
    • 888
    • 889
    • 890
    • 891
    • 892
    • 893
    • 894
    • 895
    • 896
    • 897
    • 898
    • 899
    • 900
    • 901
    • 902
    • 903
    • 904
    • 905
    • 906
    • 907
    • 908
    • 909
    • 910
    • 911
    • 912
    • 913
    • 914
    • 915
    • 916
    • 917
    • 918
    • 919
    • 920
    • 921
    • 922
    • 923
    • 924
    • 925
    • 926
    • 927
    • 928
    • 929
    • 930
    • 931
    • 932
    • 933
    • 934
    • 935
    • 936
    • 937
    • 938
    • 939
    • 940
    • 941
    • 942
    • 943
    • 944
    • 945
    • 946
    • 947
    • 948
    • 949
    • 950
    • 951
    • 952
    • 953
    • 954
    • 955
    • 956
    • 957
    • 958
    • 959
    • 960
    • 961
    • 962
    • 963
    • 964
    • 965
    • 966
    • 967
    • 968
    • 969
    • 970
    • 971
    • 972
    • 973
    • 974
    • 975
    • 976
    • 977
    • 978
    • 979
    • 980
    • 981
    • 982
    • 983
    • 984
    • 985
    • 986
    • 987
    • 988
    • 989
    • 990
    • 991
    • 992
    • 993
    • 994
    • 995
    • 996
    • 997
    • 998
    • 999
    • 1000
    • 1001
    • 1002
    • 1003
    • 1004
    • 1005
    • 1006
    • 1007
    • 1008
    • 1009
    • 1010
    • 1011
    • 1012
    • 1013
    • 1014
    • 1015
    • 1016
    • 1017
    • 1018
    • 1019
    • 1020
    • 1021
    • 1022
    • 1023
    • 1024
    • 1025
    • 1026
    • 1027
    • 1028
    • 1029
    • 1030
    • 1031
    • 1032
    • 1033
    • 1034
    • 1035
    • 1036
    • 1037
    • 1038
    • 1039
    • 1040
    • 1041
    • 1042
    • 1043
    • 1044
    • 1045
    • 1046
    • 1047
    • 1048
    • 1049
    • 1050
    • 1051
    • 1052
    • 1053
    • 1054
    • 1055
    • 1056
    • 1057
    • 1058
    • 1059
    • 1060
    • 1061
    • 1062
    • 1063
    • 1064
    • 1065
    • 1066
    • 1067
    • 1068
    • 1069
    • 1070
    • 1071
    • 1072
    • 1073
    • 1074
    • 1075
    • 1076
    • 1077
    • 1078
    • 1079
    • 1080
    • 1081
    • 1082
    • 1083
    • 1084
    • 1085
    • 1086
    • 1087
    • 1088
    • 1089
    • 1090
    • 1091
    • 1092
    • 1093
    • 1094
    • 1095
    • 1096
    • 1097
    • 1098
    • 1099
    • 1100
    • 1101
    • 1102
    • 1103
    • 1104
    • 1105
    • 1106
    • 1107
    • 1108
    • 1109
    • 1110
    • 1111
    • 1112
    • 1113
    • 1114
    • 1115
    • 1116
    • 1117
    • 1118
    • 1119
    • 1120
    • 1121
    • 1122
    • 1123
    • 1124
    • 1125
    • 1126
    • 1127
    • 1128
    • 1129
    • 1130
    • 1131
    • 1132
    • 1133
    • 1134
    • 1135
    • 1136
    • 1137
    • 1138
    • 1139
    • 1140
    • 1141
    • 1142
    • 1143
    • 1144
    • 1145
    • 1146
    • 1147
    • 1148
    • 1149
    • 1150
    • 1151
    • 1152
    • 1153
    • 1154
    • 1155
    • 1156
    • 1157
    • 1158
    • 1159
    • 1160
    • 1161
    • 1162
    • 1163
    • 1164
    • 1165
    • 1166
    • 1167
    • 1168
    • 1169
    • 1170
    • 1171
    • 1172
    • 1173
    • 1174
    • 1175
    • 1176
    • 1177
    • 1178
    • 1179
    • 1180
    • 1181
    • 1182
    • 1183
    • 1184
    • 1185
    • 1186
    • 1187
    • 1188
    • 1189
    • 1190
    • 1191
    • 1192
    • 1193
    • 1194
    • 1195
    • 1196
    • 1197
    • 1198
    • 1199
    • 1200
    • 1201
    • 1202
    • 1203
    • 1204
    • 1205
    • 1206
    • 1207
    • 1208
    • 1209
    • 1210
    • 1211
    • 1212
    • 1213
    • 1214
    • 1215
    • 1216
    • 1217

      对话框类文件代码:
      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();
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

      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 消息处理程序
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    步骤三:

    将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); 
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
  • 相关阅读:
    JAVA面试题——初级
    接口测试必备知识点(含实战项目)
    荧光染料AF488 DBCO, 5-isomer,AF488 二苯基环辛炔, 5-异构体
    C#堆排序算法
    【博学谷学习记录】超强总结,用心分享丨大数据超神之路(四):shell脚本
    蠕虫病毒流量分析案例
    【Window10 】删除‘设备和驱动器’中的百度网盘、酷狗音乐、迅雷下载等
    中断实验(按键/光电开关/火焰传感器/人体红外)
    C++ explicit 用法
    Java -- 每日一问:谈谈你的GC调优思路?
  • 原文地址:https://blog.csdn.net/linyibin_123/article/details/127572919