RippleWnd.cpp
上传用户:oldpeter23
上传日期:2013-01-09
资源大小:1111k
文件大小:7k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. //NetTalk
  2. /*------------------------------------------------------------------------------*
  3.  =============================
  4.    模块名称: RippleWnd.cpp
  5.  =============================
  6.  
  7.  [版权]
  8.  
  9.                                                  
  10. *------------------------------------------------------------------------------*/
  11. //借鉴来的水波特效,作者不详,在此谢过
  12. #include "WndX.h"
  13. #include "RippleWnd.h"
  14. #include <Stdio.h>
  15. #include <Windowsx.h>
  16. #pragma comment(lib,"ddraw")
  17. /*------------------------------------------------------------------------------*/
  18. CRippleWnd::CRippleWnd()
  19. {
  20. m_iCount=0;
  21. m_dwFps=0;
  22. }
  23. /*------------------------------------------------------------------------------*/
  24. CRippleWnd::~CRippleWnd()
  25. {
  26. }
  27. /*------------------------------------------------------------------------------*/
  28. BOOL CRippleWnd::Create(RECT &rc, HWND hParent,UINT uBmpID,int iWidth,int iHeight)
  29. {
  30. BOOL bRet=FALSE;
  31. m_iWidth=iWidth;
  32. m_iHeight=iHeight;
  33. if(!CWndX::Create(0,0,0,WS_CHILD|WS_VISIBLE,rc,hParent,0,0))
  34. goto RET;
  35. SetClassLong(m_hWnd,GCL_HBRBACKGROUND,0);
  36. if(!InitDDraw(uBmpID,iWidth,iHeight))
  37. goto RET;
  38. SetTimer(m_hWnd,1,30,0);
  39. m_dwTime=GetTickCount();
  40. bRet=TRUE;
  41. RET:
  42. return bRet;
  43. }
  44. /*------------------------------------------------------------------------------*/
  45. LRESULT CRippleWnd::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  46. {
  47. switch(uMsg)
  48. {
  49. case WM_DESTROY:
  50. KillTimer(m_hWnd,1);
  51. FreeObject();
  52. break;
  53. case WM_TIMER:
  54. {
  55. if(IsWindowVisible(m_hWnd))
  56. {
  57. UpdateFrame();
  58. }
  59. }
  60. break;
  61. case WM_LBUTTONDOWN:
  62. DropStone(LOWORD(lParam),HIWORD(lParam),3,128);
  63. break;
  64. case WM_MOUSEMOVE:
  65. if (wParam==MK_LBUTTON )
  66. {
  67. DropStone(LOWORD(lParam),HIWORD(lParam),3,128);
  68. }
  69. break;
  70. }
  71. return CWndX::WndProc(uMsg,wParam,lParam);
  72. }
  73. /*------------------------------------------------------------------------------*/
  74. BOOL CRippleWnd::InitDDraw(UINT uBmpID,int iWidth,int iHeight)
  75. {
  76. DDSURFACEDESC       ddsd;
  77.     HRESULT             ddrval;
  78.     //创建DirectDraw对象
  79. ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  80.     if( ddrval != DD_OK )
  81.         return FALSE;
  82.     ddrval = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  83.     if( ddrval != DD_OK )
  84.         return FALSE;
  85.     ddsd.dwSize = sizeof( ddsd );
  86.     ddsd.dwFlags = DDSD_CAPS ;
  87.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  88.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  89.     if( ddrval != DD_OK )
  90.         return FALSE;
  91. ZeroMemory(&ddsd, sizeof(ddsd));
  92.     ddsd.dwSize = sizeof(ddsd);
  93.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  94.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |DDSCAPS_SYSTEMMEMORY ;
  95. ddsd.dwWidth = iWidth;
  96.     ddsd.dwHeight = iHeight;
  97.     if (lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) != DD_OK)
  98. return FALSE;
  99.     if (lpDD->CreateSurface(&ddsd, &lpDDSPic2, NULL) != DD_OK)
  100. return FALSE;
  101. lpDD->CreateClipper(0, &lpClipper, NULL);
  102. lpClipper->SetHWnd(0, m_hWnd);
  103. lpDDSPrimary->SetClipper(lpClipper);
  104. DDReLoadBitmap(lpDDSPic1, MAKEINTRESOURCE(uBmpID));
  105.     buf1 = new short[iWidth*iHeight];
  106. buf2 = new short[iWidth*iHeight];
  107. ZeroMemory(buf1, iWidth*iHeight*sizeof(short));
  108. ZeroMemory(buf2, iWidth*iHeight*sizeof(short));
  109.     return TRUE;
  110. }
  111. /*------------------------------------------------------------------------------*/
  112. void CRippleWnd::FreeObject()
  113. {
  114. if( lpDD != NULL )//释放DirectDraw对象
  115.     {
  116.         if( lpDDSPrimary != NULL )//释放主页面。
  117.         {
  118.             lpDDSPrimary->Release();
  119.             lpDDSPrimary = NULL;
  120.         }
  121.         if( lpDDSPic1 != NULL )//释放离屏页面。
  122.         {
  123.             lpDDSPic1->Release();
  124.             lpDDSPic1 = NULL;
  125.         }
  126.         if( lpDDSPic2 != NULL )
  127.         {
  128.             lpDDSPic2->Release();
  129.             lpDDSPic2 = NULL;
  130.         }
  131. if (lpClipper!=NULL)
  132. {
  133. lpClipper->Release();
  134. lpClipper=NULL;
  135. }
  136.         lpDD->Release();
  137.         lpDD = NULL;
  138.     }
  139. if(buf1)
  140. delete buf1;
  141. if(buf2)
  142. delete buf2;
  143. }
  144. /*------------------------------------------------------------------------------*/
  145. void CRippleWnd::DropStone(int x,int y,int stonesize,int stoneweight)
  146. {
  147. //判断坐标是否在屏幕范围内
  148. if ((x+stonesize)>m_iWidth || 
  149. (y+stonesize)>m_iHeight||
  150. (x-stonesize)<0||
  151. (y-stonesize)<0)
  152. return;
  153. for (int posx=x-stonesize; posx<x+stonesize; posx++)
  154. for (int posy=y-stonesize; posy<y+stonesize; posy++)
  155. if ((posx-x)*(posx-x) + (posy-y)*(posy-y) < stonesize*stonesize)
  156. buf1[m_iWidth*posy+posx] = -stoneweight;
  157. }
  158. /*------------------------------------------------------------------------------*/
  159. void CRippleWnd::RenderRipple()
  160. {
  161. //锁定两个离屏页面
  162. DDSURFACEDESC ddsd1, ddsd2;
  163. ddsd1.dwSize = sizeof (DDSURFACEDESC);
  164. ddsd2.dwSize = sizeof(DDSURFACEDESC);
  165. lpDDSPic1->Lock(NULL, &ddsd1, DDLOCK_WAIT, NULL);
  166. lpDDSPic2->Lock(NULL, &ddsd2, DDLOCK_WAIT, NULL);
  167. //取得页面象素位深度,和页面内存指针
  168. int depth=ddsd1.ddpfPixelFormat.dwRGBBitCount/8;
  169. BYTE *Bitmap1 = (BYTE*)ddsd1.lpSurface;
  170. BYTE *Bitmap2 = (BYTE*)ddsd2.lpSurface;
  171. //下面进行页面渲染
  172. int xoff, yoff;
  173. int k = m_iWidth;
  174. for (int i=1; i<m_iHeight-1; i++)
  175. {
  176. for (int j=0; j<m_iWidth; j++)
  177. {
  178. //计算偏移量
  179. xoff = buf1[k-1]-buf1[k+1];
  180. yoff = buf1[k-m_iWidth]-buf1[k+m_iWidth];
  181. //判断坐标是否在窗口范围内
  182. if ((i+yoff )< 0 ) {k++; continue;}
  183. if ((i+yoff )> m_iHeight) {k++; continue;}
  184. if ((j+xoff )< 0 ) {k++; continue;}
  185. if ((j+xoff )> m_iWidth ) {k++; continue;}
  186. //计算出偏移象素和原始象素的内存地址偏移量
  187. int pos1, pos2;
  188. pos1=ddsd1.lPitch*(i+yoff)+ depth*(j+xoff);
  189. pos2=ddsd2.lPitch*i+ depth*j;
  190. //复制象素
  191. for (int d=0; d<depth; d++)
  192. Bitmap2[pos2++]=Bitmap1[pos1++];
  193. k++;
  194. }
  195. }
  196. //解锁页面
  197. lpDDSPic1->Unlock(&ddsd1);
  198. lpDDSPic2->Unlock(&ddsd2);
  199. HDC hdc;
  200. lpDDSPic2->GetDC(&hdc);
  201. char szFps[10];
  202. sprintf(szFps,"%dFPS",m_dwFps);
  203. SetBkMode(hdc,TRANSPARENT);
  204. SetTextColor(hdc,0x00ffaaaa);
  205. DrawText(hdc,szFps,strlen(szFps),&CRectX(200,5,280,20),DT_RIGHT);
  206. lpDDSPic2->ReleaseDC(hdc);
  207. }
  208. /*------------------------------------------------------------------------------*/
  209. void CRippleWnd::UpdateFrame()
  210. {
  211. m_iCount++;
  212. if(m_iCount>=20)
  213. {
  214. DropStone(
  215. (int)(m_iWidth*((short)rand()/32767.0)),
  216. (int)(m_iHeight*((short)rand()/32767.0)),
  217. 3,
  218. 128
  219. );
  220. DWORD temp=GetTickCount();
  221. m_dwFps=20000/(temp-m_dwTime);
  222. m_dwTime=temp;
  223. m_iCount=0;
  224. }
  225. RippleSpread();
  226. RenderRipple();//页面渲染
  227. //将离屏页面图象Blit到主页面
  228. RECT Window;
  229. POINT pt;
  230. GetClientRect(m_hWnd, &Window);
  231. pt.x=pt.y=0;
  232. ClientToScreen(m_hWnd, &pt);
  233. OffsetRect(&Window, pt.x, pt.y);
  234. lpDDSPrimary->Blt(&Window, lpDDSPic2, NULL, DDBLT_WAIT, NULL);
  235. }
  236. /*------------------------------------------------------------------------------*/
  237. void CRippleWnd::RippleSpread()
  238. {
  239. for (int i=m_iWidth; i<m_iWidth*m_iHeight-m_iWidth; i++)
  240. {
  241. //波能扩散
  242. buf2[i] = ((buf1[i-1]+
  243. buf1[i+1]+
  244. buf1[i-m_iWidth]+
  245. buf1[i+m_iWidth])
  246. >>1)
  247. - buf2[i];
  248. //波能衰减
  249. buf2[i] -= buf2[i]>>5;
  250. }
  251. //交换波能数据缓冲区
  252. short *ptmp =buf1;
  253. buf1 = buf2;
  254. buf2 = ptmp;
  255. }