动画特效框架

    技术2022-05-20  33

    #pragma once

    class HDCMemo{public: HDCMemo(RECT rtImg); virtual ~HDCMemo(void);

     void Record(HDC hDC); void Recover(HDC hDC); RECT getSize();private: HANDLE  m_hMutex; RECT  m_rtImg; HBITMAP  m_bmpMemo;};

     

     

    #pragma once#include "../CE600.h"#include "../HDCMemo.h"

     

    class Cartoon{public: bool Run(LPVOID pPar); bool IsOver();

    protected: Cartoon(CDialog* pDlg, HDCMemo* pHDCMemo); virtual ~Cartoon(void); virtual void Render(LPVOID pPar) = 0;

     CDialog  *m_pDlg; HDCMemo  *m_pHDCMemo; HANDLE  m_hMutex; ThreadEx* m_pThread; HANDLE  m_hClose; LPVOID  m_pRenderPar; friend DWORD CartoonThread(LPVOID pThis);};

     

     

     

     

    #pragma once#include "Cartoon.h"

     

    class CartoonPiece: public Cartoon{public: CartoonPiece(CDialog* pDlg, HDCMemo* pHDCMemo); virtual ~CartoonPiece(void);

    private: virtual void Render(LPVOID pPar);};

     

     

    使用:

    BOOL CCartoonDlg::OnInitDialog(){ CDialog::OnInitDialog(); CRect rtImg; GetClientRect(rtImg); m_pMemo = new HDCMemo(rtImg); CDC* pDC = GetDC(); CDCBuf buf(pDC,&rtImg); buf.fillRect(RGB(0,0,255)); m_pMemo->Record(buf); m_pCartoon = new CartoonPiece(this,m_pMemo); m_pCartoon->Run(NULL);

     return TRUE;  // return TRUE  unless you set the focus to a control}

     

    void CCartoonPieceDlg::OnDestroy(){ // TODO: Add your message handler code here if( NULL != m_pCartoon)  delete m_pCartoon; m_pCartoon = NULL; if( NULL != m_pMemo)  delete m_pMemo; m_pMemo = NULL;

     CDialog::OnDestroy();}

     

    BOOL CCartoonPieceDlg::OnEraseBkgnd(CDC* pDC){ m_pMemo->Recover(*pDC);

     return FALSE;}

     

    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

    png格式的渲染速度较慢,画一张480*272的图要200毫秒左右,而人眼的辨别能力为100毫秒左右,故会出现反应延迟现象。而这个现象试图通过画取部份空间来解决并不现实。因为这样会导致两种渲染逻辑:1,如果是首次画,需全画。 2, 如果是补画,需重画部份空间。但是判断是首画还是补画会比较麻烦,因为触发画图函数的消息可以是用户触发的,也可以是由系统触发的(例如窗口被遮挡住等)。而要对所有的触发情况做标志,并针对标志做相应的全画和补画,不现实也不可靠。安全的方法可能还是得每次都全画,只是在全画的过程中想办法提高效率。  另还有一个渲染动画的问题一直也没有很好的解决,因为渲染过程中系统无法响应其它消息, 所以如果是一个动画,那么只有等动画执行完毕了。 虽然还可以用线程等方法,但是目前却没有很好的打包和设计模式来解决,导致明明是一个连续的动作,却要分割成一个个图画,然后再添加相关消息处理过程控制在程序里四处散放等,导致实现不影响用户动作的一个动画很麻烦。

             解决方案:通过线程,计时器和备忘录模式(带互斥作用)解决。流程如下:

             客户端:

             动作线程:

             服务器->开启刷新定时器。

             While(X)

             {       

                       渲染。

                      备忘录记录记录(画面)。

    }

             服务器->关闭刷新定时器。

     

             服务器端:

             OnPaint()

             {

                       画图(获得备忘录记录)

             }

     

             备: 通过备忘录模式,使每次修改扩展渲染功能都不用去服务器的OnPaint功能里修改(画图一定要经过OnPaint才行,不然一些重画的情况时,画面会丢失)。通过线程,使动画过程不影响其它消息的响应。通过定时器来刷新使动画的渲染速度稳定。另,备忘录需带互斥功能,以防画面读写过程出错。

     

     

    /******************************************************************** created: 2011/03/01 created: 1:3:2011   10:52 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/HDCMemo.h file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600 file base: HDCMemo file ext: h author:  Clark  purpose: 用于动画渲染的备忘录模式*********************************************************************/

     

     

    #include "StdAfx.h"#include "HDCMemo.h"

    HDCMemo::HDCMemo(RECT rtImg){ CopyRect(&m_rtImg,&rtImg); HDC hDC = GetDC(NULL); m_bmpMemo = CreateCompatibleBitmap(hDC,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top); ReleaseDC(NULL,hDC); 

     TCHAR szTemp[MAX_PATH]; _stprintf(szTemp,_T("MUTEX_FOR_HDCMEMO_%x"),this); m_hMutex = CreateMutex(NULL,FALSE,szTemp); }

    HDCMemo::~HDCMemo(void){ DeleteObject(m_bmpMemo); if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,5000)) {  ReleaseMutex(m_hMutex); } CloseHandle(m_hMutex);}

    void HDCMemo::Record(HDC hDC){ if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE)) {  HDC dcBitmap = CreateCompatibleDC(hDC);  HGDIOBJ hOldBitmap = SelectObject(dcBitmap, m_bmpMemo);  BitBlt(dcBitmap,0,0,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top,hDC,0,0,SRCCOPY);  SelectObject(dcBitmap, hOldBitmap);  DeleteDC(dcBitmap);

      ReleaseMutex(m_hMutex); }}

    void HDCMemo::Recover(HDC hDC){ if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE)) {  HDC dcBitmap = CreateCompatibleDC(hDC);  HGDIOBJ hOldBitmap = SelectObject(dcBitmap,m_bmpMemo);  BitBlt(hDC,0,0,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top,dcBitmap,0,0,SRCCOPY);  SelectObject(dcBitmap,hOldBitmap);  DeleteDC(dcBitmap);

      ReleaseMutex(m_hMutex); }}

    RECT HDCMemo::getSize(){ return m_rtImg;}

     

    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

     

     

    /******************************************************************** created: 2011/03/01 created: 1:3:2011   11:34 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/Cartoon.h file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600 file base: Cartoon file ext: h author:  Clark  purpose: 动画渲染*********************************************************************/

    #include "StdAfx.h"#include "Cartoon.h"

    DWORD CartoonThread(LPVOID pThis){ Cartoon* pCartoon = (Cartoon*)pThis; pCartoon->Render(pCartoon->m_pRenderPar); if( WAIT_OBJECT_0 == WaitForSingleObject(pCartoon->m_hMutex,INFINITE)) {  pCartoon->m_pThread = NULL;  ReleaseMutex(pCartoon->m_hMutex); } return 0;}

    Cartoon::Cartoon(CDialog* pDlg, HDCMemo* pHDCMemo):m_pThread(NULL){ m_pDlg = pDlg; m_pHDCMemo = pHDCMemo; TCHAR szTemp[MAX_PATH]; _stprintf(szTemp,_T("MUTEX_FOR_CARTOON_%x"),this); m_hMutex = CreateMutex(NULL,FALSE,szTemp); }

    Cartoon::~Cartoon(void){ if( NULL != m_pThread)  delete m_pThread; m_pThread = NULL; if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,5000)) {  ReleaseMutex(m_hMutex); } CloseHandle(m_hMutex);}

    bool Cartoon::Run(LPVOID pPar){ bool bSign = false; if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE)) {  if( NULL == m_pThread)  {   m_pRenderPar = pPar;   m_pThread = new ThreadEx(m_hClose,CartoonThread,this);   bSign = true;  }  ReleaseMutex(m_hMutex); } return bSign;}

    bool Cartoon::IsOver(){ bool bSign = false; if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE)) {  if( NULL == m_pThread)  {   bSign = true;  }  ReleaseMutex(m_hMutex); } return bSign;}

     

    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

     

     

    /******************************************************************** created: 2011/03/01 created: 1:3:2011   11:34 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/Cartoon.h file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600 file base: Cartoon file ext: h author:  Clark  purpose: 动画渲染*********************************************************************/

    #include "StdAfx.h"#include "CartoonPiece.h"#include "../CDCBuf.h"

    CartoonPiece::CartoonPiece(CDialog* pDlg, HDCMemo* pHDCMemo):Cartoon(pDlg,pHDCMemo){ NULL;}

    CartoonPiece::~CartoonPiece(void){ NULL;}

    void CartoonPiece::Render(LPVOID pPar){ CRect rtDlg; m_pDlg->GetClientRect(rtDlg); CDC* pDC = m_pDlg->GetDC(); CDCBuf buf(pDC,&rtDlg); m_pDlg->ReleaseDC(pDC); buf.SetAuto(false); m_pMemo->Recover(buf);

     const int iCount = 8; const int iROWS = 4; const int iLINES = 4; const int iUW = rtDlg.Width()/iLINES+0.5; const int iUH = rtDlg.Height()/iROWS+0.5; const int iUW_L = iUW/iCount+0.5; const int iUH_L = iUH/iCount+0.5; int iPosX, iPosY, iW, iH;

     iW = iH = 0; for(int k=0; k<iCount; k++) {  iPosX = iPosY = 0;  iW += iUW_L;  iH += iUH_L;  for(int i=0; i<=iROWS; i++)  {   iPosX = 0;   for(int j=0; j<=iLINES; j++)   {    CRect rtImg(iPosX,iPosY,iPosX+iW,iPosY+iH);    if( NULL == pPar)     buf.fillRect(RGB(0,255,0),&rtImg);    else     buf.drawBmp((CBitmap*)pPar,&rtImg,&rtImg);    iPosX += iUW;   }   iPosY += iUH;  }  m_pMemo->Record(buf);  m_pDlg->Invalidate();  Sleep(10); } if( NULL == pPar)  buf.fillRect(RGB(0,255,0),&rtDlg); else  buf.drawBmp((CBitmap*)pPar,&rtDlg,&rtDlg); m_pMemo->Record(buf); m_pDlg->Invalidate();}


    最新回复(0)