VC++ MFC橡皮筋技術

在MFC下繪製直線,使用橡皮筋技術,可以使直線效果跟隨鼠標移動

//OnLButtionDown
       m_ptOrigin = m_ptEnd = point; 
//OnMouseMove
    CClientDC dc(this);
    if (nFlags == MK_LBUTTON )
    {
        dc.SetROP2(R2_NOT);
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);
        m_ptEnd = point;
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);
    } 
但是這個只能實現黑色直線的繪製,我們想要畫其他顏色的線,並且希望使用不同類型的線和線寬,因此要建一個畫筆,指定想要的畫筆的類型,如實線、虛線、點線,指定線寬和畫筆顏色。
void CGraphic1View::OnMouseMove(UINT nFlags, CPoint point) 
{    
    if(MK_LBUTTON == nFlags)
    {
        CClientDC dc(this);
        int oldmode=dc.SetROP2(R2_NOTXORPEN);
        CPen pen(m_nLineStyle, m_nLineWidth, m_clr), *oldpen;
        oldpen = dc.SelectObject(&pen);

        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);

        m_ptEnd=point;

        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);

        dc.SelectObject(oldpen);
        dc.SetROP2(oldmode);
        ReleaseDC(&dc);
    }
    CScrollView::OnMouseMove(nFlags, point);
}
其中
CPen pen(m_nLineStyle, m_nLineWidth, m_clr), *oldpen;
m_nLineStyle是線型,m_nLineWidth是線寬,m_clr是畫筆顏色,也可以指定如下:
CPen pen(0, 0, RGB(255, 0, 0)), *oldpen;

 

下面說一下,橡皮筋效果是如何實現的。當我們按下鼠標左鍵後,有m_ptOrigin = m_ptEnd = point; 
這時鼠標移動就會發送WM_MOUSEMOVE消息,調用OnMouseMove進行處理,我們就在這個響應函數中實現橡皮筋的效果。if(MK_LBUTTON == nFlags)判斷是否左鍵按下的鼠標移動。SetROP2函數主要用於設定當前前景色的混合模式。參數取值R2_NOT就是取反的意思,即前景色爲背景色的反色,經常用R2_NOT來畫橡皮線,因爲兩次取反可以還原背景色,但是隻能話黑色的線。

而R2_NOTXORPEN畫出來的顏色與R2_XORPEN相反,R2_XORPEN是屏幕顏色和畫筆顏色的異或。OnMouseMove第一次被調用時,還沒畫線,所以屏幕的顏色是白色的,R2_XORPEN是當前畫筆的顏色取反,那麼R2_NOTXORPEN就是當前畫筆顏色了。就是說第一次畫的線是畫筆的顏色。

第二次調用OnMouseMove時,m_ptOrigin和m_ptEnd兩個點還沒變,所以可以用這兩個點再畫線,將第一次畫的線覆蓋掉,變成畫布的顏色,然後在新的point點和m_ptOrigin之間重新畫線,顏色爲畫筆顏色。在舊的直線上面畫線,因爲線本來有顏色,所以R2_XORPEN(屏幕的顏色==畫筆顏色)就會變成黑色(1 xor 1=0,0 xor 0=0),取反,即R2_NOTXORPEN爲白色,就是畫布的顏色,看起來就像消失了一樣,其實只不過是線變成白色了(如果畫筆不是白色,比如使用你係統設置了護眼配色,客戶區變成不傷眼的淺綠色,這樣顯示出來的顏色還是白色,而不是客戶區的顏色)。舊的直線刪除了,就可以在新的點point上再次畫線了。

 

擴展:如果想實現矩形、橢圓的橡皮筋效果將語句

dc.MoveTo(m_ptOrigin);    
dc.LineTo(m_ptEnd);
換成:
dc.Rectangle(CRect(this->m_ptOrigin, m_ptEnd));
或者
dc.Ellipse(CRect(this->m_ptOrigin, m_ptEnd));
就可以了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章