CDC::DrawDragRect
void DrawDragRect(
LPCRECT lpRect,
SIZE size,
LPCRECT lpRectLast,
SIZE sizeLast,
CBrush* pBrush = NULL,
CBrush* pBrushLast = NULL
);
参数:
lpRect | 指向RECT结构或CRect对象的指针。它包含指定矩形的逻辑坐标--在此情况下,矩形的端点位置将被重新绘制。 |
size | 指定矩形外边界的左上角与内边界的左上角的偏移量(即边界的厚度)。 |
lpRectLast | 指向RECT结构或CRect对象的指针。它包含指定矩形的逻辑坐标,在此情况下,矩形的原始位置处于重新绘制状态。 |
sizeLast | 指定重新绘制的矩形的外边界的左上角与内边界的左上角的偏移量(即边界的厚度)。 |
pBrush | 指向画刷的指针。设置为NULL时,使用缺省的黑白画刷。 |
pBrushLast | 指向最近使用的画刷指针。 |
说明:
反复调用该成员函数以重新绘制一个拖动的矩形。为得到视觉反馈,可以在指定鼠标位置后循环调用该函数。当调用DrawDragRect后,前一个矩形被抹去而重新绘制一个新矩形。例如,当用户在屏幕上拖动矩形时,DrawDragRect将抹去先前的一个,而在新位置上重新绘制。缺省地,DrawDragRect用黑白画刷绘制矩形,创建一个平滑移动的矩形。当第一次调用DrawDragRect时,lpRectLast参数应设置为NULL。
利用该函数在鼠标的移动事件中可以很方便的画出一个活动的虚线框,注意该函数接受的RECT或CRect必须为常态矩形,因此当矩形的宽或长为负数时,需要作特别的处理。
福新阅读器有一个截图的功能,先画出一个虚线框,然后将选定区域变为一个深蓝色的矩形。
m_ptStart = CPoint(0, 0);//起始坐标
m_rcEnd = CRect(0, 0, 0, 0);//释放鼠标时最终选定的矩形区域
void CXXXView::OnLButtonDown(UINT nFlags, CPoint point)
{
SetCapture();//捕捉鼠标,即使出了客户区,也能捕获
m_ptStart = point;//起始点
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&m_ptStart);//将设备坐标转换成逻辑坐标
dc.LPtoDP(&m_rcEnd);//将逻辑坐标转换成设备坐标
InvalidateRect(m_rcEnd);//必须是设备坐标,将前一个选定的矩形消除
m_rcEnd = CRect(0, 0, 0, 0);//重新初始化
}
void CXXXView::OnMouseMove((UINT nFlags, CPoint point)
{
if(nFlags == MK_LBUTTON)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);//将设备坐标转换成逻辑坐标
CRect rc;
static enum
{
center,
rightbottom,
righttop,
lefttop,
leftbottom
}position = center;//指示当前点相对起始点的象限
//是否是新的一次拖拽,是,则将m_rcEnd置零
if(position == rightbottom && m_rcEnd.TopLeft() != m_ptStart)//前一个矩形位于第四象限,而现在其左上角坐标不等于起始点,说明已经是新的一次选择
{
m_rcEnd = CRect(0, 0, 0, 0);
}
else if(position == righttop && CPoint(m_rcEnd.left, m_rcEnd.bottom) != m_ptStart)//m_ptStart为右键按下时的值
{
m_rcEnd = CRect(0, 0, 0, 0);
}
else if(position == lefttop && m_rcEnd.BottomRight() != m_ptStart)
{
m_rcEnd = CRect(0, 0, 0, 0);
}
else if(position == leftbottom && CPoint(m_rcEnd.right, m_rcEnd.top) != m_ptStart)
{
m_rcEnd = CRect(0, 0, 0, 0);
}
//根据相对位置判断象限并设置rc的正确值
if(point.x > m_ptStart.x)
{
if(point.y > m_ptStart.y)
{
position = rightbottom;
rc = CRect(m_ptStart, point);
}
else
{
position = righttop;
rc = CRect(m_ptStart.x, point.y, point.x, m_ptStart.y);
}
}
else
{
if(point.y < m_ptStart.y)
{
position = lefttop;
rc = CRect(point,m_ptStart);
}
else
{
position = leftbottom;
rc = CRect(point.x, m_ptStart.y, m_ptStart.x, point.y);
}
}
}
dc.LPtoDP(&rc);
dc.LPtoDP(&m_rcEnd);
dc.DrawDragRect(&rc, CSize(1, 1), &m_rcEnd, CSize(1, 1));//该函数调用的是设备坐标,第一次和新的一次拖拽,m_rcEnd都为零
dc.DPtoLP(&rc);//调用完毕后转换为逻辑坐标存储
m_rcEnd = rc;
}
void CXXXView::OnLButtonUp(UINT nFlags, CPoint piont)
{
ReleaseCapture();
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
if(point != m_ptStart)
{
dc.LPtoDP(&m_rcEnd);//转换为设备坐标
dc.DrawDragRect(m_rcEnd, CSize(0, 0), m_rcEnd, CSize(1, 1));//将最后的虚线框去掉
CBrush brush(RGB(0, 0, 255));
CBrush* pOldBrush;
CPen pen(PS_SOLID | PS_INSIDEFRAME, 3, RGB(0, 0, 0));//则3像素位于矩形内部
CPen* pOldPen;
int nOldROP;
pOldBrush = dc.SelectObject(&brush);
pOldPen = dc.SelectObject(&pen);
nOldROP = dc.SetROP2(R2_MASKPEN);//与操作,符合颜料的性质
dc.DPtoLP(&m_rcEnd);
dc.Rectangle(m_rcEnd);//该函数必须用逻辑坐标
dc.SelectObject(pOldBrush);
dc.SetROP2(nOldROP);
dc.SelectObject(pOldPen);
}
}