mfc 单文档打开BMP

http://www.docin.com/p-448473837.html

按照这个ppt操作 可以实现 记得给变量m_hDIB = NULL; 初始化,还有析构函数的里面

	if (m_hDIB != NULL)
	{
		::GlobalFree((HGLOBAL) m_hDIB);
	}

另外添加响应调色板的消息有点复杂 ,我是在单文档里面做的

所以有的地方更改了

在mainframe里面 把添加的两个消息响应函数改了一下

void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd) 
{
	CFrameWnd::OnPaletteChanged(pFocusWnd);
	
	// TODO: Add your message handler code here
	// always realize the palette for the active view
/*	CMDIChildWnd* pMDIChildWnd = MDIGetActive();
	if (pMDIChildWnd == NULL)
		return; // no active MDI child frame
		*/
		CMainFrame * pMainFrm = (CMainFrame *)AfxGetMainWnd();
		COpenBMPView * pView = (COpenBMPView*)pMainFrm->GetActiveView();
	//CView* pView = pMDIChildWnd->GetActiveView();
	ASSERT(pView != NULL);
	
	// notify all child windows that the palette has changed
	SendMessageToDescendants(WM_REALIZEPAL, (WPARAM)pView->m_hWnd);
	
}

BOOL CMainFrame::OnQueryNewPalette() 
{
	// TODO: Add your message handler code here and/or call default
	
//	return CFrameWnd::OnQueryNewPalette();

//	CMDIChildWnd* pMDIChildWnd = MDIGetActive();
	CMainFrame * pMainFrm = (CMainFrame *)AfxGetMainWnd();
		COpenBMPView * pView = (COpenBMPView*)pMainFrm->GetActiveView();

//	CView* pView = pMDIChildWnd->GetActiveView();
	ASSERT(pView != NULL);
	
	// just notify the target view
	pView->SendMessage(WM_REALIZEPAL, (WPARAM)pView->m_hWnd);
	return TRUE;
}
mainframe.h里面记得添加

#define WM_REALIZEPAL (WM_USER + 0x100) 


对应的view类的头文件记得添加 对应的消息响应函数

// Generated message map functions
protected:
	//{{AFX_MSG(COpenBMPView)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	afx_msg void OnRealizePal(WPARAM wParam, LPARAM lParam);
	DECLARE_MESSAGE_MAP()

view 的cpp文件的消息映射也要添加

BEGIN_MESSAGE_MAP(COpenBMPView, CScrollView)
	//{{AFX_MSG_MAP(COpenBMPView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
	ON_MESSAGE(WM_REALIZEPAL, OnRealizePal)
END_MESSAGE_MAP()

接着就是具体的实现函数了

// COpenBMPView message handlers
void COpenBMPView::OnRealizePal(WPARAM wParam, LPARAM lParam)
{
	ASSERT(wParam != NULL);
	COpenBMPDoc* pDoc = GetDocument();
	
	if (pDoc->m_hDIB == NULL)
		return;  // must be a new document
	
	LPBYTE lpbi = (LPBYTE)GlobalLock(pDoc->m_hDIB);
	CPalette* pPal = CPalette::FromHandle(CreateDIBPalette(lpbi));
	GlobalUnlock(pDoc->m_hDIB);
	if (pPal != NULL)
	{
		CWnd* pAppFrame = AfxGetApp()->m_pMainWnd;
		
		CClientDC appDC(pAppFrame);
		// All views but one should be a background palette.
		// wParam contains a handle to the active view, so the SelectPalette
		// bForceBackground flag is FALSE only if wParam == m_hWnd (this view)
		CPalette* oldPalette = appDC.SelectPalette(pPal, ((HWND)wParam) != m_hWnd);
		
		if (oldPalette != NULL)
		{
			UINT nColorsChanged = appDC.RealizePalette();
			if (nColorsChanged > 0)
				GetDocument()->UpdateAllViews(NULL);
			appDC.SelectPalette(oldPalette, TRUE);
		}
		else
		{
			TRACE0("\tSelectPalette failed!\n");
		}
	}
}

今天 又尝试了一次,没有管调色板函数和其对应的消息函数,也可以打开一个位图。。。是采用默认的系统调色板,都按照24位的bmp处理?

还不知道怎么解释。。。

只在doc中添加了虚函数

