DIBPrcs.cpp
上传用户:piaozanzhu
上传日期:2008-02-14
资源大小:212k
文件大小:17k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. /*************************************************************************
  2.  * 文件DIBPrcs.cpp用来存放有关DIB的操作函数
  3.  * 文件头存放在GlobalApi.h中
  4.  *************************************************************************
  5.  */
  6. #include "GlobalApi.h"
  7. #include "stdafx.h"
  8. #include "cdib.h"
  9. /*************************************************************************
  10.  *
  11.  * 函数名称:
  12.  *   GetSystemPalette()
  13.  *
  14.  * 输入参数:
  15.  *   无
  16.  *
  17.  * 返回值:
  18.  *   HPALETTE - 系统调色板句柄
  19.  *
  20.  * 说明:
  21.  *   该函数获得当前正在使用的系统调色板的句柄
  22.  *
  23.  *************************************************************************
  24.  */
  25. HPALETTE GetSystemPalette() 
  26. // 设备上下文
  27. HDC hDC;                
  28. // 声明调色板句柄、指针等临时变量
  29. static HPALETTE hPal = NULL;   
  30. HANDLE hLogPal;         
  31. LPLOGPALETTE lpLogPal;  
  32. // 当前系统调色板的颜色数
  33. int nColors;            
  34.  
  35.      // 获得当前系统设备上下文
  36. hDC = GetDC(NULL); 
  37. if (!hDC) 
  38. return NULL; 
  39.  
  40. // 获得当前系统调色板的颜色数目
  41. nColors = ( 1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
  42.     
  43. // 给调色板分配内存
  44. hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * 
  45. sizeof(PALETTEENTRY)); 
  46. if (!hLogPal) 
  47. return NULL; 
  48.  
  49. // 得到调色板内存指针
  50. lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
  51.  
  52. // 设置调色板信息
  53. lpLogPal->palVersion = 0x300; 
  54. lpLogPal->palNumEntries = nColors; 
  55.  
  56. // 将系统的调色板拷贝到当前的逻辑调色板中
  57. GetSystemPaletteEntries(hDC, 0, nColors, 
  58.             (LPPALETTEENTRY)(lpLogPal->palPalEntry)); 
  59.  
  60. // 创建Windows调色板
  61. hPal = CreatePalette(lpLogPal); 
  62.  
  63. // 释放已分配内存并删除临时对象
  64. GlobalUnlock(hLogPal); 
  65. GlobalFree(hLogPal); 
  66. ReleaseDC(NULL, hDC); 
  67.  
  68. // 返回
  69. return hPal; 
  70.  
  71. /*************************************************************************
  72.  *
  73.  * 函数名称:
  74.  *   CopyPalette
  75.  *
  76.  * 输入参数:
  77.  *   HPALETTE hPalSrc - 需要拷贝的源调色板句柄
  78.  *
  79.  * 返回值:
  80.  *   HPALETTE - 如果操作成功,则返回拷贝的调色板句柄
  81.  *
  82.  * 说明:
  83.  *   该函数将创建一个新的调色板,并从指定的调色板拷贝调色板内容
  84.  *
  85.  *************************************************************************
  86.  */
  87. HPALETTE CopyPalette(HPALETTE hPalSrc)
  88. {
  89. // 调色板指针,临时变量
  90. PLOGPALETTE     plogPal;
  91. // 声明一个调色板句柄和一个临时句柄
  92. HPALETTE        hPalette;
  93. HANDLE hTemp;
  94. // 调色板表项数
  95. int             iNumEntries=0;
  96.     
  97. // 获取调色板中的表项数
  98. iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL);
  99. if (iNumEntries == 0) 
  100. return (HPALETTE) NULL;
  101. // 分配调色板内存,得到句柄
  102. hTemp = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries);
  103. if (! hTemp)
  104. return (HPALETTE) NULL;
  105. // 得到调色板的指针
  106. plogPal = (PLOGPALETTE)GlobalLock(hTemp);
  107. if (! plogPal) 
  108. return (HPALETTE) NULL;
  109. // 设置调色板的信息
  110. plogPal->palVersion = 0x300;
  111. plogPal->palNumEntries = (WORD) iNumEntries;
  112.     
  113. // 获取逻辑调色板中指定范围的调色板表项
  114. GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry);
  115. // 创建一个Windows调色板
  116. hPalette = CreatePalette(plogPal);
  117. // 释放以分配的内存
  118. GlobalUnlock( hTemp );
  119. GlobalFree  ( hTemp );
  120. return hPalette;
  121. }
  122.  
  123. /*************************************************************************
  124.  *
  125.  * 函数名称:
  126.  *   ReadDIB
  127.  *
  128.  * 输入参数:
  129.  *   CFile* pFile - 需要打开的DIB文件
  130.  *   LPBITMAPINFOHEADER* pLpBMIH - DIB信息头指针的指针
  131.  *   LPBYTE* pLpImage - DIB位图数据块指针的指针
  132.  *
  133.  * 返回值:
  134.  *   BOOL - 如果操作成功,则返回TRUE
  135.  *
  136.  * 说明:
  137.  *   该函数将指定文件中的DIB文件载入,其中信息头和调色板放在*pLpBMIH中
  138.  *   图象数据存放到*pLpImage中。
  139.  *
  140.  *************************************************************************
  141.  */
  142.  BOOL ReadDIB(CFile* pFile, LPBITMAPINFOHEADER* pLpBMIH, LPBYTE* pLpImage)
  143.  {
  144.  // 临时存放信息的变量
  145.   int nCount, nSize;
  146. BITMAPFILEHEADER bmfh;
  147. // 信息头指针
  148. //LPBITMAPINFOHEADER lpBMIH;
  149. // DIB图象数据指针
  150. //LPBYTE lpImage;
  151. // 进行读操作
  152. try 
  153. {
  154. // 读取文件头
  155. nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
  156. if(nCount != sizeof(BITMAPFILEHEADER)) {
  157. throw new CException;
  158. }
  159. // 如果文件类型部位"BM",则返回并进行相应错误处理
  160. if(bmfh.bfType != 0x4d42) {
  161. throw new CException;
  162. }
  163. // 计算信息头加上调色板的大小,并分配相应的内存
  164. nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
  165. *pLpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
  166. // 读取信息头和调色板
  167. nCount = pFile->Read(*pLpBMIH, nSize); 
  168. // 计算图象数据大小并设置调色板指针
  169. if((*pLpBMIH)->biSize != sizeof(BITMAPINFOHEADER)) {
  170. TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmapn");
  171. throw new CException;
  172. }
  173. // 如果图象数据内存大小为0,则重新计算
  174. if((*pLpBMIH)->biSizeImage == 0) {
  175. DWORD dwBytes = ((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) / 32;
  176. if(((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) % 32) {
  177. dwBytes++;
  178. }
  179. dwBytes *= 4;
  180. (*pLpBMIH)->biSizeImage = dwBytes * (*pLpBMIH)->biHeight;
  181. }
  182. // 分配图象数据内存,并从文件中读取图象数据
  183. *pLpImage = (LPBYTE) new char[(*pLpBMIH)->biSizeImage];
  184. nCount = pFile->Read((*pLpImage), (*pLpBMIH)->biSizeImage); 
  185. }
  186. // 错误处理
  187. catch(CException* pe) 
  188. {
  189. AfxMessageBox("Read error");
  190. pe->Delete();
  191. return FALSE;
  192. }
  193. // 将指针赋值
  194. // 返回
  195. return TRUE;
  196.  }
  197.  /*************************************************************************
  198.  *
  199.  * 函数名称:
  200.  *   MakeDIBPalette()
  201.  *
  202.  * 输入参数:
  203.  *   LPVOID lpvColorTable - 颜色表指针
  204.  *   LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
  205.  *
  206.  * 返回值:
  207.  *   HPALETTE - 如果成功,则调色板句柄
  208.  *
  209.  * 说明:
  210.  *   该函数将读取颜色表,并创建一个Windows调色板,并返回此调色板的句柄
  211.  *
  212.  ************************************************************************
  213.  */
  214. HPALETTE MakeDIBPalette(LPVOID lpvColorTable,  LPBITMAPINFOHEADER lpBMIH)
  215. {
  216. // 调色板句柄
  217. HPALETTE hPalette = NULL;
  218. // 颜色表颜色数
  219. int nColorTableEntries;
  220. // 设置DIB中的调色板指针
  221. // lpvColorTable = (LPBYTE) lpBMIH + sizeof(BITMAPINFOHEADER);
  222. // 计算调色板的表项数
  223. if(lpBMIH->biClrUsed == 0) {
  224. switch(lpBMIH->biBitCount) {
  225. case 1:
  226. nColorTableEntries = 2;
  227. break;
  228. case 4:
  229. nColorTableEntries = 16;
  230. break;
  231. case 8:
  232. nColorTableEntries = 256;
  233. break;
  234. case 16:
  235. case 24:
  236. case 32:
  237. nColorTableEntries = 0;
  238. break;
  239. default:
  240. break;
  241. }
  242. }
  243. // 否则调色板的表项数就是用到的颜色数目
  244. else {
  245. nColorTableEntries = lpBMIH->biClrUsed;
  246. }
  247. ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256)); 
  248. // 如果不存在调色板,则返回FALSE
  249. if(nColorTableEntries == 0) return FALSE;
  250. // 给逻辑调色板分配内存
  251. LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
  252. nColorTableEntries * sizeof(PALETTEENTRY)];
  253. // 设置逻辑调色板的信息
  254. pLogPal->palVersion = 0x300;
  255. pLogPal->palNumEntries = nColorTableEntries;
  256. // 拷贝DIB中的颜色表到逻辑调色板
  257. LPRGBQUAD pDibQuad = (LPRGBQUAD) lpvColorTable;
  258. for(int i = 0; i < nColorTableEntries; i++) {
  259. pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
  260. pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
  261. pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
  262. pLogPal->palPalEntry[i].peFlags = 0;
  263. pDibQuad++;
  264. }
  265. // 创建逻辑调色板
  266. hPalette = ::CreatePalette(pLogPal);
  267. // 删除临时变量
  268. delete pLogPal;
  269. // 返回调色板句柄
  270. return hPalette;
  271. }
  272.  /*************************************************************************
  273.  *
  274.  * 函数名称:
  275.  *   PaintDIB()
  276.  *
  277.  * 输入参数:
  278.  *   CDC* pDC - 指向将要接收DIB图象的设备上下文指针 
  279.  *   LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
  280.  *   LPBYTE lpImage; - DIB位图数据块地址 
  281.  *   CPoint origin - 显示DIB的逻辑坐标
  282.  *   CSize size - 显示矩形的宽度和高度
  283.  *   HPALETTE hPalette - 指向DIB的调色板句柄
  284.  *
  285.  * 返回值:
  286.  *   BOOL - 如果成功,则返回TRUE
  287.  *
  288.  * 说明:
  289.  *   该函数将DIB图象进行显示
  290.  *
  291.  ************************************************************************
  292.  */
  293. BOOL PaintDIB(CDC* pDC, LPBITMAPINFOHEADER lpBMIH, LPBYTE lpImage, CPoint origin, CSize size, HPALETTE hPalette)
  294. {
  295. if(lpBMIH == NULL) return FALSE;
  296. // 如果调色板不为空,则将调色板选入设备上下文
  297. if(hPalette != NULL) {
  298. ::SelectPalette(pDC->GetSafeHdc(), hPalette, TRUE);
  299. }
  300. // 设置显示模式
  301. pDC->SetStretchBltMode(COLORONCOLOR);
  302. // 在设备的origin位置上画出大小为size的图象
  303. ::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y,size.cx,size.cy,
  304. 0, 0, lpBMIH->biWidth, lpBMIH->biHeight,
  305. lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS, SRCCOPY);
  306. // 返回
  307. return TRUE;
  308. }
  309. /*************************************************************************
  310.  *
  311.  * 函数名称:
  312.  *   ConvertDDBToDIB()
  313.  *
  314.  * 输入参数:
  315.  *   HBITMAP hBitmap - 指向源数据的BITMAP句柄
  316.  *   CDib* pDibDst - 指向转换目标的CDib对象指针
  317.  *
  318.  * 返回值:
  319.  *   BOOL - 如果操作成功,则返回TRUE
  320.  *
  321.  * 说明:
  322.  *   该函数将源BITMAP类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
  323.  *
  324.  *************************************************************************
  325.  */
  326. BOOL ConvertDDBToDIB(HBITMAP hBitmap, CDib* pDibDest, HPALETTE hPal)
  327. {
  328. // 声明一个BITMAP结构
  329. BITMAP bm;
  330. // 设备上下文
  331. HDC hDC;
  332. // 象素位数
  333. WORD biBitCount;
  334. // 调色板表项数
  335. int nColorTableEntries;
  336. // 如果hBitmap句柄无效,则返回
  337. if(!hBitmap){
  338. return FALSE;
  339. }
  340. // 填充图象数据到bm中,其中最后一个参数表示接收这个指定的对象的指针
  341. if(!GetObject(hBitmap,sizeof(BITMAP),(LPBYTE)&bm)){
  342. return FALSE;
  343. }
  344. // 计算象素位数
  345. biBitCount=bm.bmPlanes*bm.bmBitsPixel;
  346. if(biBitCount<=1)
  347. biBitCount=1;
  348. else if(biBitCount<=4)
  349. biBitCount=4;
  350. else if(biBitCount<=8)
  351. biBitCount=8;
  352. else 
  353. biBitCount=24;
  354. // 计算调色板的尺寸
  355. // 如果biClrUsed为零,则用到的颜色数为2的biBitCount次方
  356. switch(biBitCount) {
  357. case 1:
  358. nColorTableEntries = 2;
  359. break;
  360. case 4:
  361. nColorTableEntries = 16;
  362. break;
  363. case 8:
  364. nColorTableEntries = 256;
  365. break;
  366. case 16:
  367. case 24:
  368. case 32:
  369. nColorTableEntries = 0;
  370. break;
  371. default:
  372. ASSERT(FALSE);
  373. }
  374. ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256)); 
  375. // 分配DIB信息头和调色板的内存
  376. LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char
  377. [sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries];
  378. lpBMIH->biSize = sizeof(BITMAPINFOHEADER); 
  379. lpBMIH->biWidth = bm.bmWidth; 
  380. lpBMIH->biHeight = bm.bmHeight; 
  381. lpBMIH->biPlanes = 1; 
  382. lpBMIH->biBitCount = biBitCount; 
  383. lpBMIH->biCompression = BI_RGB; 
  384. lpBMIH->biSizeImage = 0; 
  385. lpBMIH->biXPelsPerMeter = 0; 
  386. lpBMIH->biYPelsPerMeter = 0; 
  387. lpBMIH->biClrUsed = nColorTableEntries;
  388. lpBMIH->biClrImportant = nColorTableEntries;
  389. // 获得设备上下文句柄
  390. hDC=GetDC(NULL);
  391.   // select and realize our palette 
  392.  
  393. // 如果没有指定调色板,则从系统中获得当前的系统调色板
  394. if(hPal==NULL){
  395. hPal = GetSystemPalette();
  396. }
  397. hPal = SelectPalette(hDC, hPal, FALSE); 
  398. RealizePalette(hDC); 
  399.  
  400. // 调用GetDIBits填充信息头,并获得图象数据的尺寸。注意这里图象数据指针为NULL
  401. GetDIBits( hDC, hBitmap, 0, (UINT)lpBMIH->biHeight, NULL, (LPBITMAPINFO)lpBMIH, DIB_RGB_COLORS);
  402. // 如果没有正确的获得图象数据尺寸,则重新计算
  403. if( lpBMIH->biSizeImage == 0 ){
  404. lpBMIH->biSizeImage=(((bm.bmWidth*biBitCount) + 31) / 32 * 4)*bm.bmHeight;
  405. }
  406. // 分配存放图象数据的内存
  407. LPBYTE lpImage = (LPBYTE) new char[lpBMIH->biSizeImage];
  408. // 调用GetDIBits加载图象数据,注意这里给出了图象数据指针
  409. // 如果加载图象数据不成功,则释放已经分配的内存,并返回FALSE
  410. if( GetDIBits( hDC, hBitmap, 0, (UINT)lpBMIH->biHeight, (LPBYTE)lpImage,
  411. (LPBITMAPINFO)lpBMIH, DIB_RGB_COLORS) == 0 ){
  412. //clean up and return NULL
  413. delete []lpImage;
  414. delete []lpBMIH;
  415. SelectPalette( hDC, hPal, TRUE );
  416. RealizePalette( hDC );
  417. ReleaseDC( NULL, hDC );
  418. return FALSE;
  419. }
  420. // 将指针保存在CDib对象的数据成员中
  421. pDibDest->m_lpBMIH  = lpBMIH;
  422. pDibDest->m_lpImage = lpImage;
  423. pDibDest->m_nBmihAlloc = pDibDest->m_nImageAlloc = pDibDest->crtAlloc;
  424. // 删除临时变量
  425. SelectPalette(hDC, hPal, TRUE); 
  426. RealizePalette(hDC); 
  427. ReleaseDC(NULL, hDC); 
  428. return TRUE;
  429. }
  430. /*************************************************************************
  431.  *
  432.  * 函数名称:
  433.  *   CopyDIB()
  434.  *
  435.  * 输入参数:
  436.  *   CDib* pDibSrc - 指向源数据的CDib对象指针
  437.  *   CDib* pDibDst - 指向拷贝目标的CDib对象指针
  438.  *
  439.  * 返回值:
  440.  *   BOOL - 如果操作成功,则返回TRUE
  441.  *
  442.  * 说明:
  443.  *   该函数将源CDib类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
  444.  *
  445.  *************************************************************************
  446.  */
  447. BOOL CopyDIB(CDib* pDibSrc, CDib* pDibDst)
  448. {
  449. // 将目的CDib对象清空
  450. pDibDst->Empty();
  451. // 计算信息头加上调色板的大小,并分配相应的内存
  452. int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pDibSrc->m_nColorTableEntries;
  453. pDibDst->m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSizeHdr];
  454. pDibDst->m_nBmihAlloc = pDibDst->m_nImageAlloc = pDibDst->crtAlloc;
  455. try{
  456. // 拷贝信息头和调色板
  457. memcpy(pDibDst->m_lpBMIH,pDibSrc->m_lpBMIH,nSizeHdr);
  458. // 如果结构的长度不对,则进行错误处理
  459. if(pDibDst->m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
  460. TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmapn");
  461. throw new CException;
  462. }
  463. // 保存图象数据内存大小到CDib对象的数据成员中
  464. pDibDst->m_dwSizeImage = pDibDst->m_lpBMIH->biSizeImage;
  465. // 如果图象数据内存大小为0,则重新计算
  466. if(pDibDst->m_dwSizeImage == 0) {
  467. DWORD dwBytes = ((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) / 32;
  468. if(((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) % 32) {
  469. dwBytes++;
  470. }
  471. dwBytes *= 4;
  472. pDibDst->m_dwSizeImage = dwBytes * pDibDst->m_lpBMIH->biHeight; 
  473. }
  474. // 设置DIB中的调色板指针
  475. pDibDst->m_lpvColorTable = (LPBYTE) pDibDst->m_lpBMIH + sizeof(BITMAPINFOHEADER);
  476. // 计算调色板的表项数
  477. pDibDst->ComputePaletteSize(pDibDst->m_lpBMIH->biBitCount);
  478. // 如果DIB中存在调色板,则创建一个Windows调色板
  479. pDibDst->MakePalette();
  480. // 分配图象数据内存,并拷贝图象数据
  481. pDibDst->m_lpImage = (LPBYTE) new char[pDibDst->m_dwSizeImage];
  482. memcpy(pDibDst->m_lpImage, pDibSrc->m_lpImage,pDibDst->m_dwSizeImage);
  483. }
  484. catch(CException* pe) 
  485. {
  486. AfxMessageBox("Copy DIB error");
  487. pDibDst->Empty();
  488. pe->Delete();
  489. return FALSE;
  490. }
  491. return TRUE;
  492. }
  493. /*************************************************************************
  494.  *
  495.  * 函数名称:
  496.  *   CopyScreenToDIB
  497.  *
  498.  * 输入参数:
  499.  *   LPRECT lpRect - 需要拷贝的屏幕区域
  500.  *   CDib* pDibDest - 指向目标CDib对象的指针
  501.  *
  502.  * 返回值:
  503.  *   BOOL - 如果操作成功,则返回TRUE
  504.  *
  505.  * 说明:
  506.  *   该函数将指定矩形位置内的屏幕内容拷贝到DIB中源CDib类pDibSrc中的数据拷贝到pDibDst中
  507.  *
  508.  *************************************************************************
  509.  */
  510. BOOL CopyScreenToDIB(LPRECT lpRect, CDib* pDibDest)
  511. {
  512. // 屏幕设备上下文和内存设备上下文句柄
  513. HDC         hScrDC, hMemDC;         
  514. // 声明BITMAP临时句柄和以前的BITMAP句柄
  515. HBITMAP     hBitmap, hOldBitmap;    
  516. // 调色板句柄
  517. HPALETTE    hPalette;       
  518.     
  519. // 获取矩形区域的坐标
  520. int         nX, nY, nX2, nY2;
  521. // DIB图象的高度和宽度
  522. int         nWidth, nHeight; 
  523. // 屏幕分辨率
  524. int         xScrn, yScrn;    
  525.  
  526.         // 如果给定的矩形区域为空,则不进行进一步的处理
  527. if (IsRectEmpty(lpRect)) 
  528. return FALSE; 
  529.  
  530.      // 得到一个屏幕设备上下文
  531. hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
  532. // 创建与屏幕设备兼容的内存设备上下文
  533. hMemDC = CreateCompatibleDC(hScrDC); 
  534.  
  535. // 得到矩形的区域坐标
  536. nX = lpRect->left; 
  537. nY = lpRect->top; 
  538. nX2 = lpRect->right; 
  539. nY2 = lpRect->bottom; 
  540.  
  541. // 得到屏幕的分辨率,以便后面的判断处理
  542. xScrn = GetDeviceCaps(hScrDC, HORZRES); 
  543. yScrn = GetDeviceCaps(hScrDC, VERTRES); 
  544.  
  545. // 判断矩形区域是否超出屏幕
  546.  
  547. if (nX < 0) 
  548. nX = 0; 
  549. if (nY < 0) 
  550.         nY = 0; 
  551. if (nX2 > xScrn) 
  552.         nX2 = xScrn; 
  553. if (nY2 > yScrn) 
  554.         nY2 = yScrn; 
  555.  
  556. // 计算DIB图象的高度和宽度
  557. nWidth = nX2 - nX; 
  558. nHeight = nY2 - nY; 
  559.  
  560. // 创建一个与屏幕设备上下文兼容的DDB位图
  561. hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); 
  562.  
  563. // 将DDB位图选入内存设备上下文
  564. hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); 
  565.  
  566. // 将屏幕中指定区域的图象传输到内存设备上下文中
  567. BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); 
  568.  
  569. // 然后将以前的图象选入,并得到屏幕区域的DDB图象句柄
  570. hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); 
  571.  
  572. // 将临时的设备上下文删除
  573. DeleteDC(hScrDC); 
  574. DeleteDC(hMemDC); 
  575.  
  576. // 得到当前系统调色板
  577. hPalette = GetSystemPalette(); 
  578.  
  579. // 将DDB图象转换为DIB图象
  580. pDibDest->ConvertFromDDB(hBitmap,hPalette);
  581. // 删除临时对象
  582. DeleteObject(hPalette); 
  583. DeleteObject(hBitmap); 
  584. return TRUE;
  585. }