CRectTracker類的使用


      CRectTracker(俗稱“橡皮筋”類)是一個非常有意思的類。你在Windows中經常看到這樣的情況:它可以用做顯示邊界,你也可以扽它的八個角用來放大縮小,或做框選使用。如何通過編程來實現這種功能呢?這就是CRectTracker類的作用。下圖是這個程序運行的結果:

1

下面讓我們來從頭做一個新的工程文件,來慢慢掌握它的功能吧。

建立一個單文檔的工程文件,將其命名為RectTracke。單擊finish完成工程的建立;先編譯一下,第一次生成obj文件吧,在它生成的過程中,我們繼續往下講解;

第一步:

在CRectTrackeDoc類中生成一個公有的數據成員:m_RectTracker;之所以設成公有,因為要在View中調用它。

class CRectTrackeDoc : public CDocument
{
protected: // create from serialization only
    CRectTrackeDoc();
    DECLARE_DYNCREATE(CRectTrackeDoc)

// Attributes
public:
    CRectTracker m_RectTracker;

 

接着我們來初始化它,在CRectTrackeDoc構造函數中:

CRectTrackeDoc::CRectTrackeDoc()
{
    // TODO: add one-time construction code here
    m_RectTracker.m_rect.SetRect(200,200,100,100);            //矩形位置

    m_RectTracker.m_nStyle = CRectTracker::dottedLine | CRectTracker::resizeInside;
}

其中: m_rect是CRectTracker中用來控制四邊形的大小位置的數據成員, SetRect使用的是View的坐標; m_nStyle是CRectTracker的類型,CRectTracker::resizeInside和CRectTracker::resizeOutside是說明在m_rect的內部還是外部畫區域(它們是互異的),CrectTrakcer::dottedLine是用點划線來畫四邊形的區域邊界。 其他的值還有: CRectTracker::solidLine:用來畫實線邊界;(和dottedLine是互異的) CRectTracker::hatchedBorder:邊界帶拋面線; CRectTracker::hatchInside:內部帶拋面線; 你可以運行前面的例子,上述參數都有使用。你也可以在第二步中逐一使用它們來加深理解它們各自的含義;

第二步:

在CRectTrackeView 類中添加一個公有成員變量bDraw,用來判斷是否需要在矩形框中畫橢圓

class CRectTrackeView : public CView
{
protected: // create from serialization only
    CRectTrackeView();
    DECLARE_DYNCREATE(CRectTrackeView)

// Attributes
public:
    CRectTrackeDoc* GetDocument();
    BOOL bDraw;

在構造函數中初始化bDraw = false,表示初始時不在矩形寬中畫橢圓,只有鼠標左鍵按下時,bDraw為true.才進行畫橢圓操作

CRectTrackeView::CRectTrackeView()
{
    // TODO: add construction code here
     bDraw = FALSE;
}

第三步:

接着我門在視圖中畫一個藍色的橢圓; 在CRectView的OnDraw中繼續我們的工作:

void CRectTrackeView::OnDraw(CDC* pDC)
{
    CRectTrackeDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    CBrush brush(RGB(0,0,255));
    CBrush * oldBrush = pDC->SelectObject(&brush);
    CRect rect;

    pDoc->m_RectTracker.GetTrueRect(&rect); //得到CRectTracker中的m_rect的大小,將其傳遞給rect;

    if(bDraw) 
    {    
        pDC->Ellipse(&rect);
    }

    pDoc->m_RectTracker.Draw(pDC);            //這句畫才真正的將這個四邊形畫出來;

    pDC->SelectObject(oldBrush);

    // TODO: add draw code for native data here
}

 

這個時候運行程序,將會看到在視類客戶區200,200,100,100的位置出現一個矩形區域,因為bDraw參數為false,此時並沒有畫出橢圓。如下圖:

2

第四步:

如何像例子中的那樣隨着鼠標的移動自動在橢圓的周圍改變光標呢?很簡單只要將下面的代碼加入到CRectTrackeView::OnSetCursor()就可以了:它調用了CRectTracker中的SetCursor()函數。 注意:OnSetCursor是一個消息響應函數,當鼠標在改矩形區域中的時候,會產出消息,並調用OnSetCursor函數。

BOOL CRectTrackeView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
    // TODO: Add your message handler code here and/or call default