BOOL COpenBMP_testDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
	
	// TODO: Add your specialized creation code here
	m_hDIB = LoadDIB(lpszPathName);
	if (m_hDIB == NULL)
	{
		// may not be DIB format
		return FALSE;
	}
	SetPathName(lpszPathName);
	SetModifiedFlag(FALSE);     // start off with unmodified
	
	return TRUE;
}

还有view中的ondraw函数

void COpenBMP_testView::OnDraw(CDC* pDC)
{
	COpenBMP_testDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	if (pDoc->m_hDIB == NULL)
		return;	
	
//

		LPBITMAPINFOHEADER lpDIB = (LPBITMAPINFOHEADER)GlobalLock(pDoc->m_hDIB);
		m_rcDIB.left = 0;
		m_rcDIB.top = 0;
		m_rcDIB.right = ((LPBITMAPINFOHEADER)lpDIB)->biWidth;
		m_rcDIB.bottom = ((LPBITMAPINFOHEADER)lpDIB)->biHeight;


//


	PaintDIB(pDC->GetSafeHdc(),
		m_rcDIB, 
		pDoc->m_hDIB, 
		m_rcDIB, 
		NULL, 
		SRCCOPY);

}

那个OnInitialUpdate 是设置滚动条范围的,弄不弄都可以显示图片

void COpenBMP_testView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	//CSize sizeTotal;
	// TODO: calculate the total size of this view
//	sizeTotal.cx = sizeTotal.cy = 100;

	COpenBMP_testDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CSize sizeTotal;
	if (pDoc->m_hDIB != NULL)
	{
		LPBITMAPINFOHEADER lpDIB = (LPBITMAPINFOHEADER)GlobalLock(pDoc->m_hDIB);
		sizeTotal.cx = ((LPBITMAPINFOHEADER)lpDIB)->biWidth;
		sizeTotal.cy = ((LPBITMAPINFOHEADER)lpDIB)->biHeight;
		
		GlobalUnlock(pDoc->m_hDIB);
		
	}
	else
	{
		m_rcDIB.SetRectEmpty();
		sizeTotal.cx = sizeTotal.cy = 100;
	}

	SetScrollSizes(MM_TEXT, sizeTotal);
}
记得在doc中初始化和释放m_hDIB

COpenBMP_testDoc::COpenBMP_testDoc()
{
	// TODO: add one-time construction code here
	m_hDIB = NULL;

}

COpenBMP_testDoc::~COpenBMP_testDoc()
{
	if (m_hDIB != NULL)
	{
		::GlobalFree((HGLOBAL) m_hDIB);
	}
}

  

附上 常用的一个处理位图的api函数 ,微软给的打开位图的例子,添加进去就可以了

dibapi.h

/******************************************************************************** 
 *  DIBAPI.H
 * 
 *  Header file for Device-Independent Bitmap (DIB) API.  Provides 
 *  function prototypes and constants for DIB functions 
 ********************************************************************************/ 
//#include "cdib.h"
#ifndef __DIBAPI_H_
#define __DIBAPI_H_
//

// Dib Header Marker - used in writing DIBs to files 
#define DIB_HEADER_MARKER	((WORD) ('M' << 8) | 'B') 

/* DIB constants */ 
#define PALVERSION			0x300 

/* DIB Macros*/ 
// WIDTHBYTES performs DWORD-aligning of DIB scanlines.  The "bits" 
// parameter is the bit count for the scanline (biWidth * biBitCount), 
// and this macro returns the number of DWORD-aligned bytes needed  
// to hold those bits. 
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4) 
#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER)) 
#define RECTWIDTH(lpRect)   ((lpRect)->right - (lpRect)->left) 
#define RECTHEIGHT(lpRect)  ((lpRect)->bottom - (lpRect)->top) 
 
/* function prototypes */ 
HANDLE LoadDIB (LPCTSTR); 
BOOL SaveDIB (HANDLE, LPCTSTR); 
HANDLE ReadDIBFile(HANDLE); 
WORD DIBNumColors (LPBYTE lpDIB); 
HPALETTE CreateDIBPalette(LPBYTE lpDIB);
BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal);
BOOL PaintDIB(HDC, LPRECT, HANDLE, LPRECT, HPALETTE, DWORD);
//BOOL MedianFilter(CDib* pDib,  int nTempWidth, int nTempHeight,int nTempCenX, int nTempCenY);
unsigned char  GetMedianValue(unsigned char * pUnchFltValue, int iFilterLen);
unsigned char  GetEquValue(unsigned char * pUnchFltValue, int iFilterLen);
//BOOL EquFilter(CDib* pDib,  int nTempWidth, int nTempHeight, int nTempCenX, int nTempCenY);

