A logo Bitmap Inside a Client Frame

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


Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.

  • Following an IT incident through to resolution is more than just acknowledging an alert and restarting a server. The recent State of On-Call Report found that it takes most companies an average of 10-30 minutes to resolve an incident with an average of 5 people involved. Imagine how much money and time companies are spending to deal with incident resolution. But what if you had a tool that offered solutions baked in? Or a tool that sent alerts to the right person or team every time? These are the kind of …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date