按住左鍵拖曳 → 顯示反相線條(橡皮筋效果)→ 釋放左鍵 → 線條固定保留。經典「50 個 VC++ 必做範例」之一。
class CMouseView : public CView {
CString m_ClassName;
int m_Dragging = 0; // 0=靜止 1=拖曳中
HCURSOR m_HCross; // 十字光標
CPoint m_PointOld; // 上一個端點
CPoint m_pointOrigin; // 起點
};
CMouseView::CMouseView() {
m_Dragging = 0;
m_HCross = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
}
void CMouseView::OnLButtonDown(UINT nFlags, CPoint point) {
m_pointOrigin = m_PointOld = point;
SetCapture(); m_Dragging = 1;
CRect rc; GetClientRect(&rc); ClientToScreen(&rc);
::ClipCursor(&rc); // 限制滑鼠不超出客戶區
}
void CMouseView::OnMouseMove(UINT nFlags, CPoint point) {
::SetCursor(m_HCross);
if (!m_Dragging) return;
CClientDC dc(this);
dc.SetROP2(R2_NOT); // 反相模式:畫兩次即還原
// 擦除舊線
dc.MoveTo(m_pointOrigin); dc.LineTo(m_PointOld);
// 畫新線
m_PointOld = point;
dc.MoveTo(m_pointOrigin); dc.LineTo(m_PointOld);
}
void CMouseView::OnLButtonUp(UINT nFlags, CPoint point) {
if (!m_Dragging) return;
m_Dragging = 0; ReleaseCapture(); ::ClipCursor(NULL);
CClientDC dc(this);
dc.SetROP2(R2_NOT);
// 擦除最後一條橡皮筋線
dc.MoveTo(m_pointOrigin); dc.LineTo(m_PointOld);
// 以正常模式畫出永久線條
dc.SetROP2(R2_COPYPEN);
dc.MoveTo(m_pointOrigin); dc.LineTo(m_PointOld);
}
R2_NOT 光柵運算:像素反相,同一條線畫兩次即可還原背景,無需雙緩衝。SetCapture 讓視窗持續接收 `WM_MOUSEMOVE` 即使滑鼠移出客戶區。ClipCursor 選用,防止拖曳時滑鼠跑到螢幕邊緣導致座標異常。