//
#endif	//__DIBAPI_H_

dibapi.cpp

//********************************************************************** 
// 
//  AIBAPI.CPP
// 
//  Source file for Device-Independent Bitmap (DIB) API. 
// 
//********************************************************************** 
 
#include "stdafx.h"
#include <math.h> 
#include <windows.h> 
#include "dibapi.h" 

 

/************************************************************************* 
 * 
 * DIBNumColors() 
 * 
 * Parameter: 
 * 
 * LPBYTE lpDIB      - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * WORD             - number of colors in the color table 
 * 
 * Description: 
 * 
 * This function calculates the number of colors in the DIB's color table 
 * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style 
 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, 
 * if 24, no colors in color table. 
 * 
 ************************************************************************/ 
WORD DIBNumColors(LPBYTE lpDIB) 
{ 
    WORD wBitCount;  // DIB bit count 
 
    // If this is a Windows-style DIB, the number of colors in the 
    // color table can be less than the number of bits per pixel 
    // allows for (i.e. lpbi->biClrUsed can be set to some value). 
    // If this is the case, return the appropriate value. 
     
 
    if (IS_WIN30_DIB(lpDIB)) 
    { 
        DWORD dwClrUsed; 
 
        dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; 
        if (dwClrUsed) 
 
        return (WORD)dwClrUsed; 
    } 
 
    // Calculate the number of colors in the color table based on 
    // the number of bits per pixel for the DIB. 
     
    if (IS_WIN30_DIB(lpDIB)) 
        wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; 
    else 
        wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; 
 
    // return number of colors based on bits per pixel 
 
    switch (wBitCount) 
    { 
        case 1: 
            return 2; 
 
        case 4: 
            return 16; 
 
        case 8: 
            return 256; 
 
        default: 
            return 0; 
    } 
} 

 
/************************************************************************* 
 * 
 * CreateDIBPalette() 
 * 
 * Parameter: 
 * 
 * LPBYTE lpbi       - specifies the DIB 
 * 
 * Return Value: 
 * 
 * HPALETTE         - specifies the palette 
 * 
 * Description: 
 * 
 * This function creates a palette from a DIB by allocating memory for the 
 * logical palette, reading and storing the colors from the DIB's color table 
 * into the logical palette, creating a palette from this logical palette, 
 * and then returning the palette's handle. This allows the DIB to be 
 * displayed using the best possible colors (important for DIBs with 256 or 
 * more colors). 
 * 
 ************************************************************************/ 
HPALETTE CreateDIBPalette(LPBYTE lpbi) 
{ 
    LPLOGPALETTE        lpPal;          // pointer to a logical palette 
    HANDLE              hLogPal;        // handle to a logical palette 
    HPALETTE            hPal = NULL;    // handle to a palette 
    int                 i, wNumColors;  // loop index, number of colors in color table 
    LPBITMAPINFO        lpbmi;          // pointer to BITMAPINFO structure (Win3.0) 
    LPBITMAPCOREINFO    lpbmc;          // pointer to BITMAPCOREINFO structure (OS/2) 
    BOOL                bWinStyleDIB;   // Win3.0 DIB? 
 
    // if handle to DIB is invalid, return NULL 
 
    if (! lpbi) 
        return NULL; 
 
    // get pointer to BITMAPINFO (Win 3.0) 
 
    lpbmi = (LPBITMAPINFO)lpbi; 
 
    // get pointer to BITMAPCOREINFO (OS/2 1.x) 
 
    lpbmc = (LPBITMAPCOREINFO)lpbi; 
 
    // get the number of colors in the DIB  
 
    wNumColors = DIBNumColors(lpbi); 
 
    // is this a Win 3.0 DIB? 
 
    bWinStyleDIB = IS_WIN30_DIB(lpbi); 
    if (wNumColors) 
    { 
        // allocate memory block for logical palette 
 
        hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + 
                sizeof(PALETTEENTRY) * wNumColors); 
 
        // if not enough memory, clean up and return NULL 
 
        if (!hLogPal) 
            return NULL; 
 
        // lock memory block and get pointer to it 
 
        lpPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
 
        // set version and number of palette entries 
 
        lpPal->palVersion = PALVERSION; 
        lpPal->palNumEntries = wNumColors; 
 
        // store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB) 
        // into palette 
         
        for (i = 0; i < wNumColors; i++) 
        { 
            if (bWinStyleDIB) 
            { 
                lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 
                lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 
                lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; 
                lpPal->palPalEntry[i].peFlags = 0; 
            } 
            else 
            { 
                lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 
                lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 
                lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; 
                lpPal->palPalEntry[i].peFlags = 0; 
            } 
        } 
 
        // create the palette and get handle to it 
 
        hPal = CreatePalette(lpPal); 
 
        // if error getting handle to palette, clean up and return NULL 
 
        if (!hPal) 
        { 
            GlobalUnlock(hLogPal); 
            GlobalFree(hLogPal); 
            return NULL; 
        } 
    } 
 
    // clean up  
 
    GlobalUnlock(hLogPal); 
    GlobalFree(hLogPal); 
 
    // return handle to DIB's palette 
    return hPal; 
} 
 
