www.pudn.com > mfc资源大全1.rar > formview_background.shtml


 
 
    
    
   Bitmap - Painting the background for a CFormView derived class 
 
 

Painting the background for a CFormView derived class


This article was contributed by Adrian Roman.

I wanted to paint bitmaps on forms, like Access does. So I wrote some code for that: First, add in your derived CFormView two members:

 
CPalette m_palette; 
CBitmap m_bitmap;

Add the following functions to your derived class: OnDraw overrides the base class' function, and OnCtlColor is a handler for WM_CTLCOLOR message. Call in OnInitialUpdate the function:

 
	GetBitmapAndPalette( IDB_BACK, m_bitmap, m_palette );

where IDB_BACK is the identifier for the bitmap you want as background.

The code uses Keith Rule's CMemDC class. I added it here, so you don't have to search for it.

Add to your view a handler for WM_ERASEBKGND message:

BOOL CMyView::OnEraseBkgnd(CDC* pDC)

{

// TODO: Add your message handler code here and/or call default

return FALSE;

}

 

 
 
 
void CMyFormView::OnDraw(CDC* pDC)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	::DrawTheBackground(this,pDC,&m_palette,&m_bitmap);  
} 
  
HBRUSH CMyFormView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
{ 
	HBRUSH hbr = CDaoRecordView::OnCtlColor(pDC, pWnd, nCtlColor); //replace with your own base class 
	 
	// TODO: Change any attributes of the DC here 
	if(nCtlColor==CTLCOLOR_STATIC){ 
		//this is only an example - you may have to modify here the code in order to work properly for you 
		if(pWnd->GetDlgCtrlID()==IDC_STATIC){ 
			pDC->SetBkMode(TRANSPARENT); 
			//pDC->SetTextColor(RGB(255,255,255)); //you can change here the color of static text 
			return (HBRUSH)::GetStockObject(NULL_BRUSH); 
		} 
	}else pDC->SetBkMode(OPAQUE);	 
	 
	// TODO: Return a different brush if the default is not desired 
	return hbr; 
} 
  
  
  
BOOL CMyFormView::GetBitmapAndPalette(UINT nIDResource, CBitmap &bitmap, CPalette &pal) 
{ 
	LPCTSTR lpszResourceName = (LPCTSTR)nIDResource; 
	HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),  
		lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION ); 
	if( hBmp == NULL )return FALSE; 
	bitmap.Attach( hBmp ); 
	// Create a logical palette for the bitmap 
	DIBSECTION ds; 
	BITMAPINFOHEADER &bmInfo = ds.dsBmih; 
	bitmap.GetObject( sizeof(ds), &ds ); 
	int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount; 
	// Create a halftone palette if colors > 256.  
	CClientDC dc(NULL);			// Desktop DC 
	if( nColors > 256 )	pal.CreateHalftonePalette( &dc ); 
	else{ 
		// Create the palette 
		RGBQUAD *pRGB = new RGBQUAD[nColors]; 
		CDC memDC; 
		memDC.CreateCompatibleDC(&dc); 
		memDC.SelectObject( &bitmap ); 
		::GetDIBColorTable( memDC, 0, nColors, pRGB ); 
		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors); 
		LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; 
		pLP->palVersion = 0x300; 
		pLP->palNumEntries = nColors; 
		for( int i=0; i < nColors; i++){ 
			pLP->palPalEntry[i].peRed = pRGB[i].rgbRed; 
			pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen; 
			pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue; 
			pLP->palPalEntry[i].peFlags = 0; 
		} 
		pal.CreatePalette( pLP ); 
		delete[] pLP; 
		delete[] pRGB; 
	} 
	return TRUE; 
} 
 
 
void DrawTheBackground(CDaoRecordView *view,CDC *pDC,CPalette *mp_palette,CBitmap *mp_bitmap) 
{ 
	if(pDC->IsPrinting())return; 
	CRect rect; 
	CPalette *old_palette=NULL; 
	// Select and realize the palette 
	if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && mp_palette->m_hObject != NULL ){ 
		old_palette=pDC->SelectPalette( mp_palette, FALSE ); 
		pDC->RealizePalette(); 
	} 
	view->GetClientRect(rect); 
	pDC->DPtoLP(rect); 
	CMemDC DC(pDC,rect); 
	CDC dcImage; 
	if (!dcImage.CreateCompatibleDC(pDC))return; 
	BITMAP bm; 
	mp_bitmap->GetBitmap(&bm); 
	// Paint the image. 
	CBitmap* pOldBitmap = dcImage.SelectObject(mp_bitmap); 
	for(int i=((int)floor((double)rect.left/bm.bmWidth))*bm.bmWidth;i<=rect.right/*rect.Width()*/;i+=bm.bmWidth) 
	     for(int j=((int)floor((double)rect.top/bm.bmHeight))*bm.bmHeight;j<=rect.bottom/*rect.Height()*/;j+=bm.bmHeight) 
		DC->BitBlt(i, j, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY); 
	dcImage.SelectObject(pOldBitmap);	 
	pDC->SelectPalette(old_palette,FALSE); 
	pDC->RealizePalette();	 
} 
 
 
 
