用DirectDraw封装的位图动画类

时间:2022-05-01 00:06:26

头文件

  1. #pragma once
  2. #include <vector>
  3. using namespace std;
  4. #include <DShow.h>
  5. #include <uuids.h>
  6. #define DXIMAGE_WIDTH   1024
  7. #define DXIMAGE_HEIGHT  768
  8. class CDXImage
  9. {
  10. public:
  11. CDXImage(void);
  12. ~CDXImage(void);
  13. //
  14. public:
  15. // 文件中载入位图
  16. BOOL LoadImageFromFile(char *pFileName, int cx, int cy);
  17. // 载入图像
  18. void LoadDXImage(char* pBits, int cx, int cy);
  19. // 显示图像
  20. void Display(CDC *pDC);
  21. // 初始化DirectDraw
  22. void InitDraw(HWND hWnd);
  23. // 恢复丢失的图面
  24. void RestoreAll(HWND hWnd);
  25. protected:
  26. // 释放对象
  27. void ReleaseObject();
  28. // DX objects
  29. private:
  30. IDirectDraw7        *m_lpDD;                // DirectDraw Object
  31. IDirectDrawSurface7 *m_lpDDSPrimary;        // Primary Surface Object
  32. IDirectDrawSurface7 *m_lppDDSBackBuffer;    // BackBuffer Surface Object
  33. // Image Object
  34. private:
  35. vector<HBITMAP> m_vpBMPs; // BMP Objects Array
  36. HWND m_hWnd;
  37. };

#pragma once
#include <vector>
using namespace std;
#include <DShow.h>
#include <uuids.h>
#define DXIMAGE_WIDTH 1024
#define DXIMAGE_HEIGHT 768
class CDXImage
{
public:
CDXImage(void);
~CDXImage(void);
//
public:
// 文件中载入位图
BOOL LoadImageFromFile(char *pFileName, int cx, int cy);
// 载入图像
void LoadDXImage(char* pBits, int cx, int cy);
// 显示图像
void Display(CDC *pDC);
// 初始化DirectDraw
void InitDraw(HWND hWnd);
// 恢复丢失的图面
void RestoreAll(HWND hWnd);
protected:
// 释放对象
void ReleaseObject();
// DX objects
private:
IDirectDraw7 *m_lpDD; // DirectDraw Object
IDirectDrawSurface7 *m_lpDDSPrimary; // Primary Surface Object
IDirectDrawSurface7 *m_lppDDSBackBuffer; // BackBuffer Surface Object
// Image Object
private:
vector<HBITMAP> m_vpBMPs; // BMP Objects Array
HWND m_hWnd;
};

