Click here to Skip to main content
15,880,469 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 254.4K   23.6K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
/*************************************************************************
				Class Implementation : CUGSideHdg
**************************************************************************
	Source file : UGSideHd.cpp
// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
*************************************************************************/
#include "stdafx.h"
#include "UGCtrl.h"
// define WM_HELPHITTEST messages
#include <afxpriv.h>

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

/***************************************************
	Standard construction/desrtuction
***************************************************/
CUGSideHdg::CUGSideHdg()
{
	//init the varialbes
	m_isSizing	= FALSE;
	m_canSize	= FALSE;

	//set the row height focus rect to be offscreen
	m_focusRect.top = -1;
	m_focusRect.bottom = -1;
}

CUGSideHdg::~CUGSideHdg()
{
}

/********************************************
	Message handlers
*********************************************/
BEGIN_MESSAGE_MAP(CUGSideHdg, CWnd)
	//{{AFX_MSG_MAP(CUGSideHdg)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_RBUTTONDBLCLK()
	ON_WM_SETCURSOR()
	ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
	ON_WM_HELPINFO()
	ON_NOTIFY_EX( TTN_NEEDTEXT, 0, ToolTipNeedText )
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/***************************************************
OnPaint
	This routine is responsible for gathering information on cells to draw,
	and draw in an optomized fashion.
Params:
	<none>
Returns:
	<none>
*****************************************************/
void CUGSideHdg::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	m_drawHint.AddHint(m_GI->m_numberSideHdgCols * -1,0,0,m_GI->m_numberRows);

	DrawCellsIntern(&dc);
	
	m_drawHint.ClearHints();
}

/***************************************************
DrawCellsIntern
	function is the key to the fast redraw functionality in the Ultimate Grid.
	This function is responsible for drawing cells within the grid area, it
	makes sure that only the cells that are marked as invalid
	(by calling CUGDrawHint::IsInvalid function) are redrawn.
Params:
	dc		- pointer DC to draw on
Returns:
	<none>
*****************************************************/
void CUGSideHdg::DrawCellsIntern(CDC *dc)
{
	CRect rect(0,0,0,0), cellRect;
	CUGCell cell;
	CUGCellType * cellType;
	int dcID;

	int xIndex, col;
	long yIndex, row = 0;

	m_bottomRow = m_GI->m_numberRows;

	m_ctrl->OnScreenDCSetup(dc,NULL,UG_SIDEHEADING);

	if(m_GI->m_defFont != NULL)
		dc->SelectObject((CFont*)m_GI->m_defFont);

	for(yIndex = 0; yIndex <m_GI->m_numberRows; yIndex++)
	{
		if(yIndex == m_GI->m_numLockRows)
			yIndex = m_GI->m_topRow;

		row = yIndex;

		rect.top = rect.bottom;
		rect.bottom += m_ctrl->GetRowHeight(row);
		rect.right = 0;

		if(rect.top == rect.bottom)
			continue;

		for(xIndex = (m_GI->m_numberSideHdgCols*-1) ;xIndex <0;xIndex++)
		{	
			col = xIndex;
			row = yIndex;

			rect.left = rect.right;
			rect.right  += GetSHColWidth(col);

			//draw if invalid
			if(m_drawHint.IsInvalid(col,row) != FALSE)
			{
				CopyRect(&cellRect,&rect);

				m_ctrl->GetCellIndirect(col,row,&cell);

				if(cell.IsPropertySet(UGCELL_JOIN_SET))
				{
					GetCellRect(col,row,&cellRect);
					m_ctrl->GetJoinStartCell(&col,&row,&cell);
					if(m_drawHint.IsValid(col,row))
						continue;
					m_drawHint.SetAsValid(col,row);
				}

				dcID = dc->SaveDC();
				cellType = m_ctrl->GetCellType(cell.GetCellType());
				cellType->OnDraw(dc,&cellRect,col,row,&cell,0,0);

				dc->RestoreDC(dcID);
			}
		}
		if(rect.bottom > m_GI->m_gridHeight)
			break;
	}

	m_bottomRow = row;

	if(rect.bottom  < m_GI->m_gridHeight)
	{
		rect.top = rect.bottom;
		rect.bottom = m_GI->m_gridHeight;
		rect.left = 0;
		rect.right = m_GI->m_sideHdgWidth;
		// fill-in the area that is not covered by cells
		CBrush brush( m_ctrl->OnGetDefBackColor( UG_SIDEHEADING ));
		dc->FillRect( rect, &brush );
	}
}