/************************************************************************* 
 * 
 * DisplayPalette () 
 * 
 * Parameter: 
 * 
 * HDC hDC          - handle of device context to display palette
 * LPRECT lpRect      - rect range to show palette
 * HPALETTE hPal     - handle of palette to display
 * 
 * Return Value: 
 * 
 * BOOL            - TRUE, if success, else FALSE
 * 
 * Description: 
 * 
 * This function displays palette on the specified rectangle in a device context 
 * 
 ************************************************************************/ 
BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal)
{
	if (! hPal)
		return FALSE;

	int nEntries;
	PALETTEENTRY pe[256];
	nEntries = GetPaletteEntries(hPal, 0, 256, pe);
	int nSqr = (int)sqrt((double)nEntries);

	int nWidth = (lpRect->right-lpRect->left)/nSqr;
	int nHeight = (lpRect->bottom-lpRect->top)/nSqr;
	lpRect->right = lpRect->left + nWidth*nSqr;
	lpRect->bottom = lpRect->top + nHeight*nSqr;

	HPALETTE hOldPal = (HPALETTE)SelectPalette(hDC, hPal, FALSE);
	RealizePalette(hDC);

	HBRUSH hBrush, hOldBrush;
	int x, y;
	for (int i=0; i<nEntries; ++i)
	{
		x = i%nSqr;
		y = i/nSqr;
		hBrush = CreateSolidBrush(RGB(pe[i].peRed, pe[i].peGreen, pe[i].peBlue));
		hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
		Rectangle(hDC, 
			      lpRect->left + x*nWidth, 
				  lpRect->top + y*nHeight, 
				  lpRect->left + (x+1)*nWidth, 
				  lpRect->top + (y+1) *nHeight);
		SelectObject(hDC, hOldBrush);
		DeleteObject(hBrush);
	}
	
	SelectPalette(hDC, hOldPal, FALSE);

	return TRUE;
}


/************************************************************************* 
 * 
 * LoadDIB() 
 * 
 * Loads the specified DIB from a file, allocates memory for it, 
 * and reads the disk file into the memory. 
 * 
 * 
 * Parameters: 
 * 
 * LPCTSTR lpFileName - specifies the file to load a DIB from 
 * 
 * Returns: A handle to a DIB, or NULL if unsuccessful. 
 * 
 * NOTE: The DIB API were not written to handle OS/2 DIBs; This 
 * function will reject any file that is not a Windows DIB. 
 * 
 *************************************************************************/ 