#ifndef _MEMDC_H_ 
#define _MEMDC_H_ 
////////////////////////////////////////////////// 
// CMemDC - memory DC 
// 
// Author: Keith Rule 
// Email:  keithr@europa.com 
// Copyright 1996-1997, Keith Rule 
// 
// You may freely use or modify this code provided this 
// Copyright is included in all derived versions. 
// 
// History - 10/3/97 Fixed scrolling bug. 
//                   Added print support. 
//	 
// This class implements a memory Device Context 
 
 
class CMemDC : public CDC { 
private: 
	CBitmap m_bitmap; // Offscreen bitmap 
	CBitmap* m_oldBitmap; // bitmap originally found in CMemDC 
	CDC* m_pDC; // Saves CDC passed in constructor 
	CRect m_rect; // Rectangle of drawing area. 
	BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. 
public: 
	CMemDC(CDC* pDC, CRect &rect) : CDC(), m_oldBitmap(NULL), m_pDC(pDC) 
	{ 
		ASSERT(m_pDC != NULL); // If you asserted here, you passed in a NULL CDC. 
		m_bMemDC = !pDC->IsPrinting(); 
		m_rect=rect; 
		if (m_bMemDC){ 
			// Create a Memory DC 
			CreateCompatibleDC(pDC); 
			pDC->GetClipBox(&m_rect); 
			m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); 
			m_oldBitmap = SelectObject(&m_bitmap); 
			SetWindowOrg(m_rect.left, m_rect.top); 
		} else { 
			// Make a copy of the relevent parts of the current DC for printing 
			m_bPrinting = pDC->m_bPrinting; 
			m_hDC = pDC->m_hDC; 
			m_hAttribDC = pDC->m_hAttribDC; 
		} 
	} 
 
	 
	~CMemDC() 
	{ 
		if (m_bMemDC) { 
			// Copy the offscreen bitmap onto the screen. 
			m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), 
				this, m_rect.left, m_rect.top, SRCCOPY); 
			//Swap back the original bitmap. 
			SelectObject(m_oldBitmap); 
		} else { 
			// All we need to do is replace the DC with an illegal value, 
			// this keeps us from accidently deleting the handles associated with 
			// the CDC that was passed to the constructor. 
			m_hDC = m_hAttribDC = NULL; 
		} 
	} 
	// Allow usage as a pointer 
	CMemDC* operator->() {return this;} 
	// Allow usage as a pointer 
	operator CMemDC*() {return this;} 
}; 
 
 
#endif 
 
 


Goto HomePage
© 1998 Zafir Anjum 
Contact me: zafir@home.com