Click here to Skip to main content
15,861,168 members
Articles / Desktop Programming / MFC

Resource ID Organiser Add-In for Visual C++ 5.0/6.0/.NET

Rate me:
Please Sign up or sign in to vote.
4.98/5 (71 votes)
10 Jan 2005CPOL25 min read 527.5K   12.1K   201  
An application/add-in to organise and renumber resource symbol IDs
/*****************************************************************************
 *
 * Class:			CNGStatusBarPaneInfo, CNGStatusBar
 * Files:			CNGStatusBar.Cpp, CNGStatusBar.H
 * Description:	With this class complex status lines can be administered. 
 *					So can be represented in each Pane texts, bit-maps or 
 *					progress Bars, be gescrollt horizontal, vertically or diagonally 
 *					and be aligned left, on the right or centered. Also each time 
 *					between the individual modes can be shifted up and down. 
 *					For each Pane can be defined both switching on on and a switching 
 *					off text, - background or - bit-map. 
 *					
 * Functions:		operator=(), SetDefault(), SetFont(), SetMode(), 
 * (CNGStatusBarPaneInfo)		SetFgColor(), SetBkColor(), SetBitmap(), SetText(), 
 *					SetNumber(), HScroll(), VScroll(), 
 * Functions:		CreateStatusBar(), SetIndicators(), OnPaint(), 
 * (CNGStatusBar)		DrawSizing(), DrawTextPane(), DrawBitmapPane(), 
 *					DrawProgressPane(), GetCNGStatusBarPaneInfo(), OnTimer(), 
 *					SetStyle(), SetWidth(), GetStyle(), GetWidth(), GetID(), 
 *					OnDestroy(), SavePane(), RestorePane(), 
 *					GetPaneAtPosition(), OnMouseMove(),
 *					OnLButtonUp(), OnMButtonUp(), OnRButtonUp(), 
 *					OnLButtonDown(), OnMButtonDown(), OnRButtonDown(),
 *					OnLButtonDblClk(), OnMButtonDblClk(), OnRButtonDblClk(),
 *
 ****************************************************************************/

#include "StdAfx.h"
#include "NGStatusBar.h"

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

volatile static char jrrcid[] = "%J%";

#define IDC_JRLIB_STATUSBAR_TIMER	20000

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	CNGStatusBarPaneInfo, ~CNGStatusBarPaneInfo
 * Parameter:	-
 * Return:		
 *
 * The constructor initialize a Pane. In the Desturktor a possibly 
 * available progress check is again deleted. 
 * 
 ****************************************************************************/
CNGStatusBarPaneInfo::CNGStatusBarPaneInfo()
{
	progress	= NULL;
	hScrollPos	= 0;
	vScrollPos	= 0;

	SetDefault();
}

CNGStatusBarPaneInfo::CNGStatusBarPaneInfo(const CNGStatusBarPaneInfo& paneInfo)
{
	for (int i = 0; i < 2; i++)
	{
		fgColor[i]	= paneInfo.fgColor[i];
		bkColor[i]	= paneInfo.bkColor[i];
		string[i]	= paneInfo.string[i];
	}

	font			= paneInfo.font;
	mode			= paneInfo.mode;
	progress		= NULL;
	hScrollPos		= paneInfo.hScrollPos;
	vScrollPos		= paneInfo.vScrollPos;
}

