CStatic with bitmap sensitive to change in system colours

If an icon is used in a static control, it is sensitive to changes in the system colours. This means that areas of the icon that have background colour, is updated with the new background colour etc.

As far as I can see, there is not the same if instead a bitmap is used in the static control. Here is a small class that adds this functionality for bitmaps. This is useful if for instance you add your non-square logo in the About dialog box.

The example figures are from the Database Sample (Repeater Frequency Index) by Eric Hoagland.

Without the CSysColStatic

With the CSysColStatic

To use the class you add a member variable to you dialog header:

protected:
CSysColStatic m_Static;

Then you add the following to OnInitDialog:

BOOL CMyApp::OnInitDialog()
{
	CDialog::OnInitDialog();

	m_Static.SubclassDlgItem(IDC_ARROW_STATIC,this);
	m_Static.ReloadBitmap(IDB_BITMAP1);

The last statement makes the static control reload the bitmap given by IDB_BITMAP1 with correct system colours.

The implementation of the static subclass is very simple:

#if !defined(AFX_SYSCOLSTATIC_H__664DE301_4F7B_11D1_9E3D_00A0245800CF__INCLUDED_)
#define AFX_SYSCOLSTATIC_H__664DE301_4F7B_11D1_9E3D_00A0245800CF__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// SysColStatic.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CSysColStatic window

class CSysColStatic : public CStatic
{
// Construction
public:
	CSysColStatic();
	void ReloadBitmap(int nImageID = -1);
// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CSysColStatic)
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CSysColStatic();

	// Generated message map functions
protected:
	int m_nImageID;
	//{{AFX_MSG(CSysColStatic)
	afx_msg void OnSysColorChange();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SYSCOLSTATIC_H__664DE301_4F7B_11D1_9E3D_00A0245800CF__INCLUDED_)

ReloadBitmap reloads the bitmap identified by m_nImageID. ReloadBitmap is also used to set m_nImageID because I have not found a way to automatically extract the bitmap ID from the control. By loading the bitmap with LoadImage using the LR_LOADMAP3DCOLORS style, the colour changes are done automatically.

A handler is added to respond to WM_SYSCOLORCHANGE messages. It simply calls ReloadBitmap without any arguments.

// SysColStatic.cpp : implementation file
//

#include "stdafx.h"
#include "myapp.h"
#include "SysColStatic.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSysColStatic

CSysColStatic::CSysColStatic()
{
	m_nImageID == -1;
}

CSysColStatic::~CSysColStatic()
{
}

void CSysColStatic::ReloadBitmap(int nImageID)
{
	if(nImageID != -1)
		m_nImageID = nImageID;

	if(m_nImageID == -1)
		return;

	HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(), 
            MAKEINTRESOURCE(m_nImageID), IMAGE_BITMAP, 0,0, LR_LOADMAP3DCOLORS );

	if( hBmp == NULL )
		return;

	hBmp = SetBitmap(hBmp);
	if(hBmp != NULL)
		::DeleteObject(hBmp);
}

BEGIN_MESSAGE_MAP(CSysColStatic, CStatic)
	//{{AFX_MSG_MAP(CSysColStatic)
	ON_WM_SYSCOLORCHANGE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSysColStatic message handlers

void CSysColStatic::OnSysColorChange() 
{
	CStatic::OnSysColorChange();
	
	ReloadBitmap();	
}