第一步:找到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;
}

解决方案 »

  1.   

    第四步:在CRectTracker中的Construct()中加入:
    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;
    }
    }
    //---------------------------------------------------------------------------到此已经结束。在视图中相应消息中加入相应的代码即可实现。
      

  2.   

    但是经过测试有以下问题:
    (1)当用鼠标按下重新画一个方框时,限制区域不起作用;但拖动已有的方框时可以实现限制的功能。
    (2)当鼠标按住调整小滑块进行调整大小时,如果正向调整没有问题,但反向调整,限制功能也不起作用。
    哪位高手愿意继续完善?
    或者哪位感兴趣,与我联系。有完整的代码,我的E-mail:[email protected],邮件标题要注明“索取CRectTrackerEx代码",否则我可能作为垃圾邮件给删除掉。
      

  3.   

    第四步:改写。在CRectTracker中的Construct()中加入: 
    void CRectTrackerX::Construct() 

    /////////////////////////////////////////// 
    m_bLBtnDown  = false; 
    m_bUseAntLine = true; 
    m_pDrawRectInfo = NULL; 
    m_LimitRect.SetRectEmpty(); // 否则启动多个程序实例时,出现方框无限大现象
    /////////////////////////////////////////// 
    .......