/************************************************
Update 
	function makes sure that the last column in the side heading has
	proper width before the window is redrawn.
Params:
	<none>
Returns:
	<none>
*************************************************/
void CUGSideHdg::Update()
{
	//calc the last col width
	int width = 0;

	// For VC6/2002/2003/2005 compatibility
	int xIndex = -1;

	for(;xIndex > (m_GI->m_numberSideHdgCols*-1);xIndex--)
	{
		width += GetSHColWidth(xIndex);
	}

	width = m_GI->m_sideHdgWidth - width;

	if( width < 0 )
		width = 0;

	m_ctrl->SetSH_ColWidth(xIndex,width);

	//redraw the window
	InvalidateRect(NULL);
	UpdateWindow();
}

/************************************************
Moved
	function makes sure that the grid view has moved vertically
	before the window update is allowed.  With this check the Ultimate
	Grid eliminates un-necessary redraws.
Params:
	<none>
Returns:
	<none>
*************************************************/
void CUGSideHdg::Moved()
{
	if(m_GI->m_topRow == m_GI->m_lastTopRow && m_GI->m_currentRow == m_GI->m_lastRow)
		return;

	if(GetUpdateRect(NULL))
	{
		UpdateWindow();
		return;
	}

	int yScroll = 0;
	long yIndex;
	CDC * pDC;
	BOOL redrawAll = FALSE;

	//if the top row has changed then calc the scroll distance
	if(m_GI->m_topRow != m_GI->m_lastTopRow)
	{
		if(m_GI->m_topRow > m_GI->m_lastTopRow)
		{
			for(yIndex = m_GI->m_lastTopRow;yIndex < m_GI->m_topRow; yIndex++)
			{
				yScroll += m_ctrl->GetRowHeight(yIndex);
				if(yScroll > m_GI->m_gridHeight)
				{
					redrawAll = TRUE;
					break;
				}
			}
		}
		else
		{
			for(yIndex = m_GI->m_topRow;yIndex < m_GI->m_lastTopRow; yIndex++)
			{
				yScroll -= m_ctrl->GetRowHeight(yIndex);
				if(yScroll < -m_GI->m_gridHeight)
				{
					redrawAll = TRUE;
					break;
				}
			}
		}
		if(redrawAll)
		{
			yScroll = 0;
			//redraw the whole heading
			m_drawHint.AddToHint(m_GI->m_numberSideHdgCols * -1,0,0,m_GI->m_numberRows);
		}
	}

	//create the device context
	pDC = GetDC();

	//do scrolling of the window here
	if(yScroll != 0)
	{
		RECT scrollRect;
		GetClientRect(&scrollRect);
		scrollRect.top += m_GI->m_lockRowHeight;
		pDC->ScrollDC(0,-yScroll,&scrollRect,&scrollRect,NULL,NULL);
		
		//add the draw hints for the area the was uncovered by the scroll
		if(yScroll >0)
			m_drawHint.AddToHint(m_GI->m_numberSideHdgCols * -1,m_bottomRow,0,m_GI->m_numberRows);
		else if(yScroll < 0)
			m_drawHint.AddToHint(m_GI->m_numberSideHdgCols * -1,0,0,m_GI->m_lastTopRow);
	}

	//add the last and current cells 
	m_drawHint.AddHint(m_GI->m_numberSideHdgCols * -1,m_GI->m_lastRow,0,m_GI->m_lastRow);
	m_drawHint.AddHint(m_GI->m_numberSideHdgCols * -1,m_GI->m_currentRow,0,m_GI->m_currentRow);
	//call the grids main drawing routine
	DrawCellsIntern(pDC);
	//clear the draw hints
	m_drawHint.ClearHints();

	//close the device context
	ReleaseDC(pDC);
}

