第4课绘图之一API画线【参考资料:孙鑫VC++教学视频】
我们仍旧开始直接实践:
★相关的知识是绘图方面的知识
现在用VC6直接实践一下MFC编程:
1、程序类型MFC AppWizard(exe)类型;
2、选择Single Document单文档应用程序
3、完成
第一项功能:绘制直线;
可以在框架类和视类里面捕获消息:
首先在框架类CMainFrame捕获消息按下左键:
第一步:增加鼠标左键消息响应;
对类名右键:New Window Message and Event handlers for class CMainFrame.
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
MessageBox("main frame");
CFrameWnd::OnLButtonDown(nFlags, point);
}
但是,在这个函数中写了 MessageBox("main frame"); 运行后却没有反应,为什么?
在view类里面同样增加一个鼠标左键按下响应函数:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
MessageBox("view frame");
CView::OnLButtonDown(nFlags, point);
}
当我们运行后,对鼠标左键就有响应了一个警告框;
★注意:用class wizard也能增加消息响应函数;
在框架类和视类里面的响应函数都存在,不妨碍;
原因:view类在框架类之上,覆盖在框架类之上;
第一趟:
消息循环,就是把消息放在消息队列当中。
消息映射,对消息的处理。
一, 在基类,对每一种消息,做一个虚函数,当响应的时候,只要重写虚函数就可以了。调用子类的,子类没有的,就调用父类的。子类都背负一个虚表。
二, 消息机制,MFC在后台维护了一个句柄,和C++类对象的对照的一个表。
虚函数 WindowProc函数对消息来处理。
OnWndMsg
双击一下CDrawView 就直接到了头文件里。
在用Ctrl+F 搜索的时候,按F3继续搜索。
第二步:用菜单命令增加私有成员变量CPoint m_ptOrigin=0; 初始化为0
响应鼠标左键按下函数为:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// 按下去的时候是起点
m_ptOrigin = point;
CView::OnLButtonDown(nFlags, point);
}
第三步:用菜单命令增加鼠标左键up响应函数 Add Handler 处理器 + Edit Existing 编辑现成的。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonUp(nFlags, point);
}
这里面的点就是画线的终点;改变代码如下:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
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);
}
以上我们采用了API函数,也就是全局函数来完成的;
API函数和类的成员函数都有ReleaseDC函数,所以调用API函数就要特别用作用域符号注明是API函数,如果不同名,则可以直接用;
实例: ::ReleaseDC(m_hWnd, hdc);
第4课绘图之二用CDC类画线【参考资料:孙鑫VC++教学视频】
MFC中所有画图的功能都集成到了CDC这个类中:
用CDC类绘制直线;
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CDC *pDC=GetDC();
//将设备移动到起点
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
//释放设备
ReleaseDC(pDC);
CView::OnLButtonUp(nFlags, point);
}
以上我们采用了CDC类画线,看起来很简洁;
第4课绘图之三CClientDC画线【参考资料:孙鑫VC++教学视频】
CClientDC类是从CDC这个类派生出来的;
优点:构造函数中调用GetDC;析构函数调用ReleaseDC;
也就是说用CClientDC类,就不用显示调用DetDC和ReleaseDC函数;
CClientDC绘制直线;
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CClientDC dc(this);
//将设备移动到起点
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
以上我们采用了CClientDC类画线,看起来更简洁;
用this指针传递,表示在CDrawView上做图;
下面 我想和CMainFrame类相关,如何获取父窗口的指针?
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CClientDC dc(GetParent());//父类的,会在框架窗口,会画在工具栏上。
//将设备移动到起点
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
第4课绘图之四CWindowDC画线【参考资料:孙鑫VC++教学视频】
CWindowDC类是从CDC这个类派生出来的;
优点:构造函数中调用GetDC;析构函数调用ReleaseDC;
也就是说用CClientDC类,就不用显示调用DetDC和ReleaseDC函数;
可以访问整个屏幕区域,包括客户区和非客户区;
CWindowDC绘制直线;
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CWindowDC dc(GetParent());
//将设备移动到起点
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
在标题栏+菜单栏上(非客户区)可以访问整个屏幕。
能否画到vc上,或者桌面上?
桌面本身就是一个窗口。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CWindowDC dc(GetDesktopWindow());
//将设备移动到起点
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
则可以画到vc上,或者桌面上;
第4课绘图之五CPen修改颜色【参考资料:孙鑫VC++教学视频】
★如何画其他颜色的线条?
CPen修改颜色
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
RGB这个宏 参数三个 红绿蓝 三个值的改变来调整颜色。
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//弹起来的时候是终点
CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); // 创建一个画笔
CClientDC dc(this);
CPen *pOldPen=dc.SelectObject(&pen); //这个笔选在设备表
//将设备移动到起点
dc.MoveTo(m_ptOrigin); 移动到原点。
dc.LineTo(point); 终点
dc.SelectObject(pOldPen); 先前的画笔选择
CView::OnLButtonUp(nFlags, point);
}
这是画出红色的直线;
阴影线 粗细只能1或者更小
以下代码是设置新笔,保存旧的笔;
CPen *pOldPen=dc.SelectObject(&pen);
第4课绘图之六CBrush填充区域【参考资料:孙鑫VC++教学视频】
★如何矩形区域区域颜色?
CBrush填充区域
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBrush brush(RGB(255,0,0));
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin, point), &brush);
//用指定的画刷来填充指定的矩形 ,当然也有自己缺省的画刷。
不用将brush选中在设备描述表中。都是指定的!! 指定的画刷,指定的矩形区域。
CView::OnLButtonUp(nFlags, point);
}
这是画出红色的矩形;
下面讨论位图画刷:
首先要添加一个位图资源,insert菜单里面resource,添加new了一个Bitmap,它的资源ID是IDB_BITMAP1,程序如下:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1); 加载这幅位图。
CBrush brush(&bitmap); 创建位图的画刷,位图对象的指针。
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin, point), &brush);
CView::OnLButtonUp(nFlags, point);
}
第4课绘图之七透明画刷【参考资料:孙鑫VC++教学视频】
★如何矩形区域不相互遮挡?
CBrush透明画刷
仍旧在视类里面捕获消息:
注意:画线的代码发生变化,其余步骤不变;
直接修改鼠标左键up响应函数
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//获取透明画刷对象指针
CClientDC dc(this);
CBrush *pOldBrush=dc.SelectObject(pBrush); //将透明画刷选入DC
dc.Rectangle(CRect(m_ptOrigin,point)); //画矩形
dc.SelectObject(pOldBrush); //释放透明画刷
CView::OnLButtonUp(nFlags, point);
}
画出的矩形相互不遮挡,也就是透明的;
★★★★★注意点:
1)静态方法不属于某一个具体对象,而属于类本身,在类加载的时候就已经为类静态方法分配了代码去,故可用CBrush::FromHandle()形式调用。非静态的方法,是属于某个对象的。
2)静态方法中,不能引用非静态的数据成员和方法。
3)静态数据成员需要在类外单独做初始化,形式如: 变量类型 类名::变量名=初始值;
第4课绘图之八曲线【参考资料:孙鑫VC++教学视频】
★如何绘制拖动的曲线?
绘制拖动的曲线
第一步:增加一个BOOL m_bDraw;
在构造函数中m_bDraw=FALSE;
鼠标左键按下down响应函数中设置m_bDraw=TRUE;
用这个变量表示鼠标按下;
CDrawView::CDrawView()
{
// TODO: add construction code here
m_ptOrigin=0;
m_bDraw=FALSE; 鼠标起来的时候
}
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// 按下去的时候是起点
m_ptOrigin = point;
m_bDraw=TRUE; 鼠标按下去的时候
CView::OnLButtonDown(nFlags, point);
}
增加鼠标左键move响应函数,用右击菜单栏添加
void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if(m_bDraw==TRUE)
{
dc.MoveTo(m_ptOrigin); 移动到原点,就是第一次按下去的时候
dc.LineTo(point);
m_ptOrigin=point; 下一个起点就是上一个终点
}
CView::OnMouseMove(nFlags, point);
}
SetROp2 是在CDC来的。绘画的模式的设置。