Click here to Skip to main content
Click here to Skip to main content
Articles » Multimedia » GDI » Regions » Downloads
 
Add your own
alternative version

Guide to WIN32 Regions

, 10 Mar 2002 CPOL
Guide to understanding how to create and use regions with the WIN32 SDK
rgnguide_demo.zip
RgnGuide.exe
rgnguide_src.zip
arrow.cur
RgnGuide.dsp
res
RgnGuide.ico
cursor1.cur
Toolbar.bmp
/* RgnGuideView.cpp ***********************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
******************************************************************************/
#include "stdafx.h"
#include "RgnGuideView.h"

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	Constructor
******************************************************************************/
CRgnGuideView::CRgnGuideView ()
{
	m_isRubberBand = false;

	m_ptStart.x = 0;
	m_ptStart.y = 0;

	m_ptCurrent.x = 0;
	m_ptCurrent.y = 0;

	m_nMode = ID_SHAPE_RECTANGLE;
	m_nViewMode = ALL;

	m_viewAnd.SetMode(RGN_AND);
	m_viewAnd.SetParent(this);
	m_viewDiff.SetMode(RGN_DIFF);
	m_viewDiff.SetParent(this);
	m_viewOr.SetMode(RGN_OR);
	m_viewOr.SetParent(this);
	m_viewXor.SetMode(RGN_XOR);
	m_viewXor.SetParent(this);

	m_hDraggingRgn = NULL;

	m_hCsrDrag1 = ::LoadCursor(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_SRC1));
	m_hCsrDrag2 = ::LoadCursor(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_SRC2));
}

