DirectDraw.cpp
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:8k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. // DDraw.cpp: implementation of the CDirectDraw class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "..stdafx.h"
  5. #include "DirectDraw.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. #pragma comment(lib,"ddraw.lib")
  12. #pragma comment(lib,"dxguid.lib")
  13. CDirectDraw::CDirectDraw()
  14. {
  15. this->m_hWnd=NULL; 
  16. this->wndText = "";
  17. memset(&this->ddsd,0,sizeof(this->ddsd)); 
  18. this->lpDD=NULL; 
  19. this->lpDDSPrimary=NULL;
  20. this->lpDDSOffscreen=NULL; 
  21. this->lpClipper=NULL; 
  22. this->bitmap_width=0;
  23. this->bitmap_height=0;
  24. this->bitmap_depth=0;
  25. this->bitmap_size=0; 
  26. this->screen_width=0;
  27. this->screen_height=0;
  28. this->screen_depth=0; 
  29. this->ddraw_buffer=NULL;
  30. }
  31. CDirectDraw::~CDirectDraw()
  32. {
  33. this->ReleaseDirectDraw( );
  34. }
  35. BOOL CDirectDraw::InitDirectDraw( HWND hwnd , int width , int height , int depth )
  36. {
  37. if( ! ::IsWindow( hwnd ) ) return FALSE;
  38. LPDIRECTDRAW lpdd = NULL;
  39. //创建DirectDraw
  40. if( FAILED( DirectDrawCreate( NULL ,&lpdd , NULL ) ) ) 
  41. return FALSE;
  42. lpdd->QueryInterface( IID_IDirectDraw7 ,( void** )( &lpDD ) );
  43. lpdd->Release();
  44. if(this->lpDD == NULL)
  45. return FALSE;
  46. //与窗口建立关系
  47. if( FAILED ( this->lpDD->SetCooperativeLevel( hwnd , DDSCL_NORMAL ) ) )
  48. {
  49. this->ReleaseDirectDraw();
  50. return FALSE;
  51. }
  52. ZeroMemory( &ddsd,sizeof( ddsd ) );
  53. this->ddsd.dwSize = sizeof(DDSURFACEDESC2);
  54.     this->ddsd.dwFlags = DDSD_CAPS;
  55.     this->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
  56. //创建主表面
  57. if( FAILED( this->lpDD->CreateSurface( &this->ddsd , &this->lpDDSPrimary , NULL ) ) )
  58. {
  59. this->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  60. if( FAILED( this->lpDD->CreateSurface( &this->ddsd , &this->lpDDSPrimary , NULL ) ) )
  61. {
  62. this->ReleaseDirectDraw();return FALSE;
  63. }
  64. }//取屏幕分辨率
  65. if( FAILED( this->lpDD->GetDisplayMode( &this->ddsd ) ) )
  66. {
  67. this->ReleaseDirectDraw(); return FALSE;
  68. }
  69. this->screen_width = this->ddsd.dwWidth;
  70. this->screen_height = this->ddsd.dwHeight;
  71. this->screen_depth = this->ddsd.ddpfPixelFormat.dwRGBBitCount;
  72. //设定屏外图像大小
  73. this->ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
  74.     this->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; 
  75.     //屏外表面图像的宽度
  76.     this->ddsd.dwWidth = width;
  77.     //屏外表面图像的高度
  78.     this->ddsd.dwHeight = height;
  79. //创建屏外表面
  80.     if( FAILED( this->lpDD->CreateSurface( &this->ddsd , &this->lpDDSOffscreen , NULL ) ) )
  81. {
  82. this->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 
  83. if( FAILED( this->lpDD->CreateSurface( &this->ddsd , &this->lpDDSOffscreen,NULL ) ) )
  84. {
  85. this->ReleaseDirectDraw(); return FALSE;
  86. }
  87. }
  88. //创建翻转表面
  89. if(FAILED( this->lpDD->CreateClipper( 0 , &this->lpClipper , NULL ) ) )
  90. {
  91. this->ReleaseDirectDraw(); return FALSE;
  92. }//联系窗口
  93. if( FAILED( this->lpClipper->SetHWnd( 0 , hwnd ) ) )
  94. {
  95. this->ReleaseDirectDraw(); return FALSE;
  96. }//联系主表面
  97. if( FAILED( this->lpDDSPrimary->SetClipper( this->lpClipper ) ) )
  98. {
  99. this->ReleaseDirectDraw(); return FALSE;
  100. }//保存位图大小
  101. this->bitmap_width = width;
  102. this->bitmap_height = height;
  103. this->bitmap_depth = depth; 
  104.     this->bitmap_size = width * height * depth / 8; 
  105.  if(this->ddraw_buffer == NULL )
  106.  this->ddraw_buffer = new char [ this->bitmap_width * this->bitmap_height * this->screen_depth/8 ];
  107.     //保存窗口句柄
  108. this->m_hWnd = hwnd; 
  109. //保存窗口标题
  110. CWnd::FromHandle( this->m_hWnd )->GetWindowText( this->wndText );
  111. return TRUE;
  112. }
  113. void CDirectDraw::ReleaseDirectDraw( void )
  114. {
  115. if( this->lpClipper )
  116. {
  117. this->lpClipper->Release(); this->lpClipper=NULL;
  118. }
  119. if( this->lpDDSOffscreen )
  120. {
  121. this->lpDDSOffscreen->Release(); this->lpDDSOffscreen=NULL;  
  122. }
  123. if( this->lpDDSPrimary ) 
  124. {
  125. this->lpDDSPrimary->Release(); this->lpDDSPrimary=NULL;
  126. }
  127. if( this->lpDD )
  128. {
  129. this->lpDD->Release(); this->lpDD=NULL;  
  130. }
  131. if( this->ddraw_buffer )
  132. {
  133. delete this->ddraw_buffer; this->ddraw_buffer=NULL;
  134. }
  135. }
  136. //转换位图使之可以用DirextDraw画图
  137. void * CDirectDraw::ConvertImageToDDraw( void * buffer )
  138. {   //不支持带调色板的位图
  139. if( ! buffer || this->bitmap_depth == 8 || this->screen_depth == 8 )
  140. return NULL;
  141.   switch( this->bitmap_depth )
  142. {
  143. case 8  : break;
  144. case 16 : 
  145. switch(this->screen_depth)
  146. {
  147. case 8  : break;
  148. case 16 : c_color_space::rgb555_to_rgb565(this->ddraw_buffer,buffer,this->bitmap_size);break;
  149. case 24 : c_color_space::rgb555_to_rgb888(this->ddraw_buffer,buffer,this->bitmap_size);break;
  150. case 32 : c_color_space::rgb555_to_rgb8888(this->ddraw_buffer,buffer,this->bitmap_size);break;
  151. }break;
  152. case 24 :
  153. switch(this->screen_depth)
  154. {
  155. case 8  : break;
  156. case 16 : c_color_space::rgb888_to_rgb565(this->ddraw_buffer,buffer,this->bitmap_size);break;
  157. case 24 : c_color_space::rgb888_to_rgb888(this->ddraw_buffer,buffer,this->bitmap_size);break; 
  158. case 32 : c_color_space::rgb888_to_rgb8888(this->ddraw_buffer,buffer,this->bitmap_size);break; 
  159. }break;
  160. case 32 :
  161. switch(this->screen_depth)
  162. {
  163. case 8  : break;
  164. case 16 : c_color_space::rgb8888_to_rgb565(this->ddraw_buffer,buffer,this->bitmap_size);break;
  165. case 24 : c_color_space::rgb8888_to_rgb888(this->ddraw_buffer,buffer,this->bitmap_size);break;
  166. case 32 : c_color_space::rgb8888_to_rgb8888(this->ddraw_buffer,buffer,this->bitmap_size);break;
  167. }break;
  168. }
  169. return this->ddraw_buffer;
  170. }
  171. BOOL CDirectDraw::DrawDirectDraw( void * buffer , BOOL m_bCaption , int time )
  172. {
  173. if( buffer==NULL || !::IsWindow( this->m_hWnd ) ) 
  174. return FALSE;
  175. try
  176. {
  177. //显示图像
  178. HRESULT dd_result = this->lpDDSOffscreen->Lock( NULL , &this->ddsd , DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR , NULL );
  179. if( dd_result != DD_OK )
  180. {   //没有锁定视频表面,则判断视频表面是否丢失,如果丢失则要重置表面;否则直接返回
  181. if( dd_result==DDERR_SURFACELOST )
  182. {   //恢复视频表面
  183. this->lpDDSOffscreen->Restore();this->lpDDSPrimary->Restore(); 
  184. }
  185. else
  186. return FALSE;
  187. }//显示位图到directdraw屏外表面
  188. this->CopyToDDraw( this->ddsd.lpSurface , this->ConvertImageToDDraw( buffer ) ); 
  189. this->lpDDSOffscreen->Unlock( NULL );
  190. CRect rc;
  191. //画标题
  192. if( m_bCaption && ( ! this->wndText.IsEmpty( ) || time ) )
  193. {
  194. HDC  hdc=NULL;
  195. this->lpDDSOffscreen->GetDC( &hdc );
  196. ::SetBkMode( hdc , TRANSPARENT );
  197. ::GetClipBox( hdc , &rc );
  198. rc.DeflateRect( 5 , 5 );
  199. ::SetTextColor( hdc , RGB( 225 , 0 , 0 ) ); 
  200. ::DrawText( hdc , this->wndText , this->wndText.GetLength( ) , &rc , DT_LEFT );
  201. CTime tm( time );
  202. ::DrawText( hdc , tm.Format( "%Y-%m-%d %H:%M:%S" ) , tm.Format( "%Y-%m-%d %H:%M:%S" ).GetLength( ) , &rc , DT_RIGHT );
  203. this->lpDDSOffscreen->ReleaseDC( hdc );
  204. }
  205. ::GetWindowRect( this->m_hWnd , &rc );
  206. this->lpDDSPrimary->Blt( &rc , this->lpDDSOffscreen , NULL , DDBLT_WAIT , NULL );
  207. return TRUE;
  208. }
  209. catch( ... )
  210. {
  211. return FALSE;
  212. }
  213. }
  214. void CDirectDraw::CopyToDDraw( void * destination_buffer , void * source_buffer )
  215. {
  216. if( ! destination_buffer || ! source_buffer ) 
  217. return;
  218.     //一条扫描线的大小
  219. int pitch=this->bitmap_width * this->screen_depth / 8;
  220. BYTE* ps=( BYTE * )source_buffer;
  221. BYTE* pd=( BYTE * )destination_buffer;
  222. ps += this->bitmap_height * pitch; 
  223.     //每次扫描一条线
  224. for( int i = 0 ; i < this->bitmap_height ; i++ )
  225. {
  226. memcpy( pd , ps , pitch );
  227.         //从底部拷贝每一条扫描线
  228. ps-=pitch;
  229. pd += this->ddsd.lPitch;
  230. }
  231. }