/************************************************
OnLButtonDown
	Finds the cell that was clicked in, sends a notification
	updates the current cells position.
	It also sets mouse capture, which will be used with sizing operation.
Params:
	nFlags		- please see MSDN for more information on the parameters.
	point
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnLButtonDown(UINT nFlags, CPoint point)
{
	int col;
	long row;
	RECT rect;

	UNREFERENCED_PARAMETER(nFlags);

	if(GetFocus() != m_ctrl->m_CUGGrid)
		m_ctrl->m_CUGGrid->SetFocus();

	if(m_canSize)
	{
		m_isSizing = TRUE;
		SetCapture();
	}
	else if(GetCellFromPoint(&point,&col,&row,&rect) == UG_SUCCESS)
	{
		//send a notification to the cell type	
		BOOL processed = m_ctrl->GetCellType(col,row)->OnLClicked(col,row,1,&rect,&point);
		//send a notification to the main grid class
		m_ctrl->OnSH_LClicked(col,row,1,&rect,&point,processed);
	}
}

/************************************************
OnLButtonUp
	Finds the cell that was clicked in, and sends a notification to 
	CUCtrl::OnSH_LClicked.  It also releases the mouse capture.
Params:
	nFlags		- please see MSDN for more information on the parameters.
	point
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnLButtonUp(UINT nFlags, CPoint point)
{
	int col;
	long row;
	RECT rect;

	UNREFERENCED_PARAMETER(nFlags);

	if(m_isSizing)
	{
		m_isSizing = FALSE;
		m_focusRect.top = -1;
		m_focusRect.bottom = -1;		
		ReleaseCapture();

		if(m_colOrRowSizing == 0)	//col sizing
		{
			m_ctrl->OnSideHdgSized(&m_GI->m_sideHdgWidth);
		}
		else
		{
			int height = m_ctrl->GetRowHeight(m_sizingColRow);
			// send the resize notification to all visible cells in this row
			for(int nIndex=m_ctrl->GetLeftCol(); nIndex<m_ctrl->GetRightCol(); nIndex++)
			{
				CUGCellType* pCellType=m_ctrl->GetCellType(nIndex,m_sizingColRow);
				if(pCellType!=NULL)
				{
					pCellType->OnChangedCellHeight(nIndex,m_sizingColRow,&height);
				}
			}
			m_ctrl->OnRowSized(m_sizingColRow,&height);
			m_ctrl->SetRowHeight(m_sizingColRow,height);
		}
		m_ctrl->AdjustComponentSizes();

	}
	else if(GetCellFromPoint(&point,&col,&row,&rect) == UG_SUCCESS)
	{
		//send a notification to the cell type	
		BOOL processed = m_ctrl->GetCellType(col,row)->OnLClicked(col,row,0,&rect,&point);
		//send a notification to the main grid class
		m_ctrl->OnSH_LClicked(col,row,0,&rect,&point,processed);
	}	
}

/************************************************
OnLButtonDblClk
	Finds the cell that was clicked in and sends a notification to
	CUCtrl::OnSH_DClicked.
Params:
	nFlags		- mouse button states
	point		- point where the mouse is
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	int col;
	long row;
	RECT rect;

	UNREFERENCED_PARAMETER(nFlags);

	if(GetCellFromPoint(&point,&col,&row,&rect) == UG_SUCCESS)
	{
		//send a notification to the cell type	
		BOOL processed = m_ctrl->GetCellType(col,row)->OnLClicked(col,row,0,&rect,&point);
		//send a notification to the main grid class
		m_ctrl->OnSH_DClicked(col,row,&rect,&point,processed);
	}
}

/************************************************
OnMouseMove
	Checks to see if the mouse is over a cell separation line, if it is then it
	checks to see if sizing is allowed.  If it is then the cusor is changed to
	the sizing cusror.
	If sizing is in progress then row height or column width within the heading are
	updated.
Params:
	nFlags		- mouse button states
	point		- point where the mouse is
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnMouseMove(UINT nFlags, CPoint point)
{
	//check to see ifthe mouse is over a cell separation
	//but only if the mouse is not currently sizing 
	if(m_isSizing == FALSE && (nFlags&MK_LBUTTON) == 0 && m_GI->m_userSizingMode >0)
	{
		m_canSize = FALSE;

		//side heading column width sizing
		int width = m_GI->m_sideHdgWidth;
		for(int col = 0; col < m_GI->m_numberSideHdgCols ;col++)
		{
			if(point.x < width+3 && point.x > width-3)
			{
				if(m_ctrl->OnCanSizeSideHdg() == FALSE)
					return;

				m_canSize = TRUE;
				m_colOrRowSizing = 0;
				m_sizingColRow = col;
				m_sizingStartSize = m_GI->m_sideHdgWidths[col];
				m_sizingStartPos = point.x;
				m_sizingStartWidth = m_GI->m_sideHdgWidth;

				SetCursor(m_GI->m_WEResizseCursor);
				return;
			}
			width -= m_GI->m_sideHdgWidths[col];
		}

		//side heading row height sizing
		int height = 0;
		for(long row = 0;row < m_GI->m_numberRows;row++)
		{
			if(row == m_GI->m_numLockRows)
				row = m_GI->m_topRow;

			height += m_ctrl->GetRowHeight(row);
			if(height > m_GI->m_gridHeight)
				break;

			if(point.y < height+3 && point.y > height-3)
			{
				if(m_ctrl->GetRowHeight(row+1) == 0 && (row+1) < m_GI->m_numberRows)
					row++;

				if(m_ctrl->OnCanSizeRow(row) == FALSE)
					return;

				m_canSize = TRUE;
				m_colOrRowSizing = 1;
				m_sizingColRow = row;
				m_sizingStartSize = m_ctrl->GetRowHeight(row);
				m_sizingStartPos = point.y;
				if(m_GI->m_uniformRowHeightFlag)
				{
					if( 0 != m_GI->m_defRowHeight )
						m_sizingNumRowsDown =  point.y / m_GI->m_defRowHeight;
				}	
				SetCursor(m_GI->m_NSResizseCursor);
				return;
			}
		}

	}

	//perform the sizing
	else if(m_isSizing)
	{
		if(m_colOrRowSizing == 0)	//col sizing
		{
			int width = m_sizingStartSize +( point.x - m_sizingStartPos);
			if(width <0)
				width = 0;
			m_GI->m_sideHdgWidths[m_sizingColRow] = width;
			width = m_sizingStartWidth + (point.x - m_sizingStartPos);
			if(width <0)
				width = 0;

			m_ctrl->OnSideHdgSizing(&width);

			m_GI->m_sideHdgWidth = width;
			m_ctrl->AdjustComponentSizes();

		}
		else					//row sizing
		{
			int height;
			if(m_GI->m_uniformRowHeightFlag)
			{
				if(point.y <1)
					point.y = 1;
				if(m_sizingNumRowsDown>0)
					height = point.y / m_sizingNumRowsDown;
				else
					height = point.y;
			}
			else
				height = m_sizingStartSize+(point.y - m_sizingStartPos);

			if(height < 0)
				height = 0 ;

			// send the resize notification to all visible cells in this row
			for(int nIndex=m_ctrl->GetLeftCol(); nIndex<m_ctrl->GetRightCol(); nIndex++)
			{
				CUGCellType* pCellType=m_ctrl->GetCellType(nIndex,m_sizingColRow);
				if(pCellType!=NULL)
				{
					pCellType->OnChangingCellHeight(nIndex,m_sizingColRow,&height);
				}
			}

			m_ctrl->OnRowSizing(m_sizingColRow,&height);

			m_ctrl->SetRowHeight(m_sizingColRow,height);

			if(m_GI->m_userSizingMode == 1) // focus rect
			{
				Update();
				CDC* dc = m_ctrl->m_CUGGrid->GetDC();
				dc->DrawFocusRect(&m_focusRect);
				m_focusRect.top = point.y-1;
				m_focusRect.bottom = point.y+1;
				m_focusRect.left = 0;
				m_focusRect.right = m_GI->m_gridWidth;
				dc->DrawFocusRect(&m_focusRect);
				m_ctrl->m_CUGGrid->ReleaseDC(dc);

			}
			else
				m_ctrl->RedrawAll();
		}
	}
}

/************************************************
OnRButtonDown
	function sends a mouse click notification to the main grid class, 
	checks to see if menus are enabled. If so then menu specific
	notifications are sent as well.
Params:
	nFlags		- mouse button states
	point		- point where the mouse is
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnRButtonDown(UINT nFlags, CPoint point)
{
	int col;
	long row;
	RECT rect;

	UNREFERENCED_PARAMETER(nFlags);

	if(GetFocus() != m_ctrl->m_CUGGrid)
		m_ctrl->m_CUGGrid->SetFocus();

	if(GetCellFromPoint(&point,&col,&row,&rect) == UG_SUCCESS)
	{
		//send a notification to the cell type	
		BOOL processed = m_ctrl->GetCellType(col,row)->OnLClicked(col,row,0,&rect,&point);
		//send a notification to the main grid class
		m_ctrl->OnSH_RClicked(col,row,1,&rect,&point,processed);
	}

	if(m_GI->m_enablePopupMenu)
	{
		ClientToScreen(&point);
		m_ctrl->StartMenu(col,row,&point,UG_SIDEHEADING);
	}
}

/************************************************
OnRButtonUp
	Sends a mouse click notification to the main grid class.
Params:
	nFlags		- mouse button states
	point		- point where the mouse is
Returns:
	<none>
*************************************************/
void CUGSideHdg::OnRButtonUp(UINT nFlags, CPoint point)
{
	int col;
	long row;
	RECT rect;

	UNREFERENCED_PARAMETER(nFlags);

	if(GetCellFromPoint(&point,&col,&row,&rect) == UG_SUCCESS)
	{
		//send a notification to the cell type	
		BOOL processed = m_ctrl->GetCellType(col,row)->OnLClicked(col,row,0,&rect,&point);
		//send a notification to the main grid class
		m_ctrl->OnSH_RClicked(col,row,0,&rect,&point,processed);
	}
}

