热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

简介:http操作下,有时会碰到请求过程中,界面卡死问题,多点几次后导致程序崩溃问题。这严重影响到软件的稳定性和降低客户体验



简介:

  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_)

  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)&#43;1)));
// get the background color if GCT is present
unsigned char *pBkClr &#61; m_pRawData &#43; sizeof(TGIFHeader) &#43;
sizeof(TGIFLSDescriptor) &#43; 3*m_pGIFLSDescriptor->m_cBkIndex;
m_clrBackground &#61; RGB(pBkClr[0],pBkClr[1],pBkClr[2]);
};
// store the picture&#39;s size
m_PictureSize.cx &#61; m_pGIFLSDescriptor->m_wWidth;
m_PictureSize.cy &#61; m_pGIFLSDescriptor->m_wHeight;
// determine frame count for this picture
UINT nFrameCount&#61;0;
ResetDataPointer();
while (SkipNextGraphicBlock())
nFrameCount&#43;&#43;;
#ifdef GIF_TRACING
TRACE(
_T(" -&#61; GIF encountered\n"
"Logical Screen dimensions &#61; %dx%d\n"
"Global color table &#61; %d\n"
"Color depth &#61; %d\n"
"Sort flag &#61; %d\n"
"Size of Global Color Table &#61; %d\n"
"Background color index &#61; %d\n"
"Pixel aspect ratio &#61; %d\n"
"Frame count &#61; %d\n"
"Background color &#61; %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 &#61;&#61; 0) // it&#39;s an empty GIF!
{
m_pRawData &#61; NULL;
GlobalUnlock(hGlobal);
return FALSE;
};
// now check the frame count
// if there&#39;s only one frame, no need to animate this GIF
// therefore, treat it like any other pic
if (nFrameCount &#61;&#61; 1)
{
// clear GIF variables
m_pRawData &#61; NULL;
GlobalUnlock(hGlobal);
// don&#39;t delete memory on object&#39;s release
if (CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) !&#61; S_OK)
return FALSE;
if (OleLoadPicture(pStream,dwSize,FALSE,IID_IPicture,
(LPVOID *)&m_pPicture) !&#61; 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 &#61; 0;
ResetDataPointer();
while (hFrameData &#61; 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&#43;&#43;;
#endif // GIF_TRACING
IStream *pStream &#61; NULL;
// delete memory on object&#39;s release
if (CreateStreamOnHGlobal(hFrameData,TRUE,&pStream) !&#61; S_OK)
{
GlobalFree(hFrameData);
continue;
};
if (OleLoadPicture(pStream,nBlockLen,FALSE,
IID_IPicture,
reinterpret_cast(&frame.m_pPicture)) !&#61; S_OK)
{
pStream->Release();
continue;
};
pStream->Release();
// everything went well, add this frame
m_arrFrames.push_back(frame);
};
// clean after ourselves
m_pRawData &#61; NULL;
GlobalUnlock(hGlobal);
if (m_arrFrames.empty()) // couldn&#39;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 &#61; NULL;
};
std::vector::iterator it;
for (it&#61;m_arrFrames.begin();it (*it).m_pPicture->Release();
m_arrFrames.clear();
if (m_hMemDC)
{
SelectObject(m_hMemDC,m_hOldBitmap);
::DeleteDC(m_hMemDC);
::DeleteObject(m_hBitmap);
m_hMemDC &#61; NULL;
m_hBitmap &#61; NULL;
};
if (m_hDispMemDC)
{
SelectObject(m_hDispMemDC,m_hDispOldBM);
::DeleteDC(m_hDispMemDC);
::DeleteObject(m_hDispMemBM);
m_hDispMemDC &#61; NULL;
m_hDispMemBM &#61; NULL;
};
SetRect(&m_PaintRect,0,0,0,0);
m_pGIFLSDescriptor &#61; NULL;
m_pGIFHeader &#61; NULL;
m_pRawData &#61; NULL;
m_hThread &#61; NULL;
m_bIsInitialized &#61; FALSE;
m_bExitThread &#61; FALSE;
m_bIsGIF &#61; FALSE;
m_clrBackground &#61; RGB(255,255,255); // white by default
m_nGlobalCTSize &#61; 0;
m_nCurrOffset &#61; 0;
m_nCurrFrame &#61; 0;
m_nDataSize &#61; 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&#39;ll start the thread that will handle it for us
unsigned int nDummy;
m_hThread &#61; (HANDLE) _beginthreadex(NULL,0,_ThreadAnimation,this,
CREATE_SUSPENDED,&nDummy);
if (!m_hThread)
{
TRACE(_T("Draw: Couldn&#39;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) &#61;&#61; 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 &#61; file.GetLength();
hGlobal &#61; GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
if (!hGlobal)
{
TRACE(_T("Load (file): Error allocating memory\n"));
return FALSE;
};
char *pData &#61; 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 &#61; Load(hGlobal,dwSize);
GlobalFree(hGlobal);
return bRetValue;
}
BOOL CPictureEx::Load(LPCTSTR szResourceName, LPCTSTR szResourceType)
{
ASSERT(szResourceName);
ASSERT(szResourceType);
HRSRC hPicture &#61; FindResource(AfxGetResourceHandle(),szResourceName,szResourceType);
HGLOBAL hResData;
if (!hPicture || !(hResData &#61; LoadResource(AfxGetResourceHandle(),hPicture)))
{
TRACE(_T("Load (resource): Error loading resource %s\n"),szResourceName);
return FALSE;
};
DWORD dwSize &#61; SizeofResource(AfxGetResourceHandle(),hPicture);
// hResData is not the real HGLOBAL (we can&#39;t lock it)
// let&#39;s make it real
HGLOBAL hGlobal &#61; GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
if (!hGlobal)
{
TRACE(_T("Load (resource): Error allocating memory\n"));
FreeResource(hResData);
return FALSE;
};
char *pDest &#61; reinterpret_cast (GlobalLock(hGlobal));
char *pSrc &#61; 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 &#61; Load(hGlobal,dwSize);
GlobalFree(hGlobal);
return bRetValue;
}
void CPictureEx::ResetDataPointer()
{
// skip header and logical screen descriptor
m_nCurrOffset &#61;
sizeof(TGIFHeader)&#43;sizeof(TGIFLSDescriptor)&#43;m_nGlobalCTSize;
}
BOOL CPictureEx::SkipNextGraphicBlock()
{
if (!m_pRawData) return FALSE;
// GIF header &#43; LSDescriptor [&#43; GCT] [&#43; Control block] &#43; Data
enum GIFBlockTypes nBlock;
nBlock &#61; GetNextBlock();
while ((nBlock !&#61; BLOCK_CONTROLEXT) &&
(nBlock !&#61; BLOCK_IMAGE) &&
(nBlock !&#61; BLOCK_PLAINTEXT) &&
(nBlock !&#61; BLOCK_UNKNOWN) &&
(nBlock !&#61; BLOCK_TRAILER) )
{
if (!SkipNextBlock()) return NULL;
nBlock &#61; GetNextBlock();
};
if ((nBlock &#61;&#61; BLOCK_UNKNOWN) ||
(nBlock &#61;&#61; BLOCK_TRAILER))
return FALSE;
// it&#39;s either a control ext.block, an image or a plain text
if (GetNextBlockLen() <&#61; 0) return FALSE;
if (nBlock &#61;&#61; BLOCK_CONTROLEXT)
{
if (!SkipNextBlock()) return FALSE;
nBlock &#61; GetNextBlock();
// skip everything until we meet an image block or a plain-text block
while ((nBlock !&#61; BLOCK_IMAGE) &&
(nBlock !&#61; BLOCK_PLAINTEXT) &&
(nBlock !&#61; BLOCK_UNKNOWN) &&
(nBlock !&#61; BLOCK_TRAILER) )
{
if (!SkipNextBlock()) return NULL;
nBlock &#61; GetNextBlock();
};
if ((nBlock &#61;&#61; BLOCK_UNKNOWN) ||
(nBlock &#61;&#61; 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 &#61; 0;
UINT nCurOffset &#61; nStartingOffset;
while (m_pRawData[nCurOffset] !&#61; 0)
{
nRet &#43;&#61; m_pRawData[nCurOffset]&#43;1;
nCurOffset &#43;&#61; m_pRawData[nCurOffset]&#43;1;
};
return nRet&#43;1;
}
enum CPictureEx::GIFBlockTypes CPictureEx::GetNextBlock() const
{
switch(m_pRawData[m_nCurrOffset])
{
case 0x21:
// extension block
switch(m_pRawData[m_nCurrOffset&#43;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 &#61; GetNextBlockLen();
if ((nLen <&#61; 0) || ((m_nCurrOffset&#43;nLen) > m_nDataSize))
return FALSE;
m_nCurrOffset &#43;&#61; nLen;
return TRUE;
}
int CPictureEx::GetNextBlockLen() const
{
GIFBlockTypes nBlock &#61; GetNextBlock();
int nTmp;
switch(nBlock)
{
case BLOCK_UNKNOWN:
return -1;
break;
case BLOCK_TRAILER:
return 1;
break;
case BLOCK_APPEXT:
nTmp &#61; GetSubBlocksLen(m_nCurrOffset&#43;sizeof(TGIFAppExtension));
if (nTmp > 0)
return sizeof(TGIFAppExtension)&#43;nTmp;
break;
case BLOCK_COMMEXT:
nTmp &#61; GetSubBlocksLen(m_nCurrOffset&#43;sizeof(TGIFCommentExt));
if (nTmp > 0)
return sizeof(TGIFCommentExt)&#43;nTmp;
break;
case BLOCK_CONTROLEXT:
return sizeof(TGIFControlExt);
break;
case BLOCK_PLAINTEXT:
nTmp &#61; GetSubBlocksLen(m_nCurrOffset&#43;sizeof(TGIFPlainTextExt));
if (nTmp > 0)
return sizeof(TGIFPlainTextExt)&#43;nTmp;
break;
case BLOCK_IMAGE:
TGIFImageDescriptor *pIDescr &#61;
reinterpret_cast (&m_pRawData[m_nCurrOffset]);
int nLCTSize &#61; (int)
(pIDescr->GetPackedValue(ID_PACKED_LOCALCT)*3*
(1 <<(pIDescr->GetPackedValue(ID_PACKED_LOCALCTSIZE)&#43;1)));
int nTmp &#61; GetSubBlocksLen(m_nCurrOffset&#43;
sizeof(TGIFImageDescriptor) &#43; nLCTSize &#43; 1);
if (nTmp > 0)
return sizeof(TGIFImageDescriptor) &#43; nLCTSize &#43; 1 &#43; nTmp;
break;
};
return 0;
}
UINT WINAPI CPictureEx::_ThreadAnimation(LPVOID pParam)
{
ASSERT(pParam);
CPictureEx *pPic &#61; reinterpret_cast (pParam);
pPic->m_bIsPlaying &#61; TRUE;
pPic->ThreadAnimation();
pPic->m_bIsPlaying &#61; 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&#39;t Wait on it)
pPic->m_hThread &#61; 0;
return 0;
}
void CPictureEx::ThreadAnimation()
{
// first, restore background (for stop/draw support)
// disposal method #2
m_clrBackground &#61; RGB(255,255,255);
if (m_arrFrames[m_nCurrFrame].m_nDisposal &#61;&#61; 2)
{
HBRUSH hBrush &#61; CreateSolidBrush(m_clrBackground);
if (hBrush)
{
RECT rect &#61; {
m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
m_arrFrames[m_nCurrFrame].m_frameOffset.cx &#43; m_arrFrames[m_nCurrFrame].m_frameSize.cx,
m_arrFrames[m_nCurrFrame].m_frameOffset.cy &#43; 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 &#61;&#61; 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 &#61; NULL;
DeleteObject(m_hDispMemBM); m_hDispMemBM &#61; NULL;
};
while (!m_bExitThread)
{
if (m_arrFrames[m_nCurrFrame].m_pPicture)
{
///
// Before rendering a frame we should take care of what&#39;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 &#61;&#61; 3)
{
// prepare a memory DC and store the background in it
m_hDispMemDC &#61; CreateCompatibleDC(m_hMemDC);
m_hDispMemBM &#61; CreateCompatibleBitmap(m_hMemDC,
m_arrFrames[m_nCurrFrame].m_frameSize.cx,
m_arrFrames[m_nCurrFrame].m_frameSize.cy);

if (m_hDispMemDC && m_hDispMemBM)
{
m_hDispOldBM &#61; 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) &#61;&#61; 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 &#61;&#61; 2)
{
HBRUSH hBrush &#61; CreateSolidBrush(m_clrBackground);
if (hBrush)
{
RECT rect &#61; {
m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
m_arrFrames[m_nCurrFrame].m_frameOffset.cx &#43; m_arrFrames[m_nCurrFrame].m_frameSize.cx,
m_arrFrames[m_nCurrFrame].m_frameOffset.cy &#43; m_arrFrames[m_nCurrFrame].m_frameSize.cy };
FillRect(m_hMemDC,&rect,hBrush);
DeleteObject(hBrush);
};
}
else
if (m_hDispMemDC && (m_arrFrames[m_nCurrFrame].m_nDisposal &#61;&#61; 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 &#61; NULL;
DeleteObject(m_hDispMemBM); m_hDispMemBM &#61; NULL;
};
};
m_nCurrFrame&#43;&#43;;
if (m_nCurrFrame &#61;&#61; m_arrFrames.size())
{
m_nCurrFrame
&#61; 0;
// init the screen for the first frame,
HBRUSH hBrush &#61; CreateSolidBrush(m_clrBackground);
if (hBrush)
{
RECT rect &#61; {0,0,m_PictureSize.cx,m_PictureSize.cy};
FillRect(m_hMemDC,&rect,hBrush);
DeleteObject(hBrush);
};
};
};
}
void CPictureEx::Stop()
{
m_bIsPlaying &#61; FALSE;
m_bExitThread &#61; TRUE;
SetEvent(m_hExitEvent);
if (m_hThread)
{
// we&#39;ll wait for 5 seconds then continue execution
WaitForSingleObject(m_hThread,5000);
CloseHandle(m_hThread);
m_hThread &#61; NULL;
}
// make it possible to Draw() again
ResetEvent(m_hExitEvent);
m_bExitThread &#61; FALSE;
}
HGLOBAL CPictureEx::GetNextGraphicBlock(UINT *pBlockLen,
UINT *pDelay, SIZE *pBlockSize, SIZE *pBlockOffset,
UINT *pDisposal)
{
if (!m_pRawData) return NULL;
// GIF header &#43; LSDescriptor [&#43; GCT] [&#43; Control block] &#43; Data
*pDisposal &#61; 0;
enum GIFBlockTypes nBlock;
nBlock &#61; GetNextBlock();
while (
(nBlock !&#61; BLOCK_CONTROLEXT) &&
(nBlock !&#61; BLOCK_IMAGE) &&
(nBlock !&#61; BLOCK_PLAINTEXT) &&
(nBlock !&#61; BLOCK_UNKNOWN) &&
(nBlock !&#61; BLOCK_TRAILER)
)
{
if (!SkipNextBlock()) return NULL;
nBlock &#61; GetNextBlock();
};
if ((nBlock &#61;&#61; BLOCK_UNKNOWN) ||
(nBlock &#61;&#61; BLOCK_TRAILER))
return NULL;
// it&#39;s either a control ext.block, an image or a plain text
int nStart &#61; m_nCurrOffset;
int nBlockLen &#61; GetNextBlockLen();
if (nBlockLen <&#61; 0) return NULL;
if (nBlock &#61;&#61; BLOCK_CONTROLEXT)
{
// get the following data
TGIFControlExt *pControl &#61;
reinterpret_cast (&m_pRawData[m_nCurrOffset]);
// store delay time
*pDelay &#61; pControl->m_wDelayTime;
// store disposal method
*pDisposal &#61; pControl->GetPackedValue(GCX_PACKED_DISPOSAL);
if (!SkipNextBlock()) return NULL;
nBlock &#61; GetNextBlock();
// skip everything until we find data to display
// (image block or plain-text block)
while (
(nBlock !&#61; BLOCK_IMAGE) &&
(nBlock !&#61; BLOCK_PLAINTEXT) &&
(nBlock !&#61; BLOCK_UNKNOWN) &&
(nBlock !&#61; BLOCK_TRAILER)
)
{
if (!SkipNextBlock()) return NULL;
nBlock &#61; GetNextBlock();
nBlockLen &#43;&#61; GetNextBlockLen();
};
if ((nBlock &#61;&#61; BLOCK_UNKNOWN) || (nBlock &#61;&#61; BLOCK_TRAILER))
return NULL;
nBlockLen &#43;&#61; GetNextBlockLen();
}
else
*pDelay &#61; -1; // to indicate that there was no delay value
if (nBlock &#61;&#61; BLOCK_IMAGE)
{
// store size and offsets
TGIFImageDescriptor *pImage &#61;
reinterpret_cast (&m_pRawData[m_nCurrOffset]);
pBlockSize->cx &#61; pImage->m_wWidth;
pBlockSize->cy &#61; pImage->m_wHeight;
pBlockOffset->cx &#61; pImage->m_wLeftPos;
pBlockOffset->cy &#61; pImage->m_wTopPos;
};
if (!SkipNextBlock()) return NULL;
HGLOBAL hGlobal &#61; GlobalAlloc(GMEM_FIXED,
sizeof(TGIFHeader) &#43;
sizeof(TGIFLSDescriptor) &#43;
m_nGlobalCTSize &#43;
nBlockLen &#43;
1); // for the trailer
if (!hGlobal) return NULL;
int nOffset &#61; 0;
// GMEM_FIXED means we get a pointer
unsigned char *pGlobal &#61; reinterpret_cast (hGlobal);
CopyMemory(pGlobal,m_pRawData,
sizeof(TGIFHeader)&#43;sizeof(TGIFLSDescriptor)&#43;m_nGlobalCTSize);
nOffset &#43;&#61; sizeof(TGIFHeader)&#43;sizeof(TGIFLSDescriptor)&#43;m_nGlobalCTSize;
CopyMemory(pGlobal &#43; nOffset,&m_pRawData[nStart], nBlockLen);
nOffset &#43;&#61; nBlockLen;
pGlobal[nOffset] &#61; 0x3B; // trailer
nOffset&#43;&#43;;
*pBlockLen &#61; 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 &#61; m_PaintRect.right-m_PaintRect.left;
if (nPaintWidth > 0)
{
LONG nPaintHeight &#61; 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 &#61; ::GetDC(m_hWnd);
if (!hWinDC) return FALSE;
m_hMemDC &#61; CreateCompatibleDC(hWinDC);
if (!m_hMemDC)
{
::ReleaseDC(m_hWnd,hWinDC);
return FALSE;
};
m_hBitmap &#61; CreateCompatibleBitmap(hWinDC,nWidth,nHeight);
if (!m_hBitmap)
{
::ReleaseDC(m_hWnd,hWinDC);
::DeleteDC(m_hMemDC);
return FALSE;
};
m_hOldBitmap &#61; reinterpret_cast
(SelectObject(m_hMemDC,m_hBitmap));
// fill the background
m_clrBackground &#61; GetSysColor(COLOR_3DFACE);
RECT rect &#61; {0,0,nWidth,nHeight};
FillRect(m_hMemDC,&rect,(HBRUSH)(COLOR_WINDOW));
::ReleaseDC(m_hWnd,hWinDC);
m_bIsInitialized &#61; TRUE;
return TRUE;
}
void CPictureEx::OnDestroy()
{
Stop();
CStatic::OnDestroy();
}
void CPictureEx::SetBkColor(COLORREF clr)
{
if (!m_bIsInitialized) return;
m_clrBackground &#61; clr;
HBRUSH hBrush &#61; CreateSolidBrush(clr);
if (hBrush)
{
RECT rect &#61; {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 &#61; 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 {
nBlock &#61; 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 &#61;
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 &#61;
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);
}

  对话框类文件代码&#xff1a;
  DlgExec.h

#pragma once
#include "PictureEx.h"
// CDlgExec 对话框
class CDlgExec : public CDialogEx
{
DECLARE_DYNAMIC(CDlgExec)
public:
CDlgExec(CWnd* pParent &#61; NULL); // 标准构造函数
virtual ~CDlgExec();
void setIsStop(bool bStop);
// 对话框数据
enum { IDD &#61; 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 /*&#61;NULL*/)
: CDialogEx(CDlgExec::IDD, pParent)
{
m_bClose &#61; false;
}
CDlgExec::~CDlgExec()
{
}
void CDlgExec::setIsStop(bool bStop)
{
m_bClose &#61; 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 &#61;&#61; WM_KEYDOWN&&pMsg->wParam&#61;&#61;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 &#61; 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 &#61;&#61; 0)
{
if (m_bClose)
{
SendMessage(WM_CLOSE);
}
}
CDialogEx::OnTimer(nIDEvent);
}
void CDlgExec::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_PictureEx.DestroyWindow();
CDialogEx::OnClose();
}
// CDlgExec 消息处理程序

步骤三&#xff1a;

将waitimage.gif添加到自己工程目录中&#xff1a;

请添加图片描述

使用&#xff1a;

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

void CDlgAgingTest::OnBtnStart()
{
TCHAR tzText[MAX_PATH] &#61; {0};
UpdateData(TRUE);
CProductToolDlg *pMainWnd &#61; (CProductToolDlg*)AfxGetMainWnd();
CString strIPStart, strPwd, strUser;
m_edIPStart.GetWindowText(strIPStart);
strIPStart.TrimLeft();
strIPStart.TrimRight();
TCHAR tsTempText[256] &#61; {0};

char strStartIP[256] &#61; {0};
Widechar_2_Multibyte(CP_ACP, strIPStart, strStartIP, sizeof(strStartIP)-1);
int nIp1&#61;0, nIp2&#61;0, nIp3&#61;0, nIp4&#61;0;
if((sscanf(strStartIP, "%d.%d.%d.%d", &nIp1, &nIp2, &nIp3, &nIp4) !&#61; 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 &#61; 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 &#61; NULL;
}
if(NULL &#61;&#61; m_ThreadTimer)
{
m_ThreadTimer &#61; my_thread_create(20000, ThreadCheckUserPwd, this);
}
//模态阻塞&#xff0c;直到线程http请求完毕
m_pWaitDlg &#61; new CDlgExec(this);
m_pWaitDlg->DoModal();
if(!m_bCheckpwdSuc)
{
ys_print("m_bCheckpwdSuc false");
return;
}
......
}
void* ThreadCheckUserPwd(void* dwUser)
{
CDlgAgingTest* Dialog &#61; (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 &#61; true;
for (int i &#61; 0; i {
CString sLanIpStart &#61; AscIpAddr(strIPStart, i);
char sIP[32] &#61; {0};
Widechar_2_Multibyte(CP_ACP, sLanIpStart, sIP, 32);
if(CheckUserPwd(sIP) &#61;&#61; -1)
{
bCheckSuc &#61; false;
break;
}
}
if(bCheckSuc)
m_bCheckpwdSuc &#61; true;
else
m_bCheckpwdSuc &#61; false;
//http请求完成&#xff0c;关闭模态阻塞对话框&#xff0c;继续执行主线程代码
if(m_pWaitDlg)
m_pWaitDlg->setIsStop(true);

}






推荐阅读
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 本文介绍了关于Java异常的八大常见问题,包括异常管理的最佳做法、在try块中定义的变量不能用于catch或finally的原因以及为什么Double.parseDouble(null)和Integer.parseInt(null)会抛出不同的异常。同时指出这些问题是由于不同的开发人员开发所导致的,不值得过多思考。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • JavaWeb中读取文件资源的路径问题及解决方法
    在JavaWeb开发中,读取文件资源的路径是一个常见的问题。本文介绍了使用绝对路径和相对路径两种方法来解决这个问题,并给出了相应的代码示例。同时,还讨论了使用绝对路径的优缺点,以及如何正确使用相对路径来读取文件。通过本文的学习,读者可以掌握在JavaWeb中正确找到和读取文件资源的方法。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
author-avatar
123妖_精
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有