源文件

  1. #include "StdAfx.h"
  2. #include "DXImage.h"
  3. CDXImage::CDXImage(void)
  4. {
  5. // 成员变量初始化
  6. this->m_lpDD = NULL;
  7. this->m_lpDDSPrimary = NULL;
  8. this->m_lppDDSBackBuffer = NULL;
  9. this->m_hWnd = NULL;
  10. }
  11. CDXImage::~CDXImage(void)
  12. {
  13. ReleaseObject();
  14. }
  15. /************************************************************************
  16. * 函数名称:LoadDXImage
  17. * 函数功能:从DSP端接收图像数据
  18. * 函数参数:
  19. *          char *pBits : 图像数据
  20. *          int cx      : 图像宽度
  21. *          int cy      : 图像高度
  22. * 返回值:void
  23. ************************************************************************/
  24. void CDXImage::LoadDXImage(char *pBits, int cx,int cy)
  25. {
  26. }
  27. /************************************************************************
  28. * 函数名称:LoadImageFromFile
  29. * 函数功能:从硬盘文件中读取图像
  30. * 函数参数:
  31. *           char *pFileName : 图像文件名
  32. *           int cx          : 图像宽度
  33. *           int cy          : 图像高度
  34. * 返回值类型:BOOL
  35. true : 文件载入成功
  36. false: 文件载入失败
  37. ************************************************************************/
  38. BOOL CDXImage::LoadImageFromFile(char *pFileName, int cx, int cy)
  39. {
  40. HBITMAP hbmp;
  41. hbmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), pFileName, IMAGE_BITMAP, cx, cy, LR_LOADFROMFILE);
  42. if (hbmp == NULL)
  43. {
  44. AfxMessageBox("Failed to Load Image /n Please Check the File Path!");
  45. return FALSE;
  46. }
  47. m_vpBMPs.push_back(hbmp);
  48. return TRUE;
  49. }
  50. /************************************************************************
  51. * 函数名称:InitDraw
  52. * 函数功能:初始化DirectDraw
  53. * 函数参数:
  54. *           HWND hWnd : 图像显示窗口句柄
  55. * 返回值类型:void
  56. ************************************************************************/
  57. void CDXImage::InitDraw(HWND hWnd)
  58. {
  59. ASSERT(m_lpDD == NULL);
  60. ASSERT(m_lpDDSPrimary == NULL);
  61. ASSERT(m_lppDDSBackBuffer == NULL);
  62. ASSERT(m_vpBMPs.size() == 0);
  63. ASSERT(m_hWnd == NULL);
  64. m_hWnd = hWnd;
  65. // 创建DirectDraw对象
  66. HRESULT hr;
  67. hr = DirectDrawCreateEx(NULL, (VOID**)&m_lpDD, IID_IDirectDraw7, NULL);
  68. if (FAILED(hr))
  69. {
  70. AfxMessageBox("Failed to Create DirectDraw Object!");
  71. return;
  72. }
  73. hr = m_lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
  74. if (FAILED(hr))
  75. {
  76. AfxMessageBox("Failed to Initialize DirectDraw");
  77. return;
  78. }
  79. // 创建主图面
  80. DDSURFACEDESC2 ddsd;
  81. memset(&ddsd, 0, sizeof(ddsd));
  82. ddsd.dwSize = sizeof(ddsd);
  83. ddsd.dwFlags = DDSD_CAPS;
  84. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  85. hr = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL);
  86. if (FAILED(hr))
  87. {
  88. AfxMessageBox("Failed to Create primary surface!");
  89. return;
  90. }
  91. // 创建裁剪
  92. IDirectDrawClipper *lpClipper = NULL;
  93. hr = m_lpDD->CreateClipper(NULL, &lpClipper, NULL);
  94. if (FAILED(hr))
  95. {
  96. AfxMessageBox("Failed to Create Clipper!");
  97. return;
  98. }
  99. hr = lpClipper->SetHWnd(0, hWnd);
  100. if (FAILED(hr))
  101. {
  102. AfxMessageBox("Failed to Create Window Clipper!");
  103. return;
  104. }
  105. hr = m_lpDDSPrimary->SetClipper(lpClipper);
  106. if (FAILED(hr))
  107. {
  108. AfxMessageBox("Failed to Set Clipper of Primary Surface!");
  109. return;
  110. }
  111. lpClipper->Release();
  112. // 创建辅助画面
  113. memset(&ddsd, 0, sizeof(ddsd));
  114. ddsd.dwSize = sizeof(ddsd);
  115. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  116. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  117. ddsd.dwWidth = DXIMAGE_WIDTH;
  118. ddsd.dwHeight = DXIMAGE_HEIGHT;
  119. hr = m_lpDD->CreateSurface(&ddsd, &m_lppDDSBackBuffer, NULL);
  120. if (FAILED(hr))
  121. {
  122. AfxMessageBox("Failed to Create Assistant Surface!");
  123. return;
  124. }
  125. }
  126. /************************************************************************
  127. * 函数名称:Display
  128. * 函数功能:显示图像
  129. * 函数参数:
  130. *           CDC pDC : 图像显示设备上下文
  131. * 返回值类型:void
  132. ************************************************************************/
  133. void CDXImage::Display(CDC *pDC = NULL)
  134. {
  135. // 绘制辅助图面
  136. HRESULT hr;
  137. DDSURFACEDESC2 desc;
  138. memset(&desc, 0, sizeof(desc));
  139. desc.dwSize = sizeof(desc);
  140. hr = m_lppDDSBackBuffer->GetSurfaceDesc(&desc);
  141. if (FAILED(hr))
  142. {
  143. AfxMessageBox("Failed to Get Assistant Surface Descriptor");
  144. return;
  145. }
  146. for (vector<HBITMAP>::iterator it = m_vpBMPs.begin(); it != m_vpBMPs.end(); it++)
  147. {
  148. // 获取设备DC
  149. HDC hDC;
  150. if (m_lppDDSBackBuffer->GetDC(&hDC) != DD_OK)
  151. {
  152. return;
  153. }
  154. // 保存DC
  155. CDC dc; //dbg
  156. dc.m_hDC = hDC;
  157. int nSavedDC = dc.SaveDC();
  158. CDC memDC;
  159. memDC.CreateCompatibleDC(&dc);
  160. HBITMAP hbmp = *it;
  161. memDC.SelectObject(hbmp);
  162. dc.BitBlt(0, 0, DXIMAGE_WIDTH, DXIMAGE_HEIGHT, &memDC, 0, 0, SRCCOPY);
  163. memDC.DeleteDC();
  164. DeleteObject(hbmp);
  165. //m_vpBMPs.erase(it);
  166. CRect rcClient;
  167. GetClientRect(m_hWnd, &rcClient);
  168. ClientToScreen(m_hWnd, &rcClient.TopLeft());
  169. ClientToScreen(m_hWnd, &rcClient.BottomRight());
  170. dc.RestoreDC(nSavedDC);
  171. dc.m_hDC = NULL;
  172. m_lppDDSBackBuffer->ReleaseDC(hDC);
  173. m_lpDDSPrimary->Blt(&rcClient, m_lppDDSBackBuffer, NULL, DDBLT_WAIT, NULL);
  174. }
  175. }
  176. /************************************************************************
  177. * 函数名称:ReleaseObject
  178. * 函数功能:释放DirectDraw对象
  179. * 函数参数:无
  180. * 返回值类型:void
  181. ************************************************************************/
  182. void CDXImage::ReleaseObject()
  183. {
  184. // 删除对象
  185. if (m_lpDDSPrimary != NULL)
  186. {
  187. m_lpDDSPrimary->Release();
  188. m_lpDDSPrimary = NULL;
  189. }
  190. if (m_lppDDSBackBuffer != NULL)
  191. {
  192. m_lppDDSBackBuffer->Release();
  193. m_lppDDSBackBuffer = NULL;
  194. }
  195. if (m_lpDD != NULL)
  196. {
  197. m_lpDD->Release();
  198. m_lpDD = NULL;
  199. }
  200. }
  201. /************************************************************************
  202. * 函数名称:RestoreAll
  203. * 函数功能:所有DirectDraw对象复位
  204. * 函数参数:
  205. HWND hWnd : 图像显示设备句柄
  206. * 返回值类型:void
  207. ************************************************************************/
  208. void CDXImage::RestoreAll(HWND hWnd)
  209. {
  210. HRESULT hr;
  211. hr = m_lpDDSPrimary->Restore();
  212. if (hr == DDERR_WRONGMODE)
  213. {
  214. TRACE("Dispaly model changed");
  215. ReleaseObject();
  216. m_hWnd = hWnd;
  217. InitDraw(m_hWnd);
  218. return;
  219. }
  220. else if (FAILED(hr))
  221. {
  222. return;
  223. }
  224. if (FAILED(m_lppDDSBackBuffer->Restore()))
  225. {
  226. return;
  227. }
  228. }