/************************************************
OnSetCursor
	The framework calls this member function if mouse input is not captured
	and the mouse causes cursor movement within the CWnd object.
Params:
	pWnd		- please see MSDN for more information on the parameters.
	nHitTest
	message
Returns:
	Nonzero to halt further processing, or 0 to continue.
*************************************************/
BOOL CUGSideHdg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	UNREFERENCED_PARAMETER(*pWnd);
	UNREFERENCED_PARAMETER(nHitTest);
	UNREFERENCED_PARAMETER(message);

	if(!m_canSize)
		SetCursor(m_GI->m_arrowCursor);
	else if(m_colOrRowSizing == 0)
		SetCursor(m_GI->m_WEResizseCursor);
	else
		SetCursor(m_GI->m_NSResizseCursor);
		
	return 1;
}

/************************************************
GetCellRect
	Returns the rectangle for the given cell co-ordinates.
	If the cell is joined then the given co-ordinates 
	are modified to point to the start cell for the join.
Params:
	col		- column to find the rect of
	row		- row to find the rect of
	rect	- rectangle to calculate
Returns:
	UG_SUCCESS	- success
*************************************************/
int CUGSideHdg::GetCellRect(int col,long row,RECT *rect)
{
	return GetCellRect(&col,&row,rect);

}
/************************************************
GetCellRect
	Returns the rectangle for the given cell co-ordinates.
	If the cell is joined then the given co-ordinates 
	are modified to point to the start cell for the join.
Params:
	col		- column to find the rect of
	row		- row to find the rect of
	rect	- rectangle to calculate
Returns:
	UG_SUCCESS	- success
*************************************************/
int CUGSideHdg::GetCellRect(int *col,long *row,RECT *rect)
{
	int xIndex,yIndex;
	int width	= 0;
	int height	= 0;

	int startCol	= *col;
	long startRow	= *row;
	int endCol		= *col;
	long endRow		= *row;

	rect->left		= 0;
	rect->top		= 0;
	rect->right		= m_GI->m_sideHdgWidth;
	rect->bottom	= 0;
	
	//if the specified cell is within a join then find the joined range
	if(m_GI->m_enableJoins)
	{
		if(m_ctrl->GetJoinRange(&startCol,&startRow,&endCol,&endRow) == UG_SUCCESS)
		{
			*col = startCol;
			*row = startRow;
		}
	}

	//find the col
	for(xIndex= (m_GI->m_numberSideHdgCols * -1);xIndex < 0;xIndex++)
	{
		if(xIndex == startCol)
			rect->left = width;
		
		width += GetSHColWidth(xIndex);

		if(xIndex == endCol)
		{
			rect->right = width;
			break;
		}
	}

	//find the row
	if(startRow >= m_GI->m_numLockRows)
	{
		rect->top = m_GI->m_lockRowHeight;
		rect->bottom = m_GI->m_lockRowHeight;
	}
	for(yIndex= 0;yIndex < m_GI->m_numberRows ;yIndex++)
	{		
		if(yIndex == m_GI->m_numLockRows)
			yIndex = m_GI->m_topRow;

		if(yIndex == startRow)
			rect->top = height;

		height += m_ctrl->GetRowHeight(yIndex);

		if(yIndex == endRow)
		{
			rect->bottom = height;	
			break;
		}
	}

	return UG_SUCCESS;
}