CNGStatusBarPaneInfo::~CNGStatusBarPaneInfo()
{
	if (progress)	delete progress;
	progress = NULL;
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	operator=
 * Parameter:	paneInfo	Zweites CNGStatusBarPaneInfo-Element, dessen Informationen
 *							kopiert werden.
 * Return:		Kopie des CNGStatusBarPaneInfo-Elements
 *
 * Allocation operator!!! NOTE!!! ' progress ' is not copied! Possibly
 * available progress bar one deletes 
 * 
 * 
 ****************************************************************************/
CNGStatusBarPaneInfo CNGStatusBarPaneInfo::operator=(const CNGStatusBarPaneInfo& paneInfo)
{
	for (int i = 0; i < 2; i++)
	{
		fgColor[i]	= paneInfo.fgColor[i];
		bkColor[i]	= paneInfo.bkColor[i];
		string[i]	= paneInfo.string[i];
	}

	font			= paneInfo.font;
	mode			= paneInfo.mode;
	hScrollPos		= paneInfo.hScrollPos;
	vScrollPos		= paneInfo.vScrollPos;

	if (progress)	delete progress;
	progress = NULL;

	return *this;
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetDefault
 * Parameter:	-
 * Return:		-
 *
 * Here the Members is initialized
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetDefault()
{
	bkColor[1]	= COLORREF(GetSysColor(COLOR_3DFACE));
	bkColor[0]	= bkColor[1];

	fgColor[1]	= GetSysColor(COLOR_BTNTEXT);
	fgColor[0]	= RGB(GetRValue(bkColor[1])/2, GetGValue(bkColor[1])/2, GetBValue(bkColor[1])/2);

	mode		= XSB_TEXT | DT_LEFT;
	SetFont(CFont::FromHandle((HFONT) GetStockObject(ANSI_VAR_FONT)));

	if (progress)	delete progress;
	progress = NULL;
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetFont
 * Parameter:	name	Name der Schriftart (Bsp.: Arial)
 *				size	Gr��e der Schriftart in 1/10 Pt (Bsp.: 120)
 * Return:		-
 * 
 * The Font for a Pane sets on the basis the font name and the point size 
 * (10 * Point).
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetFont(LPCSTR name, int size)
{
	CFont pointFont;
	pointFont.CreatePointFont(size, name);
	pointFont.GetLogFont(&font);
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetMode
 * Parameter:	newMode		Neuer Anzeigemodus
 * Return:		-
 * 
 * Sets the mode for the current Pane. If this Pane were filled with progress 
 * CTRL before, this is deleted before.  
 * 
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetMode(int newMode)
{
	if ((mode = newMode) & XSB_PROGRESS)
	{
		if (!progress)
		{
			UINT style = WS_VISIBLE | WS_CHILD;
			if (mode & XSB_SMOOTH) style |= PBS_SMOOTH;

			progress = new CProgressCtrl();
			progress->Create(style, CRect(0,0,0,0), CNGStatusBar::aktBar, 1);
		}
	}
	else if (progress)
	{
		delete progress;
		progress = NULL;
	}
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetFgColor
 * Parameter:	on		Text-Farbe im aktiven Zustand
 *				off		Text-Farbe im inaktiven Zustand
 * Return:		-
 *
 * Defines the colours for a displayed text. Here two colours for the active 
 * and the inactive status can be defined. If the second colour is forgotten, 
 * it is pre-defined with the half intensity of the background colour. 
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetFgColor(COLORREF on, COLORREF off)
{
	fgColor[1] = on;

	if (off != -1)
		fgColor[0] = off;
	else
	{
		COLORREF bk = GetSysColor(COLOR_3DFACE);
		fgColor[0] = RGB(GetRValue(bk)/2, GetGValue(bk)/2, GetBValue(bk)/2);
	}
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetBkColor
 * Parameter:	on		Hintergrundfarbe im aktiven Zustand
 *				off		Hintergrundfarbe im inaktiven Zustand
 * Return:		-
 *
 * Defines the background colours for a displayed text. Here two colours for 
 * the active and the inactive status can be defined. If the second colour is 
 * forgotten, it is pre-defined with the background colour. 
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetBkColor(COLORREF on, COLORREF off)
{
	bkColor[1] = on;
	if (off != -1)	bkColor[0] = off;
	else			bkColor[0] = GetSysColor(COLOR_3DFACE);
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	SetBitmap, SetText, SetNumber
 * Parameter:	newBitmap		Name des im Pane anzuzeigenden Bitmaps
 *				newText			Im Pane anzuzeigender Text
 *				newNumber		Im Pane anzuzeigende Nummer
 * Return:		-
 *
 * With these functions the bit-maps, texts or numbers for the display
 * in the current Pane are set. 
 ****************************************************************************/
void CNGStatusBarPaneInfo::SetBitmap(LPCSTR newOnBitmap, LPCSTR newOffBitmap)
{
	string[1]	= newOnBitmap;
	string[0]	= newOffBitmap;
}

void CNGStatusBarPaneInfo::SetText(LPCSTR newOnText, LPCSTR newOffText)
{
	string[1]	= newOnText;
	string[0]	= newOffText;
}

void CNGStatusBarPaneInfo::SetIconAndText(DWORD iconResourceID, LPCSTR text)
{
	string[1].Format("%d", iconResourceID);
	string[0]	= text;
}

void CNGStatusBarPaneInfo::SetNumber(int newOnNumber, int newOffNumber)
{
	string[1].Format("%d", newOnNumber);
	string[0].Format("%d", newOffNumber);
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	HScroll, VScroll
 * Parameter:	rect			Ausgaberechteck des aktuellen Panes
 *				maxWidth		Maximale Breite, bzw. H�he beim Scrollen
 *				maxHeight		(z. B. Textl�nge oder Bitmapbreite)
 *				nullValue		Wert f�r Turnaround
 * Return:		-
 *
 * Increments the respective Scrollvariable, so that the text or the bit-map 
 * of the current Panes is gescrollt represented. If the max. size is exceeded, 
 * the scrolling begins again from the front. 
 ****************************************************************************/
void CNGStatusBarPaneInfo::HScroll(CRect& rect, int maxWidth, int nullValue)
{
	if (++hScrollPos > maxWidth)	hScrollPos = nullValue;
	rect.left -= hScrollPos;
}

void CNGStatusBarPaneInfo::VScroll(CRect& rect, int maxHeight, int nullValue)
{
	if (++vScrollPos > maxHeight)	vScrollPos = nullValue;
	rect.top -= vScrollPos;
}

/*****************************************************************************
 * Klasse:		CNGStatusBarPaneInfo
 * Funktion:	Dump, AssertValid, operator<<
 * Parameter:	dc			CDumpContext
 *				paneInfo	Ausgabelement
 * Return:		-
 *
 * 
 * 
 * 
 ****************************************************************************/
#ifdef _DEBUG
void CNGStatusBarPaneInfo::Dump(CDumpContext& dc) const
{
	dc	<< "FgColor / BkColor / Value:\t"
	<< fgColor[1] << " - " << fgColor[0] << " / "
	<< bkColor[1] << " - " << bkColor[0] << " / "
	<< string[1]  << " - " << string[0]  << "\n"
	<< "Mode:\t"  << mode  << "\n";
}

void CNGStatusBarPaneInfo::AssertValid() const
{
	ASSERT((progress == NULL) || _CrtIsValidHeapPointer(progress));
}

CDumpContext& AFXAPI operator<<(CDumpContext& dc, CNGStatusBarPaneInfo& paneInfo)
{
	paneInfo.Dump(dc);
	return dc;
}
#endif // _DEBUG

//****************************************************************************
//****************************************************************************
//****************************************************************************

CNGStatusBar *CNGStatusBar::aktBar = NULL;

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	CNGStatusBar, ~CNGStatusBar
 * Parameter:	-
 * Return:		
 *
 * Constructor and Destructor.
 ****************************************************************************/
CNGStatusBar::CNGStatusBar()
{
	aktBar		= this;
	timerID		= 0;
}

CNGStatusBar::~CNGStatusBar()
{}


BEGIN_MESSAGE_MAP(CNGStatusBar, CStatusBar)
//{{AFX_MSG_MAP(CNGStatusBar)
ON_WM_DESTROY()
ON_WM_TIMER()
ON_WM_PAINT()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_RBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

int CNGStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CStatusBar::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	CStatusBarCtrl & rCtrl = GetStatusBarCtrl();
	rCtrl.SetMinHeight(22);

	m_ToolTip.Create(this, TTS_ALWAYSTIP );
	m_ToolTip.SetDelayTime(250); //delay before tip appears
	m_ToolTip.SetDelayTime(4000, TTDT_AUTOPOP); // linger time once tip is up

	m_IconImageList.Create(16,16,ILC_MASK|ILC_COLOR, 0, 1);
	return 0;
}


/////////////////////////////////////////////////////////////////////////////
// PreTranslateMessage() - standard handler.
BOOL CNGStatusBar::PreTranslateMessage(MSG* pMsg) 
{
	// Because modal dialogs will cause all CToolTipCtrls to get deactivated,
	// the tool tip control needs to be manually reactivated.
	// TT 3 TT Step 6
	m_ToolTip.Activate(TRUE);

	// RelayEvent is required for CToolTipCtrl objects -
	// it passes mouse messages on to the tool tip control
	// so it can decide when to show the tool tip
	// TT 3 TT Step 4
	m_ToolTip.RelayEvent(pMsg);
	
	return CStatusBar::PreTranslateMessage(pMsg);
}




/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	CreateStatusBar
 * Parameter:	lpIDArray	Array mit den ID's der einzelnen Panes
 *				nIDCount	Anzahl der Panes in der Statuszeile
 *				pane0Style	Zusatzstyle f�r Pane 0 (normalerweise SBPS_STRETCH)
 * Return:		true wenn die Erzeugung erfolgreich war, sonst false
 *
 * Produces a status line at the lower edge of window. Here all necessary steps 
 * in a function are united: Produce the Toolbar, define the individual Panes, 
 * possibly a changing of the 0-Panes over. 
 ****************************************************************************/
bool CNGStatusBar::CreateStatusBar(CWnd *pWnd, const UINT* lpIDArray, int nIDCount, UINT pane0Style)
{
	bool ret = (Create(pParent = pWnd) &&
				SetIndicators(lpIDArray, nIDCount));

	if (ret)	SetStyle(0, pane0Style);
	else		AfxMessageBox("Unable to create Statusbar.");

	return ret;
}
/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	SetIndicators
 * Parameter:	lpIDArray
 *				nIDCount
 * Return:		BOOL
 *
 * This (overridden) function produces the einzlenen Panes and defines then 
 * for each Pane a CNGStatusBarPaneInfo variable in a list. Additionally a timer defined 
 * for scrolling. 
 ****************************************************************************/
BOOL CNGStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
	CNGStatusBarPaneInfo defaultInfo;
	paneInfo.RemoveAll();
	paneInfo.SetSize(nIDCount);

	for (int i = 0; i < nIDCount; i++)
		paneInfo[i] = defaultInfo;
	
	BOOL ret = CStatusBar::SetIndicators(lpIDArray, nIDCount);

	return ret;
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	OnPaint
 * Parameter:	-
 * Return:		-
 *
 * Here the actual status line is produced. For this first the background is 
 * deleted and drawn then on each Pane a 3D-Rechteck and output the information. 
 * Over flickering the picture to avoid takes place the entire output first in 
 * a MemoryDC and into the actual PaintDC is only then copied. 
 ****************************************************************************/
void CNGStatusBar::OnPaint()
{
	CPaintDC	dc(this);
	CRect		client;
	GetClientRect(client);
	CDC			memDC;
	memDC.CreateCompatibleDC(&dc);
	CBitmap		bitmap;
	bitmap.CreateCompatibleBitmap(&dc, client.Width(), client.Height());
	CBitmap		*oldBitmap	= (CBitmap *) memDC.SelectObject(&bitmap);
	COLORREF	hell		= GetSysColor(COLOR_3DHILIGHT);
	COLORREF	dunkel		= GetSysColor(COLOR_3DSHADOW);

	memDC.FillSolidRect(client, GetSysColor(COLOR_3DFACE));

	//========================================================================
	// Zeichne alle Pane-Rechtecke mit ihrem Inhalt
	//========================================================================
	bool scroll = false;
	for (int i = 0, n = paneInfo.GetSize(); i < n; i++)
	{
		CNGStatusBarPaneInfo &aktPane = paneInfo[i];

		CRect	rect;
		GetItemRect(i, rect);
		UINT style = GetPaneStyle(i);

		if (style & SBPS_POPOUT)
			memDC.Draw3dRect(rect, hell, dunkel);
		else if (!(style & SBPS_NOBORDERS))
			memDC.Draw3dRect(rect, dunkel, hell);

		on = (GetPaneStyle(i) & SBPS_DISABLED) == 0;

		rect.DeflateRect(1, 1);
		memDC.FillSolidRect(rect, aktPane.GetBkColor(on));

		CRgn clip;
		clip.CreateRectRgnIndirect(&rect);
		memDC.SelectClipRgn(&clip);

		rect.DeflateRect(1,1);

		switch (aktPane.GetMode() & XSB_MODE)
		{
			case XSB_TEXT:
			case XSB_NUMBER:
				DrawTextPane(	 &memDC, i, rect, aktPane);
				break;
			case XSB_BITMAP:
				DrawBitmapPane(	 &memDC, i, rect, aktPane);
				break;
			case XSB_ICON_AND_TEXT:
				DrawIconAndText( &memDC, i, rect, aktPane);
				break;
			case XSB_PROGRESS:
				DrawProgressPane(&memDC, i, rect, aktPane);
				break;
			default:
				break;
		}

		if (aktPane.GetMode() & XSB_SCROLL)	scroll = true;

		memDC.SelectClipRgn(NULL);
	}

	if (scroll  && (timerID == 0))
	{
		timerID = SetTimer(IDC_JRLIB_STATUSBAR_TIMER, 100, NULL);
	}
	else if (!scroll && (timerID != 0))
	{
		KillTimer(timerID);
		timerID = 0;
	}

	if (!GetParent()->IsZoomed())
	{
		DrawSizing(&memDC);
	}

	dc.BitBlt(0, 0, client.Width(), client.Height(), &memDC, 0, 0, SRCCOPY);

	memDC.SelectObject(oldBitmap);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	DrawSizing
 * Parameter:	pDC		aktueller Device-Kstring[1]
 * Return:		-
 *
 * This function draws the diagonal lines at the right, lower edge of window. 
 ****************************************************************************/
void CNGStatusBar::DrawSizing(CDC *pDC)
{
	CRect rect;
	GetWindowRect(&rect);
	rect.OffsetRect(-rect.left, -rect.top);

	CPen hellPen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
	CPen dunkelPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
	CPen *oldPen = pDC->SelectObject(&dunkelPen);
	for (int i = 1; i < 16; i++)
	{
		switch (i % 4)
		{
			case 0:
				pDC->SelectObject(&dunkelPen);
				break;
			case 1:
				pDC->SelectObject(&hellPen);
				break;
			case 2:
				continue;
			case 3:
				pDC->SelectObject(&dunkelPen);
				break;
		}

		CPoint from(rect.right-1 - i, rect.bottom-1);
		CPoint to(rect.right-1,       rect.bottom-1 - i);

		pDC->MoveTo(from);
		pDC->LineTo(to);
	}

	pDC->SelectObject(oldPen);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	DrawTextPane
 * Parameter:	pDC			Aktueller Device-Kstring[1]
 *				ix			Index des aktuellen Panes
 *				rect		Bounding Rectangle des aktuellen Panes
 *				aktPane		Aktueller Pane
 * Return:		-
 *
 * Outputs a text in a Pane. If required, can this text in horizontal and/or 
 * vertical direction are gescrollt or aligned left, on the right or centered. 
 * With the Scrollen several copies of the text secondary or one above the other 
 * can be set, so that a continuous movement develops. 
 ****************************************************************************/
void CNGStatusBar::DrawTextPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
	CString		text		= aktPane.GetText(on);

	if (text.IsEmpty())		
		text = GetPaneText(ix);

	if (text.IsEmpty())		
		return;

	CFont		font;
	font.CreateFontIndirect(&aktPane.GetFont());
	COLORREF	textColor	= aktPane.GetFgColor(on);
	CFont		*oldFont	= pDC->SelectObject(&font);
	int			oldBkMode	= pDC->SetBkMode(TRANSPARENT);
	COLORREF	oldFgColor	= pDC->SetTextColor(textColor);
	const int	mode		= aktPane.GetMode();
	const int	repeat		= mode & XSB_REPEAT;
	const int	hScroll		= mode & XSB_HSCROLL;
	const int	vScroll		= mode & XSB_VSCROLL;
	int			textAlign	= mode & XSB_ALIGN;
	
	if (hScroll)
		textAlign	&= ~(DT_CENTER | DT_RIGHT);

	if (repeat)
	{
		text += "  ";
		CSize s = pDC->GetTextExtent(text);
		
		if (hScroll)	
			aktPane.HScroll(rect, s.cx, 1);
		
		if (vScroll)	
			aktPane.VScroll(rect, s.cy, 1);

		int y = rect.top;
		if (hScroll && vScroll)
		{
			for ( ; rect.left <= rect.right; rect.left += s.cx)
			{
				for (rect.top = y ; rect.top <= rect.bottom; rect.top += s.cy)
				{
					pDC->DrawText(text, rect, textAlign);
				}
			}
		}
		else if (hScroll)
		{
			for ( ; rect.left <= rect.right; rect.left += s.cx)
			{
				pDC->DrawText(text, rect, textAlign);
			}
		}
		else if (vScroll)
		{
			for ( ; rect.top <= rect.bottom; rect.top += s.cy)
			{
				pDC->DrawText(text, rect, textAlign);
			}
		}
		else
		{
			pDC->DrawText(text, rect, textAlign);
		}
	}
	else
	{
		CSize s = pDC->GetTextExtent(text);
		
		if (hScroll)	
			aktPane.HScroll(rect, s.cx, -rect.Width());
		
		if (vScroll)	
			aktPane.VScroll(rect, s.cy, -rect.Height());

		pDC->DrawText(text, rect, textAlign);
	}

	pDC->SelectObject(oldFont);
	pDC->SetTextColor(oldFgColor);
	pDC->SetBkMode(oldBkMode);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	DrawIconAndText
 * Parameter:	pDC			Aktueller Device-Kstring[1]
 *				ix			Index des aktuellen Panes
 *				rect		Bounding Rectangle des aktuellen Panes
 *				aktPane		Aktueller Pane
 * Return:		-
 *
 * Outputs icon and text in a Pane.  
 ****************************************************************************/
void CNGStatusBar::DrawIconAndText(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
	CSize iconSize(16,16);
	int nIndex = m_IconImageList.AddIcon(aktPane.GetIcon());

	m_IconImageList.Draw(pDC, nIndex, rect.TopLeft(), ILD_NORMAL|ILD_TRANSPARENT);

	rect.left += iconSize.cx + 3;
	
	//::DestroyIcon(hIcon);

	CString		text		= aktPane.GetIconText();
	if (text.IsEmpty())		
	{
		text = GetPaneText(ix);
	}
	if (!text.IsEmpty())		
	{
		CFont		font;
		font.CreateFontIndirect(&aktPane.GetFont());
		COLORREF	textColor	= aktPane.GetFgColor(on);
		const int	mode		= aktPane.GetMode();
		CFont		*oldFont	= pDC->SelectObject(&font);
		int			oldBkMode	= pDC->SetBkMode(TRANSPARENT);
		COLORREF	oldFgColor	= pDC->SetTextColor(textColor);
		int			textAlign	= mode & XSB_ALIGN;
		

		CSize s = pDC->GetTextExtent(text);
		pDC->DrawText(text, rect, textAlign|DT_END_ELLIPSIS);
		pDC->SelectObject(oldFont);
		pDC->SetTextColor(oldFgColor);
		pDC->SetBkMode(oldBkMode);
	}

}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	DrawBitmapPane
 * Parameter:	pDC			Aktueller Device-Kstring[1]
 *				ix			Index des aktuellen Panes
 *				rect		Bounding Rectangle des aktuellen Panes
 *				aktPane		Aktueller Pane
 * Return:		-
 *
 * A bit-map in a Pane outputs. If, gescrollt can this bit-map in horizontal 
 * and/or vertical direction is required. The adjustment can take place left, 
 * on the right or centered or the bit-map can to the current Pane size be adapted 
 * (stretching). With the scrollen several pictures can be secondary or set, 
 * so that a continuous movement develops. 
 ****************************************************************************/
void CNGStatusBar::DrawBitmapPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
	UNUSED_ALWAYS(ix);

	CString		bmString	= aktPane.GetBitmap(on);
	if (bmString.IsEmpty())
		return;
	CDC			memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap		bitmap;
	bitmap.LoadBitmap(bmString);
	BITMAP		bm;
	bitmap.GetBitmap(&bm);

	CBitmap		*oldBitmap	= memDC.SelectObject(&bitmap);
	const int	mode		= aktPane.GetMode();
	const int	hScroll		= mode & XSB_HSCROLL;
	const int	vScroll		= mode & XSB_VSCROLL;
	const int	repeat		= mode & XSB_REPEAT;
	const int	stretch		= mode & XSB_STRETCH;

	if (repeat)
	{
		if (hScroll)	
			aktPane.HScroll(rect, bm.bmWidth, 1);

		if (vScroll)	
			aktPane.VScroll(rect, bm.bmHeight, 1);

		if (hScroll && !vScroll)
		{
			for (int x = rect.left; x < rect.right; x += bm.bmWidth)
			{
				pDC->BitBlt(x, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
			}
		}
		else if (vScroll && !hScroll)
		{
			for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
			{
				pDC->BitBlt(rect.left, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
			}
		}
		else
		{
			for (int x = rect.left; x < rect.right; x += bm.bmWidth)
			{
				for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
				{
					pDC->BitBlt(x, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
				}
			}
		}
	}
	else
	{
		if (hScroll)	
			aktPane.HScroll(rect, bm.bmWidth, -rect.Width());

		if (vScroll)	
			aktPane.VScroll(rect, bm.bmHeight, -rect.Height());

		if (hScroll || vScroll)
		{
			pDC->BitBlt(rect.left, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
		}
		else if (stretch)
		{
			pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
		}
		else
		{
			if (mode & DT_RIGHT)	
				rect.left	= rect.right - bm.bmWidth;

			if (mode & DT_CENTER)	
				rect.left	= (rect.left + rect.right - bm.bmWidth) / 2;

			if (mode & DT_BOTTOM)	
				rect.top	= rect.bottom - bm.bmHeight;

			if (mode & DT_VCENTER)	
				rect.top	= (rect.top + rect.bottom - bm.bmHeight) / 2;

			pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
		}
	}

	memDC.SelectObject(oldBitmap);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	DrawProgressPane
 * Parameter:	pDC			Aktueller Device-Kstring[1]
 *				ix			Index des aktuellen Panes
 *				rect		Bounding Rectangle des aktuellen Panes
 *				aktPane		Aktueller Pane
 * Return:		-
 *
 * This function draws the progress check. For this only the definition of the size is necessary. 
 ****************************************************************************/
void CNGStatusBar::DrawProgressPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
	UNUSED_ALWAYS(pDC);
	UNUSED_ALWAYS(aktPane);
	rect.InflateRect(1, 1);
	GetProgressCtrl(ix)->MoveWindow(rect, FALSE);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	GetCNGStatusBarPaneInfo
 * Parameter:	ix
 * Return:		CNGStatusBarPaneInfo&
 *
 * This function returns the CNGStatusBarPaneInfo variable for the current Pane as reference,
 * so that the Members of this variables can be changed directly. 
 ****************************************************************************/
CNGStatusBarPaneInfo& CNGStatusBar::GetCNGStatusBarPaneInfo(int ix)
{
	ASSERT(ix < GetCount());
	return paneInfo[ix];
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	OnTimer
 * Parameter:	nIDEvent	Aktuelle Timer-Event-ID
 * Return:		-
 *
 * After each timer vent ethose is again drawn status bar.
 ****************************************************************************/
void CNGStatusBar::OnTimer(UINT nIDEvent)
{
	if (nIDEvent == timerID)	Invalidate(FALSE);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	SetStyle, SetWidth, GetStyle, GetWidth, GetID
 * Parameter:	ix		Index des Panes
 *				style	Neuer Style f�r das Pane
 *				width	Neue Breite f�r das Pane
 * Return:		Vorheriger Style bzw. vorherige Breite des Panes bzw.
 *				gew�nschter Style
 *
 * Or new width for the indicated Pane sets a new Style or gives the value back 
 * 
 ****************************************************************************/
#define GET_PANE_INFO(ix)	ASSERT(ix < GetCount()); \
UINT id, style; int width; \
GetPaneInfo(ix, id, style, width)

UINT CNGStatusBar::SetStyle(int ix, UINT newStyle)
{
	GET_PANE_INFO(ix);
	SetPaneInfo(ix, id, newStyle, width);
	return style;
}
int  CNGStatusBar::SetWidth(int ix, int newWidth)
{
	GET_PANE_INFO(ix);
	SetPaneInfo(ix, id, style, newWidth);
	return width;
}
UINT CNGStatusBar::GetStyle(int ix)
{
	GET_PANE_INFO(ix);
	return style;
}
int  CNGStatusBar::GetWidth(int ix)
{
	GET_PANE_INFO(ix);
	return width;
}
UINT CNGStatusBar::GetID(int ix)
{
	GET_PANE_INFO(ix);
	return id;
}

#undef GET_PANE_INFO

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	OnDestroy
 * Parameter:	-
 * Return:		-
 *
 * When destroying the status line the timer must be deleted. 
 ****************************************************************************/
void CNGStatusBar::OnDestroy()
{
	if (timerID)	KillTimer(timerID);
	timerID = 0;

	CStatusBar::OnDestroy();
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	SavePane, RestorePane
 * Parameter:	ix		Aktueller Paneindex
 * Return:		-
 *
 * With these two functions the current status of a Panes can be restored 
 * temporarly secured and at a later point in time again, or into another Pane 
 * to be copied. This is then meaningful for example if in a Pane temporarily 
 * to another mode (for example a progress bar) is switched. For each Pane 
 * a buffer is available.
 ****************************************************************************/
void CNGStatusBar::SavePane(int ix)
{
	ASSERT(ix < GetCount());

	CNGStatusBarPaneInfo	value;
	if (!buffer.Lookup(ix, value))
		buffer[ix] = paneInfo[ix];
}

void CNGStatusBar::RestorePane(int ix)
{
	ASSERT(ix < GetCount());

	CNGStatusBarPaneInfo	value;
	if (buffer.Lookup(ix, value))
	{
		paneInfo[ix] = value;
		buffer.RemoveKey(ix);
	}

	Invalidate(FALSE);
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	GetPaneAtPosition
 * Parameter:	point		Aktuelle Mausposition
 * Return:		Index des Panes, der unter der Maus liegt
 *
 * With this function one tests, which is to Pane under the mouse and which 
 * index of this Panes returned. It must be noted that the mouse position 
 * must be transferred to the status line in Client coordinates. If the father 
 * window is a dialog, a coordinate adjustment must be executed before the position 
 * examination. 
 ****************************************************************************/
int CNGStatusBar::GetPaneAtPosition(CPoint& point)
{
	if (pParent->IsKindOf(RUNTIME_CLASS(CDialog)))
	{
		pParent->ClientToScreen(&point);
		ScreenToClient(&point);
	}

	CRect rect;
	for (int i = 0, n = GetCount(); i < n; i++)
	{
		GetItemRect(i, rect);
		if (rect.PtInRect(point))	return i;
	}

	return -1;
}

/*****************************************************************************
 * Klasse:		CNGStatusBar
 * Funktion:	OnLButtonUp, OnMButtonUp, OnRButtonUp, OnMouseMove,
 *				OnLButtonDown, OnMButtonDown, OnRButtonDown,
 *				OnLButtonDblClk, OnMButtonDblClk, OnRButtonDblClk
 * Parameter:	nFlags		Zusatztasten bei der Mausoperation
 *				point		Aktuelle Mausposition
 * Return:		-
 *
 * These mouse functions pass the message on directly to the parent window. 
 * 
 ****************************************************************************/
#define TO_PARENT(fkt, event)	\
void CNGStatusBar::fkt(UINT nFlags, CPoint point) \
{ \
pParent->SendMessage(event, (WPARAM) nFlags, MAKELPARAM(point.x, point.y)); \
CStatusBar::fkt(nFlags, point); \
}

TO_PARENT(OnLButtonUp,		WM_LBUTTONUP);
TO_PARENT(OnMButtonUp,		WM_MBUTTONUP);
TO_PARENT(OnRButtonUp,		WM_RBUTTONUP);
TO_PARENT(OnLButtonDown,	WM_LBUTTONDOWN);
TO_PARENT(OnMButtonDown,	WM_MBUTTONDOWN);
TO_PARENT(OnRButtonDown,	WM_RBUTTONDOWN);
TO_PARENT(OnLButtonDblClk,	WM_LBUTTONDBLCLK);
TO_PARENT(OnMButtonDblClk,	WM_MBUTTONDBLCLK);
TO_PARENT(OnRButtonDblClk,	WM_RBUTTONDBLCLK);
TO_PARENT(OnMouseMove,		WM_MOUSEMOVE);

#undef TO_PARENT

BOOL CNGStatusBar::OnEraseBkgnd(CDC* pDC) 
{
	UNUSED_ALWAYS(pDC);
	
	return TRUE;//CMDIFrameWnd::OnEraseBkgnd(pDC);
}


/////////////////////////////////////////////////////////////////////////////
// Tool tip operations
void CNGStatusBar::AddToolTip(LPCTSTR lpszText, LPCRECT lpRectTool, UINT nIDTool)
{
	m_ToolTip.AddTool(this, lpszText, lpRectTool, nIDTool);
}

void CNGStatusBar::SetToolRects()
{
	CRect rect;
	for (int i = 1, n = GetCount(); i < n; i++)
	{
		GetItemRect(i, &rect);
		m_ToolTip.SetToolRect(this, i, &rect);
	}
}

void CNGStatusBar::UpdateTipText(LPCTSTR lpszText, UINT nIDTool)
{
	m_ToolTip.UpdateTipText(lpszText, this, nIDTool);
}

void CNGStatusBar::DeleteToolTip(UINT nIDTool)
{
	m_ToolTip.DelTool(this, nIDTool);
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder Riverblade Limited
United Kingdom United Kingdom
I haven't always written software for a living. When I graduated from Surrey University in 1989, it was with an Electronic Engineering degree, but unfortunately that never really gave me the opportunity to do anything particularly interesting (with the possible exception of designing Darth Vader's Codpiece * for the UK Army in 1990).
    * Also known as the Standard Army Bootswitch. But that's another story...
Since the opportunity arose to lead a software team developing C++ software for Avionic Test Systems in 1996, I've not looked back. More recently I've been involved in the development of subsea acoustic navigation systems, digital TV broadcast systems, port security/tracking systems, and most recently software development tools with my own company, Riverblade Ltd.

One of my personal specialities is IDE plug-in development. ResOrg was my first attempt at a plug-in, but my day to day work is with Visual Lint, an interactive code analysis tool environment with works within the Visual Studio and Eclipse IDEs or on build servers.

I love lots of things, but particularly music, photography and anything connected with history or engineering. I despise ignorant, intolerant and obstructive people - and it shows...I can be a bolshy cow if you wind me up the wrong way...Laugh | :laugh:

I'm currently based 15 minutes walk from the beach in Bournemouth on the south coast of England. Since I moved here I've grown to love the place - even if it is full of grockles in Summer!

Comments and Discussions