以矩形元素为例,为其增加移动、拉伸大小相关功能
定义位置类型
enum EcPosType
{
Null = -1,
TopLeft,
TopCenter,
TopRight,
RightCenter,
BottomRight,
BottomCenter,
BottomLeft,
LeftCenter,
SelectRect,
};
在基类CEleBase中定义操作点、鼠标光标以及操作点计算相关代码
class CEleBase : public SWindow
{
//....
public:
SOUI::CRect m_rcPos[8];
HCURSOR m_hCursorLeft, m_hCursorRight, m_hCursorTop, m_hCursorBottom,
m_hCursorTopLeft, m_hCursorTopRight, m_hCursorBottomLeft, m_hCursorBottomRight,
m_hCursorHand, m_hCursorArrow, m_hCursorSelect;
public:
void CalcPos();
EcPosType HitPos(SOUI::CPoint& pt);
void ShowCursor(EcPosType ePos);
}
CEleBase::CEleBase()
{
//...
m_hCursorSelect = LoadCursor(NULL, IDC_SIZEALL);
m_hCursorTopRight = LoadCursor(NULL, IDC_SIZENESW);
m_hCursorBottomRight = LoadCursor(NULL, IDC_SIZENWSE);
m_hCursorTop = LoadCursor(NULL, IDC_SIZENS);
m_hCursorBottom = LoadCursor(NULL, IDC_SIZENS);
m_hCursorLeft = LoadCursor(NULL, IDC_SIZEWE);
m_hCursorRight = LoadCursor(NULL, IDC_SIZEWE);
m_hCursorTopLeft = LoadCursor(NULL, IDC_SIZENWSE);
m_hCursorBottomLeft = LoadCursor(NULL, IDC_SIZENESW);
m_hCursorHand = LoadCursor(NULL, IDC_HAND);
m_hCursorArrow = LoadCursor(NULL, IDC_ARROW);
}
void CEleBase::CalcPos()
{
CRect rc = GetClientRect();
rc.InflateRect(2, 2, 2, 2);
SOUI::CPoint center = rc.CenterPoint();
m_rcPos[(int)EcPosType::TopLeft].SetRect(rc.left, rc.top, rc.left + 8, rc.top + 8);// 上左 方块
m_rcPos[(int)EcPosType::TopCenter].SetRect(center.x - 4, rc.top, center.x + 4, rc.top + 8);// 上中 方块
m_rcPos[(int)EcPosType::TopRight].SetRect(rc.right - 8, rc.top, rc.right, rc.top + 8);// 上右 方块
m_rcPos[(int)EcPosType::RightCenter].SetRect(rc.right - 8, center.y - 4, rc.right, center.y + 4);// 右中 方块
m_rcPos[(int)EcPosType::BottomRight].SetRect(rc.right - 8, rc.bottom - 8, rc.right, rc.bottom);// 下右 方块
m_rcPos[(int)EcPosType::BottomCenter].SetRect(center.x - 4, rc.bottom - 8, center.x + 4, rc.bottom);// 下中 方块
m_rcPos[(int)EcPosType::BottomLeft].SetRect(rc.left, rc.bottom - 8, rc.left + 8, rc.bottom);// 下左 方块
m_rcPos[(int)EcPosType::LeftCenter].SetRect(rc.left, center.y - 4, rc.left + 8, center.y + 4);// 左中 方块
}
EcPosType CEleBase::HitPos(SOUI::CPoint& pt)
{
CPoint pt2(pt);
for (int i = 0; i < 8; ++i)
{
if (m_rcPos[i].PtInRect(pt2))
return EcPosType(i);
}
return EcPosType::Null;
}
void CEleBase::ShowCursor(EcPosType ePos)
{
switch (ePos)
{
case EcPosType::TopLeft:
case EcPosType::BottomRight:
::SetCursor(m_hCursorTopLeft);
break;
case EcPosType::TopCenter:
case EcPosType::BottomCenter:
::SetCursor(m_hCursorTop);
break;
case EcPosType::TopRight:
case EcPosType::BottomLeft:
::SetCursor(m_hCursorTopRight);
break;
case EcPosType::LeftCenter:
case EcPosType::RightCenter:
::SetCursor(m_hCursorLeft);
break;
case EcPosType::SelectRect:
::SetCursor(m_hCursorSelect);
break;
case EcPosType::Null:
::SetCursor(m_hCursorSelect);
break;
default:
break;
}
}
在Rect元素中绘制操作点
void CEleRect::OnPaint(IRenderTarget* pRT)
{
//...
CalcPos();
if (m_bSelected)
{
CAutoRefPtr<IBrush> brush, oldbrush;
pRT->CreateSolidColorBrush(RGBA(255, 0, 0, 255), &brush);
pRT->SelectObject(brush, (IRenderObj**)&oldbrush);
for (int i = 0; i < 8; ++i)
{
CRect rcDot(m_rcPos[i]);
pRT->FillRectangle(rcDot);
}
pRT->SelectObject(oldbrush, NULL);
}
}
定义元素鼠标事件
#pragma once
#include "CEleBase.h"
class CEleRect : public CEleBase
{
DEF_SOBJECT(SWindow, L"ele_rect")
public:
CEleRect();
~CEleRect();
public:
void OnPaint(IRenderTarget* pRT);
protected:
LRESULT OnCreate(LPVOID);
void OnLButtonDown(UINT nFlags, SOUI::CPoint point);
void OnLButtonUp(UINT nFlags, SOUI::CPoint point);
void OnMouseMove(UINT nFlags, SOUI::CPoint point);
void OnLButtonDblClk(UINT nFlags, SOUI::CPoint point);
void OnRButtonUp(UINT nFlags, CPoint point);
protected:
SOUI_MSG_MAP_BEGIN()
MSG_WM_CREATE(OnCreate)
MSG_WM_PAINT_EX(OnPaint)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
MSG_WM_RBUTTONUP(OnRButtonUp)
MSG_WM_MOUSEMOVE(OnMouseMove)
SOUI_MSG_MAP_END()
private:
CPoint m_ptDown;
EcPosType m_curEcPosType;
};
void CEleRect::OnLButtonDown(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
SetCapture();
m_ptDown = point;
m_bSelected = true;
EcPosType posType = HitPos(point);
ShowCursor(posType);
m_curEcPosType = posType;
Invalidate();
}
void CEleRect::OnLButtonUp(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
ReleaseCapture();
switch (m_curEcPosType)
{
case Null:
{
CPoint ptLT(m_ptLT);
int nWid = m_ptRB.x - m_ptLT.x;
int nHei = m_ptRB.y - m_ptLT.y;
if (m_ptDown.x > point.x)
ptLT.x -= (m_ptDown.x - point.x);
else
ptLT.x += (point.x - m_ptDown.x);
if (m_ptDown.y > point.y)
ptLT.y -= (m_ptDown.y - point.y);
else
ptLT.y += (point.y - m_ptDown.y);
if (ptLT.x < 0) ptLT.x = 0;
if (ptLT.y < 0) ptLT.y = 0;
SStringW sstrPos;
sstrPos.Format(L"%d,%d", ptLT.x, ptLT.y);
SetAttribute(L"pos", sstrPos);
CPoint ptRB(ptLT.x + nWid, ptLT.y + nHei);
m_ptLT = ptLT;
m_ptRB = ptRB;
}
break;
case TopLeft:
{
CPoint ptLT(m_ptLT);
if (m_ptDown.x > point.x) //x往左
ptLT.x -= (m_ptDown.x - point.x);
else//x往右
ptLT.x += (point.x - m_ptDown.x);
if (m_ptDown.y > point.y)//y往上
ptLT.y -= (m_ptDown.y - point.y);
else //y往下
ptLT.y += (point.y - m_ptDown.y);
if (ptLT.x < 0)
ptLT.x = 0;
if (ptLT.y < 0)
ptLT.y = 0;
int nWid = m_ptRB.x - ptLT.x;
int nHei = m_ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
CalcPos();
}
break;
case TopCenter:
{
CPoint ptLT(m_ptLT);
if (m_ptDown.y > point.y)//y往上
ptLT.y -= (m_ptDown.y - point.y);
else //y往下
ptLT.y += (point.y - m_ptDown.y);
if (ptLT.y < 0)
ptLT.y = 0;
int nWid = m_ptRB.x - ptLT.x;
int nHei = m_ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
CalcPos();
}
break;
case TopRight:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptLT.y -= m_ptDown.y - point.y;
else
ptLT.y += point.y - m_ptDown.y;
if (ptLT.y < 0)
ptLT.y = 0;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case RightCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case BottomRight:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case BottomCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case BottomLeft:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptLT.x -= m_ptDown.x - point.x;
else
ptLT.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case LeftCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptLT.x -= m_ptDown.x - point.x;
else
ptLT.x += point.x - m_ptDown.x;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
m_ptLT = ptLT;
m_ptRB = ptRB;
CalcPos();
}
break;
case SelectRect:
break;
default:
break;
}
m_curEcPosType = Null;
Invalidate();
}
void CEleRect::OnMouseMove(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
ShowCursor(HitPos(point));
if ((nFlags & MK_LBUTTON))
{
switch (m_curEcPosType)
{
case Null:
{
CPoint ptPos(m_ptLT);
if (m_ptDown.x > point.x)
ptPos.x -= (m_ptDown.x - point.x);
else
ptPos.x += (point.x - m_ptDown.x);
if (m_ptDown.y > point.y)
ptPos.y -= (m_ptDown.y - point.y);
else
ptPos.y += (point.y - m_ptDown.y);
if (ptPos.x < 0) ptPos.x = 0;
if (ptPos.y < 0) ptPos.y = 0;
SStringW sstrPos;
sstrPos.Format(L"%d,%d", ptPos.x, ptPos.y);
SetAttribute(L"pos", sstrPos);
}
break;
case TopLeft:
{
CPoint ptPos(m_ptLT);
if (m_ptDown.x > point.x) //x往左
ptPos.x -= (m_ptDown.x - point.x);
else//x往右
ptPos.x += (point.x - m_ptDown.x);
if (m_ptDown.y > point.y)//y往上
ptPos.y -= (m_ptDown.y - point.y);
else //y往下
ptPos.y += (point.y - m_ptDown.y);
if (ptPos.x < 0)
ptPos.x = 0;
if (ptPos.y < 0)
ptPos.y = 0;
int nWid = m_ptRB.x - ptPos.x;
int nHei = m_ptRB.y - ptPos.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptPos.x, ptPos.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case TopCenter:
{
CPoint ptPos(m_ptLT);
if (m_ptDown.y > point.y)//y往上
ptPos.y -= (m_ptDown.y - point.y);
else //y往下
ptPos.y += (point.y - m_ptDown.y);
if (ptPos.y < 0)
ptPos.y = 0;
int nWid = m_ptRB.x - ptPos.x;
int nHei = m_ptRB.y - ptPos.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptPos.x, ptPos.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case TopRight:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptLT.y -= m_ptDown.y - point.y;
else
ptLT.y += point.y - m_ptDown.y;
if (ptLT.y < 0)
ptLT.y = 0;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case RightCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case BottomRight:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptRB.x -= m_ptDown.x - point.x;
else
ptRB.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case BottomCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case BottomLeft:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptLT.x -= m_ptDown.x - point.x;
else
ptLT.x += point.x - m_ptDown.x;
if (m_ptDown.y > point.y) //to down
ptRB.y -= m_ptDown.y - point.y;
else
ptRB.y += point.y - m_ptDown.y;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case LeftCenter:
{
CPoint ptLT(m_ptLT);
CPoint ptRB(m_ptRB);
if (m_ptDown.x > point.x) //to left
ptLT.x -= m_ptDown.x - point.x;
else
ptLT.x += point.x - m_ptDown.x;
int nWid = ptRB.x - ptLT.x;
int nHei = ptRB.y - ptLT.y;
SStringW sstrPos;
sstrPos.Format(L"%d,%d,@%d,@%d", ptLT.x, ptLT.y, nWid, nHei);
SetAttribute(L"pos", sstrPos);
}
break;
case SelectRect:
break;
default:
break;
}
}
Invalidate();
}
void CEleRect::OnLButtonDblClk(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
}
void CEleRect::OnRButtonUp(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
}