/************************************************
GetCellFromPoint
	Returns the column and row that lies over the given x,y co-ordinates.
	The co-ordinates are relative to the top left hand corner of the grid.
Params:
	point - point to check
	col	  - column that lies over the point
	row   - row that lies over the point
	rect  - rectangle of the cell found
Returns:
	UG_SUCCESS	- if a matching cell was found 
	UG_ERROR	- point provided does not correspond to a cell
*************************************************/
int CUGSideHdg::GetCellFromPoint(CPoint *point,int *col,long *row,RECT *rect)
{
	int ptsFound = 0;
	int xIndex;
	long yIndex;

	rect->left		=0;
	rect->top		=0;
	rect->right		=0;
	rect->bottom	=0;

	//find the row
	for(yIndex=0;yIndex<m_GI->m_numberRows;yIndex++)
	{	
		if(yIndex == m_GI->m_numLockRows)
			yIndex = m_GI->m_topRow;
		
		rect->bottom += m_ctrl->GetRowHeight(yIndex);

		if(rect->bottom > point->y)
		{
			rect->top = rect->bottom - m_ctrl->GetRowHeight(yIndex);
			ptsFound ++;
			*row = yIndex;
			break;
		}
	}

	//find the col
	for(xIndex= m_GI->m_numberSideHdgCols * -1 ;xIndex <0 ;xIndex++)
	{
		rect->right += GetSHColWidth(xIndex);

		if(rect->right > point->x)
		{
			rect->left = rect->right - GetSHColWidth(xIndex);
			ptsFound ++;
			*col = xIndex;
			break;
		}
	}

	if(ptsFound == 2)
		return UG_SUCCESS;

	*col = -1;
	*row = -1;
	return UG_ERROR;
}