    CRectTrackeDoc* pDoc = GetDocument();

    if((pWnd == this) && (pDoc->m_RectTracker.SetCursor(this,nHitTest)))
    {
        return TRUE;
    }
    
    return CView::OnSetCursor(pWnd, nHitTest, message);
}

編譯運行一下,鼠標變化了。

第五步:

添加鼠標左鍵按下消息響應函數,該函數功能呢:當在矩形區域內點擊左鍵並拖動的時候,則在矩形區域內把橢圓繪制出來, 當在矩形區域外點擊鼠標左鍵並拖動的時候,則重新繪制一個矩形區域。運行結果如第一張圖。

void CRectTrackeView::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    //判斷鼠標點擊的區域是在哪里,在在矩形區域內,還是區域外
    int nRetCode = GetDocument()->m_RectTracker.HitTest(point);

    if(nRetCode < 0)            //不在矩形區域
    {
        //給temp變量初始化
        CRectTracker  temp;
         temp.m_rect.SetRect(0,0,0,0);
         temp.m_nStyle = CRectTracker::dottedLine | CRectTracker::resizeInside;

        //TrackRubberBand函數直到鼠標左鍵提起的時候才會返回,並把左鍵提起的位置也記錄了下來
        //該函數過程中,不會產生鼠標移動消息
        temp.TrackRubberBand(this,point,TRUE);
        //使得矩形為正確的坐標,不會出現負的坐標
        temp.m_rect.NormalizeRect();
        //此時把bDraw設為false
         bDraw = FALSE;
         CClientDC dc(this);
        //把新的矩形區域繪制出來
        temp.Draw(&dc);
    }
    else                        //在矩形區域內
    {
        //Track和TrackRubberBand類似,直到鼠標左鍵提起的時候才會返回,並把左鍵提起的位置也記錄了下來
        //該函數過程中,不會產生鼠標移動消息
        GetDocument()->m_RectTracker.Track(this,point,TRUE);
        //設置為true,則需要在矩形內繪制橢圓
        bDraw = TRUE;

        //窗口無效,調用Onpaint函數
        Invalidate(TRUE);
    }
    
    CView::OnLButtonDown(nFlags, point);
}

編譯運行,當你按下鼠標並拖動,你將看到效果了。

我們如何讓鼠標畫一個“橡皮筋”區域呢? 在CRectTracker類中的成員函數就是:TrackRubberBand(this,point,TRUE); 注意其中的三個參數:

第一個參數,畫“橡皮筋”的窗體的指針,當然是this; 第二個參數,畫“橡皮筋”的起始點。 讓我們注意第三個參數,它非常有意思。當你使用 FALSE時(TRUE 值是缺省的),你的“橡皮筋”只能從左上到右下的畫,不允許反向。也就是不能夠從下往上繪圖。編譯運行一下FALSE這個值。

特別值得注意的是:在TrackRubberBand的過程中是以右鍵的抬起為結束的,這其間並沒有CView的MouseMove發生。這一點一定要記住!這時鼠標畫過的區域已經記錄在temp的m_rect 中了,你可以根據它進行后續的判斷工作。至於下面的正規化語句函數的作用與CRect中的正規化函數的作用一致:使四邊形的四個角的坐標符合右大於左,底大於頂的坐標值。它主要是為了防止你使用TrackRubberBand 的FALSE參數而引起的可能出現的錯誤。

HitTest(CPoint point)的功能:當你鼠標被按下的時候,你可以調用這個函數,它將返回鼠標點在了四邊形的什么位置:

3

以上就是CRectTracker類的用法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM