天天看點

MFC 抓取視窗或螢幕位圖

int CGoogleMapDlg::SaveBitmapToFile()
{
    TCHAR UserProfile[MAX_PATH];
    memset(UserProfile, 0, sizeof(TCHAR)*MAX_PATH);
    GetEnvironmentVariable(_T("USERPROFILE"), UserProfile, MAX_PATH);
    _tcscat_s(UserProfile,MAX_PATH, _T("\\My Documents\\"));

    SYSTEMTIME timeNow;
    GetLocalTime(&timeNow);
    TCHAR FileName[MAX_PATH];
    memset(FileName, 0, sizeof(FileName));
    _sntprintf_s(FileName,MAX_PATH, MAX_PATH-1, _T("%04d%02d%02d%02d%02d%02d.bmp"), timeNow.wYear, timeNow.wMonth, timeNow.wDay, timeNow.wHour, timeNow.wMinute, timeNow.wSecond);
    _tcscat_s(UserProfile,MAX_PATH, FileName);
    LPSTR   lpFileName = UserProfile;//為位圖檔案名

    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;//調色闆句柄

    CDC   dc;
    HDC   hdc = ::GetDC(m_hWnd);
    dc.Attach(hdc);
    CDC   memDC;
    memDC.CreateCompatibleDC(&dc);
    CRect   r;
    GetClientRect(&r);
    CSize   sz(r.Width(), r.Height());

    CBitmap   bm;
    bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy);
    CBitmap* oldBitmap = memDC.SelectObject(&bm);
    memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY);
    HBITMAP   hBitmap = (HBITMAP)bm;//hBitmap   為剛才的螢幕位圖句柄

    //計算位圖檔案每個像素所占位元組數
    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   if(iBits   <=   24)
        wBitCount = 24;
    else   if(iBits   <=   32)
        wBitCount = 32;
    //計算調色闆大小
    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)
    {
        //   設定位圖檔案頭
        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);

    memDC.SelectObject(oldBitmap);
    bm.Detach();     //   make   sure   bitmap   not   deleted   with   CBitmap   object

    return 0;
}