Chinaunix首页 | 论坛 | 博客
  • 博客访问: 185856
  • 博文数量: 90
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2017-08-23 16:48
文章分类

全部博文(90)

文章存档

2015年(1)

2011年(21)

2010年(59)

2009年(9)

我的朋友

分类: C/C++

2009-11-17 17:22:33

  1. /*
  2.   目的:BMP位图处理类。(定义文件)
  3.   创建:张伟(SXZ)
  4.   版本:2.4
  5.   SXZ software workgroup. No.200001
  6. */
  7. ///////////////////////////////////////////////////////////////////////
  8. #ifndef __BMPPROC_H__
  9. #define __BMPPROC_H__
  10. /* 版本 */
  11. #define BMPPROC_VERSION   0x240
  12. // DIBSCANLINE_WIDTHBYTES 执行DIB扫描行的DWORD对齐操作。宏参数“bits”是
  13. // DIB信息结构中成员biWidth和biBitCount的乘积。宏的结果是经过对齐后一个
  14. // 扫描行所占的字节数。
  15. #define DIBSCANLINE_WIDTHBYTES(bits)    (((bits)+31)/32*4)
  16. // DDBSCANLINE_WIDTHBYTES 执行DDB扫描行的WORD对齐操作。宏参数“bits”是
  17. // DDB信息结构中成员bmWidth和bmBitCount的乘积。宏的结果是经过对齐后一个
  18. // 扫描行所占的字节数。
  19. #define DDBSCANLINE_WIDTHBYTES(bits)    (((bits)+15)/16*2)
  20. /* DIB 文件头标志("BM") */
  21. #define DIB_HEADER_MARKER   ((WORD)('M'<<8)|'B')
  22. // 常用颜色定义
  23. #define CBPCOLOR_BLACK        ((COLORREF)RGB(0,0,0))
  24. #define CBPCOLOR_GRAY        ((COLORREF)RGB(128,128,128))
  25. #define CBPCOLOR_HIGHGRAY    ((COLORREF)RGB(192,192,192))
  26. #define CBPCOLOR_WHITE        ((COLORREF)RGB(255,255,255))
  27. #define CBPCOLOR_RED        ((COLORREF)RGB(255,0,0))
  28. #define CBPCOLOR_GREEN        ((COLORREF)RGB(0,255,0))
  29. #define CBPCOLOR_BLUE        ((COLORREF)RGB(0,0,255))
  30. // 注意:类CBmpProc是从CBitmap类公有继承而来的,但最好不要使用类CBitmap
  31. // 中的函数!如果使用了(尤其是读入或创建型的函数),则就不要再使用CBmpProc
  32. // 类中的函数,以免混乱。
  33. class CBmpProc : public CBitmap
  34. {
  35. public:
  36.     CBmpProc();
  37.     ~CBmpProc();
  38.     BOOL Create(int width, int height, WORD nBitCount, const void *lpBits=NULL);
  39.     BOOL Create(CSize size, WORD nBitCount, const void *lpBits=NULL);
  40.     BOOL CreateCompatible(int width, int height, CDC *pDC=NULL, const void *lpBits=NULL);
  41.     BOOL CopyFromObject(CBmpProc& souBmp, CRect *pDesRect=NULL, CRect *pSouRect=NULL);
  42.     BOOL CopyFromHbmp(HBITMAP souBmp, CRect *pDesRect=NULL, CRect *pSouRect=NULL);
  43.     BOOL CopyTran(CBmpProc& souBmp, COLORREF crColour=CBPCOLOR_WHITE,
  44.             CRect *pDesRect=NULL, CRect *pSouRect=NULL, int mode=0);
  45.     BOOL CopyTran(CBmpProc& souBmp, COLORREF crColour=CBPCOLOR_WHITE,
  46.             int x=0, int y=0, CRect *pSouRect=NULL, int mode=0);
  47.     BOOL CopyTranCenter(CBmpProc& souBmp, CRect* crArea=NULL,
  48.             COLORREF crColour=CBPCOLOR_WHITE, int mode=0);
  49.     BOOL CopyTranTile(CBmpProc& souBmp, CRect* crArea=NULL,
  50.             COLORREF crColour=CBPCOLOR_WHITE, int mode=0);
  51.     BOOL LoadFromFile(LPCTSTR lpszPathName);
  52.     BOOL LoadFromResourceID(UINT uID, HINSTANCE hInst);
  53.     BOOL LoadFromResourceName(LPCTSTR lpResourceName, HINSTANCE hInst);
  54.     BOOL LoadFromObject(CBmpProc& souBmp, CRect *pSouRect=NULL);
  55.     BOOL LoadFromHbmp(HBITMAP sou, CRect *pSouRect=NULL);
  56.     BOOL LoadFromClipboard();
  57.     BOOL Save(LPCTSTR lpszNewFileName=NULL, WORD nBitsPerPixel=0);
  58.     BOOL SaveToClipboard();
  59.     BOOL Draw(CDC& dc, const CRect* rcDst=NULL, const CRect* rcSrc=NULL);
  60.     BOOL DrawTile(CDC& dc, CRect* crArea);
  61.     BOOL DrawCenter(CDC& dc, CRect* crArea);
  62.     BOOL DrawTransparentInRect(CDC& dc, COLORREF crColour=CBPCOLOR_WHITE,
  63.             CRect* crDest=NULL, CRect* crSou=NULL, int mode=0);
  64.     BOOL DrawTransparentInPoint(CDC& dc, COLORREF crColour=CBPCOLOR_WHITE,
  65.             int x=0, int y=0, CRect* crSou=NULL, int mode=0);
  66.     BOOL DrawTranCenter(CDC& dc, CRect* crArea, COLORREF crColour=CBPCOLOR_WHITE, int mode=0);
  67.     BOOL DrawTranTile(CDC& dc, CRect* crArea, COLORREF crColour=CBPCOLOR_WHITE, int mode=0);
  68.     BOOL Attach(HBITMAP hBmp);
  69.     HBITMAP Detach();
  70.     void Clear();
  71.     HRGN ExportRegion(COLORREF cTranColor=CBPCOLOR_WHITE);
  72.     BOOL Fill(COLORREF crColour=CBPCOLOR_WHITE, CRect *crArea=NULL);
  73.     BOOL ReSetColor(COLORREF oldcolr, COLORREF newcolr, CRect *crArea=NULL);
  74.           
  75.     // 重载操作符函数
  76.     CBmpProc& operator=(const CBmpProc& ds);
  77.     CBmpProc& operator=(const HBITMAP sou);
  78.     BOOL operator==(const CBmpProc& ds);
  79.     BOOL operator!=(const CBmpProc& ds);
  80.     operator HBITMAP() const { return (HBITMAP)m_hObject; };
  81.     // 类数据访问函数
  82.     CSize Size() const;
  83.     CRect Rect() const;
  84.     int   Width() const;
  85.     int   Height() const;
  86.     int   ScanWidth() const;
  87.     int   BitsPerPixel() const;
  88.     BOOL  IsValid() const;
  89.     //访问类内部数据的介面函数
  90.     int   GetImageType() const;
  91.     DWORD GetInAddInfo() const;
  92.     const CString& GetFileName() const;
  93.     BOOL  SetFileName(LPSTR pSou);
  94.     int   GetObject(LPBITMAP lpBitmap) const;
  95.     HANDLE GetHDib() const;
  96.     WORD GetVersion() const;
  97. #ifdef _DEBUG
  98.     static DWORD GetObjectCount() {return m_ObjectCount;};
  99. #endif
  100. protected:
  101.     // 助手函数(与类无关)
  102.     LPSTR FindDIBBits(LPSTR lpbi) const;
  103.     DWORD DIBWidth(LPBITMAPINFOHEADER lpbi) const;
  104.     DWORD DIBHeight(LPBITMAPINFOHEADER lpbi) const;
  105.     WORD PaletteSize(LPBITMAPINFOHEADER lpbi) const;
  106.     WORD DIBNumColors(LPBITMAPINFOHEADER lpbi) const;
  107.     int    GetBitsPerPixel(LPBITMAPINFOHEADER lpbi) const;
  108.     LPVOID CreateMemoryBlockFromHandle(HANDLE handle, DWORD dwCount=0);
  109.     LPVOID CreateMemoryBlockFromAddress(LPVOID pSou, DWORD dwCount=0);
  110.     BOOL IsValidBmpFile(CFile& file);
  111.     LPBITMAPINFO GetBmpFileInfo(CFile& file);
  112.     LPSTR GetBmpFileBits(CFile& file);
  113.     BOOL IsValidDibFormat(WORD nBitsPerPixel);
  114.     BOOL IsFileExist(LPCTSTR lpFileName);
  115.     DWORD CalculateDIBFileSize(LPBITMAPINFOHEADER lpbi) const;
  116.     DWORD CalculateDIBSize(LPBITMAPINFOHEADER lpbi) const;
  117.     DWORD CalculateDIBitsOff(LPBITMAPINFOHEADER lpbi) const;
  118.     DWORD CalculateDIBInfoSize(LPBITMAPINFOHEADER lpbi) const;
  119.     DWORD CalculateDIBitsSize(LPBITMAPINFOHEADER lpbi) const;
  120.     
  121.     BOOL PasteAvailable();
  122.     // 内部服务函数(与类有关)
  123.     BOOL SaveBaseSpecifyFileName(LPCTSTR fn);
  124.     BOOL SaveBaseSpecifyFormat(WORD nBitsPerPixel);
  125.     LPBITMAPINFO GetSpecifyFormatInfo(WORD newBitCount=0);
  126.     BOOL ClearAndSetData(int type, DWORD addinfo, LPCTSTR lpFn, LPBITMAPINFO pInfo, HBITMAP hBmp);
  127. public:
  128.     enum            // 位图的初始来源类型:
  129.     {
  130.         IT_NULL,        // 无位图类型
  131.         IT_DISKFILE,    // 文件位图
  132.         IT_RESOURCE,    // 资源位图
  133.         IT_MEMORY,        // 内存位图
  134.         IT_CLIP,        // 剪贴板位图
  135.         IT_CREATE        // 创建型位图
  136.     };
  137. private:
  138.     // 数据成员
  139.     BOOL m_mark;        // 类的有效标志。(TRUE-本类中有位图,
  140.                         // FALSE-本类中没有位图)
  141.     int  m_type;        // 图像类型,只能使用上面枚举类型值
  142.     DWORD   m_addInfo;    // 附加信息。
  143.     CString    m_cFileName;// 文件路径。
  144.     LPBITMAPINFO  m_pInfo;    // DIB 信息结构
  145. #ifdef _DEBUG
  146.     static DWORD m_ObjectCount;    // 本类构造的实例目标个数,供调试使用
  147. #endif
  148. };
  149. #endif /*__BMPPROC_H__*/


  150. 代码文件 BmpProc.cpp

