參考
https://blog.csdn.net/chenjie863/article/details/17531339 未實驗
https://blog.csdn.net/bsnry/article/details/8484047
https://blog.csdn.net/Yuer_Arya/article/details/82052451
在我們在使用微軟的繪圖程序時。當要畫一條直線,先用鼠標確定起始位置,然后鼠標在屏幕上來回移動時,我們會發現,這條直線就像橡皮筋一樣,隨着鼠標在屏幕中的位置,長短和終點都隨之變化。我們在編制自己的程序時,有時也需實現類似的功能,本文將通過簡單的編程實例,並說明實現原理。
一。實現原理:
利用了WINDOWS繪圖模式中的“異或”的繪圖特性。即在屏幕上用異或的模式畫圖形,然后再用異或的模式,在相同的位置重新畫一次此圖形,則就會在屏幕上擦出掉上一次所繪制的內容。
具體在程序中,
1。當按下鼠標左鍵時,用異或的繪圖模式在屏幕上畫圖形。
2。當鼠標移動后,先用異或的繪圖模式擦掉上次繪制的圖形。然后在新的位置繪制圖形。
3。當鼠標左鍵被抬起時。在最終的位置用正常的顏色重新繪制圖形。結束。
要解決這個問題,需要先了解SetROP2函數的兩個參數R2_NOT與R2_NOTXORPEN的使用效果,以下為該兩種繪畫模式舉例:
- R2_NOTXORPEN繪畫模式
你用紅色畫筆在黑色背景上畫一條直線,顯示紅色,但你再用這只筆在剛畫的直線上重畫一遍,就相當於把開始畫的紅線擦除掉了,划線的地方顯示為背景色。 - R2_NOT繪畫模式
同樣有在同一個地方畫兩次相當於什么都沒畫的功能,不過R2_NOT繪畫模式第一次畫的時候顯示顏色並不是你選定的畫筆顏色,而是默認的顏色。
當了解以上兩種繪畫模式后,我們就可以實現拖動鼠標時平滑繪制出動態的矩形框,假設在鼠標移動過程中經過點A, 以點A為末點繪制一個矩形框,接着鼠標移動到下一個點B時,在點B繪制矩形前,再次以點A繪制一次矩形,利用R2_NOT的模式特定,再次繪畫末點A后,原來的矩形會被擦除(在同一個地方畫兩次相當於什么都沒畫的功能),最后在以點B作為末點,繪制矩形
CPoint m_chRegionLeftTopPoint;//開始點
CPoint m_chRegionRightBottomPoint;//結束點
BOOL m_fLButtonDownNotUp = FALSE;//鼠標是否按下
void CmfcimageDlg::OnLButtonDown(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//獲得屏幕坐標 ScreenToClient(&m_picRect);//轉到客戶區相對坐標 //記錄起始點坐標 m_fLButtonDownNotUp = true; if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { m_chRegionLeftTopPoint = point; m_chRegionRightBottomPoint = point; } CDialogEx::OnLButtonDown(nFlags, point); } void CmfcimageDlg::OnMouseMove(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//獲得屏幕坐標 ScreenToClient(&m_picRect);//轉到客戶區相對坐標 if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { if (m_fLButtonDownNotUp) { /* 當了解以上兩種繪畫模式后,我們就可以實現拖動鼠標時平滑繪制出動態的矩形框, 1 假設在鼠標移動過程中經過點A, 以點A為末點繪制一個矩形框, 2 接着鼠標移動到下一個點B時,在點B繪制矩形前,再次以點A繪制一次矩形, 3 利用R2_NOT的模式特定,再次繪畫末點A后,原來的矩形會被擦除(在同一個地方畫兩次相當於什么都沒畫的功能), 4 最后在以點B作為末點,繪制矩形! */ CDC* pDC = GetDlgItem(IDC_PIC_SHOW)->GetDC(); CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH); CPen* pen = new CPen(PS_SOLID, 1, RGB(0, 255, 0)); CPen* oldPen = pDC->SelectObject(pen); pDC->SelectObject(pOldBrush); pDC->SetROP2(R2_NOTXORPEN); pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint));//第二次畫出A點,那么上次畫的框會消失 m_chRegionRightBottomPoint = point; pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint));//畫出B點 pDC->SelectObject(oldPen); delete pen; } } CDialogEx::OnMouseMove(nFlags, point); } void CmfcimageDlg::OnLButtonUp(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//獲得屏幕坐標 ScreenToClient(&m_picRect);//轉到客戶區相對坐標 // if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { if (m_fLButtonDownNotUp) { m_chRegionRightBottomPoint = point; //繪制矩形 CDC* pDC = GetDlgItem(IDC_PIC_SHOW)->GetDC(); CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH); CPen* pen = new CPen(PS_SOLID, 1, RGB(0, 255, 0)); CPen* oldPen = pDC->SelectObject(pen); pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint)); pDC->SelectObject(pOldBrush); pDC->SelectObject(oldPen); delete pen;
} } m_fLButtonDownNotUp = false; CDialogEx::OnLButtonUp(nFlags, point); }