/************************************************
GetSHColWidth
	function returns height (in pixels) of a side heading' column that user is
	interested in.  The column number passed in has to be a negative value ranging
	from zero to negative value of number of side heading columns set.
	((m_GI->m_numberSideHdgCols) * -1)
Params:
	col			- indicates row of interest
Returns:
	width in pixels of the column in question, or zero if column not found.
*************************************************/
int CUGSideHdg::GetSHColWidth(int col)
{
	//translate the column number into a 0 based positive index
	col = (col * -1) -1;

	if(col <0 || col > m_GI->m_numberSideHdgCols)
		return 0;

	return m_GI->m_sideHdgWidths[col];
}

/************************************************
OnHelpHitTest
	Sent as a result of context sensitive help
	being activated (with mouse) over side heading
Params:
	WPARAM - not used
	LPARAM - x, y coordinates of the mouse event
Returns:
	Context help ID to be displayed
*************************************************/
LRESULT CUGSideHdg::OnHelpHitTest(WPARAM, LPARAM lParam)
{
	// this message is fired as result of mouse activated
	// context help being hit over the grid.
	int col;
	long row;
	CRect rect(0,0,0,0);
	CPoint point( LOWORD(lParam), HIWORD(lParam));
	GetCellFromPoint( &point, &col, &row, &rect );
	// return context help ID to be looked up
	return m_ctrl->OnGetContextHelpID( col, row, UG_SIDEHEADING );
}

