大虾:
   小弟初学VC,现有这样一个问题:
我在CScrollview类中绘制了一个比客户区(及窗口的可视区域)大的图形,现在要把整个图形保存bmp文件,该怎么做??我现在只能将客户区的部分保存下来,超出的部分无法保存!(请具体说明保存大于客户区的图形与保存客户区内的图形之间的主要区别)

解决方案 »

  1.   

    Storing an Image
    Many applications store images permanently as files. For example, drawing applications store pictures, spreadsheet applications store charts, CAD applications store drawings, and so on. If you are writing an application that stores a bitmap image in a file, you should use the bitmap file format described in Bitmap Storage. To store a bitmap in this format, you must use a BITMAPINFOHEADER, a BITMAPV4HEADER, or a BITMAPV5HEADER structure and an array of RGBQUAD structures, as well as an array of palette indexes. The following example code defines a function that uses a BITMAPINFO structure and allocates memory for and initializes members within a BITMAPINFOHEADER structure. Note that the BITMAPINFO structure cannot be used with either a BITMAPV4HEADER or a BITMAPV5HEADER structure.PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)

        BITMAP bmp; 
        PBITMAPINFO pbmi; 
        WORD    cClrBits;     // Retrieve the bitmap color format, width, and height. 
        if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
            errhandler("GetObject", hwnd);     // Convert the color format to a count of bits. 
        cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
        if (cClrBits == 1) 
            cClrBits = 1; 
        else if (cClrBits <= 4) 
            cClrBits = 4; 
        else if (cClrBits <= 8) 
            cClrBits = 8; 
        else if (cClrBits <= 16) 
            cClrBits = 16; 
        else if (cClrBits <= 24) 
            cClrBits = 24; 
        else cClrBits = 32;     // Allocate memory for the BITMAPINFO structure. (This structure 
        // contains a BITMAPINFOHEADER structure and an array of RGBQUAD 
        // data structures.)      if (cClrBits != 24) 
             pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                        sizeof(BITMAPINFOHEADER) + 
                        sizeof(RGBQUAD) * (1<< cClrBits));      // There is no RGBQUAD array for the 24-bit-per-pixel format.      else 
             pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                        sizeof(BITMAPINFOHEADER));     // Initialize the fields in the BITMAPINFO structure.     pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
        pbmi->bmiHeader.biWidth = bmp.bmWidth; 
        pbmi->bmiHeader.biHeight = bmp.bmHeight; 
        pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
        pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
        if (cClrBits < 24) 
            pbmi->bmiHeader.biClrUsed = (1<<cClrBits);     // If the bitmap is not compressed, set the BI_RGB flag. 
        pbmi->bmiHeader.biCompression = BI_RGB;     // Compute the number of bytes in the array of color 
        // indices and store the result in biSizeImage. 
        // For Windows NT, the width must be DWORD aligned unless 
        // the bitmap is RLE compressed. This example shows this. 
        // For Windows 95/98/Me, the width must be WORD aligned unless the 
        // bitmap is RLE compressed.
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                      * pbmi->bmiHeader.biHeight; 
        // Set biClrImportant to 0, indicating that all of the 
        // device colors are important. 
         pbmi->bmiHeader.biClrImportant = 0; 
         return pbmi; 
     } 
    The following example code defines a function that initializes the remaining structures, retrieves the array of palette indices, opens the file, copies the data, and closes the file. void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, 
                      HBITMAP hBMP, HDC hDC) 
     { 
         HANDLE hf;                 // file handle 
        BITMAPFILEHEADER hdr;       // bitmap file-header 
        PBITMAPINFOHEADER pbih;     // bitmap info-header 
        LPBYTE lpBits;              // memory pointer 
        DWORD dwTotal;              // total count of bytes 
        DWORD cb;                   // incremental count of bytes 
        BYTE *hp;                   // byte pointer 
        DWORD dwTmp;     pbih = (PBITMAPINFOHEADER) pbi; 
        lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);    if (!lpBits) 
             errhandler("GlobalAlloc", hwnd);     // Retrieve the color table (RGBQUAD array) and the bits 
        // (array of palette indices) from the DIB. 
        if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
            DIB_RGB_COLORS)) 
        {
            errhandler("GetDIBits", hwnd); 
        }    // Create the .BMP file. 
        hf = CreateFile(pszFile, 
                       GENERIC_READ | GENERIC_WRITE, 
                       (DWORD) 0, 
                        NULL, 
                       CREATE_ALWAYS, 
                       FILE_ATTRIBUTE_NORMAL, 
                       (HANDLE) NULL); 
        if (hf == INVALID_HANDLE_VALUE) 
            errhandler("CreateFile", hwnd); 
        hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M" 
        // Compute the size of the entire file. 
        hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                     pbih->biSize + pbih->biClrUsed 
                     * sizeof(RGBQUAD) + pbih->biSizeImage); 
        hdr.bfReserved1 = 0; 
        hdr.bfReserved2 = 0;     // Compute the offset to the array of color indices. 
        hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                        pbih->biSize + pbih->biClrUsed 
                        * sizeof (RGBQUAD);     // Copy the BITMAPFILEHEADER into the .BMP file. 
        if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
            (LPDWORD) &dwTmp,  NULL)) 
        {
           errhandler("WriteFile", hwnd); 
        }    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
        if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                      + pbih->biClrUsed * sizeof (RGBQUAD), 
                      (LPDWORD) &dwTmp, ( NULL)) 
            errhandler("WriteFile", hwnd);     // Copy the array of color indices into the .BMP file. 
        dwTotal = cb = pbih->biSizeImage; 
        hp = lpBits; 
        if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
               errhandler("WriteFile", hwnd);     // Close the .BMP file. 
         if (!CloseHandle(hf)) 
               errhandler("CloseHandle", hwnd);     // Free memory. 
        GlobalFree((HGLOBAL)lpBits);
    }
      

  2.   

    int CGetimageDlg::Tofile(HBITMAP hbitmap , LPSTR lpfilename)

    HDC hdc; //设备描述表
    int ibits; 
    WORD wbitcount;  //当前显示分辨率下每个像素所占字节数

    //位图中每个像素所占字节数,定义调色板大小,位图中像素字节大小,位图文件大小 ,写入文件字节数
    DWORD dwpalettesize=0, dwbmbitssize, dwdibsize, dwwritten; BITMAP bitmap; //位图属性结构
    BITMAPFILEHEADER bmfhdr; //位图文件头结构
    BITMAPINFOHEADER bi; //位图信息头结构
    LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 //定义文件,分配内存句柄,调色板句柄
    HANDLE fh, hdib, 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 if (ibits <= 16)
    wbitcount = 16;
    else if (ibits <= 24)
    wbitcount = 24;
    else 
    wbitcount = 32; //计算调色板大小
    if (wbitcount <= 8)
    dwpalettesize = (1 << wbitcount) * sizeof(RGBQUAD); //设置位图信息头结构
    GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&bitmap);
    bi.biSize = sizeof(LPBITMAPINFOHEADER);
    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 = GetStockObject(DEFAULT_PALETTE);
    if (hpal)
    {
    hdc = ::GetDC(NULL);
    holdpal = SelectPalette(hdc, (HPALETTE)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, (HPALETTE)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);
    return true;
    }