Click here to Skip to main content
15,892,809 members
Articles / Desktop Programming / WTL

Norm Almond CLabel Class Port to ATL/WTL

Rate me:
Please Sign up or sign in to vote.
3.00/5 (9 votes)
24 Jan 2001 74.1K   1.8K   27  
A fully stocked owner drawn CStatic class for WTL
/////////////////////////////////////////////////////////////////////////////
//
// Original CLabel Class written by Norm Almond
//
/////////////////////////////////////////////////////////////////////////////
//
// CLabel Version 1.2
//
// From now on I'll try to keep a log of fixes and enhancements...
// 
// The new feature were added due to the response of people.
// All I ask is to all you programmers out there, is if you add, fix or
// enhance this code, sent me a copy and I'll send the copy on to www.codeproject.com
//
// Happy Software Engineer :)
// 
// New features include:
//
// A. Support for 3D Fonts
// B. Support for background transparency
// C. More comments provided
// D. If alignment is 'centered' and the window text is seperated by '\r\n'
//	  the will be centered accordingly - requested by someone @ nasa ;)
// E. Support for font rotation.
// F. Respond to System Color Change
// G. OnPaint improved performance - using Double Buffering Technique
//
// Thanks to:
// Mark McDowell	- For suggestion on 'Increasing the flexibility of "hypertext" setting...'
// Erich Ruth		- For suggestion on 'Font Rotation'
//

/////////////////////////////////////////////////////////////////////////////
// CLabel Version 1.3
//
// A. Added SS_LEFTNOWORDWRAP to include wordwrap
// B. Fix repainting problem 
// C. Fix SetBkColor
// D. Added SS_CENTER

// Thanks to:
// Marius						- Added styling problem.
// Azing Vondeling & Broker		- Spotting painting Problem.
// Mel Stober					- Back Color & SS_CENTER
// 
/////////////////////////////////////////////////////////////////////////////
// CLabel Version 1.4
//
// A. Fix to transparency mode
// B. Added new SetText3DHiliteColor to change the 3D Font face color - default is white.
// 
// Thanks to:
// michael.groeger				- Spotting Transparency with other controls bug.
//
//
/////////////////////////////////////////////////////////////////////////////
// CLabel Version 1.5
//
// A. Sanity handle check
// B. Support Interface Charset
// C. Check compilition with _UNICODE
// D. Fix hyperlink feature
// E. Support default Dialog Font
// F. Inclusion of SS_OWNERDRAW via control creation and subclassing
// G. Modification to Text aligmnent code
// H. New background gradient fill function
// 
// Thanks to:
// Steve Kowald				- Using null handles 
// Alan Chan				- Supporting International Windows
// Dieter Fauth				- Request for default Dialog font
// Herb Illfelder			- Text Alignment code
// 
//
/////////////////////////////////////////////////////////////////////////////
// CLabel Version 1.5a
//
// A. Port to ATL / WTL (Rashid Thadha) 10/12/2000
// 
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(ATL_LABEL_H)
#define ATL_LABEL_H

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

#define	NM_LINKCLICK	WM_APP + 0x200
#if (WINVER < 0x0500)
__declspec(selectany) struct
{
	enum { cxWidth = 32, cyHeight = 32 };
	int xHotSpot;
	int yHotSpot;
	unsigned char arrANDPlane[cxWidth * cyHeight / 8];
	unsigned char arrXORPlane[cxWidth * cyHeight / 8];
} _AtlLabel_CursorData = 
{
	5, 0, 
	{
		0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 
		0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 
		0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 
		0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 
		0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 
		0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
	},
	{
		0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
		0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00, 
		0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00, 
		0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 
		0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 
		0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	}
};
#endif //(WINVER < 0x0500)

// =============================================================================================
// CLabel window

class CLabel :	public CWindowImpl<CLabel, CStatic>
			                   
{
// Construction
public:
	static enum FlashType {None, Text, Background };
	static enum Type3D { Raised, Sunken};
	static enum BackFillMode { Normal, Gradient };