/************************************************
OnHelpInfo
	Sent as a result of context sensitive help
	being activated (with mouse) over side heading
	if the grid is on the dialog
Params:
	HELPINFO - structure that contains information on selected help topic
Returns:
	TRUE or FALSE to allow further processing of this message
*************************************************/
BOOL CUGSideHdg::OnHelpInfo(HELPINFO* pHelpInfo) 
{
	if (pHelpInfo->iContextType == HELPINFO_WINDOW)
	{
		// this message is fired as result of mouse activated help in a dialog
		int col;
		long row;
		CRect rect(0,0,0,0);
		CPoint point;
		point.x = pHelpInfo->MousePos.x;
		point.y = pHelpInfo->MousePos.y;

		ScreenToClient( &point );
		GetCellFromPoint( &point, &col, &row, &rect );
		// call context help with ID returned by the user notification
		AfxGetApp()->WinHelp( m_ctrl->OnGetContextHelpID( col, row, UG_SIDEHEADING ));
		// prevent further handling of this message
		return TRUE;
	}
	return FALSE;
}

/***************************************************
OnToolHitTest
	The framework calls this member function to detemine whether a point is in
	the bounding rectangle of the specified tool. If the point is in the
	rectangle, it retrieves information about the tool.
Params:
	point	- please see MSDN for more information on the parameters.
	pTI
Returns:
	If 1, the tooltip control was found; If -1, the tooltip control was not found.
*****************************************************/
// v7.2 - update 02 - 64-bit - changed from int to UGINTRET - see UG64Bit.h
UGINTRET CUGSideHdg::OnToolHitTest(  CPoint point, TOOLINFO *pTI ) const
{
	int col;
	long row;
	CRect rect;
	static int lastCol = -2;
	static long lastRow = -2;	

	if( m_ctrl->m_CUGSideHdg->GetCellFromPoint( &point, &col, &row, &rect ) == UG_SUCCESS)
	{
		if(col != lastCol || row != lastRow)
		{
			lastCol = col;
			lastRow = row;
			CancelToolTips();
			return -1;
		}

		pTI->uFlags =  TTF_NOTBUTTON | TTF_ALWAYSTIP |TTF_IDISHWND ;
		pTI->uId = (UINT_PTR)m_hWnd;
		pTI->hwnd = (HWND)m_hWnd;
		pTI->lpszText = LPSTR_TEXTCALLBACK;
		return 1;
	}	
	return -1;
}

/***************************************************
ToolTipNeedText (TTN_NEEDTEXT)
	message handler will be called whenever a text is required for a tool tip.
	The Ultimate Grid uses the CUGCtrl::OnHint virtual function to obtain
	proper text to be displayed in the too tip.
Params:
		id			- Identifier of the control that sent the notification. Not
					  used. The control id is taken from the NMHDR structure.
		pTTTStruct	- A pointer to theNMTTDISPINFO structure. This structure is
					  also discussed further in The TOOLTIPTEXT Structure.
		pResult		- A pointer to result code you can set before you return.
					  TTN_NEEDTEXT handlers can ignore the pResult parameter.
Returns:
	<none>
*****************************************************/
BOOL CUGSideHdg::ToolTipNeedText( UINT id, NMHDR* pTTTStruct, LRESULT* pResult )
{
	UNREFERENCED_PARAMETER(id);
	UNREFERENCED_PARAMETER(*pResult);

	TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;

	static CString string;
	int col;
	long row;
	CPoint point;
	CRect rect;

	GetCursorPos(&point);
	ScreenToClient(&point);

	if ( GetCellFromPoint( &point,&col,&row, &rect ) == UG_SUCCESS )
	{
		if ( m_ctrl->OnHint(col,row,UG_SIDEHEADING,&string) == TRUE )
		{
			// v7.2 - update 01 - Do this to Enable multiline ToolTips - reported by kassinen
			::SendMessage( pTTT->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, SHRT_MAX );
			::SendMessage( pTTT->hdr.hwndFrom, TTM_SETDELAYTIME, TTDT_AUTOPOP, SHRT_MAX );
			::SendMessage( pTTT->hdr.hwndFrom, TTM_SETDELAYTIME, TTDT_INITIAL, 200 );
			::SendMessage( pTTT->hdr.hwndFrom, TTM_SETDELAYTIME, TTDT_RESHOW, 200 );
 			pTTT->lpszText = const_cast<LPTSTR>((LPCTSTR)string);
			return TRUE;
		}
	}

	return FALSE;
}

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
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions