学习


```cpp
⑵创建Ribbon功能区。正确添加工具按钮图像,添加一个菜单资源并为其添加相应的菜单命令、设置属性。在CMainFrame类的InitializeRibbon函数中创建“绘图”列表,并且创建面板、添加工具按钮,代码如下:
void CMainFrame::InitializeRibbon()
{//……
//添加“绘图”类别
CMFCRibbonCategory* pCategoryDraw=m_wndRibbonBar.AddCategory(_T("绘图(&D)"),IDB_DRAWSMALL,IDB_DRAWLARGE);
//创建“工具”面板
CMFCRibbonPanel* pPanelTool=pCategoryDraw->AddPanel(_T("工具"));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_PEN,_T("画笔"),0,0));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_LINE,_T("直线"),1,1));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_RECT,_T("矩形"),2,2));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_ELLIPSE,_T("椭圆"),3,3));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_CIRCLE,_T("圆"),4,4));
pPanelTool->Add(new CMFCRibbonSeparator());
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_ERASER,_T("橡皮擦"),8,8));
pPanelTool->Add(new CMFCRibbonButton(ID_DRAW_TEXT,_T("文本"),9,9));
//创建“颜色”面板
CMFCRibbonPanel* pPanelColor=pCategoryDraw->AddPanel(_T("颜色"));
pPanelColor->Add(new CMFCRibbonButton(ID_DRAW_COLOR,_T("画笔颜色"),10,10));
pPanelColor->Add(new CMFCRibbonButton(ID_FILL_COLOR,_T("填充颜色"),11,11));
bNameValid=strTemp.LoadString(IDS_RIBBON_STYLE);
//……}
⑶新建绘图类。使用MFC向导添加新类CDrawShape,CDrawShape类的绘图成员根据绘图类型调用设备环境CDC中的函数绘制图形并指定颜色填充图形。
void CDrawShape::DrawPen(CDC* pDC, POINT point)
{
ASSERT(m_dwShapeType==SHAPE_PEN);//画笔
m_ptBegPoint=m_ptEndPoint;
m_ptEndPoint=point;
CPen *pOldPen,pen;
pen.CreatePen(PS_SOLID,1,m_crDrawColor);
pOldPen=(CPen*)pDC->SelectObject(&pen);
pDC->MoveTo(m_ptBegPoint);
pDC->LineTo(m_ptEndPoint);
pDC->SelectObject(pOldPen);
}
void CDrawShape::DrawLine(CDC* pDC,POINT point)
{
ASSERT(m_dwShapeType==SHAPE_LINE);//直线
m_ptEndPoint=point;
CPen *pOldPen,pen;
pen.CreatePen(PS_SOLID,1,m_crDrawColor);
pOldPen=(CPen*)pDC->SelectObject(&pen);
pDC->MoveTo(m_ptBegPoint);
pDC->LineTo(m_ptEndPoint);
pDC->SelectObject(pOldPen);
}
RECT CDrawShape::GetShapeRect(POINT ptBeg,POINT ptEnd)
{
CRect rtShape(ptBeg,ptEnd);//构造矩形
rtShape.NormalizeRect();
return rtShape;
}
void CDrawShape::DrawRect(CDC* pDC, POINT point)
{
ASSERT(m_dwShapeType==SHAPE_RECT);//矩形
m_ptEndPoint=point;
m_rtShapeRect=GetShapeRect(m_ptBegPoint,m_ptEndPoint);
CPen *pOldPen,pen; 
pen.CreatePen(PS_SOLID,1,m_crDrawColor);
pOldPen=(CPen*)pDC->SelectObject(&pen);
CBrush *pOldBrush,brush;
brush.CreateSolidBrush(m_crFillColor);
pOldBrush=(CBrush*)pDC->SelectObject(&brush);
pDC->Rectangle(&m_rtShapeRect);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
void CDrawShape::DrawEllipse(CDC* pDC, POINT point)
{
ASSERT(m_dwShapeType==SHAPE_ELLIPSE);//椭圆
m_ptEndPoint=point;
m_rtShapeRect=GetShapeRect(m_ptBegPoint,m_ptEndPoint);
CPen *pOldPen,pen; 
pen.CreatePen(PS_SOLID,1,m_crDrawColor);
pOldPen=(CPen*)pDC->SelectObject(&pen);
CBrush *pOldBrush,brush;
brush.CreateSolidBrush(m_crFillColor);
pOldBrush=(CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(&m_rtShapeRect);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
RECT CDrawShape::GetCircleRect(POINT ptBeg, POINT ptEnd)
{
CRect rtShape(CRect(ptBeg,ptEnd));//规范化矩形
rtShape.NormalizeRect();
int cx=rtShape.Width();
int cy=rtShape.Height();
int diameter=(cx<=cy)?cx:cy;
if(ptBeg.x<=ptEnd.x)
rtShape.left=ptBeg.x,rtShape.right=ptBeg.x+diameter;
else
rtShape.left=ptBeg.x-diameter,rtShape.right=ptBeg.x;
if(ptBeg.y<=ptEnd.y)
rtShape.top=ptBeg.y,rtShape.bottom=ptBeg.y+diameter;
else
rtShape.top=ptBeg.x-diameter,rtShape.bottom=ptBeg.y;
	return rtShape;
}
void CDrawShape::DrawCircle(CDC* pDC, POINT point)
{
ASSERT(m_dwShapeType==SHAPE_CIRCLE);//圆
m_ptEndPoint=point;
m_rtShapeRect=GetShapeRect(m_ptBegPoint,m_ptEndPoint);
CPen *pOldPen,pen; 
pen.CreatePen(PS_SOLID,1,m_crDrawColor);
pOldPen=(CPen*)pDC->SelectObject(&pen);
CBrush *pOldBrush,brush;
brush.CreateSolidBrush(m_crFillColor);
pOldBrush=(CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(&m_rtShapeRect);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
void CDrawShape::DrawEraser(CDC* pDC, POINT point)
{
ASSERT(m_dwShapeType==SHAPE_ERASER);//橡皮擦
m_ptBegPoint=m_ptEndPoint;
m_ptEndPoint=point;
CPen *pOldPen,pen; 
pen.CreatePen(PS_SOLID,8,RGB(255,255,255));
pOldPen=(CPen*)pDC->SelectObject(&pen);
pDC->MoveTo(m_ptBegPoint);
pDC->LineTo(m_ptEndPoint);
pDC->SelectObject(pOldPen);
}
⑷响应绘图命令,为工具命令添加消息响应函数。
void CMyPaint1View::OnDrawCircle()
{//圆
m_nDrawShape=SHAPE_CIRCLE;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawColor()
{//颜色
 m_nDrawShape=SHAPE_COLOR;
 CMFCColorDialog dlg(m_crDrawColor);
 if(dlg.DoModal()!=IDOK) return;
 m_crDrawColor=dlg.GetColor();
 if(m_bShowCaret) HideCaret();//隐藏插入符
 m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawEllipse()
{//椭圆
m_nDrawShape=SHAPE_ELLIPSE;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawEraser()
{//橡皮
m_nDrawShape=SHAPE_ERASER;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawLine()
{//直线
m_nDrawShape=SHAPE_LINE;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawPen()
{//画笔
m_nDrawShape=SHAPE_PEN;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawRect()
{//矩形
m_nDrawShape=SHAPE_RECT;
if(m_bShowCaret) HideCaret();//隐藏插入符
m_bShowCaret=FALSE;//未显示插入符
}
void CMyPaint1View::OnDrawText()
{
 m_nDrawShape=SHAPE_TEXT;
 if(m_bShowCaret) HideCaret();//隐藏插入符
 m_bShowCaret=FALSE;//未显示插入符
 m_strTextBuf=" ";
}
⑸实现图形绘制。分别响应鼠标左键按下、弹起及鼠标移动的消息。
void CMyPaint1View::OnLButtonDown(UINT nFlags, CPoint point)
{ 
if(m_nDrawShape!=SHAPE_TEXT&&PtInRect(&m_rtCanvas,point))
{
m_bDrawShape=TRUE;
if(m_pCurrShape!=NULL)
delete m_pCurrShape;
m_pCurrShape=new CDrawShape();
m_pCurrShape->m_dwShapeType=m_nDrawShape;
m_pCurrShape->m_crDrawColor=m_crDrawColor;
m_pCurrShape->m_crFillColor=m_crFillColor;
m_pCurrShape->StartDraw(point);
RECT rtClient=m_rtCanvas;
ClientToScreen(&rtClient);
ClipCursor(&rtClient);
}
else
{
	m_ptCaretPos=point;
	SetCaretPos(point);
	if(!m_bShowCaret)
		ShowCaret();
	m_strTextBuf=" ";
	m_bShowCaret=TRUE;
	m_bInputText=TRUE;
	m_bDrawShape=FALSE;
}
    ptStart=point;

    SetCapture();			//捕捉鼠标
	::SetCursor(m_hCross);		//设置十字光标
	m_ptOrigin=point;
	m_bDragging=TRUE;		//设置拖拽标记
CScrollView::OnMButtonDown(nFlags,point);
}
void CMyPaint1View::OnMouseMove(UINT nFlags, CPoint point)
{ 
	if(m_bDrawShape&&m_pCurrShape!=NULL)
	{CClientDC dc(this);
	switch(m_nDrawShape)
	{case SHAPE_PEN:
	m_pCurrShape->DrawPen(&dc,point);
	m_dcMemory.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&dc,0,0,SRCCOPY);
		break;
	case SHAPE_ERASER:
	m_pCurrShape->DrawEraser(&dc,point);
	m_dcMemory.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&dc,0,0,SRCCOPY);
		break;
	case SHAPE_LINE:
	dc.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&m_dcMemory,0,0,SRCCOPY);
		m_pCurrShape->DrawLine(&dc,point);
		break;
	case SHAPE_RECT:
	dc.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&m_dcMemory,0,0,SRCCOPY);
		m_pCurrShape->DrawRect(&dc,point);
		break;
	case SHAPE_CIRCLE:
		dc.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&m_dcMemory,0,0,SRCCOPY);
m_pCurrShape->DrawCircle(&dc,point);
		break;
	case SHAPE_ELLIPSE:
	dc.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&m_dcMemory,0,0,SRCCOPY);
		m_pCurrShape->DrawEllipse(&dc,point);
		break;
	default:
	  break;
	}
	}
	if(m_bDragging)
	{
		CClientDC  dc(this);
		dc.MoveTo(m_ptOrigin);
		dc.LineTo(point);		//绘制线段
		m_ptOrigin=point;//新的起始点

		ptEnd=point;
		dc.MoveTo(ptStart);
		dc.LineTo(ptEnd);		//绘制线段
		CMyPaint1Doc *pDoc=GetDocument();         //获得文档对象的指针
        ASSERT_VALID(pDoc);	//测试文档对象是否运行有效
        pDoc->AddLine(ptStart,ptEnd);//加入线段到指针数组
	    ptStart=ptEnd;	
		CPoint ptOrg;
		ptOrg=GetScrollPosition();	//获得当前工作区原点的坐标
		ptStart=ptStart+ptOrg;	//加上原点的坐标来修正线段的坐标
		ptEnd=point+ptOrg;
		pDoc->AddLine(ptStart,ptEnd); //加入线段到指针数组
	}
	CScrollView::OnMouseMove(nFlags,point);
}
void CMyPaint1View::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(m_bDrawShape&&m_pCurrShape!=NULL)
	{CClientDC dc(this);
	m_dcMemory.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&dc,0,0,SRCCOPY);
	ClipCursor(NULL);
	delete m_pCurrShape;
	m_pCurrShape=NULL;
	m_bDrawShape=FALSE;
	}
    if(m_bDragging)
	{
		m_bDragging=false;  //清除拖拽标记
		ReleaseCapture();     //释放鼠标,还原鼠标形状
	}
	CScrollView::OnLButtonUp(nFlags, point);
}
⑹实现文本输出。涉及到文本、颜色、插入符的位置。
创建插入符:
void CMyPaint1View::OnSetFocus(CWnd* pOldWnd)
{
	CScrollView::OnSetFocus(pOldWnd);
	CreateSolidCaret(2,-m_lfTextFont.lfHeight);
	SetCaretPos(m_ptCaretPos);
	if(m_bShowCaret) ShowCaret();
}
删处插入符:
void CMyPaint1View::OnKillFocus(CWnd* pNewWnd)
{
	CScrollView::OnKillFocus(pNewWnd);
	m_ptCaretPos=GetCaretPos();
	if(m_bShowCaret) HideCaret();
	DestroyCaret();
}
//字符处理
void CMyPaint1View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{ CSize sizeText;
CFont ft,*pOld;
int nLength=m_strTextBuf.GetLength();
ft.CreateFontIndirect(&m_lfTextFont);
pOld=(CFont*)m_dcMemory.SelectObject(&ft);
m_dcMemory.SetTextColor(m_crDrawColor);
HideCaret();
switch(nChar)
{
case 8:                        //退格
	if(nLength>0) m_strTextBuf.SetAt(nLength-1,' ');
	m_dcMemory.TextOut(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);
	if(nLength>0) m_strTextBuf.Delete(nLength-1);
	m_dcMemory.TextOut(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);
	sizeText=m_dcMemory.GetTextExtent(m_strTextBuf);
	SetCaretPos(CPoint(m_ptCaretPos.x+sizeText.cx,m_ptCaretPos.y));
	break;
case 13:                       //回车
	if(m_ptCaretPos.y+sizeText.cy<m_rtCanvas.bottom)
	{m_dcMemory.TextOut(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);
	m_strTextBuf=" ";
	sizeText=m_dcMemory.GetTextExtent(m_strTextBuf);}
	if(m_ptCaretPos.y+sizeText.cy<m_rtCanvas.bottom)
	{SetCaretPos(CPoint(m_ptCaretPos.x,m_ptCaretPos.y+sizeText.cy));
	m_ptCaretPos.y+=sizeText.cy;
	}
	break;
default:                     //其他字符
	m_strTextBuf+=(char)nChar;
	sizeText=m_dcMemory.GetTextExtent(m_strTextBuf);
	if(m_ptCaretPos.x+sizeText.cx<m_rtCanvas.right)
	{m_dcMemory.TextOut(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);
	SetCaretPos(CPoint(m_ptCaretPos.x+sizeText.cx,m_ptCaretPos.y));
	}
	break;
}
ShowCaret();
CClientDC dc(this);
dc.BitBlt(0,0,m_rtCanvas.right,m_rtCanvas.bottom,&m_dcMemory,0,0,SRCCOPY);
m_dcMemory.SelectObject(pOld);
   // TODO: 在此添加消息处理程序代码和/或调用默认值
  CScrollView::OnChar(nChar, nRepCnt, nFlags);
}
⑺修改绘图光标。
⑻实现保存功能。
①为线段定义新类Cline;
②为类CLine定义成员变量和成员函数;
CPoint m_pt1;
CPoint m_pt2;
CLine();			//序列化要求有一个不带参的构造函数
virtual ~CLine();
CLine(CPoint pt1,CPoint pt2);  //声明线段的构造函数
void DrawLine(CDC *pDC);		//声明绘制线段的成员函数
③保存多条线段数据。使用MFC类模板实现。修改文档类头文件,包含以下头文件:
#include "line.h"
#include <afxtempl.h>
在类定义中添加:
protected: // create from serialization only
	CTypedPtrArray<CObArray,CLine *>  m_LineArray; 
//存放线段对象指针的动态数组
public:
	CLine *GetLine(int nIndex);		//获取指定序号线段对象的指针
	void AddLine(CPoint pt1,CPoint pt2); 
    //向动态数组中添加新的线段对象的指针
	int GetNumLines();	 //获取线段的数量
在文档类实现文件中添加如下代码:
void CMyDrawDoc::AddLine(CPoint pt1,CPoint pt2)
{   CLine *pLine=new CLine(pt1,pt2); //新建一条线段对象
	m_LineArray.Add(pLine);			//将该线段对象加到动态数组
	SetModifiedFlag();				//设置文档修改标志
}
CLine *CMyDrawDoc::GetLine(int nIndex)
{
	if(nIndex<0||nIndex>m_LineArray.GetUpperBound())  //判断是否越界
		return NULL;
	return m_LineArray.GetAt(nIndex);   //返回给定序号线段对象的指针
}
int CMyDrawDoc::GetNumLines()
{return m_LineArray.GetSize();    //返回线段的数量}
④在视图类定义中加:
 CPoint ptStart,ptEnd;
在鼠标左键按下加:ptStart=point;
因此修改视图类的鼠标移动消息处理函数中添加如下代码:
ptEnd=point;
		dc.MoveTo(ptStart);
		dc.LineTo(ptEnd);		//绘制线段
		CMyPaint1Doc *pDoc=GetDocument();         //获得文档对象的指针
        ASSERT_VALID(pDoc);	//测试文档对象是否运行有效
        pDoc->AddLine(ptStart,ptEnd);//加入线段到指针数组
	    ptStart=ptEnd;	
⑤在OnDraw函数中重绘前面用鼠标所绘制的线段。
CMyPaint1Doc* pDoc = GetDocument();
{
ASSERT_VALID(pDoc);
	if (!pDoc)
while(nIndex--)
	{
		TRACE("nIndex2=%d\n",nIndex);
		pDoc->GetLine(nIndex)->DrawLine(pDC);  //类CLine的成员函数
	}
}
⑥使用序列化函数Serialize实现图形的保存。在CLine类的声明头文件中添加函数Serialize的声明和DECLARE_SERIAL宏。
	void Serialize(CArchive &ar);    //类CLine的序列化函数
	DECLARE_SERIAL(CLine)	  //声明序列化类CLine
在CLine的实现文件中成员函数的定义前添加IMPLEMENT_SERIAL宏:
 IMPLEMENT_SERIAL(CLine,CObject,1)   //实现序列化类Cline
  编写CLine的序列化函数Serialize()的实现代码:
void CLine::Serialize(CArchive &ar)
{
	if(ar.IsStoring())
		ar<<m_pt1<<m_pt2;     //保存对象的数据
	else
		ar>>m_pt1>>m_pt2;     //读出该对象的数据
}
⑦在文档类中完成所有线段的读写操作。修改文档类的序列化函数:
void CMyDrawDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		m_LineArray.Serialize(ar);   //调用CObArray类的序列化函数
	}
	else
	{
		m_LineArray.Serialize(ar); 
	}
}
⑧为了在执行File|New能将当前客户窗口中所绘制的图形清除,要重载文档类的虚函数DeleteContents,并添加如下代码:
void CMyPaint1Doc::DeleteContents()
{
	int nIndex=GetNumLines();
	while(nIndex--)
		delete m_LineArray.GetAt(nIndex);  //清除线段
	m_LineArray.RemoveAll();   //释放指针数组	
	CDocument::DeleteContents();
}
⑨为程序增加提示保存功能。修改文档类的成员函数AddLine:
void CMyDrawDoc::AddLine(CPoint pt1,CPoint pt2)
{
	CLine *pLine=new CLine(pt1,pt2); //新建一条线段对象
	m_LineArray.Add(pLine);	//将该线段对象加到动态数组
	SetModifiedFlag();		//设置文档修改标志
}
⑼增加滚动视图。
①替换工程中的所有CView,改为CScrollView。
②为视图类重载OnInitialUpdate,添加如下代码:
void CMyDrawView::OnInitialUpdate() 
{
	CScrollView::OnInitialUpdate();
	CSize sizeTotal;
	sizeTotal.cx=sizeTotal.cy=1000;    //定义滚动视图的大小
	SetScrollSizes(MM_TEXT,sizeTotal); 
      //设置滚动视图的映射模式和大小
}
③修改鼠标移动消息映射函数:
void CMyDrawView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(m_bDragging)
	{   …
	   CPoint ptOrg;
		ptOrg=GetScrollPosition();	//获得当前工作区原点的坐标
		ptStart=ptStart+ptOrg;	//加上原点的坐标来修正线段的坐标
		ptEnd=point+ptOrg;
		pDoc->AddLine(ptStart,ptEnd); //加入线段到指针数组
		…}
}
在这里插入代码片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值