Introduction
While working on a recent project, I noticed that Microsoft doesn't provide any kind of class to track line-based objects. I took a peek at the CRectTracker
class and then I wrote my own class that is similar to CRectTracker
.
The implementation is very much like CRectTracker
and most of the function names are the same. I only need to track a single line in my project, so I didn't add support for multiple lines to be tracked at once. Although I didn't add multiple line support, there are a few variables and functions that are the beginnings of adding this functionality
Ok, now let's get on to the part you've been waiting for. I have encapsulated a lot of logic for the OnLButtonDown()
handler inside my class. Let's take a look at the OnLButtonDown()
hander from the demo application:
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!m_pLineTracker->OnLButtonDown(this, nFlags, point, &m_LineList))
{
CLineTracker tracker;
if (tracker.TrackRubberLine(this, point))
{
if ((abs(tracker.m_points.Width()) > 20) ||
(abs(tracker.m_points.Height()) > 20))
{
CLineItem* pLine = new CLineItem();
pLine->m_rcPoints.SetRect(tracker.m_points.left,
tracker.m_points.top, tracker.m_points.right,
tracker.m_points.bottom);
m_LineList.Add(pLine);
}
}
}
Invalidate();
CWnd::OnLButtonDown(nFlags, point);
}
The one parameter that may need to be explained is &m_LineList
. This is a pointer to a simple linked list of lines. See the classes CLineList
and CLineItem
in the demo project. CLineTracker
's OnLButtonDown()
function scans through the linked list to see if any lines are selected, moved, or have their "handles" tracked.
To make sure that the mouse cursor is changed to reflect the tracking operation status, you need to add some code to your OnSetCursor()
message handler. Here's the OnSetCursor()
handler from the demo application:
BOOL CChildView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (m_pLineTracker->SetCursor(pWnd, nHitTest))
return TRUE;
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
Now we need to make sure that CLineTracker
's "handles" are drawn. In the demo application, the OnPaint()
handler takes care of this. Here's the demo applications's OnPaint()
code:
void CChildView::OnPaint()
{
CPaintDC dc(this);
CLineItem* pLine;
pLine = m_LineList.GetFirst();
CPoint ptStart;
CPoint ptEnd;
while(pLine)
{
ptStart.x = pLine->m_rcPoints.left;
ptStart.y = pLine->m_rcPoints.top;
ptEnd.x = pLine->m_rcPoints.right;
ptEnd.y = pLine->m_rcPoints.bottom;
DrawArrow(&dc, ptStart, ptEnd);
pLine = pLine->m_pNext;
}
m_pLineTracker->Draw(&dc);
}
This is my first-ever source code submission and I hope this class provides some useful ideas to some of you fellow developers out there.