HANDLE LoadDIB(LPCTSTR lpFileName) 
{ 
    HANDLE        hDIB; 
    HANDLE      hFile; 
 
    // Set the cursor to a hourglass, in case the loading operation 
    // takes more than a sec, the user will know what's going on. 
 
    SetCursor(LoadCursor(NULL, IDC_WAIT)); 
 
    if ((hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
            NULL)) != INVALID_HANDLE_VALUE) 
    { 
        hDIB = ReadDIBFile(hFile); 
        CloseHandle(hFile); 
        SetCursor(LoadCursor(NULL, IDC_ARROW)); 
        return hDIB; 
    } 
    else 
    { 
        SetCursor(LoadCursor(NULL, IDC_ARROW)); 
        return NULL; 
    } 
} 
 
 
/************************************************************************* 
 * 
 * Function:  ReadDIBFile (int) 
 * 
 *  Purpose:  Reads in the specified DIB file into a global chunk of 
 *            memory. 
 * 
 *  Returns:  A handle to a dib (hDIB) if successful. 
 *            NULL if an error occurs. 
 * 
 * Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything 
 *            from the end of the BITMAPFILEHEADER structure on is 
 *            returned in the global memory handle. 
 * 
 * 
 * NOTE: The DIB API were not written to handle OS/2 DIBs, so this 
 * function will reject any file that is not a Windows DIB. 
 * 
 *************************************************************************/ 
HANDLE ReadDIBFile(HANDLE hFile) 
{ 
    BITMAPFILEHEADER    bmfHeader; 
    DWORD               dwBitsSize; 
    UINT                nNumColors;   // Number of colors in table 
    HANDLE              hDIB;         
    HANDLE              hDIBtmp;      // Used for GlobalRealloc() //MPB 
    LPBITMAPINFOHEADER  lpbi; 
    DWORD               offBits; 
    DWORD               dwRead; 
 
    // get length of DIB in bytes for use when reading 
 
    dwBitsSize = GetFileSize(hFile, NULL); 
 
    // Allocate memory for header & color table. We'll enlarge this 
    // memory as needed. 
 
    hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 
            256 * sizeof(RGBQUAD))); 
 
    if (!hDIB) 
        return NULL; 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    if (!lpbi)  
    { 
        GlobalFree(hDIB); 
        return NULL; 
    } 
 
    // read the BITMAPFILEHEADER from our file 
 
    if (!ReadFile(hFile, (LPBYTE)&bmfHeader, sizeof (BITMAPFILEHEADER), 
            &dwRead, NULL)) 
        goto ErrExit; 
 
    if (sizeof (BITMAPFILEHEADER) != dwRead) 
        goto ErrExit; 
 
    if (bmfHeader.bfType != 0x4d42)  // 'BM' 
        goto ErrExit; 
 
    // read the BITMAPINFOHEADER 
 
    if (!ReadFile(hFile, (LPBYTE)lpbi, sizeof(BITMAPINFOHEADER), &dwRead, 
            NULL)) 
        goto ErrExit; 
 
    if (sizeof(BITMAPINFOHEADER) != dwRead) 
        goto ErrExit; 
 
    // Check to see that it's a Windows DIB -- an OS/2 DIB would cause 
    // strange problems with the rest of the DIB API since the fields 
    // in the header are different and the color table entries are 
    // smaller. 
    // 
    // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL. 
 
    if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) 
        goto ErrExit; 
 
    // Now determine the size of the color table and read it.  Since the 
    // bitmap bits are offset in the file by bfOffBits, we need to do some 
    // special processing here to make sure the bits directly follow 
    // the color table (because that's the format we are susposed to pass 
    // back) 
 
    if (!(nNumColors = (UINT)lpbi->biClrUsed)) 
    { 
        // no color table for 24-bit, default size otherwise 
 
        if (lpbi->biBitCount != 24) 
            nNumColors = 1 << lpbi->biBitCount; // standard size table 
    } 
 
    // fill in some default values if they are zero 
 
    if (lpbi->biClrUsed == 0) 
        lpbi->biClrUsed = nNumColors; 
 
    if (lpbi->biSizeImage == 0) 
    { 
        lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 
                31) & ~31) >> 3) * lpbi->biHeight; 
    } 
 
    // get a proper-sized buffer for header, color table and bits 
 
    GlobalUnlock(hDIB); 
    hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * 
            sizeof(RGBQUAD) + lpbi->biSizeImage, 0); 
 
    if (!hDIBtmp) // can't resize buffer for loading 
        goto ErrExitNoUnlock; //MPB 
    else 
        hDIB = hDIBtmp; 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    // read the color table 
 
    ReadFile (hFile, (LPBYTE)(lpbi) + lpbi->biSize, 
            nNumColors * sizeof(RGBQUAD), &dwRead, NULL); 
 
    // offset to the bits from start of DIB header 
 
    offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD); 
 
    // If the bfOffBits field is non-zero, then the bits might *not* be 
    // directly following the color table in the file.  Use the value in 
    // bfOffBits to seek the bits. 
 
    if (bmfHeader.bfOffBits != 0L) 
        SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN); 
 
    if (ReadFile(hFile, (LPBYTE)lpbi + offBits, lpbi->biSizeImage, &dwRead, 
            NULL)) 
        goto OKExit; 
 