#include "StdAfx.h"
#include "DXImage.h"
CDXImage::CDXImage(void)
{
// 成员变量初始化
this->m_lpDD = NULL;
this->m_lpDDSPrimary = NULL;
this->m_lppDDSBackBuffer = NULL;
this->m_hWnd = NULL;
}
CDXImage::~CDXImage(void)
{
ReleaseObject();
}
/************************************************************************
* 函数名称:LoadDXImage
* 函数功能:从DSP端接收图像数据
* 函数参数:
* char *pBits : 图像数据
* int cx : 图像宽度
* int cy : 图像高度
* 返回值:void
************************************************************************/
void CDXImage::LoadDXImage(char *pBits, int cx,int cy)
{

}
/************************************************************************
* 函数名称:LoadImageFromFile
* 函数功能:从硬盘文件中读取图像
* 函数参数:
* char *pFileName : 图像文件名
* int cx : 图像宽度
* int cy : 图像高度
* 返回值类型:BOOL
true : 文件载入成功
false: 文件载入失败
************************************************************************/
BOOL CDXImage::LoadImageFromFile(char *pFileName, int cx, int cy)
{
HBITMAP hbmp;
hbmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), pFileName, IMAGE_BITMAP, cx, cy, LR_LOADFROMFILE);
if (hbmp == NULL)
{
AfxMessageBox("Failed to Load Image /n Please Check the File Path!");
return FALSE;
}
m_vpBMPs.push_back(hbmp);
return TRUE;
}
/************************************************************************
* 函数名称:InitDraw
* 函数功能:初始化DirectDraw
* 函数参数:
* HWND hWnd : 图像显示窗口句柄
* 返回值类型:void
************************************************************************/
void CDXImage::InitDraw(HWND hWnd)
{
ASSERT(m_lpDD == NULL);
ASSERT(m_lpDDSPrimary == NULL);
ASSERT(m_lppDDSBackBuffer == NULL);
ASSERT(m_vpBMPs.size() == 0);
ASSERT(m_hWnd == NULL);
m_hWnd = hWnd;
// 创建DirectDraw对象
HRESULT hr;
hr = DirectDrawCreateEx(NULL, (VOID**)&m_lpDD, IID_IDirectDraw7, NULL);
if (FAILED(hr))
{
AfxMessageBox("Failed to Create DirectDraw Object!");
return;
}
hr = m_lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
if (FAILED(hr))
{
AfxMessageBox("Failed to Initialize DirectDraw");
return;
}
// 创建主图面
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL);
if (FAILED(hr))
{
AfxMessageBox("Failed to Create primary surface!");
return;
}
// 创建裁剪
IDirectDrawClipper *lpClipper = NULL;
hr = m_lpDD->CreateClipper(NULL, &lpClipper, NULL);
if (FAILED(hr))
{
AfxMessageBox("Failed to Create Clipper!");
return;
}
hr = lpClipper->SetHWnd(0, hWnd);
if (FAILED(hr))
{
AfxMessageBox("Failed to Create Window Clipper!");
return;
}
hr = m_lpDDSPrimary->SetClipper(lpClipper);
if (FAILED(hr))
{
AfxMessageBox("Failed to Set Clipper of Primary Surface!");
return;
}
lpClipper->Release();
// 创建辅助画面
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = DXIMAGE_WIDTH;
ddsd.dwHeight = DXIMAGE_HEIGHT;
hr = m_lpDD->CreateSurface(&ddsd, &m_lppDDSBackBuffer, NULL);
if (FAILED(hr))
{
AfxMessageBox("Failed to Create Assistant Surface!");
return;
}
}
/************************************************************************
* 函数名称:Display
* 函数功能:显示图像
* 函数参数:
* CDC pDC : 图像显示设备上下文
* 返回值类型:void
************************************************************************/
void CDXImage::Display(CDC *pDC = NULL)
{
// 绘制辅助图面
HRESULT hr;
DDSURFACEDESC2 desc;
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
hr = m_lppDDSBackBuffer->GetSurfaceDesc(&desc);
if (FAILED(hr))
{
AfxMessageBox("Failed to Get Assistant Surface Descriptor");
return;
}

for (vector<HBITMAP>::iterator it = m_vpBMPs.begin(); it != m_vpBMPs.end(); it++)
{
// 获取设备DC
HDC hDC;
if (m_lppDDSBackBuffer->GetDC(&hDC) != DD_OK)
{
return;
}
// 保存DC
CDC dc; //dbg
dc.m_hDC = hDC;
int nSavedDC = dc.SaveDC();
CDC memDC;
memDC.CreateCompatibleDC(&dc);
HBITMAP hbmp = *it;
memDC.SelectObject(hbmp);
dc.BitBlt(0, 0, DXIMAGE_WIDTH, DXIMAGE_HEIGHT, &memDC, 0, 0, SRCCOPY);
memDC.DeleteDC();
DeleteObject(hbmp);
//m_vpBMPs.erase(it);

CRect rcClient;
GetClientRect(m_hWnd, &rcClient);
ClientToScreen(m_hWnd, &rcClient.TopLeft());
ClientToScreen(m_hWnd, &rcClient.BottomRight());
dc.RestoreDC(nSavedDC);
dc.m_hDC = NULL;
m_lppDDSBackBuffer->ReleaseDC(hDC);
m_lpDDSPrimary->Blt(&rcClient, m_lppDDSBackBuffer, NULL, DDBLT_WAIT, NULL);
}
}
/************************************************************************
* 函数名称:ReleaseObject
* 函数功能:释放DirectDraw对象
* 函数参数:无
* 返回值类型:void
************************************************************************/
void CDXImage::ReleaseObject()
{
// 删除对象
if (m_lpDDSPrimary != NULL)
{
m_lpDDSPrimary->Release();
m_lpDDSPrimary = NULL;
}
if (m_lppDDSBackBuffer != NULL)
{
m_lppDDSBackBuffer->Release();
m_lppDDSBackBuffer = NULL;
}
if (m_lpDD != NULL)
{
m_lpDD->Release();
m_lpDD = NULL;
}
}
/************************************************************************
* 函数名称:RestoreAll
* 函数功能:所有DirectDraw对象复位
* 函数参数:
HWND hWnd : 图像显示设备句柄
* 返回值类型:void
************************************************************************/
void CDXImage::RestoreAll(HWND hWnd)
{
HRESULT hr;
hr = m_lpDDSPrimary->Restore();
if (hr == DDERR_WRONGMODE)
{
TRACE("Dispaly model changed");
ReleaseObject();
m_hWnd = hWnd;
InitDraw(m_hWnd);
return;
}
else if (FAILED(hr))
{
return;
}
if (FAILED(m_lppDDSBackBuffer->Restore()))
{
return;
}
}

用法:

适用于Win32平台

一、创建一个CDXImage类对象

  1. CDXImage m_DXImage;

CDXImage m_DXImage;

二、初始化并载入位图

  1. m_DXImage.InitDraw(GetSafeHwnd());  // 初始化DX图像对象
  2. m_DXImage.LoadImageFromFile("pics//0.bmp", 1024, 768);
  3. m_DXImage.LoadImageFromFile("pics//2.bmp", 1024, 768);

m_DXImage.InitDraw(GetSafeHwnd()); // 初始化DX图像对象
m_DXImage.LoadImageFromFile("pics//0.bmp", 1024, 768);
m_DXImage.LoadImageFromFile("pics//2.bmp", 1024, 768);

三、显示位图

  1. m_DXImage.Display(NULL);

m_DXImage.Display(NULL);

然后可借助定时器使用。