复制代码
  1. ///////////////////////////////////////////////////////////////////////
  2. /*
  3.   目的:BMP位图处理类。(源代码文件)
  4.   创建:张伟(SXZ)
  5.   版本:2.4
  6.   SXZ software workgroup. No.200001
  7. */
  8. ///////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////
  10. /*
  11.   注释:
  12.   # 类中的位图都是兼容于当前显示器颜色格式的DDB位图
  13.   # 如果读入的位图格式与当前显示器的颜色格式不同,则读入函数会先将其转换
  14.     为兼容于当前显示器颜色格式的位图之后才放入类中
  15.   # 对于所有BOOL型返回的函数,TRUE表示成功,FALSE表示失败
  16. */
  17. ///////////////////////////////////////////////////////////////////////
  18. #include "stdafx.h"
  19. #include
  20. #include
  21. #include
  22. #include
  23. #include
  24. #include
  25. #include
  26. #include
  27. #include "BmpProc.h"
  28. ////////////////////////////// defines ///////////////////////////////////
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. // 用于调试目的计数变量,它表示程序中构造的CBmpProc类实例个数
  35. // 可以用类中static DWORD GetObjectCount()成员函数访问该变量
  36. // 注意:该变量和访问它的函数都只是在调试模式下才会有效,如果
  37. //         转换为发布模式,它们都会失效。所以在使用GetObjectCount()
  38. //         这个成员函数时,应加入#ifdef _DEBUG .... #endif语句块
  39. #ifdef _DEBUG
  40.     DWORD CBmpProc::m_ObjectCount = 0;
  41. #endif
  42. /*************************************************************************
  43. * 构造函数。初始化类为空。
  44. *************************************************************************/
  45. CBmpProc::CBmpProc()
  46. {
  47.     // 初始化核心数据为空
  48.     m_mark = FALSE;            // 有效标志。(TRUE-有有效位图,否则为FALSE)
  49.     m_type = IT_NULL;        // 图像类型。
  50.     m_addInfo = 0;            // 附加信息。
  51.     m_cFileName.Empty();    // 文件路径。
  52.     m_pInfo = NULL;            // DIB信息结构
  53.     m_hObject = NULL;        // 清除核心DDB位图句柄。(基类成员)
  54. #ifdef _DEBUG
  55.     CBmpProc::m_ObjectCount++;
  56. #endif
  57. }
  58. /*************************************************************************
  59. * 调试用函数,获取进程中CBmpProc类目标的个数。
  60. *************************************************************************
  61. #ifdef _DEBUG
  62. DWORD CBmpProc::GetObjectCount()
  63. {
  64.     return m_ObjectCount;
  65. }
  66. #endif
  67. *************************************************************************/
  68. /*************************************************************************
  69. * 析构函数。如果类不为空则清空它。
  70. *************************************************************************/
  71. CBmpProc::~CBmpProc()
  72. {
  73.     Clear();
  74. #ifdef _DEBUG
  75.     CBmpProc::m_ObjectCount--;
  76. #endif
  77. }
  78. /*************************************************************************
  79. *
  80. * operator=()
  81. *
  82. * 参数说明:
  83. *
  84. * const CBmpProc& ds        - 源位图类
  85. *
  86. * 返回值:
  87. *
  88. * CBmpProc&                - 类自身引用
  89. *
  90. * 描述:
  91. *
  92. * 复制取指定的位图类
  93. *
  94. * 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
  95. * 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
  96. * 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
  97. * 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
  98. *
  99. ************************************************************************/
  100. CBmpProc& CBmpProc::operator=(const CBmpProc& ds)
  101. {
  102.     // 如果类中没有图像,直接返回
  103.     if (!ds.IsValid())
  104.         return *this;
  105.     ASSERT(ds.m_pInfo);
  106.     ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  107.     // 复制源图信息块
  108.     LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
  109.         (LPVOID)ds.m_pInfo);
  110.     if (!pInfo)
  111.         return *this;
  112.     // 复制源图
  113.     CBitmap        tempBmp;
  114.     HBITMAP        hBmp;
  115.     HWND hWnd = ::GetDesktopWindow();
  116.     ASSERT(hWnd);
  117.     HDC hDC = ::GetDC(hWnd);
  118.     CDC dc;
  119.     dc.Attach(hDC);
  120.     if (tempBmp.CreateCompatibleBitmap(&dc, ds.Width(), ds.Height()))
  121.     {
  122.         CDC            compDC, compDC2;
  123.         CBitmap        *pOldBmp, *pOldBmp2;
  124.         // 创建与当前显示设备兼容的内存设备描述表
  125.         compDC.CreateCompatibleDC(NULL);
  126.         compDC2.CreateCompatibleDC(NULL);
  127.         pOldBmp    = compDC.SelectObject((CBitmap*)&tempBmp);
  128.         pOldBmp2= compDC2.SelectObject((CBitmap*)&ds);
  129.         // 复制指定尺寸的源位图到目标位图
  130.         compDC.BitBlt(0, 0, ds.Width(), ds.Height(),
  131.                     &compDC2, 0, 0, SRCCOPY);
  132.         compDC2.SelectObject(pOldBmp2);
  133.         compDC.SelectObject(pOldBmp);
  134.         hBmp = (HBITMAP)tempBmp.Detach();
  135.         // 如果分离操作失败,返回FALSE
  136.         ASSERT(hBmp);
  137.         if (!hBmp)
  138.         {
  139.             ::ReleaseDC(hWnd, dc.Detach());
  140.             ::free((void*)pInfo);
  141.             return *this;;
  142.         }
  143.         ::ReleaseDC(hWnd, dc.Detach());
  144.         // 删除原来的图像,并且设置新的位图
  145.         if (!ClearAndSetData(IT_MEMORY,0,(LPCTSTR)"",pInfo,hBmp))
  146.         {
  147.             ::free((void*)pInfo);
  148.             ::DeleteObject(hBmp);
  149.             return *this;
  150.         }
  151.         return *this;
  152.     }
  153.     else
  154.     {
  155.         ::ReleaseDC(hWnd, dc.Detach());
  156.         ::free((void*)pInfo);
  157.         return *this;;
  158.     }
  159. }
  160. /*************************************************************************
  161. *
  162. * operator=()
  163. *
  164. * 参数说明:
  165. *
  166. * const HBITMAP sou        - 源位图句柄
  167. *
  168. * 返回值:
  169. *
  170. * CBmpProc&                - 类自身引用
  171. *
  172. * 描述:
  173. *
  174. * 复制取指定的位图
  175. *
  176. * 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
  177. * 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
  178. * 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
  179. * 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
  180. * 如果入口参数指定的位图句柄无效,则函数失败。
  181. *
  182. ************************************************************************/
  183. CBmpProc& CBmpProc::operator=(const HBITMAP sou)
  184. {
  185.     // 入口检测
  186.     if (!sou)
  187.         return *this;
  188.     CBmpProc tmp;
  189.     if (!tmp.Attach(sou))
  190.         return *this;
  191.     ASSERT(sou == (HBITMAP)tmp);
  192.     // 调用类赋值操作符函数
  193.     *this = tmp;
  194.     // 分离源位图,防止析构函数将其删除
  195.     tmp.Detach();
  196.     return *this;
  197. }
  198. /*************************************************************************
  199. *
  200. * operator==()
  201. *
  202. * 参数说明:
  203. *
  204. * const CBmpProc& ds        - 源位图类
  205. *
  206. * 返回值:
  207. *
  208. * BOOL                        - 如果相同返回TRUE,不同返回FALSE
  209. *
  210. * 描述:
  211. *
  212. * 判断源位图类与本身类是否相同
  213. *
  214. * 该函数通过比较两个类的位图来判定它们是否具有相同的图像。
  215. *
  216. * 注:# 如果两个类都是空的(即都没有图像),则该函数将视它们是不相同的
  217. *
  218. ************************************************************************/
  219. BOOL CBmpProc::operator==(const CBmpProc& ds)
  220. {
  221.     // 如果两个类中有一个或都是空的(即都没有图像),则该函数将视它们
  222.     // 是不相同的
  223.     if ((ds.IsValid()==FALSE)||(IsValid()==FALSE))
  224.         return FALSE;
  225.     // 如果是与自身比较,则直接返回TRUE
  226.     if (this == &ds)
  227.         return TRUE;
  228.     ASSERT(m_pInfo);
  229.     ASSERT(ds.m_pInfo);
  230.     ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  231.     ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  232.     // 信息块长度比较
  233.     if (::_msize(m_pInfo) != ::_msize(ds.m_pInfo))
  234.         return FALSE;
  235.     // 信息块内容比较
  236.     if (::memcmp((const void*)m_pInfo, \
  237.         (const void*)ds.m_pInfo,::_msize(m_pInfo)))
  238.         return FALSE;
  239.     // 创建存放DIB位数据的缓冲区
  240.     LPSTR pBits1 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
  241.         CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
  242.     if (!pBits1)
  243.         return FALSE;
  244.     LPSTR pBits2 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
  245.         CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
  246.     if (!pBits2)
  247.     {
  248.         ::free((void*)pBits1);
  249.         return FALSE;
  250.     }
  251.     // 复制位图信息块,因为GetDIBits()函数有可能会改变颜色表数据
  252.     LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
  253.         (LPVOID)m_pInfo);
  254.     if (!pInfo)
  255.     {
  256.         ::free((void*)pBits1);
  257.         ::free((void*)pBits2);
  258.         return FALSE;
  259.     }
  260.     ASSERT(pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  261.     HWND hWnd = ::GetDesktopWindow();
  262.     ASSERT(hWnd);
  263.     HDC hDC;
  264.     // 获取位图的DIB位数据
  265.     hDC = ::GetDC(hWnd);
  266.     ASSERT(m_hObject);
  267.     ASSERT(ds.m_hObject);
  268.     if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,pInfo->bmiHeader.biHeight, \
  269.             (LPVOID)pBits1,pInfo,DIB_RGB_COLORS))
  270.     {
  271.         ::free((void*)pBits1);
  272.         ::free((void*)pBits2);
  273.         ::free((void*)pInfo);
  274.         ::ReleaseDC(hWnd, hDC);
  275.         return FALSE;
  276.     }
  277.     if (!::GetDIBits(hDC,(HBITMAP)ds.m_hObject,0,pInfo->bmiHeader.biHeight, \
  278.             (LPVOID)pBits2,pInfo,DIB_RGB_COLORS))
  279.     {
  280.         ::free((void*)pBits1);
  281.         ::free((void*)pBits2);
  282.         ::free((void*)pInfo);
  283.         ::ReleaseDC(hWnd, hDC);
  284.         return FALSE;
  285.     }
  286.     ::ReleaseDC(hWnd, hDC);
  287.     ::free((void*)pInfo);
  288.     // 位内容比较
  289.     LONG leng = (LONG)CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo)/4;
  290.     LPDWORD lp1 = (LPDWORD)pBits1;    // DIB位数据是DWORD对齐的
  291.     LPDWORD lp2 = (LPDWORD)pBits2;
  292.     // 因为不清楚memcmp()函数是否可以比较大于64K的数据,所以才采用这种
  293.     // 老笨的方法。
  294.     while(leng--)
  295.     {
  296.         if (*lp1 != *lp2) break;
  297.         lp1++; lp2++;
  298.     }
  299.     // 比较完之后,位数据已无用,释放
  300.     ::free((void*)pBits1);
  301.     ::free((void*)pBits2);
  302.     
  303.     if (leng != -1L)
  304.         return FALSE;    // 位数据不同返回FALSE
  305.     return TRUE;
  306. }
  1. /*************************************************************************
  2. *
  3. * operator!=()
  4. *
  5. * 参数说明:
  6. *
  7. * const CBmpProc& ds        - 源位图类
  8. *
  9. * 返回值:
  10. *
  11. * BOOL                        - 如果不同返回TRUE,相同返回FALSE
  12. *
  13. * 描述:
  14. *
  15. * 判断源位图类是否与本身类不同
  16. *
  17. * 该函数通过比较两个类的位图来判定它们是否具有相同的图像。
  18. *
  19. * 注:# 如果两个类都是空的(即都没有图像),则该函数将视它们是不相同的
  20. *
  21. ************************************************************************/
  22. BOOL CBmpProc::operator!=(const CBmpProc& ds)
  23. {
  24.     return ((*this) == ds) ? FALSE:TRUE;
  25. }
  26. /*************************************************************************
  27. *
  28. * Draw()
  29. *
  30. * 参数说明:
  31. *
  32. * CDC& dc                    - 显示位图的设备描述表
  33. * const CRect* rcDst        - 目标矩形
  34. * const CRect* rcSrc        - 源矩形
  35. *
  36. * 返回值:
  37. *
  38. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  39. *
  40. * 描述:
  41. *
  42. * 将类中指定区域的图像绘入目标设备描述表的指定区域,如果源区域(即矩形)
  43. * 和目标区域不同,将产生拉伸或压缩动作
  44. *
  45. * 如果源矩形和目标矩形是NULL,则函数将视这两个矩形都等于类中图像的尺寸
  46. *
  47. * 如果类中没有图像,它什么也不作,直接返回
  48. * 如果待绘制的图像不在当前剪贴区域内,则直接返回
  49. *
  50. ************************************************************************/
  51. BOOL CBmpProc::Draw(CDC& dc, const CRect* rcDst, const CRect* rcSrc)
  52. {
  53.     // 如果类中没有图像,直接返回
  54.     if (!IsValid())
  55.         return TRUE;
  56.     ASSERT(m_hObject);
  57.     // 缺省矩形等于图像尺寸
  58.     CRect DCRect(Rect());            // 目标位置数据
  59.     CRect DibRect(Rect());            // 源位置数据
  60.     if (rcDst)
  61.         DCRect = *rcDst;
  62.     if (rcSrc)
  63.         DibRect = *rcSrc;
  64.     // 如果待绘制的图像不在当前剪贴区域内,则直接返回
  65.     if (!dc.RectVisible(&DCRect))
  66.         return TRUE;
  67.     CDC            compDC;
  68.     CBitmap        *pOldBmp;
  69.     compDC.CreateCompatibleDC(NULL);
  70.     pOldBmp    = compDC.SelectObject((CBitmap*)this);
  71.     /* 设置目标DC的拉伸模式为STRETCH_DELETESCANS,也就是不显示拉伸掉的图像 */
  72.     int srlold = dc.SetStretchBltMode(STRETCH_DELETESCANS);
  73.     // 显示位图
  74.     dc.StretchBlt(DCRect.left, DCRect.top, DCRect.Width(), DCRect.Height(),
  75.                     &compDC, DibRect.left, DibRect.top,
  76.                     DibRect.Width(), DibRect.Height(), SRCCOPY);
  77.     
  78.     // 恢复设备描述表原来的设置
  79.     dc.SetStretchBltMode(srlold);
  80.     compDC.SelectObject(pOldBmp);
  81.     return TRUE;
  82. }
  83. /*************************************************************************
  84. *
  85. * DrawTile()
  86. *
  87. * 参数说明:
  88. *
  89. * CDC& dc                    - 显示位图的设备描述表
  90. * CRect* crArea            - 铺设范围(矩形坐标)
  91. *
  92. * 返回值:
  93. *
  94. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  95. *
  96. * 描述:
  97. *
  98. * 将类中的图像以平铺方式排满指定区域
  99. *
  100. * 如果入口参数crArea是NULL,则函数返回FALSE,如果矩形坐标不符合规范(比如
  101. * 左边的坐标大于右边的坐标)则函数将自动将其规范化。如果矩形坐标的宽度
  102. * 或高度是0,则函数将返回FALSE
  103. *
  104. * 如果类中没有图像,它什么也不作,直接返回
  105. *
  106. ************************************************************************/
  107. BOOL CBmpProc::DrawTile(CDC& dc, CRect* crArea)
  108. {
  109.     if (!crArea)
  110.         return FALSE;
  111.     // 如果类中没有图像,直接返回
  112.     if (!IsValid())
  113.         return TRUE;
  114.     CRect rect = *crArea;
  115.     CRect tprc;
  116.     // 矩形坐标规范化
  117.     rect.NormalizeRect();
  118.     if ((rect.Width()==0)||(rect.Height()==0))
  119.         return FALSE;
  120.     ASSERT(m_pInfo);
  121.     ASSERT(m_hObject);
  122.     // 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
  123.     int savedc = dc.SaveDC();
  124.     CRgn newrgn;
  125.     newrgn.CreateRectRgnIndirect(&rect);
  126.     // 只显示指定矩形中可见的部分(用AND操作)
  127.     dc.SelectClipRgn(&newrgn, RGN_AND);
  128.     for (int y=rect.top;y    {
  129.         for (int x=rect.left;x        {
  130.             // 以瓦片方式重复显示图像
  131.             tprc.SetRect(x,y,x+Width(),y+Height());
  132.             Draw(dc, &tprc);
  133.         }
  134.     }
  135.     dc.RestoreDC(savedc);
  136.     // 恢复设备描述表的内容之后,将区域的句柄显示的删除
  137.     // (微软在文档中特意注明要用CGdiObject::DeleteObject()
  138.     //   函数显示的删除区域句柄,不知是什么原因)
  139.     newrgn.CGdiObject::DeleteObject();
  140.     return TRUE;
  141. }
  142. /*************************************************************************
  143. *
  144. * DrawCenter()
  145. *
  146. * 参数说明:
  147. *
  148. * CDC& dc                    - 显示位图的设备描述表
  149. * CRect* crArea            - 显示范围(矩形坐标)
  150. *
  151. * 返回值:
  152. *
  153. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  154. *
  155. * 描述:
  156. *
  157. * 将类中图像绘入目标设备描述表的指定区域(矩形)的中央,即图像中点与矩
  158. * 形中点重合
  159. *
  160. * 如果矩形的尺寸小于图像尺寸,则图像的四周部分会不可见
  161. * 如果入口参数crArea是NULL,函数将返回FALSE
  162. * 如果类中没有图像,它什么也不作,直接返回
  163. * 如果矩形坐标不符合规范(比如左边的坐标大于右边的坐标)则函数将自动将
  164. * 其规范化。如果矩形坐标的宽度或高度是0,则函数将返回FALSE
  165. *
  166. ************************************************************************/
  167. BOOL CBmpProc::DrawCenter(CDC& dc, CRect* crArea)
  168. {
  169.     if (!crArea)
  170.         return FALSE;
  171.     // 如果类中没有图像,直接返回
  172.     if (!IsValid())
  173.         return TRUE;
  174.     CRect rect = *crArea;
  175.     // 矩形坐标规范化
  176.     rect.NormalizeRect();
  177.     if ((rect.Width()==0)||(rect.Height()==0))
  178.         return FALSE;
  179.     ASSERT(m_pInfo);
  180.     ASSERT(m_hObject);
  181.     // 取指定矩形的中点坐标
  182.     CPoint cpce = rect.CenterPoint();
  183.     CRect  tprc(CPoint(cpce.x-Width()/2,cpce.y-Height()/2), Size());
  184.     // 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
  185.     int savedc = dc.SaveDC();
  186.     CRgn newrgn;
  187.     newrgn.CreateRectRgnIndirect(&rect);
  188.     // 只显示指定矩形中可见的部分(用AND操作)
  189.     dc.SelectClipRgn(&newrgn, RGN_AND);
  190.     Draw(dc, &tprc);
  191.     dc.RestoreDC(savedc);
  192.     newrgn.CGdiObject::DeleteObject();
  193.     return TRUE;
  194. }
  195. /*************************************************************************
  196. *
  197. * DrawTranCenter()
  198. *
  199. * 参数说明:
  200. *
  201. * CDC& dc                    - 显示位图的设备描述表
  202. * CRect* crArea            - 显示范围(矩形坐标)
  203. * COLORREF crColour        - 要滤掉或保留的颜色(缺省值是白色)
  204. * int mode                    - 如果是0则将不显示指定的颜色,如果是1则保留指定
  205. *                              的颜色(缺省值为0)
  206. *
  207. * 返回值:
  208. *
  209. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  210. *
  211. * 描述:
  212. *
  213. * 将类中图像透明的绘入目标设备描述表的指定区域(矩形)的中央,即图像中点
  214. * 与矩形中点重合
  215. *
  216. * 如果矩形的尺寸小于图像尺寸,则超出矩形的图像部分会不可见
  217. * 如果入口参数crArea是NULL,函数将返回FALSE
  218. * 如果类中没有图像,它什么也不作,直接返回
  219. * 如果矩形坐标不符合规范(比如左边的坐标大于右边的坐标)则函数将自动将
  220. * 其规范化。如果矩形坐标的宽度或高度是0,则函数将返回FALSE
  221. *
  222. ************************************************************************/
  223. BOOL CBmpProc::DrawTranCenter(CDC& dc,
  224.                               CRect* crArea,
  225.                               COLORREF crColour,
  226.                               int mode)
  227. {
  228.     if (!crArea)
  229.         return FALSE;
  230.     // 如果类中没有图像,直接返回
  231.     if (!IsValid())
  232.         return TRUE;
  233.     CRect rect = *crArea;
  234.     // 矩形坐标规范化
  235.     rect.NormalizeRect();
  236.     if ((rect.Width()==0)||(rect.Height()==0))
  237.         return FALSE;
  238.     ASSERT(m_pInfo);
  239.     ASSERT(m_hObject);
  240.     // 取指定矩形的中点坐标
  241.     CPoint cpce = rect.CenterPoint();
  242.     CRect  tprc(CPoint(cpce.x-Width()/2,cpce.y-Height()/2), Size());
  243.     // 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
  244.     int savedc = dc.SaveDC();
  245.     CRgn newrgn;
  246.     newrgn.CreateRectRgnIndirect(&rect);
  247.     // 只显示指定矩形中可见的部分(用AND操作)
  248.     dc.SelectClipRgn(&newrgn, RGN_AND);
  249.     DrawTransparentInRect(dc, crColour, &tprc, NULL, mode);    // 显示透明图像
  250.     dc.RestoreDC(savedc);
  251.     newrgn.CGdiObject::DeleteObject();
  252.     return TRUE;
  253. }
  254. /*************************************************************************
  255. *
  256. * DrawTranTile()
  257. *
  258. * 参数说明:
  259. *
  260. * CDC& dc                    - 显示位图的设备描述表
  261. * CRect* crArea            - 显示范围(矩形坐标)
  262. * COLORREF crColour        - 要滤掉或保留的颜色(缺省值是白色)
  263. * int mode                    - 如果是0则将不显示指定的颜色,如果是1则保留指定
  264. *                              的颜色(缺省值为0)
  265. *
  266. * 返回值:
  267. *
  268. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  269. *
  270. * 描述:
  271. *
  272. * 将类中的图像以平铺并且是透明的方式排满指定区域
  273. *
  274. * 如果入口参数crArea是NULL,则函数返回FALSE,如果矩形坐标不符合规范(比如
  275. * 左边的坐标大于右边的坐标)则函数将自动将其规范化。如果矩形坐标的宽度
  276. * 或高度是0,则函数将返回FALSE
  277. *
  278. * 如果类中没有图像,它什么也不作,直接返回
  279. *
  280. ************************************************************************/
  281. BOOL CBmpProc::DrawTranTile(CDC& dc,
  282.                             CRect* crArea,
  283.                             COLORREF crColour,
  284.                             int mode)
  285. {
  286.     if (!crArea)
  287.         return FALSE;
  288.     // 如果类中没有图像,直接返回
  289.     if (!IsValid())
  290.         return TRUE;
  291.     CRect rect = *crArea;
  292.     CRect tprc;
  293.     // 矩形坐标规范化
  294.     rect.NormalizeRect();
  295.     if ((rect.Width()==0)||(rect.Height()==0))
  296.         return FALSE;
  297.     ASSERT(m_pInfo);
  298.     ASSERT(m_hObject);
  299.     // 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
  300.     int savedc = dc.SaveDC();
  301.     CRgn newrgn;
  302.     newrgn.CreateRectRgnIndirect(&rect);
  303.     // 只显示指定矩形中可见的部分(用AND操作)
  304.     dc.SelectClipRgn(&newrgn, RGN_AND);
  305.     for (int y=rect.top;y    {
  306.         for (int x=rect.left;x        {
  307.             // 以瓦片方式重复显示图像
  308.             tprc.SetRect(x,y,x+Width(),y+Height());
  309.             // 显示透明图像
  310.             DrawTransparentInRect(dc, crColour, &tprc, NULL, mode);
  311.         }
  312.     }
  313.     dc.RestoreDC(savedc);
  314.     newrgn.CGdiObject::DeleteObject();
  315.     return TRUE;
  316. }
  317. /*************************************************************************
  318. *
  319. * Clear()
  320. *
  321. * 参数说明:无
  322. *
  323. *
  324. * 返回值:无
  325. *
  326. *
  327. * 描述:
  328. *
  329. * 清除类中的图像
  330. *
  331. * 这个函数将删除类中的位图句柄,并清除类中的描述变量
  332. *
  333. * 如果类中没有图像,它什么也不作,直接返回
  334. *
  335. ************************************************************************/
  336. void CBmpProc::Clear()
  337. {
  338.     // 如果本类中没有有效的BMP,则直接返回
  339.     if (m_mark == FALSE)
  340.     {
  341.         ASSERT(m_type == IT_NULL);
  342.         ASSERT(m_pInfo == NULL);
  343.         ASSERT(m_hObject == NULL);
  344.         return;
  345.     }
  346.     switch(m_type)
  347.     {
  348.     case    IT_NULL:
  349.         ASSERT(FALSE);    // 此时m_type不应该是IT_NULL
  350.         break;
  351.     case    IT_DISKFILE:
  352.         ASSERT(!m_cFileName.IsEmpty());    // 文件来源的位图应该有文件名
  353.     case    IT_RESOURCE:
  354.     case    IT_MEMORY:
  355.     case    IT_CLIP:
  356.     case    IT_CREATE:
  357.         m_cFileName.Empty();
  358.         ASSERT(m_pInfo);
  359.         ::free((void*)m_pInfo);
  360.         m_pInfo = NULL;
  361.         // 先分离出原来的BMP句柄,然后删除
  362.         ASSERT((HBITMAP)m_hObject);
  363.         ::DeleteObject(CGdiObject::Detach());
  364.         m_hObject = NULL;
  365.         m_addInfo = 0;
  366.         m_type = IT_NULL;
  367.         m_mark = FALSE;
  368.         break;
  369.     default:
  370.         ASSERT(FALSE);
  371.         break;
  372.     }
  373. }
  374. /*************************************************************************
  375. *
  376. * Attach()
  377. *
  378. * 参数说明:
  379. *
  380. * HBITMAP hBmp                - 待粘贴的位图句柄
  381. *
  382. * 返回值:
  383. *
  384. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  385. *
  386. * 描述:
  387. *
  388. * 将指定的位图贴入本身类中。
  389. *
  390. * 注:
  391. *
  392. * # 如果hBmp是一个无效的句柄或是NULL,函数返回FALSE
  393. * # 如果本身类中原来存在图像,则调用函数成功之后,原来的图像将被删除
  394. * # hBmp必须是一个兼容于当前显示器颜色格式的DDB位图句柄
  395. * # 如果函数执行成功后,调用它的程序不应再使用hBmp句柄,因为它已被贴入类中
  396. * # 如果函数失败,调用它的程序仍可以正常使用hBmp句柄
  397. *
  398. ************************************************************************/
  399. BOOL CBmpProc::Attach(HBITMAP hBmp)
  400. {
  401.     ASSERT(hBmp);
  402.     // 如果hBmp是NULL,则立即返回
  403.     if (!hBmp)
  404.         return FALSE;
  405.     HWND hWnd = ::GetDesktopWindow();
  406.     ASSERT(hWnd);
  407.     HDC hDC;
  408.     BITMAP    bmp;
  409.     // 获取给定位图的宽度、高度及颜色格式信息
  410.     if (::GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bmp) != sizeof(BITMAP))
  411.         return FALSE;
  412.     // 创建临时位图信息块(不带颜色表)
  413.     LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)CreateMemoryBlockFromAddress(
  414.         (LPVOID)NULL, sizeof(BITMAPINFOHEADER));
  415.     if (!lpbi)
  416.         return FALSE;
  417.     // 设置DIB信息块内容
  418.     lpbi->biSize = sizeof(BITMAPINFOHEADER);
  419.     lpbi->biWidth = bmp.bmWidth;
  420.     lpbi->biHeight = bmp.bmHeight;
  421.     lpbi->biPlanes = 1;
  422.     // 在16色系统中,平面数是4,而位数是1,但这在DIB中是不允许的
  423.     lpbi->biBitCount = max(bmp.bmPlanes, bmp.bmBitsPixel);
  424.     if ((lpbi->biBitCount==16)||(lpbi->biBitCount==32))
  425.         lpbi->biCompression = BI_BITFIELDS;
  426.     else
  427.         lpbi->biCompression = BI_RGB;
  428.     // 计算设备分辩率
  429.     hDC = ::GetDC(hWnd);
  430.     lpbi->biXPelsPerMeter = \
  431.         (GetDeviceCaps(hDC,HORZRES)*1000)/GetDeviceCaps(hDC,HORZSIZE);
  432.     lpbi->biYPelsPerMeter = \
  433.         (GetDeviceCaps(hDC,VERTRES)*1000)/GetDeviceCaps(hDC,VERTSIZE);
  434.     ::ReleaseDC(hWnd, hDC);
  435.     lpbi->biClrUsed = 0;
  436.     lpbi->biClrImportant = 0;
  437.     lpbi->biSizeImage = CalculateDIBitsSize(lpbi);
  438.     // 计算颜色表的尺寸
  439.     WORD wPalSize = PaletteSize(lpbi);
  440.     // 创建带颜色表的信息块,并复制lpbi信息块中的内容
  441.     LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
  442.         (LPVOID)lpbi, sizeof(BITMAPINFOHEADER)+wPalSize);
  443.     if (!pInfo)
  444.     {
  445.         ::free((void*)lpbi);
  446.         return FALSE;
  447.     }
  448.     ASSERT(pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  449.     // 此时该结构已经无用,释放
  450.     ::free((void*)lpbi);
  451.     // 创建存放DIB位数据的缓冲区
  452.     LPSTR pBits = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
  453.         pInfo->bmiHeader.biSizeImage);
  454.     if (!pBits)
  455.     {
  456.         ::free((void*)pInfo);
  457.         return FALSE;
  458.     }
  459.     // 下面的代码并不是要获取位图的DIB位数据,而是要取得位图的颜色表
  460.     // 颜色表数据在函数(GetDIBits())调用成功后被填写在pInfo结构中
  461.     hDC = ::GetDC(hWnd);
  462.     if (!::GetDIBits(hDC,hBmp,0,pInfo->bmiHeader.biHeight, \
  463.             (LPVOID)pBits,pInfo,DIB_RGB_COLORS))
  464.     {
  465.         ::free((void*)pBits);
  466.         ::free((void*)pInfo);
  467.         ::ReleaseDC(hWnd, hDC);
  468.         return FALSE;
  469.     }
  470.     ::ReleaseDC(hWnd, hDC);
  471.     // 此时并不需要DIB位数据,释放
  472.     ::free((void*)pBits);
  473.     // 删除原来的图像,并且设置新的位图
  474.     if (!ClearAndSetData(IT_MEMORY,0,(LPCTSTR)"",pInfo,hBmp))
  475.     {
  476.         ::free((void*)pInfo);
  477.         // hBmp指定的位图并不删除
  478.         return FALSE;
  479.     }
  480.     return TRUE;
  481. }
  482. /*************************************************************************
  483. *
  484. * Detach()
  485. *
  486. * 参数说明:无
  487. *
  488. *
  489. * 返回值:
  490. *
  491. * HBITMAP                    - 如果成功,返回分离出的位图句柄,否则返回NULL
  492. *
  493. * 描述:
  494. *
  495. * 将本身类中的位图分离出来。
  496. *
  497. * 注:
  498. *
  499. * # 如果本身类中原来存在位图,函数成功调用之后,本身类将被清空
  500. * # 如果本身类中原来没有位图,函数返回NULL
  501. *
  502. ************************************************************************/
  503. HBITMAP CBmpProc::Detach()
  504. {
  505.     if (!IsValid())
  506.         return NULL;
  507.     ASSERT(m_pInfo);
  508.     ASSERT(m_hObject);
  509.     HBITMAP hBmp = (HBITMAP)CGdiObject::Detach();
  510.     ASSERT(hBmp);
  511.     if (!hBmp)
  512.         return NULL;
  513.     m_hObject = NULL;
  514.     switch(m_type)
  515.     {
  516.     case    IT_NULL:
  517.         ASSERT(FALSE);    // 此时m_type不应该是IT_NULL
  518.         break;
  519.     case    IT_DISKFILE:
  520.         ASSERT(!m_cFileName.IsEmpty());    // 文件来源的位图应该有文件名
  521.     case    IT_RESOURCE:
  522.     case    IT_MEMORY:
  523.     case    IT_CLIP:
  524.     case    IT_CREATE:
  525.         m_cFileName.Empty();
  526.         ASSERT(m_pInfo);
  527.         ::free((void*)m_pInfo);
  528.         m_pInfo = NULL;
  529.         m_addInfo = 0;
  530.         m_type = IT_NULL;
  531.         m_mark = FALSE;
  532.         break;
  533.     default:
  534.         ASSERT(FALSE);
  535.         break;
  536.     }
  537.     return hBmp;
  538. }
  539. /*************************************************************************
  540. *
  541. * Save()
  542. *
  543. * 参数说明:
  544. *
  545. * LPCTSTR lpszNewFileName    - 指定的新文件名(可以是NULL)
  546. * WORD nBitsPerPixel        - 指定的新颜色格式(即每像素多少位,可以是0)
  547. *
  548. * 返回值:
  549. *
  550. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  551. *
  552. * 描述:
  553. *
  554. * 将本身类中的位图以新的格式或新的名称保存到文件中
  555. *
  556. * 注:
  557. *
  558. * # 如果没有指定新的文件名(入口参数lpszNewFileName被指定为NULL),函数
  559. *   就使用类中原来的文件名,如果类中原来没有文件名则函数失败,返回FALSE
  560. * # 如果没有指定新的位数(入口参数nBitsPerPixel被指定为0),函数就使用类
  561. *   中原来的位数值。如果新指定的位数值非法则函数失败,返回FALSE。合法的
  562. *   位数值是1,4,8,16,24,32 其中之一
  563. * # 如果本身类中原来没有位图(空类),函数返回FALSE
  564. * # 如果文件没有打开或是写文件时出错,函数返回FALSE
  565. * # 函数执行成功之后,本身类中的文件名或位数将改为新值
  566. * # 无论函数成功与否,本身类中的位图不会改变
  567. *
  568. ************************************************************************/
  569. BOOL CBmpProc::Save(LPCTSTR lpszNewFileName, WORD nBitsPerPixel)
  570. {
  571.     // 如果本身类中原来没有位图,函数返回FALSE
  572.     if (!IsValid())
  573.         return FALSE;
  574.     ASSERT(m_pInfo);
  575.     ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  576.     LPBITMAPINFO pInfo;
  577.     BOOL bRet;
  578.     CString cOldFN;
  579.     // 以原来的格式保存到原来的文件中
  580.     if ((lpszNewFileName==NULL)&&(nBitsPerPixel==0))
  581.     {
  582.         // 应该有文件名
  583.         if (m_cFileName.IsEmpty())
  584.             return FALSE;
  585.         return SaveBaseSpecifyFileName((LPCTSTR)m_cFileName);
  586.     }
  587.     // 以原来的格式保存到新的文件中
  588.     if ((lpszNewFileName!=NULL)&&(nBitsPerPixel==0))
  589.     {
  590.         bRet = SaveBaseSpecifyFileName((LPCTSTR)lpszNewFileName);
  591.         if (bRet)
  592.             m_cFileName = lpszNewFileName;
  593.         return bRet;
  594.     }
  595.     // 以新的格式保存到原来的文件中
  596.     if ((lpszNewFileName==NULL)&&(nBitsPerPixel!=0))
  597.     {
  598.         // 检测位数合法性
  599.         if (!IsValidDibFormat(nBitsPerPixel))
  600.             return FALSE;
  601.         // 应该有文件名
  602.         if (m_cFileName.IsEmpty())
  603.             return FALSE;
  604.         bRet = SaveBaseSpecifyFormat(nBitsPerPixel);
  605.         if (bRet)
  606.         {
  607.             pInfo = GetSpecifyFormatInfo(nBitsPerPixel);
  608.             if (!pInfo)
  609.                 return FALSE;
  610.             ::free((void*)m_pInfo);
  611.             m_pInfo = pInfo;
  612.         }
  613.         return bRet;
  614.     }
  615.     // 以新的格式保存到新的文件中
  616.     if ((lpszNewFileName!=NULL)&&(nBitsPerPixel!=0))
  617.     {
  618.         // 检测位数合法性
  619.         if (!IsValidDibFormat(nBitsPerPixel))
  620.             return FALSE;
  621.         cOldFN = m_cFileName;
  622.         m_cFileName = lpszNewFileName;
  623.         bRet = SaveBaseSpecifyFormat(nBitsPerPixel);
  624.         if (bRet)
  625.         {    // 获取指定格式的信息块
  626.             pInfo = GetSpecifyFormatInfo(nBitsPerPixel);
  627.             if (!pInfo)
  628.             {
  629.                 m_cFileName = cOldFN;
  630.                 return FALSE;
  631.             }
  632.             ::free((void*)m_pInfo);
  633.             m_pInfo = pInfo;
  634.         }
  635.         else
  636.             m_cFileName = cOldFN;
  637.         return bRet;
  638.     }
  639.     return FALSE;
  640. }
  641. /*************************************************************************
  642. *
  643. * SaveToClipboard()
  644. *
  645. * 参数说明:无
  646. *
  647. *
  648. * 返回值:
  649. *
  650. * BOOL                        - 如果成功返回TRUE,否则返回FALSE
  651. *
  652. * 描述:
  653. *
  654. * 保存本身类中的位图到剪贴板
  655. *
  656. * 注:
  657. *
  658. * # 如果本身类中原来没有位图,函数返回FALSE
  659. * # 如果在打开或写入剪贴板时出错,函数返回FALSE
  660. * # 无论函数成功与否,本身类中的内容都不会改变
  661. *
  662. ************************************************************************/
  663. BOOL CBmpProc::SaveToClipboard()
  664. {
  665.     // 如果本身类中原来没有位图,函数返回FALSE
  666.     if (!IsValid())
  667.         return FALSE;
  668.     ASSERT(m_pInfo);
  669.     ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  670.     // 打开剪贴板
  671.     if (::OpenClipboard(NULL))
  672.     {
  673.         // 清空剪贴板
  674.         if (::EmptyClipboard())
  675.         {
  676.             DWORD DibSize = CalculateDIBSize((LPBITMAPINFOHEADER)m_pInfo);
  677.             DWORD infosize =CalculateDIBInfoSize((LPBITMAPINFOHEADER)m_pInfo);
  678.             // 分配DIB内部格式内存块
  679.             HANDLE hDib = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, DibSize);
  680.             if (hDib)
  681.             {
  682.                 LPSTR lpDib = (LPSTR)::GlobalLock(hDib);
  683.                 if (lpDib)
  684.                 {
  685.                     ::memcpy((void*)lpDib, (const void*)m_pInfo, infosize);
  686.                     // 获取DIB位数据
  687.                     HWND hWnd = ::GetDesktopWindow();
  688.                     ASSERT(hWnd);
  689.                     HDC hDC = ::GetDC(hWnd);
  690.                     if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,m_pInfo->bmiHeader.biHeight,\
  691.                             (LPVOID)((DWORD)lpDib+infosize),(LPBITMAPINFO)lpDib,DIB_RGB_COLORS))
  692.                     {
  693.                         ::GlobalUnlock(hDib);
  694.                         ::GlobalFree(hDib);
  695.                         ::CloseClipboard();
  696.                         ::ReleaseDC(hWnd, hDC);
  697.                         return FALSE;
  698.                     }
  699.                     ::ReleaseDC(hWnd, hDC);
  700.                     ::GlobalUnlock(hDib);
  701.                     // 将DIB数据贴入剪贴板
  702.                     if (::SetClipboardData(CF_DIB, hDib))
  703.                     {
  704.                         // 如果成功,DIB句柄不应释放
  705.                         ::CloseClipboard();
  706.                         return TRUE;        // 成功
  707.                     }
  708.                     else
  709.                     {
  710.                         ::GlobalFree(hDib);
  711.                         ::CloseClipboard();
  712.                         return FALSE;        // 失败
  713.                     }
  714.                 }
  715.                 ::GlobalFree(hDib);
  716.             }
  717.         }
  718.         ::CloseClipboard();
  719.     }
  720.     return FALSE;    // 失败
  721. }
阅读(1682) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:架构设计学习心得(转)

给主人留下些什么吧!~~