ErrExit: 
    GlobalUnlock(hDIB);     
 
ErrExitNoUnlock:     
    GlobalFree(hDIB); 
    return NULL; 
 
OKExit: 
    GlobalUnlock(hDIB); 
    return hDIB; 
} 
 
/************************************************************************* 
 * 
 * SaveDIB() 
 * 
 * Saves the specified DIB into the specified file name on disk.  No 
 * error checking is done, so if the file already exists, it will be 
 * written over. 
 * 
 * Parameters: 
 * 
 * HANDLE hDib - Handle to the dib to save 
 * 
 * LPCTSTR lpFileName - pointer to full pathname to save DIB under 
 * 
 * Return value: TRUE if successful
 *				 FALSE if failure
 * 
 *************************************************************************/ 
BOOL SaveDIB(HANDLE hDib, LPCTSTR lpFileName) 
{ 
    BITMAPFILEHEADER    bmfHdr;     // Header for Bitmap file 
    LPBITMAPINFOHEADER  lpBI;       // Pointer to DIB info structure 
    HANDLE              fh;         // file handle for opened file 
    DWORD               dwDIBSize; 
    DWORD               dwWritten; 
 
    if (!hDib) 
        return FALSE; 
 
    fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
 
    if (fh == INVALID_HANDLE_VALUE) 
        return FALSE; 
 
    // Get a pointer to the DIB memory, the first of which contains 
    // a BITMAPINFO structure 
 
    lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
    if (!lpBI) 
    { 
        CloseHandle(fh); 
        return FALSE; 
    } 
 
    // Check to see if we're dealing with an OS/2 DIB.  If so, don't 
    // save it because our functions aren't written to deal with these 
    // DIBs. 
 
    if (lpBI->biSize != sizeof(BITMAPINFOHEADER)) 
    { 
        GlobalUnlock(hDib); 
        CloseHandle(fh); 
        return FALSE; 
    } 
 
    // Fill in the fields of the file header 
 
    // Fill in file type (first 2 bytes must be "BM" for a bitmap) 
 
    bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
 
    // Calculating the size of the DIB is a bit tricky (if we want to 
    // do it right).  The easiest way to do this is to call GlobalSize() 
    // on our global handle, but since the size of our global memory may have 
    // been padded a few bytes, we may end up writing out a few too 
    // many bytes to the file (which may cause problems with some apps, 
    // like HC 3.0). 
    // 
    // So, instead let's calculate the size manually. 
    // 
    // To do this, find size of header plus size of color table.  Since the 
    // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains 
    // the size of the structure, let's use this. 
 
    // Partial Calculation 
 
    dwDIBSize = *(LPDWORD)lpBI + DIBNumColors((LPBYTE)lpBI) * sizeof(RGBQUAD);   
 
    // Now calculate the size of the image 
 
    // It's an RLE bitmap, we can't calculate size, so trust the biSizeImage 
    // field 
 
    if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
        dwDIBSize += lpBI->biSizeImage; 
    else 
    { 
        DWORD dwBmBitsSize;  // Size of Bitmap Bits only 
 
        // It's not RLE, so size is Width (DWORD aligned) * Height 
 
        dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * 
                lpBI->biHeight; 
 
        dwDIBSize += dwBmBitsSize; 
 
        // Now, since we have calculated the correct size, why don't we 
        // fill in the biSizeImage field (this will fix any .BMP files which  
        // have this field incorrect). 
 
        lpBI->biSizeImage = dwBmBitsSize; 
    } 
 
 
    // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
                    
    bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
    bmfHdr.bfReserved1 = 0; 
    bmfHdr.bfReserved2 = 0; 
 
    // Now, calculate the offset the actual bitmap bits will be in 
    // the file -- It's the Bitmap file header plus the DIB header, 
    // plus the size of the color table. 
     
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + 
            DIBNumColors((LPBYTE)lpBI) * sizeof(RGBQUAD); 
 
    // Write the file header 
 
    WriteFile(fh, (LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
 
    // Write the DIB header and the bits -- use local version of 
    // MyWrite, so we can write more than 32767 bytes of data 
     
    WriteFile(fh, (LPBYTE)lpBI, dwDIBSize, &dwWritten, NULL); 
 
    GlobalUnlock(hDib); 
    CloseHandle(fh); 
 
    if (dwWritten == 0) 
        return FALSE; // oops, something happened in the write 
    else 
        return TRUE; // Success code 
} 
 
/************************************************************************* 
 * 
 * PaintDIB() 
 * 
 * Parameters: 
 * 
 * HDC hDC          - DC to do output to 
 * 
 * LPRECT lpDCRect  - rectangle on DC to do output to 
 * 
 * HANDLE hDIB        - handle to global memory with a DIB spec 
 *                    in it followed by the DIB bits 
 * 
 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 
 *
 * HPALETTE hPal    - Palette used to diaplsy DIB, if is NULL, 
 *					  use DIB palette to display
 *
 * DWORD dwRop      - ROP mode to display DIB
 * 
 * Return Value: 
 * 
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
 * 
 * Description: 
 *   Painting routine for a DIB.  Calls StretchDIBits() or 
 *   SetDIBitsToDevice() to paint the DIB.  The DIB is 
 *   output to the specified DC, at the coordinates given 
 *   in lpDCRect.  The area of the DIB to be output is 
 *   given by lpDIBRect. 
 * 
 * NOTE: This function always selects the palette as background. Before 
 * calling this function, be sure your palette is selected to desired 
 * priority (foreground or background). 
 * 
 * 
 ************************************************************************/ 
BOOL PaintDIB(HDC hDC, LPRECT lpDCRect, HANDLE hDIB, LPRECT lpDIBRect, 
        HPALETTE hPal, DWORD dwRop)
{ 
    LPBYTE        lpDIBHdr;           // Pointer to BITMAPINFOHEADER 
    LPBYTE        lpDIBBits;          // Pointer to DIB bits 
    BOOL         bSuccess=FALSE;     // Success/fail flag 
    HPALETTE     hOldPal=NULL;       // Previous palette 
 
    // Check for valid DIB handle 
 
    if (!hDIB) 
        return FALSE; 

    // Lock down the DIB, and get a pointer to the beginning of the bit 
    // buffer 
     
    lpDIBHdr  = (LPBYTE)GlobalLock(hDIB); 
    lpDIBBits = lpDIBHdr + sizeof(BITMAPINFOHEADER) + 
                DIBNumColors(lpDIBHdr)*sizeof(RGBQUAD);
	
 
	// if no palette provided, create one from DIB

    if (! hPal) 
		hPal = CreateDIBPalette(lpDIBHdr);

    // Select and realize our palette as background 
 
    if (hPal) 
    { 
        hOldPal = SelectPalette(hDC, hPal, TRUE); 
        RealizePalette(hDC); 
    } 
 
    // Make sure to use the stretching mode best for color pictures 
 
    SetStretchBltMode(hDC, COLORONCOLOR); 
 
    // Call StretchDIBits() with dwRop
 
	bSuccess = StretchDIBits(hDC, 
							 lpDCRect->left, 
							 lpDCRect->top, 
							 RECTWIDTH(lpDCRect), 
							 RECTHEIGHT(lpDCRect), 
							 lpDIBRect->left, 
				             ((LPBITMAPINFOHEADER)lpDIBHdr)->biHeight - lpDIBRect->top - RECTHEIGHT(lpDIBRect), 
							 RECTWIDTH(lpDIBRect), 
							 RECTHEIGHT(lpDIBRect), 
							 lpDIBBits, 
							 (LPBITMAPINFO)lpDIBHdr, 
							 DIB_RGB_COLORS, 
							 SRCCOPY); 
 
    // Unlock the memory block 
 
    GlobalUnlock(hDIB); 
 
    // Reselect old palette 
 
    if (hOldPal) 
		SelectPalette(hDC, hOldPal, FALSE); 
 
	GlobalUnlock(hDIB);

    // Return with success/fail flag 
    return bSuccess; 
} 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值