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


 
 
    
    
   Bitmap & Palette - A logo bitmap inside client frame 
 
 

A logo bitmap inside client frame


This article was contributed by Adrian Roman.

If you want to paint inside client area (a logo in the middle or even all background), this class should fit your needs. If you want to paint a logo, it will redraw only the rectangle, which cover the invalid rectangle, the old bitmap area, and the new logo area. Because I used the memory dc, it draws it very smoothly, even with "Show window contents while dragging" from Plus Pack.

This class is not so original. It contains some code from codeguru, some from MSJ, and of course, some of mine. I made it as fast as I could, so I reused as much code I could found.

In CMainFrame, override the OnCreateClient virtual function:

 
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	if(CMDIFrameWnd::OnCreateClient(lpcs, pContext)){ 
		m_ClientFrame.SubclassWindow(m_hWndMDIClient) ; 
		return TRUE; 
	}else return FALSE;  
} 
Header file:
  
#if !defined(AFX_CLIENTFRAME_H__9F201E20_8B54_11D1_87E4_00AA00242F4F__INCLUDED_) 
#define AFX_CLIENTFRAME_H__9F201E20_8B54_11D1_87E4_00AA00242F4F__INCLUDED_ 
 
#if _MSC_VER >= 1000 
#pragma once 
#endif // _MSC_VER >= 1000 
// ClientFrame.h : header file 
// 
 
///////////////////////////////////////////////////////////////////////////// 
// CClientFrame frame 
 
class CClientFrame : public CWnd 
{ 
	DECLARE_DYNCREATE(CClientFrame) 
protected: 
	 
	// Attributes 
public: 
	CClientFrame(); // protected constructor used by dynamic creation 
	virtual ~CClientFrame(); 
	static WNDPROC pfnSuper; 
	 
	// Operations 
public: 
	CPalette m_palette; 
	CBitmap m_bitmap; 
	virtual WNDPROC* GetSuperWndProcAddr() ; 
	 
	// Overrides 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CClientFrame) 
	//}}AFX_VIRTUAL 
	 
	// Implementation 
protected: 
	 
	// Generated message map functions 
	//{{AFX_MSG(CClientFrame) 
	afx_msg BOOL OnEraseBkgnd(CDC* pDC); 
	afx_msg void OnPaint(); 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
///////////////////////////////////////////////////////////////////////////// 
 
//{{AFX_INSERT_LOCATION}} 
// Microsoft Developer Studio will insert additional declarations immediately before the previous line. 
 
#endif // !defined(AFX_CLIENTFRAME_H__9F201E20_8B54_11D1_87E4_00AA00242F4F__INCLUDED_) 
  
Implementation frame: 
  
// ClientFrame.cpp : implementation file 
// 
  
#include "stdafx.h" 
#include "ClientFrame.h" 
#include "helper.h" 
  
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
  
  
extern CRect oldrect; 
  
WNDPROC CClientFrame::pfnSuper = NULL; 
  
///////////////////////////////////////////////////////////////////////////// 
// CClientFrame 
  
IMPLEMENT_DYNCREATE(CClientFrame, CWnd) 
  
CClientFrame::CClientFrame() 
{ 
	GetBitmapAndPalette( IDB_LOGO, m_bitmap, m_palette );  
} 
  
CClientFrame::~CClientFrame() 
{ 
} 
 
BEGIN_MESSAGE_MAP(CClientFrame, CWnd) 
//{{AFX_MSG_MAP(CClientFrame) 
ON_WM_ERASEBKGND() 
ON_WM_PAINT() 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
  
///////////////////////////////////////////////////////////////////////////// 
// CClientFrame message handlers 
  
BOOL CClientFrame::OnEraseBkgnd(CDC* pDC)  
{ 
	// TODO: Add your message handler code here and/or call default 
	return TRUE; 
} 
 
 
 
 
WNDPROC* CClientFrame::GetSuperWndProcAddr() 
{ 
	return &pfnSuper; 
} 
 
 
 
void CClientFrame::OnPaint()  
{ 
	// Do not call CWnd::OnPaint() for painting messages 
	// TODO: Add your message handler code here 
	InvalidateRect(&oldrect); 
	CRect newrect; 
	GetClientRect(&newrect); 
	//CDC *dc=GetDC(); 
	//dc->DPtoLP(newrect); 
	//ReleaseDC(dc); 
	BITMAP bm; 
	m_bitmap.GetBitmap(&bm); 
	newrect=CRect(newrect.Width()/2-bm.bmWidth/2,newrect.Height()/2-bm.bmHeight/2,newrect.Width()/2-bm.bmWidth/2+ bm.bmWidth,newrect.Height()/2-bm.bmHeight/2+ bm.bmHeight); 
	InvalidateRect(&newrect); 
	 
	{ 
		CPaintDC dc(this); // device context for painting 
		//dc.SelectClipRgn(NULL); 
		DrawTheBackground(this,&dc,&m_palette,&m_bitmap,TRUE); 
	} 
} 
  
  
  
#ifndef __HELPER_H_ 
#define __HELPER_H_ 
void DrawTheBackground(CWnd *view,CDC *pDC,CPalette *mp_palette,CBitmap *mp_bitmap,BOOL middle = FALSE); 
BOOL GetBitmapAndPalette(UINT nIDResource, CBitmap &bitmap, CPalette &pal); 
#endif 
  
Helper implementation: 
  
#include "stdafx.h" 
#include "helper.h" 
#include "memdc.h" 
  
CRect oldrect(0,0,0,0); 
  
  
  
void DrawTheBackground(CWnd *view,CDC *pDC,CPalette *mp_palette,CBitmap *mp_bitmap,BOOL middle) 
{ 
	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); 
	if(middle){ 
		CBrush* pOldBrush = (CBrush*)DC->SelectStockObject(GRAY_BRUSH); 
		CRect crect; 
		oldrect=CRect((rect.Width()-bm.bmWidth)/2,(rect.Height()-bm.bmHeight)/2,(rect.Width()-bm.bmWidth)/2+ bm.bmWidth,(rect.Height()-bm.bmHeight)/2+ bm.bmHeight); 
		pDC->GetClipBox(&crect); 
		DC->PatBlt( crect.left, crect.top, crect.Width(), crect.Height(),PATCOPY); 
		DC->SelectObject(pOldBrush); 
		DC->BitBlt(oldrect.left, oldrect.top, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY); 
	}else{ 
		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();  
} 
 
 
 
BOOL 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; 
} 
CMemDC implementation (for those who don't have it yet):
  
#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. 
// 12/19/97 Adrian Roman - modified the constructor to take two parameters 
// 
// 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 
	BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. 
public: 
	CRect m_rect; // Rectangle of drawing area. 
	 
	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