	BEGIN_MSG_MAP(CLabel)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_TIMER, OnTimer)
		MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
	END_MSG_MAP()

	// =============================================================================================
	// Function name	: CLabel::CLabel
	// Description	    : Default contructor
	// Return type		: 
	// =============================================================================================
	CLabel::CLabel() :	m_bPaintLabel(true), m_hBackBrush(NULL), m_crHiColor(0), m_crLoColor(0),
						m_bTimer(FALSE), m_bState(FALSE), m_bTransparent(FALSE), m_bLink(TRUE),
						m_hCursor(NULL), m_Type(None), m_bFont3d(FALSE), m_bNotifyParent(FALSE),
						m_bToolTips(FALSE), m_bRotation(FALSE), m_fillmode(Normal), m_hFont(NULL)
	{
		m_crText = GetSysColor(COLOR_WINDOWTEXT);
		m_cr3DHiliteColor =	RGB(255,255,255);		
		m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE));
	}

	// =============================================================================================
	// Function name	: ~CLabel
	// Description	    : Destructor
	// Return type		: virtual 
	// =============================================================================================
	virtual ~CLabel()
	{
		if(m_hFont != NULL)
			::DeleteObject(m_hFont);
		if (m_hwndBrush)
			::DeleteObject(m_hwndBrush);

		// Stop Checking complaining
		if (m_hBackBrush)
			::DeleteObject(m_hBackBrush);
		
#if (WINVER < 0x0500)
		// It was created, not loaded, so we have to destroy it
		if(m_hCursor != NULL)
			::DestroyCursor(m_hCursor);
#endif //(WINVER < 0x0500)
	}

	// =============================================================================================
	// Function name	: SetBkColor
	// Description	    : Sets background color
	// Return type		: Reference to 'this' object
	// Argument         : COLORREF crBkgnd
	// Argument         : COLORREF crBkgndHigh = 0
	// Argument         : BackFillMode mode = Normal
	// =============================================================================================
	virtual CLabel& SetBkColor(COLORREF crBkgnd, COLORREF crBkgndHigh = 0, BackFillMode mode = Normal)
	{
		m_crLoColor = crBkgnd;
		m_crHiColor = crBkgndHigh;

		m_fillmode = mode;

		if (m_hBackBrush)
			::DeleteObject(m_hBackBrush);
		
		if (m_fillmode == Normal)
			m_hBackBrush = ::CreateSolidBrush(crBkgnd);

		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: SetTextColor
	// Description	    : Sets the text color
	// Return type		: Reference to 'this' object
	// Argument         : COLORREF crText
	// =============================================================================================
	virtual CLabel& SetTextColor(COLORREF crText)
	{
		m_crText = crText;		
		UpdateSurface();
		
    return *this;
	}

	// =============================================================================================
	// Function name	: SetText
	// Description	    : Short cut to set window text - caption - label
	// Return type		: Reference to 'this' object
	// Argument         : const CString& strText
	// =============================================================================================
	virtual CLabel& SetText(const CString& strText)
	{
		SetWindowText(strText);
		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: SetFontBold
	// Description	    : Sets the font ot bold 
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bBold
	// =============================================================================================
	virtual CLabel& SetFontBold(BOOL bBold)
	{	

		m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
		ReconstructFont();
		UpdateSurface();
		return *this;
	}
	
	// =============================================================================================
	// Function name	: SetFontName
	// Description	    : Sets the fonts face name
	// Return type		: Reference to 'this' object
	// Argument         : const CString& strFont
	// Argument         : BYTE byCharSet = ANSI_CHARSET
	// =============================================================================================
	virtual CLabel& SetFontName(const CString& strFont, BYTE byCharSet = ANSI_CHARSET)
	{	
		m_lf.lfCharSet = byCharSet;

		_tcscpy(m_lf.lfFaceName,strFont);
		ReconstructFont();
		UpdateSurface();

		return *this;
	}
	
	// =============================================================================================
	// Function name	: SetFontUnderline
	// Description	    : Sets font underline attribue
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// =============================================================================================
	virtual CLabel& SetFontUnderline(BOOL bSet)
	{	
		m_lf.lfUnderline = bSet;
		ReconstructFont();
		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: SetFontItalic
	// Description	    : Sets font italic attribute 
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// =============================================================================================
	virtual CLabel& SetFontItalic(BOOL bSet)
	{
		m_lf.lfItalic = bSet;
		ReconstructFont();
		UpdateSurface();

		return *this;	
	}

	// =============================================================================================
	// Function name	: SetFontSize
	// Description	    : Sets the font size 
	// Return type		: Reference to 'this' object
	// Argument         : int nSize
	// =============================================================================================
	virtual CLabel& SetFontSize(int nSize)
	{
		CFont cf;
		LOGFONT lf;

		cf.CreatePointFont(nSize * 10, m_lf.lfFaceName);
		cf.GetLogFont(&lf);

		m_lf.lfHeight = lf.lfHeight;
		m_lf.lfWidth  = lf.lfWidth;

		ReconstructFont();
		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: SetSunken
	// Description	    : Sets sunken effect on border
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// =============================================================================================
	virtual CLabel& SetSunken(BOOL bSet)
	{

		if (!bSet)
			ModifyStyleEx(WS_EX_STATICEDGE,0,SWP_DRAWFRAME);
		else
			ModifyStyleEx(0,WS_EX_STATICEDGE,SWP_DRAWFRAME);
			
		return *this;	
	}

	// =============================================================================================
	// Function name	: SetBorder
	// Description	    : Toggles the border on/off
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// =============================================================================================
	virtual CLabel& SetBorder(BOOL bSet)
	{

		if (!bSet)
			ModifyStyle(WS_BORDER,0,SWP_DRAWFRAME);
		else
			ModifyStyle(0,WS_BORDER,SWP_DRAWFRAME);
			
		return *this;	
	}

	// =============================================================================================
	// Function name	: SetTransparent
	// Description	    : Sets the Label window to be transpaent
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// =============================================================================================
	virtual CLabel& SetTransparent(BOOL bSet)
	{

		m_bTransparent = bSet;
		ModifyStyleEx(0,WS_EX_TRANSPARENT); // Fix for transparency
		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: FlashText
	// Description	    : As the function states
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bActivate
	// =============================================================================================
	virtual CLabel& FlashText(BOOL bActivate)
	{
		if (m_bTimer)
			KillTimer(1);

		if (bActivate)
		{
			m_bState = FALSE;			
			m_bTimer = TRUE;			
			SetTimer(1,500);
			m_Type = Text;
		}
		else
			m_Type = None; // Fix

		return *this;
	}

	// =============================================================================================
	// Function name	: FlashBackground
	// Description	    : As the function states
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bActivate
	// =============================================================================================
	virtual CLabel& FlashBackground(BOOL bActivate)
	{

		if (m_bTimer)
			KillTimer(1);

		if (bActivate)
		{
			m_bState = FALSE;

			m_bTimer = TRUE;
			SetTimer(1,500);

			m_Type = Background;
		}

		return *this;
	}

	// =============================================================================================
	// Function name	: SetLink
	// Description	    : Indicates the string is a link
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bLink
	// Argument         : BOOL bNotifyParent
	// =============================================================================================
	virtual CLabel& SetLink(BOOL bLink,BOOL bNotifyParent)
	{

		m_bLink = bLink;
		m_bNotifyParent = bNotifyParent;

		if (bLink)
			ModifyStyle(0,SS_NOTIFY);
		else
			ModifyStyle(SS_NOTIFY,0);

		return *this;
	}

	// =============================================================================================
	// Function name	: SetLinkCursor
	// Description	    : Sets the internet browers link
	// Return type		: Reference to 'this' object
	// =============================================================================================
	virtual CLabel& SetLinkCursor()
	{
    // create or load a cursor
#if (WINVER >= 0x0500)
		m_hCursor = ::LoadCursor(NULL, IDC_HAND);
#else
		m_hCursor = ::CreateCursor(_Module.GetModuleInstance(), _AtlLabel_CursorData.xHotSpot, _AtlLabel_CursorData.yHotSpot, _AtlLabel_CursorData.cxWidth, _AtlLabel_CursorData.cyHeight, _AtlLabel_CursorData.arrANDPlane, _AtlLabel_CursorData.arrXORPlane);
#endif //!(WINVER >= 0x0500)
		ATLASSERT(m_hCursor != NULL);
		return *this;
	}

	// =============================================================================================
	// Function name	: SetFont3D
	// Description	    : Sets the 3D attribute of the font.
	// Return type		: Reference to 'this' object
	// Argument         : BOOL bSet
	// Argument         : Type3D type=Raised
	// =============================================================================================
	virtual CLabel& SetFont3D(BOOL bSet,Type3D type=Raised)
	{

		m_bFont3d = bSet;
		m_3dType = type;
		UpdateSurface();


		return *this;
	}

	// =============================================================================================
	// Function name	: SetRotationAngle
	// Description	    : Sets the rotation angle for the current font.
	// Return type		: Reference to 'this' object
	// Argument         : UINT nAngle
	// Argument         : BOOL bRotation
	// =============================================================================================
	virtual CLabel& SetRotationAngle(UINT nAngle,BOOL bRotation)
	{
		// Arrrrh...
		// Your looking in here why the font is rotating, aren't you?
		// Well try setting the font name to 'Arial' or 'Times New Roman'
		// Make the Angle 180 and set bRotation to true.
		//
		// Font rotation _ONLY_ works with TrueType fonts...
		//
		// 
		m_lf.lfEscapement = m_lf.lfOrientation = (nAngle * 10);
		m_bRotation = bRotation;
		
		ReconstructFont();		
		UpdateSurface();

		return *this;
	}

	// =============================================================================================
	// Function name	: SetText3DHiliteColor
	// Description	    : Sets the 3D font hilite color
	// Return type		: Reference to 'this' object
	// Argument         : COLORREF cr3DHiliteColor
	// =============================================================================================
	virtual CLabel& SetText3DHiliteColor(COLORREF cr3DHiliteColor)
	{
		m_cr3DHiliteColor = cr3DHiliteColor;
		UpdateSurface();


		return *this;
	}


	// =============================================================================================
	// Function name	: SubclassWindow
	// Description	    : 
	// Return type		: BOOL 
	// Argument         : HWND hWnd
	// =============================================================================================
	BOOL SubclassWindow(HWND hWnd)
	{
		BOOL bRet = CWindowImpl<CLabel, CStatic>::SubclassWindow(hWnd);
		if(bRet)
			Init();
		return bRet;
	}

protected:
	
	// =============================================================================================
	// Function name	: UpdateSurface
	// Description	    : 
	// Return type		: void 
	// =============================================================================================
	void UpdateSurface()
	{
		CRect (rc);
		GetWindowRect(rc);
		RedrawWindow();

		CWindow parent(GetParent());
		parent.ScreenToClient(rc);
		parent.InvalidateRect(rc,TRUE);
		parent.UpdateWindow();
	}

	// =============================================================================================
	// Function name	: ReconstructFont
	// Description	    : Helper function to build font after it was changed
	// Return type		: void 
	// =============================================================================================
	void ReconstructFont()
	{
		if(m_hFont != NULL)
		{
			::DeleteObject(m_hFont);
			m_hFont = NULL;
		}
		m_hFont = ::CreateFontIndirect(&m_lf);

		ATLASSERT(m_hFont);
	}

	// =============================================================================================
	// Function name	: DrawGradientFill
	// Description	    : Internal help function to gradient fill background
	// Return type		: void 
	// Argument         : CDC* pDC
	// Argument         : CRect* pRect
	// Argument         : COLORREF crStart
	// Argument         : COLORREF crEnd
	// Argument         : int nSegments
	// =============================================================================================
	void DrawGradientFill(CDC* pDC, CRect* pRect, COLORREF crStart, COLORREF crEnd, int nSegments)
	{
		// Get the starting RGB values and calculate the incremental
		// changes to be applied.

		COLORREF cr;
		int nR = GetRValue(crStart);
		int nG = GetGValue(crStart);
		int nB = GetBValue(crStart);

		int neB = GetBValue(crEnd);
		int neG = GetGValue(crEnd);
		int neR = GetRValue(crEnd);

		if(nSegments > pRect->Width())
			nSegments = pRect->Width();

		int nDiffR = (neR - nR);
		int nDiffG = (neG - nG);
		int nDiffB = (neB - nB);

		int ndR = 256 * (nDiffR) / (max(nSegments,1));
		int ndG = 256 * (nDiffG) / (max(nSegments,1));
		int ndB = 256 * (nDiffB) / (max(nSegments,1));

		nR *= 256;
		nG *= 256;
		nB *= 256;

		neR *= 256;
		neG *= 256;
		neB *= 256;

		int nCX = pRect->Width() / max(nSegments,1), nLeft = pRect->left, nRight;
		pDC->SelectStockPen(NULL_PEN);

		for (int i = 0; i < nSegments; i++, nR += ndR, nG += ndG, nB += ndB)
		{
			// Use special code for the last segment to avoid any problems
			// with integer division.

			if (i == (nSegments - 1))
				nRight = pRect->right;
			else
				nRight = nLeft + nCX;

			cr = RGB(nR / 256, nG / 256, nB / 256);
			
			{
				CBrush br;
				br.CreateSolidBrush(cr);
				HBRUSH pbrOld = pDC->SelectBrush(br);
				pDC->Rectangle(nLeft, pRect->top, nRight + 1, pRect->bottom);
				pDC->SelectBrush(pbrOld);
			}

			// Reset the left side of the drawing rectangle.

			nLeft = nRight;
		}
	}

	COLORREF		m_crText;
	COLORREF		m_cr3DHiliteColor;
	HBRUSH			m_hwndBrush;
	HBRUSH			m_hBackBrush;
	LOGFONT			m_lf;
	HFONT			m_hFont;
	CString			m_strText;
	BOOL			m_bState;
	BOOL			m_bTimer;
	BOOL			m_bLink;
	BOOL			m_bTransparent;
	BOOL			m_bFont3d;
	BOOL			m_bToolTips;
	BOOL			m_bNotifyParent;
	BOOL			m_bRotation;
	BOOL      m_bPaintLabel;
	FlashType		m_Type;
	HCURSOR			m_hCursor;
	Type3D			m_3dType;
	BackFillMode	m_fillmode;
	COLORREF		m_crHiColor;
	COLORREF		m_crLoColor;

protected:

	// =============================================================================================
	// Function name	: OnPaint
	// Description	    : Handles all the drawing code for the label
	//					: Called by Windows... not by USER
	// Return type		: LRESULT 
	// Argument         : UINT
	// Argument         : WPARAM wParam
	// Argument         : LPARAM
	// Argument         : BOOL& bHandled
	// =============================================================================================
	LRESULT OnPaint(UINT, WPARAM wParam, LPARAM, BOOL& bHandled)
	{
		if(!m_bPaintLabel)
		{
			bHandled = FALSE;
			return 1;
		}
		
		CPaintDC dc(m_hWnd); // device context for painting

		DWORD dwFlags = 0;

		CRect rc;
		GetClientRect(rc);
		TCHAR cValue[1000];
		GetWindowText(cValue, sizeof(cValue));
		CString strText(cValue);
		CBitmap bmp;

		// Set up for double buffering...	
		CDC* pDCMem;

		if (!m_bTransparent)
		{
			pDCMem = new CDC;
			pDCMem->CreateCompatibleDC(dc.m_hDC);
			bmp.CreateCompatibleBitmap(dc.m_hDC,rc.Width(),rc.Height());
			pDCMem->SelectBitmap(bmp);
		}
		else
		{
			pDCMem = &dc;
		}

		UINT nMode = pDCMem->SetBkMode(TRANSPARENT);

		COLORREF crText = pDCMem->SetTextColor(m_crText);
		HFONT OldTempFont;
		if(m_hFont != NULL)
			OldTempFont = pDCMem->SelectFont(m_hFont);
		
		// Fill in backgound if not transparent
		if (!m_bTransparent)
		{
			if (m_fillmode == Normal)
			{
				CBrush br;
				
				if (m_hBackBrush != NULL)
					br.Attach(m_hBackBrush);
				else
					br.Attach(m_hwndBrush);
						
				pDCMem->FillRect(rc,br);

				br.Detach();
			}
			else // Gradient Fill
			{
				DrawGradientFill(pDCMem, &rc, m_crLoColor, m_crHiColor, 100);
			}

		}

		// If the text is flashing turn the text color on
		// then to the color of the window background.

		LOGBRUSH lb;
		ZeroMemory(&lb,sizeof(lb));

		// Stop Checking complaining
		if (m_hBackBrush)
			::GetObject(m_hBackBrush,sizeof(lb),&lb);


		// Something to do with flashing
		if (!m_bState && m_Type == Text)
			pDCMem->SetTextColor(lb.lbColor);

		DWORD style = GetStyle();
		
		switch (style & SS_TYPEMASK)
		{
			case SS_RIGHT: 
				dwFlags = DT_RIGHT | DT_WORDBREAK; 
				break; 
			
			case SS_CENTER: 
				dwFlags = SS_CENTER | DT_WORDBREAK;
				break;

			case SS_LEFTNOWORDWRAP: 
				dwFlags = DT_LEFT; 
				break;

			default: // treat other types as left
				case SS_LEFT: 
					dwFlags = DT_LEFT | DT_WORDBREAK; 
					break;
		}	

			
		// If the text centered make an assumtion that
		// the will want to center verticly as well
		if (style & SS_CENTERIMAGE)
		{
			dwFlags = DT_CENTER;

			// Apply 
			if (strText.Find(_T("\r\n")) == -1)
			{
				dwFlags |= DT_VCENTER;

				// And because DT_VCENTER only works with single lines
				dwFlags |= DT_SINGLELINE; 
			}
		}

		//
		// 3333   DDDDD
		//     3  D    D
		//   33   D     D    E F X 
		//     3  D    D
		// 3333   DDDDD
		//
		//
		if (m_bRotation)
		{
			int nAlign = pDCMem->SetTextAlign (TA_BASELINE);

			CPoint pt;
			GetViewportOrgEx (pDCMem->m_hDC,&pt) ;
			SetViewportOrgEx (pDCMem->m_hDC,rc.Width() / 2, rc.Height() / 2, NULL) ;
			pDCMem->TextOut (0, 0, strText) ;
			SetViewportOrgEx (pDCMem->m_hDC,pt.x / 2, pt.y / 2, NULL) ;
			pDCMem->SetTextAlign (nAlign);
		}
		else
		{
			pDCMem->DrawText(cValue, -1,rc,dwFlags);
			if (m_bFont3d)
			{
				pDCMem->SetTextColor(m_cr3DHiliteColor);

				if (m_3dType == Raised)
					rc.OffsetRect(-1,-1);
				else
					rc.OffsetRect(1,1);

				pDCMem->DrawText(cValue, -1, rc,dwFlags);
				m_3dType;
			}
		}

		// Restore DC's State
		pDCMem->SetBkMode(nMode);
		pDCMem->SelectFont(OldTempFont);
		pDCMem->SetTextColor(crText);

		if (!m_bTransparent)
		{
			dc.BitBlt(0,0,rc.Width(),rc.Height(),pDCMem->m_hDC,0,0,SRCCOPY);
			delete pDCMem;
		}

		return 0;
	}

	// =============================================================================================
	// Function name	: OnTimer
	// Description	    : Used in conjunction with 'FLASH' functions
	// Return type		: LRESULT 
	// Argument         : UINT uMsg
	// Argument         : WPARAM wParam
	// Argument         : LPARAM lParam
	// Argument         : BOOL& bHandled
	// =============================================================================================
	LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{

		m_bState = !m_bState;

		UpdateSurface();
		
		return 0;
	}

	// =============================================================================================
	// Function name	: OnSysColorChange
	// Description	    : 
	// Return type		: LRESULT 
	// Argument         : UINT uMsg
	// Argument         : WPARAM wParam
	// Argument         : LPARAM lParam
	// Argument         : BOOL& bHandled
	// =============================================================================================
	LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{

		if (m_hwndBrush)
			::DeleteObject(m_hwndBrush);

		m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE));
		
		UpdateSurface();
		return 0;		
	}

	// =============================================================================================
	// Function name	: OnLButtonDown
	// Description	    : Called when a link is click on
	// Return type		: LRESULT 
	// Argument         : UINT uMsg
	// Argument         : WPARAM wParam
	// Argument         : LPARAM lParam
	// Argument         : BOOL& bHandled
	// =============================================================================================
	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{

		if (!m_bNotifyParent) // Fix
		{
			TCHAR cValue[1000];
			GetWindowText(cValue, sizeof(cValue));
			CString strLink(cValue);
			ShellExecute(NULL,_T("open"),strLink,NULL,NULL,SW_SHOWNORMAL);
		}
		else
		{
			// To use notification in parent window
			// Respond to a OnNotify in parent and disassemble the message
			//
			NMHDR nm;

			nm.hwndFrom = m_hWnd;
			nm.idFrom  = GetDlgCtrlID();
			nm.code = NM_LINKCLICK;
			CWindow wnd(GetParent());
			wnd.SendMessage(WM_NOTIFY,nm.idFrom,(LPARAM) &nm);
		}
			
		return 0;
	}
	
	// =============================================================================================
	// Function name	: OnSetCursor
	// Description	    : Used in conjunction with 'LINK' function
	// Return type		: LRESULT 
	// Argument         : UINT uMsg
	// Argument         : WPARAM wParam
	// Argument         : LPARAM lParam
	// Argument         : BOOL& bHandled
	// =============================================================================================
	LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{

		if (m_hCursor)
		{
			::SetCursor(m_hCursor);
			return TRUE;
		}

		return 0;
	}


	// =============================================================================================
	// Function name	: Init
	// Description	    : 
	// Return type		: void 
	// =============================================================================================
	void Init()
	{
		ATLASSERT(::IsWindow(m_hWnd));

		// Check if we should paint a label
		TCHAR lpszBuffer[8];
		if(::GetClassName(m_hWnd, lpszBuffer, 8))
		{
			if(lstrcmpi(lpszBuffer, _T("static")) == 0)
			{
				ModifyStyle(0, SS_NOTIFY);	// we need this
				DWORD dwStyle = GetStyle() & 0x000000FF;
				if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT || 
						dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME || 
						dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW || 
						dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
					m_bPaintLabel = FALSE;
			}
		}

		// set font
		if(m_bPaintLabel)
		{
			CWindow wnd = GetParent();
			CFontHandle font = wnd.GetFont();
			if(font.m_hFont != NULL)
			{
				font.GetLogFont(&m_lf);
				m_hFont = ::CreateFontIndirect(&m_lf);
			}
		}
	}
};

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

#endif // !defined(ATL_LABEL_H)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
Was made redundant in early 2003 after 10 years in computer programming, since then started my own business (selling computer books on the net)
www.pricecutbook.co.uk


Comments and Discussions