在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; |
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)); |