保存dc內容爲bmp文件 ,屏幕截圖也可以(zt)

HBITMAP CopyScreenToBitmap(LPRECT lpRect)

//lpRect 代表選定區域

{

 HDC       hScrDC, hMemDC;     

 // 屏幕和內存設備描述表

 HBITMAP    hBitmap, hOldBitmap;  

 // 位圖句柄

 int       nX, nY, nX2, nY2;     

 // 選定區域座標

 int       nWidth, nHeight;     

 // 位圖寬度和高度

 int       xScrn, yScrn;        

 // 屏幕分辨率

 // 確保選定區域不爲空矩形

 if (IsRectEmpty(lpRect))

  return NULL;

 //爲屏幕創建設備描述表

 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);

 //爲屏幕設備描述表創建兼容的內存設備描述表

 hMemDC = CreateCompatibleDC(hScrDC);

 // 獲得選定區域座標

 nX = lpRect->left;

 nY = lpRect->top;

 nX2 = lpRect->right;

 nY2 = lpRect->bottom;

 // 獲得屏幕分辨率

 xScrn = GetDeviceCaps(hScrDC, HORZRES);

 yScrn = GetDeviceCaps(hScrDC, VERTRES);

 //確保選定區域是可見的

 if (nX < 0)

  nX = 0;

 if (nY < 0)

  nY = 0;

 if (nX2 > xScrn)

  nX2 = xScrn;

 if (nY2 > yScrn)

  nY2 = yScrn;

 nWidth = nX2 - nX;

 nHeight = nY2 - nY;

 // 創建一個與屏幕設備描述表兼容的位圖

 hBitmap = CreateCompatibleBitmap

  (hScrDC, nWidth, nHeight);

 // 把新位圖選到內存設備描述表中

 hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

 // 把屏幕設備描述表拷貝到內存設備描述表中

 BitBlt(hMemDC, 0, 0, nWidth, nHeight,

  hScrDC, nX, nY, SRCCOPY);

 //得到屏幕位圖的句柄

 hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);//這個時候可以把得到的句柄交給savebitmaptofile保存到文件,我在這裏繼續偷懶寫

 //清除
 BITMAPINFOHEADER bih;
 bih.biSize =sizeof(BITMAPINFOHEADER);
 bih.biWidth =800;
 bih.biHeight = 600;
 bih.biPlanes = 1;
 bih.biBitCount= 8;//8bit bitmap
 bih.biCompression = BI_RGB;
 bih.biSizeImage = 0;
 bih.biXPelsPerMeter =0;
 bih.biYPelsPerMeter = 0;
 bih.biClrUsed = 0;
 bih.biClrImportant = 0;
 DWORD dwBmBitsSize=800*600*8/8;
 HANDLE hDib=GlobalAlloc(GHND,dwBmBitsSize+256*sizeof(RGBQUAD)+sizeof(BITMAPINFOHEADER));//分配內存,GlobalAlloc分配內存能夠和dll程序共享分配的內存(可以由非c++編譯的dll釋放),malloc的話只能有c++自己知道怎麼釋放

//分配的內容包括 BITMAPINFOHEADER + PALETTE(調色板) + 位圖內容
 LPVOID ptr=(LPVOID)GlobalLock(hDib);
 *(BITMAPINFOHEADER*)ptr=bih;//保存那個BITMAPINFOHEADER到我們分配的內存
 HDC xdc=GetDC(NULL);
 //HPALETTE hPal= (HPALETTE)GetStockObject(DEFAULT_PALETTE);
 //HPALETTE hOldPal=(HPALETTE)SelectPalette(xdc,hPal,FALSE);
 //RealizePalette(xdc);
 if(!GetDIBits(hScrDC,hBitmap,0,600,
  (LPSTR)ptr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD),
  (BITMAPINFO *)ptr,
  DIB_RGB_COLORS))

//參數說明 從哪個dc(一定要有正確的PALETTE) ,位圖句柄,從哪一行(scanline),保存多少行,保存位圖內容的地方,一個保存BITMAPINFO結構(GetDIBits會幫我們完善該死的PALETTE),顏色的表示方式,要得到bmp就一定要DIB_RGB_COLORS


 {
  return hBitmap;//如果GetDIBits 返回0那就失敗了……
 }
 HANDLE fh = CreateFile("c://b.bmp", GENERIC_WRITE,

  0, NULL, CREATE_ALWAYS,

  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  NULL);

 if (fh == INVALID_HANDLE_VALUE)

  return FALSE;

 // 設置位圖文件頭
 BITMAPFILEHEADER bmfHdr;
 bmfHdr.bfType = 0x4D42;  // "BM"

 DWORD dwDIBSize    = sizeof(BITMAPFILEHEADER)

  + sizeof(BITMAPINFOHEADER)

  + 256*sizeof(RGBQUAD) + dwBmBitsSize; 

 bmfHdr.bfSize = dwDIBSize;

 bmfHdr.bfReserved1 = 0;

 bmfHdr.bfReserved2 = 0;

 bmfHdr.bfOffBits = (DWORD)sizeof

  (BITMAPFILEHEADER)

  + (DWORD)sizeof(BITMAPINFOHEADER)

  + 256*sizeof(RGBQUAD);

 // 寫入位圖文件頭
 DWORD dwWritten;
 WriteFile(fh, (LPSTR)&bmfHdr, sizeof

  (BITMAPFILEHEADER), &dwWritten, NULL);

 // 寫入位圖文件其餘內容

 WriteFile(fh, (LPSTR)ptr, dwDIBSize,

  &dwWritten, NULL);

 DeleteDC(hScrDC);

 DeleteDC(hMemDC);

 // 返回位圖句柄

 return hBitmap;

}

