当我们鼠标左键按下时,就有了一个点(消息响应,捕获其中一点),即源点
按住鼠标左键拖动,到左键松开的时候就有了另外一个点了。即终点
也就是说我们需要捕获两个消息按下和弹起,消息响应中能获取到两个点。
首先我们用的是API函数(全局的::)
要想作图,首先要获取一个DC的句柄。
全局SDK用::
当前VIEW类窗口的句柄m_hWnd;
MoveToEX
BOOL MoveToEx(
__in HDC hdc,
__in int X,
__in int Y,
__out LPPOINT lpPoint
);
The MoveToEx function updates the current position to the specified point and optionally returns the previous position.
更新当前的点到指定的点,选择性地返回先前的点。
BOOL LineTo(
__in HDC hdc,
__in int nXEnd,
__in int nYEnd
);
用当前画笔画一条线,从当前位置连到一个指定的点。这个函数调用完毕,当前位置变成x,y
当然别忘了释放DC
::ReleaseDC(m_hWnd,hdc)
代码如下:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ptOrigin=point;//这点在构造函数里要有定义
CView::OnLButtonDown(nFlags, point);
}
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
HDC hdc;
hdc=::GetDC(m_hWnd);//全局的
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc);
CView::OnLButtonUp(nFlags, point);
}
而在MFC中给我们提供了一个类了CDC
从CObject派生出来
CWnd::GetDC这和全局的GetDC是不一样的,见上文
这里用到是MoveTo不是MoveToEx。
Moves the current position to the point specified by x and y (or by point).
移动当前的点到用x,y指定的点或
point:
Specifies the new position. You can pass either a POINT structure or a CPoint object for this parameter
有两个版本:
CPoint MoveTo(
int x,
int y
);
CPoint MoveTo(
POINT point
);
接下来用CDC::LineTo,不解释
当然还得释放ReleaseDC。
关键代码:
CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);
这样更容易地画出了一条直线。
下面我们再换一个方式:(这么多方法?)
这里又有一个类了CClient,派生自CDC
构造的时候调用GetDC,析构的时候调用ReleaseDC
CClientDC dc(this);因为是在View类里作图,所以直接用this指针传递
这里构造的是对象不是指针所以用点操作符调用成员函数
这样又一种方法又产生了(一种比一种包装的深)
代码:
CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
如果把this换成GetParent()的话我们发现画线都能画到工具栏上面。
这个函数能返回指向父窗口的指针。
而Cview是从CFrame派生来的
接下来又讲了一个CwindowDC类,哎两个多小时的视频
还是从CDC派生来的
构造的时候调用GetDC,析构的时候调用ReleaseDC
比CCLient还高级
最牛逼的地方在于它的对象能访问屏幕区域,包括客户区和非客户区。
一样的,它需要一个Cwnd的指针去构造。
参数为this和GetParent()的时候不咋样,
C++6.0能到画到标题栏,2010就不能了
如果参数用的是GetDesktopWindow()那就牛逼了,直接画到了桌面上了。
下面我们看一下如何画出其他颜色的线条
上面的程序用的是缺省的画笔。我们可以创建画笔,然后选到我们的设备描述表中
画笔类CPen
CPen::CPen
CPen(
int nPenStyle,
int nWidth,
COLORREF crColor
);
CPen(
int nPenStyle,
int nWidth,
const LOGBRUSH* pLogBrush,
int nStyleCount = 0,
const DWORD* lpStyle = NULL
);
例如Pen(PS_SOLID, 2, RGB(255,0,0))
第二个参数为笔的宽度,
COLORREF RGB
(BYTE byRed,
BYTE byGreen,
BYTE byBlue)
三个参数取值范围都是0-255.
(0,0,0)为黑
(255,255,255)为白
代表了红绿蓝三原色。相当于调色板
笔创建完之后要把笔选到设备描述表中
CDC::SelectObject()当然做完之后要选择回去
代码:
CPen pen(PS_SOLID, 2, RGB(255,0,0));
CClientDC dc(this);
CPen *pOldPen=dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(&pen);//选择回去
注意PS_DASH为画阴影线,MSDN上说了,必须是宽度小于等于1时才有效
类似PS_DOT等画笔风格
接下来是画刷的创建(画刷用来填充一块矩形区域)
又是类CBrush,可以用一种颜色去构造画刷(RGB)
用到函数FillRect(),用指定的画刷去填充矩形区域,第一个参数为矩形区域(CRect的构造函数),第二个参数当然就是画刷了。
我们现在正好有两个点,两点也可以确定一个矩形哦。
上代码:
CBrush brush(RGB(255,0,0,));
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
完事,矩形就这么画出来了
还是画矩形,但是是空心的
用Rectangle(可以用CRect(去构造)
BOOL Rectangle(
int x1,
int y1,
int x2,
int y2
);
BOOL Rectangle(
LPCRECT lpRect
);
代码:
dc.Rectangle(CRect(m_ptOrigin,point));
画出来就发现会相互覆盖,怎么办呢?创建透明画刷
用到了GetStockObject(NULL_BRUSH)
The GetStockObject function retrieves a handle to one of the stock pens, brushes, fonts, or palettes.
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
各种转换啊。
(1)CBrush::FromHandle
Returns a pointer to a CBrush object when given a handle to a Windows HBRUSH object.
CPen *pOldPen=dc.SelectObject(&pen);
if(m_bDraw==TRUE)//这里弄错了,导致我的错误半天楞是没看出来。
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin=point;
}
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen *pOldPen=dc.SelectObject(&pen);
if(m_bDraw==TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin=point;
}
dc.SelectObject(pOldPen);
接下来我们试试画个扇形,首先得再增加一个变量
关键代码:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
m_ptOrigin=m_ptOld=point;//鼠标按下时,这个函数捕获了当前点,即point,然后再赋给这两个点
void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
CClientDC dc(this);
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen *pOldPen=dc.SelectObject(&pen);
if(m_bDraw==TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(m_ptOld);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOld=point;
}
dc.SelectObject(pOldPen);
上边这几行看不怎么明白,不知道老师怎么想的
反正我用
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
这两行就实现了。
好像是为了讲后面的带边线用的
dc.MoveTo(m_ptOrigin);
dc.LineTo(m_ptOld);
dc.MoveTo(m_ptOld);
dc.LineTo(point);
m_ptOld=point;
不咋明白,以后回来看吧