第一步:找到CRectTracker类的源代码在函数BOOL CRectTracker::TrackHandle(int nHandle, CWnd* pWnd, CPoint point, CWnd* pWndClipTo)中的如下位置加入以下代码:
.....
VERIFY(::GetMessage(&msg, NULL, 0, 0));
if (CWnd::GetCapture() != pWnd)
break;
DispatchMessage(&msg);// 新加入的代码
switch (msg.message)
....
第二步:以CRectTracker为基类,新建一个类CRectTrackerEx
class CRectTrackerEx : public CRectTracker
{
protected:
CDrawRectInfo *m_pDrawRectInfo;
bool m_bLBtnDown; // 鼠标左键是否按下 按下true,否则false
void AdjustRect(CRect &rc, const CRect Oldrc);
void OnChangedRect(const CRect& rectOld);
public:
bool m_bUseAntLine; // true用蚂蚁线 false不用
CRect m_LimitRect; // 只有在限制区域内才可以画选择框
void StartDraw(); // m_bLBtnDown = false
void StopDraw(); // m_bLBtnDown = true
bool IsStartDraw(); // m_bLBtnDown == false
public:
CRectTrackerEx(CWnd* pWnd, bool bDrawAntLine=true, CCreateThreadInfo *pCreateThreadInfo=NULL);
CRectTrackerEx(void);
~CRectTrackerEx(void);
};
第三步:实现画蚂蚁线的线程
DWORD _Counter = 0;
DWORD _CounterStart = 0;
//---------------------------------------------------------------------------
void CALLBACK MovingDots(int X, int Y, LPARAM lpParam)
{
CDC *pDC = (CDC*) lpParam;
_Counter = (_Counter + 1) % 10; COLORREF vColor;
if (_Counter < 5) vColor = RGB(0,0,0);
else vColor = RGB(255,255,255);
pDC->SetPixel(X, Y, vColor);
}
//---------------------------------------------------------------------------void DrawTheRect(CRect *R, CDC * pDC)//LPVOID pParam)
{
// Determines starting pixel color of Rect
_Counter = _CounterStart;
// Use LineDDA to draw each of the 4 edges of the rectangle
LineDDA(R->right,R->top, R->left, R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->left, R->bottom,R->left, R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->right,R->bottom,R->right,R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->right,R->bottom,R->left, R->bottom,(LINEDDAPROC)MovingDots,(long)pDC);
}
//---------------------------------------------------------------------------
UINT ThreadProc(LPVOID pParam)
{
_Counter = 0;
_CounterStart = 0; CDrawRectInfo *pDrawRectInfo = (CDrawRectInfo*)pParam;
CDC *pDC = CDC::FromHandle(pDrawRectInfo->m_hDC);
CRectTrackerX *pRectTrackerX = (CRectTrackerX*)(pDrawRectInfo->pParam);
CRect tmpRc; while (true)
{
_CounterStart = (_CounterStart + 1) % 0XFFFFFFFF; // 根据用户选择工具的类型来具体画图
// 只有鼠标不移动时才进行动画(蚂蚁线)画图
if ( pRectTrackerX->m_bUseAntLine && pRectTrackerX->IsStartDraw())
{
tmpRc = pRectTrackerX->m_rect;
tmpRc.left -= 1;
tmpRc.top -= 1;
DrawTheRect(&tmpRc, pDC);
}
Sleep(100);
}
return 0;
}
.....
VERIFY(::GetMessage(&msg, NULL, 0, 0));
if (CWnd::GetCapture() != pWnd)
break;
DispatchMessage(&msg);// 新加入的代码
switch (msg.message)
....
第二步:以CRectTracker为基类,新建一个类CRectTrackerEx
class CRectTrackerEx : public CRectTracker
{
protected:
CDrawRectInfo *m_pDrawRectInfo;
bool m_bLBtnDown; // 鼠标左键是否按下 按下true,否则false
void AdjustRect(CRect &rc, const CRect Oldrc);
void OnChangedRect(const CRect& rectOld);
public:
bool m_bUseAntLine; // true用蚂蚁线 false不用
CRect m_LimitRect; // 只有在限制区域内才可以画选择框
void StartDraw(); // m_bLBtnDown = false
void StopDraw(); // m_bLBtnDown = true
bool IsStartDraw(); // m_bLBtnDown == false
public:
CRectTrackerEx(CWnd* pWnd, bool bDrawAntLine=true, CCreateThreadInfo *pCreateThreadInfo=NULL);
CRectTrackerEx(void);
~CRectTrackerEx(void);
};
第三步:实现画蚂蚁线的线程
DWORD _Counter = 0;
DWORD _CounterStart = 0;
//---------------------------------------------------------------------------
void CALLBACK MovingDots(int X, int Y, LPARAM lpParam)
{
CDC *pDC = (CDC*) lpParam;
_Counter = (_Counter + 1) % 10; COLORREF vColor;
if (_Counter < 5) vColor = RGB(0,0,0);
else vColor = RGB(255,255,255);
pDC->SetPixel(X, Y, vColor);
}
//---------------------------------------------------------------------------void DrawTheRect(CRect *R, CDC * pDC)//LPVOID pParam)
{
// Determines starting pixel color of Rect
_Counter = _CounterStart;
// Use LineDDA to draw each of the 4 edges of the rectangle
LineDDA(R->right,R->top, R->left, R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->left, R->bottom,R->left, R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->right,R->bottom,R->right,R->top, (LINEDDAPROC)MovingDots,(long)pDC);
LineDDA(R->right,R->bottom,R->left, R->bottom,(LINEDDAPROC)MovingDots,(long)pDC);
}
//---------------------------------------------------------------------------
UINT ThreadProc(LPVOID pParam)
{
_Counter = 0;
_CounterStart = 0; CDrawRectInfo *pDrawRectInfo = (CDrawRectInfo*)pParam;
CDC *pDC = CDC::FromHandle(pDrawRectInfo->m_hDC);
CRectTrackerX *pRectTrackerX = (CRectTrackerX*)(pDrawRectInfo->pParam);
CRect tmpRc; while (true)
{
_CounterStart = (_CounterStart + 1) % 0XFFFFFFFF; // 根据用户选择工具的类型来具体画图
// 只有鼠标不移动时才进行动画(蚂蚁线)画图
if ( pRectTrackerX->m_bUseAntLine && pRectTrackerX->IsStartDraw())
{
tmpRc = pRectTrackerX->m_rect;
tmpRc.left -= 1;
tmpRc.top -= 1;
DrawTheRect(&tmpRc, pDC);
}
Sleep(100);
}
return 0;
}
void CRectTrackerX::Construct()
{
///////////////////////////////////////////
m_bLBtnDown = false;
m_bUseAntLine = true;
m_pDrawRectInfo = NULL;
///////////////////////////////////////////
.......
}
第五步:加入的函数实现
void CRectTrackerEx::StartDraw()
{
m_bLBtnDown = false;
}
//---------------------------------------------------------------------------void CRectTrackerEx::StopDraw()
{
m_bLBtnDown = true;
}
//---------------------------------------------------------------------------
bool CRectTrackerEx::IsStartDraw()
{
return m_bLBtnDown==false;
}
//---------------------------------------------------------------------------
CRectTrackerEx::CRectTrackerEx(CWnd* pWnd, bool bDrawAntLine, CCreateThreadInfo *pCreateThreadInfo)
{
Construct();
if (bDrawAntLine)
{
if (m_pDrawRectInfo == NULL)
{
m_pDrawRectInfo = new CDrawRectInfo;
m_pDrawRectInfo->m_hDC = pWnd->GetDC()->m_hDC;
m_pDrawRectInfo->pParam = this;
} if (pCreateThreadInfo != NULL)
{
AfxBeginThread((AFX_THREADPROC)ThreadProc,
m_pDrawRectInfo,
pCreateThreadInfo->m_nPriority,
pCreateThreadInfo->m_nStackSize,
pCreateThreadInfo->m_dwCreateFlags,
pCreateThreadInfo->m_lpSecurityAttrs);
} else
{
AfxBeginThread((AFX_THREADPROC)ThreadProc, m_pDrawRectInfo);
}
}
}
//-----------------------------------------------------------------------------
void CRectTrackerEx::OnChangedRect(const CRect& rectOld)
{
AdjustRect(m_rect, rectOld);
}
//-----------------------------------------------------------------------------
void CRectTrackerEx::AdjustRect(CRect &rc, const CRect Oldrc)
{
if (rc.IsRectEmpty() || m_LimitRect.IsRectEmpty()) return;
int nW = Oldrc.Width();
int nH = Oldrc.Height(); if (rc.left < m_LimitRect.left)
{
rc.left = m_LimitRect.left;
rc.right = rc.left + nW;
} if (rc.top < m_LimitRect.top)
{
rc.top = m_LimitRect.top;
rc.bottom = rc.top + nH;
} if (rc.right > m_LimitRect.right)
{
rc.right = m_LimitRect.right;
rc.left = rc.right - nW;
} if (rc.bottom > m_LimitRect.bottom)
{
rc.bottom = m_LimitRect.bottom;
rc.top = rc.bottom - nH;
}
}
//---------------------------------------------------------------------------到此已经结束。在视图中相应消息中加入相应的代码即可实现。
(1)当用鼠标按下重新画一个方框时,限制区域不起作用;但拖动已有的方框时可以实现限制的功能。
(2)当鼠标按住调整小滑块进行调整大小时,如果正向调整没有问题,但反向调整,限制功能也不起作用。
哪位高手愿意继续完善?
或者哪位感兴趣,与我联系。有完整的代码,我的E-mail:[email protected],邮件标题要注明“索取CRectTrackerEx代码",否则我可能作为垃圾邮件给删除掉。
void CRectTrackerX::Construct()
{
///////////////////////////////////////////
m_bLBtnDown = false;
m_bUseAntLine = true;
m_pDrawRectInfo = NULL;
m_LimitRect.SetRectEmpty(); // 否则启动多个程序实例时,出现方框无限大现象
///////////////////////////////////////////
.......
}