int SaveBitmapToFile(HBITMAP hBitmap ,

      LPSTR lpFileName) //hBitmap 爲剛纔的屏幕位圖句柄

{      //lpFileName 爲位圖文件名

 HDC            hDC;        

 //設備描述表

 int            iBits;     

 //當前顯示分辨率下每個像素所佔字節數

 WORD            wBitCount;  

 //位圖中每個像素所佔字節數

 //定義調色板大小, 位圖中像素字節大小 ,

 //位圖文件大小 , 寫入文件字節數

 DWORD           dwPaletteSize=0,

  dwBmBitsSize,

  dwDIBSize, dwWritten;

 BITMAP          Bitmap;       

 //位圖屬性結構

 BITMAPFILEHEADER   bmfHdr;       

 //位圖文件頭結構

 BITMAPINFOHEADER   bi;           

 //位圖信息頭結構

 LPBITMAPINFOHEADER lpbi;         

 //指向位圖信息頭結構

 HANDLE          fh, hDib;
 HPALETTE hPal,hOldPal=NULL;

 //定義文件,分配內存句柄,調色板句柄

 //計算位圖文件每個像素所佔字節數

 hDC = CreateDC("DISPLAY",NULL,NULL,NULL);

 iBits = GetDeviceCaps(hDC, BITSPIXEL) *

  GetDeviceCaps(hDC, PLANES);

 DeleteDC(hDC);

 if (iBits <= 1)

  wBitCount = 1;

 else if (iBits <= 4)

  wBitCount = 4;

 else if (iBits <= 8)

  wBitCount = 8;

 else

  wBitCount = 24;

 //計算調色板大小
 wBitCount=8;
 if (wBitCount <= 8)

  dwPaletteSize = (1 <<  wBitCount) *

  sizeof(RGBQUAD);

 //設置位圖信息頭結構

 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);

 bi.biSize            = sizeof(BITMAPINFOHEADER);

 bi.biWidth           = Bitmap.bmWidth;

 bi.biHeight          = Bitmap.bmHeight;

 bi.biPlanes          = 1;

 bi.biBitCount         = wBitCount;

 bi.biCompression      = BI_RGB;

 bi.biSizeImage        = 0;

 bi.biXPelsPerMeter     = 0;

 bi.biYPelsPerMeter     = 0;

 bi.biClrUsed         = 0;

 bi.biClrImportant      = 0;

 dwBmBitsSize = ((Bitmap.bmWidth *

  wBitCount+31)/32)* 4

  *Bitmap.bmHeight ;

 //爲位圖內容分配內存

 hDib  = GlobalAlloc(GHND,dwBmBitsSize+

  dwPaletteSize+sizeof(BITMAPINFOHEADER));

 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);

 *lpbi = bi;

 // 處理調色板  

 hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);

 if (hPal)

 {

  hDC  = GetDC(NULL);

  hOldPal = SelectPalette(hDC, hPal, FALSE);

  RealizePalette(hDC);

 }

 // 獲取該調色板下新的像素值

 GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,

  (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)

  +dwPaletteSize,

  (BITMAPINFO *)lpbi,
  DIB_RGB_COLORS);

 //恢復調色板  

 if (hOldPal)

 {

  SelectPalette(hDC, hOldPal, TRUE);

  RealizePalette(hDC);

  ReleaseDC(NULL, hDC);

 }

 //創建位圖文件   

 fh = CreateFile(lpFileName, GENERIC_WRITE,

  0, NULL, CREATE_ALWAYS,

  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN
  , NULL);

 if (fh == INVALID_HANDLE_VALUE)

  return FALSE;

 // 設置位圖文件頭

 bmfHdr.bfType = 0x4D42;  // "BM"

 dwDIBSize    = sizeof(BITMAPFILEHEADER)

  + sizeof(BITMAPINFOHEADER)

  + dwPaletteSize + dwBmBitsSize; 

 bmfHdr.bfSize = dwDIBSize;

 bmfHdr.bfReserved1 = 0;

 bmfHdr.bfReserved2 = 0;

 bmfHdr.bfOffBits = (DWORD)sizeof

  (BITMAPFILEHEADER)

  + (DWORD)sizeof(BITMAPINFOHEADER)

  + dwPaletteSize;

 // 寫入位圖文件頭

 WriteFile(fh, (LPSTR)&bmfHdr, sizeof

  (BITMAPFILEHEADER), &dwWritten, NULL);

 // 寫入位圖文件其餘內容

 WriteFile(fh, (LPSTR)lpbi, dwDIBSize,

  &dwWritten, NULL);

 //清除  

 GlobalUnlock(hDib);

 GlobalFree(hDib);

 CloseHandle(fh);

}

//我也是半懂不懂的狀態..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章