CRgnGuideView::~CRgnGuideView ()
{
	if (m_hDraggingRgn)
	{
		::DeleteObject(m_hDraggingRgn);
	}

	::DeleteObject(m_hCsrDrag1);
	::DeleteObject(m_hCsrDrag2);
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
BOOL CRgnGuideView::PreTranslateMessage(MSG* pMsg)
{
	pMsg;
	return FALSE;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
UINT CRgnGuideView::GetMode()
{
	return m_nMode;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
void CRgnGuideView::SetMode(UINT nMode)
{
	m_nMode = nMode;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/8/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
UINT CRgnGuideView::GetViewMode()
{
	return m_nViewMode;
}
/* Public *********************************************************************
Author:		Paul Watt
Date:		3/8/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
void CRgnGuideView::SetViewMode(UINT ViewMode)
{
	m_nViewMode = ViewMode;
	RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	Handles the WM_CREATE message.  This function will create the 
			sub-views that combine the regions in different ways, as well as
			the views that display the information about the two src regions.
******************************************************************************/
LRESULT CRgnGuideView::OnCreate (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
	RECT rView;
	RECT rClient;
	GetClientRect(&rClient);

	UINT nHeight	= rClient.bottom - rClient.top;
	UINT nWidth		= rClient.right - rClient.left;

	UINT nViewWidth  = nWidth / 4;
	UINT nViewHeight = nHeight / 4;
			//C: Create the 4 combine views for the two src regions.
			//C: Create the And view.
	rView.left	= nWidth - nViewWidth;
	rView.top	= 0;
	rView.right	= nViewWidth;
	rView.bottom= nViewHeight;
	m_viewAnd.Create(m_hWnd, rView, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER);
			//C: Create the Difference view.
	rView.top	+= nViewHeight;
	rView.right	+= nViewWidth;
	rView.bottom+= nViewHeight;
	m_viewDiff.Create(m_hWnd, rView, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER);
			//C: Create the Or view.
	rView.top	+= nViewHeight;
	rView.right	+= nViewWidth;
	rView.bottom+= nViewHeight;
	m_viewOr.Create(m_hWnd, rView, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER);
			//C: Create the XOR view.
	rView.top	+= nViewHeight;
	rView.right	+= nViewWidth;
	rView.bottom+= nViewHeight;
	m_viewXor.Create(m_hWnd, rView, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER);

	return 0;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/5/2002 
Purpose:	Handles the WM_LBUTTONDOWN message.  This function will start the
			rubberbanding effect when the user drags the mouse until the
			left button is released.  If the Escape button is pressed before the 
			left button is released, then the action will be cancelled. 
******************************************************************************/
LRESULT CRgnGuideView::OnButtonDown (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
	UINT x = LOWORD(lParam);
	UINT y = HIWORD(lParam);
			//C: Set the start point.
	m_ptStart.x = x;
	m_ptStart.y = y;
			//C: Set the rubberband mode to true.
	m_isRubberBand = true;
			//C: Set the current point to the start point as well.
	m_ptCurrent.x = x;
	m_ptCurrent.y = y;
			//C: Draw the initial rubber band.
	DrawRubberBand();
			//C: Return.
	return 0;	
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/5/2002 
Purpose:	Handles the WM_MOUSEMOVE message.  This function will continue the
			rubberbanding effect when the user drags the mouse until the
			left button is released.  If the Escape button is pressed before the 
			left button is released, then the action will be cancelled. 
******************************************************************************/
LRESULT CRgnGuideView::OnMouseMove   (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
			//C: If the current mode is not rubber band, then exit.
	if (!m_isRubberBand)
	{
		return 0;
	}

	UINT x = LOWORD(lParam);
	UINT y = HIWORD(lParam);
			//C: Undo the last rectangle shape that was drawn.
	DrawRubberBand();
			//C: Update the current position.
	m_ptCurrent.x = x;
	m_ptCurrent.y = y;
			//C: Draw the next rubberband position.
	DrawRubberBand();
			//C: Exit with success.
	return 0;		
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/8/2002
Purpose:	If the user presses Eacape while they are dragging a region, or drawing
			a rectangle, then that operation will be cancelled.
******************************************************************************/
LRESULT CRgnGuideView::OnChar   (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
	if (VK_ESCAPE == wParam)
	{
		if (m_isRubberBand)
		{
			//C: Set rubberbanding to false.
			m_isRubberBand = false;
			//C: Erase the last rubber band rectangle that was drawn.
			DrawRubberBand();
		}
		else if (m_hDraggingRgn)
		{
			::DeleteObject(m_hDraggingRgn);
			m_hDraggingRgn = NULL;

			ReleaseCapture();
		}
	}

	return 0;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/5/2002 
Purpose:	Handles the WM_LBUTTONDOWN message.  This function will end the
			rubberbanding effect and add a new shape to the current set of shapes.
			If the Escape button is pressed before the left button is released, 
			then the action will be cancelled. 
******************************************************************************/
LRESULT CRgnGuideView::OnButtonUp   (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
			//C: Verify that this message is for either the right or the left
			//   mouse button.
	if (WM_LBUTTONUP != uMsg && WM_RBUTTONUP != uMsg)
	{
		bHandled = FALSE;
		return 0;
	}
			//C: Check if there is currently a region beign dragged.
	if (m_hDraggingRgn)
	{
			//C: Set this region into one of the src regions, and clear the other
			//   region, only if the cursor is currently over this window.
		if (WM_LBUTTONUP == uMsg)
		{
			::CombineRgn(::g_rgnDoc.hSrc1, m_hDraggingRgn, NULL, RGN_COPY);
		}
		else if(WM_RBUTTONUP == uMsg)
		{
			::CombineRgn(::g_rgnDoc.hSrc2, m_hDraggingRgn, NULL, RGN_COPY);
		}
			//C: Clear the dragging region.
		::DeleteObject(m_hDraggingRgn);
		m_hDraggingRgn = NULL;
			//C: Invalidate the Window.
		RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN);
			//C: End the mouse capture.
		ReleaseCapture();

		return 0;
	}
	else if (!m_isRubberBand)
	{
			//C: If the current mode is not rubber band, then exit.
		return 0;
	}
			//C: Undo the last rectangle shape that was drawn.
	DrawRubberBand();
			//C: Combine the proper region to the current set of regions.
			//C: Get the current shape mode.
	HRGN hRgnNew = NULL;
	switch (m_nMode)
	{
	case ID_SHAPE_RECTANGLE:
		{
			hRgnNew = CreateRectRgn	(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	case ID_SHAPE_ELLIPSE:
		{
			hRgnNew = CreateEllipticRgn (	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	case ID_SHAPE_ROUNDRECT:
		{
			UINT nWidth		= abs(m_ptCurrent.x - m_ptStart.x);
			UINT nHeight	= abs(m_ptCurrent.y - m_ptStart.y);

			hRgnNew = CreateRoundRectRgn(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y,
						nWidth / 4,
						nHeight / 4
						);
		}
		break;
	case ID_SHAPE_POLYGON:
		{
			hRgnNew = CreateRectRgn(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	}
			//C: Combine the new region with one of the current src regions
			//   depending on the button that is beign released.
	if (WM_LBUTTONUP == uMsg)
	{
		::CombineRgn(::g_rgnDoc.hSrc1, ::g_rgnDoc.hSrc1, hRgnNew, RGN_OR);
	}
	else if (WM_RBUTTONUP == uMsg)
	{
		::CombineRgn(::g_rgnDoc.hSrc2, ::g_rgnDoc.hSrc2, hRgnNew, RGN_OR);
	}
			//C: Disable the rubberband mode.
	m_isRubberBand = false;
			//C: Update the window.
	RedrawWindow();
			//C: Force the 4 ombine views to repaint as well.
	m_viewAnd.InvalidateRect(NULL, TRUE);
	m_viewDiff.InvalidateRect(NULL, TRUE);
	m_viewOr.InvalidateRect(NULL, TRUE);
	m_viewXor.InvalidateRect(NULL, TRUE);
			//C: Delete the newly created region object.
	::DeleteObject(hRgnNew);
			//C: Return with success.
	return 0;		
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
LRESULT CRgnGuideView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CPaintDC dc(m_hWnd);
			//C: Draw both of the regions.
	CBrushHandle	brBlack = (HBRUSH)::GetStockObject(BLACK_BRUSH);
	CBrush			brSrc1;
	CBrush			brSrc2;
	
	brSrc1.CreateSolidBrush(RGB(0xFF, 0, 0));
	brSrc2.CreateSolidBrush(RGB(0, 0, 0xFF));

	if (RGN1 == m_nViewMode || ALL == m_nViewMode)
	{
		dc.FillRgn(::g_rgnDoc.hSrc1, brSrc1);
	}

	if (RGN2 == m_nViewMode || ALL == m_nViewMode)
	{
		dc.FillRgn(::g_rgnDoc.hSrc2, brSrc2);
	}

	CBrush			brBreakA;
	CBrush			brBreakB;
	HRGN hBreakRgn = NULL;
	if (BREAK1 == m_nViewMode)
	{
		hBreakRgn = ::g_rgnDoc.hSrc1;
		brBreakA = brSrc1;
		brBreakB.CreateSolidBrush(RGB(0xFF, 0x80, 0x80));
	}

	if (BREAK2 == m_nViewMode)
	{
		hBreakRgn = ::g_rgnDoc.hSrc2;
		brBreakA = brSrc2;
		brBreakB.CreateSolidBrush(RGB(0x80, 0x80, 0xFF));
	}

			//C: Draw Each rectangle of the region.
	if (hBreakRgn)
	{

			//C: Get the region data from the region.
		BYTE	*pData;
		DWORD   dwSize;

		dwSize = ::GetRegionData(hBreakRgn, 0, NULL);
		if (0 == dwSize)
		{
			return 0;
		}
			//C: Allocate space for the region data strcture.
		pData = new BYTE[dwSize];
		if (NULL == pData)
		{
			return 0;
		}

		::GetRegionData(hBreakRgn, dwSize, (RGNDATA*)pData);
			//C: Get the number of rectangles contained in the Region.
		RGNDATA *prData = (RGNDATA*)pData;
		RECT    *prRectangles = (RECT*)prData->Buffer;
		UINT nCount = prData->rdh.nCount;
			//C: Paint each rectangle in the region with an alternating brush color.
		UINT index = 0;
		for (;index < nCount; index++)
		{
			if (index % 2)
			{
				dc.FillRect(&prRectangles[index], brBreakA);
			}
			else
			{
				dc.FillRect(&prRectangles[index], brBreakB);
			}
		}

		delete[] pData;
	}
			//C: Paint an aoutline of each region.
	dc.FrameRgn(::g_rgnDoc.hSrc1, brBlack, 3, 3);
	dc.FrameRgn(::g_rgnDoc.hSrc2, brBlack, 3, 3);

	return 0;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	Handles the WM_SIZE message.  This handler will resize all of the 
			child controls to fit inside of this view properly.
Parameters:			
Return:		
******************************************************************************/
LRESULT CRgnGuideView::OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	RECT rClient;
	GetClientRect(&rClient);

	UINT nHeight	= rClient.bottom - rClient.top;
	UINT nWidth		= rClient.right - rClient.left;
			//C: Resize the combine views.
			//C: Resize the And view.
	POINT ptPos;
	SIZE  nSize;

	nSize.cx = nWidth / 4;
	nSize.cy = nHeight / 4;
	ptPos.x = nWidth - nSize.cx;
	ptPos.y = 0;
	m_viewAnd.MoveWindow(ptPos.x, ptPos.y, nSize.cx, nSize.cy, TRUE);
			//C: Create the Difference view.
	ptPos.y += nSize.cy;
	m_viewDiff.MoveWindow(ptPos.x, ptPos.y, nSize.cx, nSize.cy, TRUE);
			//C: Create the Or view.
	ptPos.y += nSize.cy;
	m_viewOr.MoveWindow(ptPos.x, ptPos.y, nSize.cx, nSize.cy, TRUE);
			//C: Create the XOR view.
	ptPos.y += nSize.cy;
	m_viewXor.MoveWindow(ptPos.x, ptPos.y, nSize.cx, nSize.cy, TRUE);

	return 0;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/1/2002
Purpose:	Draws the rubberband shape using the dimensions of the start
			and current point global variables.
Parameters:	NONE
Return:		-
******************************************************************************/
void CRgnGuideView::DrawRubberBand()
{
	CClientDC dc(m_hWnd);
			//C: Set the current drawing mode to XOR, this will allow us
			//   to add the rubber band, and later remove it by sending the
			//   exact same drawing command.
	dc.SetROP2(R2_NOT);
			//C: Select a NULL Brush into the DC so that no fill is performed.
	dc.SelectBrush((HBRUSH)::GetStockObject(NULL_BRUSH));
			//C: Get the current shape mode, adn draw teh appropriate shape.
	switch (m_nMode)
	{
	case ID_SHAPE_RECTANGLE:
		{
			dc.Rectangle(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	case ID_SHAPE_ELLIPSE:
		{
			dc.Ellipse	(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	case ID_SHAPE_ROUNDRECT:
		{
			UINT nWidth		= abs(m_ptCurrent.x - m_ptStart.x);
			UINT nHeight	= abs(m_ptCurrent.y - m_ptStart.y);

			dc.RoundRect(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y,
						nWidth / 4,
						nHeight / 4
						);
		}
		break;
	case ID_SHAPE_POLYGON:
		{
			dc.Rectangle(	
						m_ptStart.x, 
						m_ptStart.y, 
						m_ptCurrent.x,
						m_ptCurrent.y
						);
		}
		break;
	}
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
void CRgnGuideView::SetDraggingRegion (HRGN hDraggingRgn, bool isSrc1)
{
			//C: Set the state variables that will be important to set the dragging region
			//   into this view properly.
	m_hDraggingRgn	= hDraggingRgn;
	m_isSrc1		= isSrc1;
			//C: Set the mouse capture, so that this window will be notified when 
			//   the mouse button is released.
	SetCapture();

	if (isSrc1)
	{
		SetCursor(m_hCsrDrag1);
	}
	else
	{
		SetCursor(m_hCsrDrag2);
	}
}



/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	Constructor
******************************************************************************/
CRgnGuideSubView::CRgnGuideSubView ()
{
	m_nCombineMode	= RGN_AND;
	m_Parent		= NULL;
	m_RgnCombine	= ::CreateRectRgn(0,0,0,0);

}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	Destructor
******************************************************************************/
CRgnGuideSubView::~CRgnGuideSubView ()
{
	::DeleteObject(m_RgnCombine);
	m_RgnCombine = NULL;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
BOOL CRgnGuideSubView::PreTranslateMessage(MSG* pMsg)
{
	pMsg;
	return FALSE;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
void CRgnGuideSubView::SetMode(UINT nMode)
{
	m_nCombineMode = nMode;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
void CRgnGuideSubView::SetParent(CRgnGuideView *pParent)
{
	m_Parent = pParent;
}

/* Public *********************************************************************
Author:		Paul Watt
Date:		3/5/2002 
Purpose:	Handles the WM_LBUTTONDOWN message.  If this view has a valid 
			RgnGuideView as a parent, then the dragging action will be started
			to allow the region that is stored in this view to be placed into
			the parent view.
******************************************************************************/
LRESULT CRgnGuideSubView::OnButtonDown (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
			//C: Verify that there is a parent before this function proceeds.
	if (!m_Parent)
	{
		return 0;
	}
			//C: Tell the parent that a new region is being dragged.
	HRGN hDraggingRgn = ::CreateRectRgn(0,0,0,0);
	::CombineRgn(hDraggingRgn, m_RgnCombine, NULL, RGN_COPY);

	m_Parent->SetDraggingRegion(hDraggingRgn, uMsg == WM_LBUTTONDOWN);
			//C: Return.
	return 0;	
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		3/6/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
LRESULT CRgnGuideSubView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CPaintDC dc(m_hWnd);

	RECT rClient;
	GetClientRect(&rClient);
			//C: If there is not parent window, then display a message indicating
			//   this.
	if (!m_Parent)
	{
		dc.DrawText(_T("No Parent"), -1, &rClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		return 0;
	}
			//C: Save the DC context.
	int iContext = dc.SaveDC();
			//C: Set the viewport and window extents to be a scaled down version of
			//   the parent view.  This will allow the same region objects to be used
			//   to paint the window, but it will appear smaller.
	RECT rParent;
	m_Parent->GetClientRect(&rParent);

	dc.SetMapMode(MM_ANISOTROPIC);
	dc.SetWindowExt(rParent.right - rParent.left, rParent.bottom - rParent.top, NULL);
	dc.SetViewportExt(rClient.right - rClient.left, rClient.bottom - rClient.top, NULL);
			//C: Draw both of the regions.
	CBrushHandle	brBlack = (HBRUSH)::GetStockObject(BLACK_BRUSH);
	CBrush			brSrc1;
	CBrush			brSrc2;
	CBrush			brCombine;
	
	brSrc1.CreateSolidBrush(RGB(0xFF, 0x00, 0x00));
	brSrc2.CreateSolidBrush(RGB(0x00, 0x00, 0xFF));

	dc.FillRgn(::g_rgnDoc.hSrc1, brSrc1);
	dc.FrameRgn(::g_rgnDoc.hSrc1, brBlack, 3, 3);

	dc.FillRgn(::g_rgnDoc.hSrc2, brSrc2);
	dc.FrameRgn(::g_rgnDoc.hSrc2, brBlack, 3, 3);
			//C: Update the combine rgn.
	::CombineRgn(m_RgnCombine, g_rgnDoc.hSrc1, g_rgnDoc.hSrc2, m_nCombineMode);
			//C: How the combined region is painted will depend on the current position
			//   of the cursor.

	brCombine.CreateSolidBrush(RGB(0xFF, 0x00, 0xFF));
			//C: Otherwise paint the region.
	dc.FillRgn(m_RgnCombine, brCombine);
	dc.FrameRgn(m_RgnCombine, brBlack, 3, 3);
			//C: Return the DC to its original state,
	dc.RestoreDC(iContext);
			//C: Add text to indicate the label of the current view.
	TCHAR szLabel[16];
	::LoadString(::GetModuleHandle(NULL), m_nCombineMode + IDS_RGN_BASE, szLabel, 16);

	dc.DrawText(szLabel, -1, &rClient, DT_CENTER);

	return 0;
}

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)

Share

About the Author

Paul M Watt
Architect L3 Communications
United States United States
I have been developing software for almost two decades. The majority of my expertise as well as my strongest language is C++ with the networking software as my domain of focus. I have had the opportunity to develop:
* Desktop applications (Data Layer, Business Layer, Presentation Layer)
* Application virtualization
* Web clients
* Mobile device management software
* Device drivers
* Embedded system software for
- IP routers
- ATM switches
- Microwave frequency radio/modems
 
Over the years I have learned to value maintainable design solutions first. This has allowed me to adapt my projects to meet the challenges that inevitably appear during development, including:
* My own misjudgments
* Incomplete requirements
* Feature creep
* Poor decisions for which I have no control
 
I am a Mentor and frequent contributor to CodeProject.com with tutorial articles that teach others about the inner workings of the Windows APIs.
 
I am the creator of an open source project on GitHub called Network Alchemy[^], which is a set of Network APIs that are focused on helping developers write robust network communication software.
 
I maintain my own repository and blog at CodeOfTheDamned.com/[^], a site dedicated to guiding developers through the damn code.
Follow on   Twitter   LinkedIn

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 11 Mar 2002
Article Copyright 2002 by Paul M Watt
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid