提纲:
属性方面的设置(添加)
画图
位图,文件操作的简单介绍
CRgn类的介绍
Normalize()函数
鼠标的捕获
具体内容:
一、 属性方面的设置:
1. 添加画笔和画刷 //实现对图形属性的设置
(1)在View类当中添加画笔和画刷颜色的变量,并在构造函数中初始化
View.h中:
COLORREF m_penColor; //绘制颜色
COLORREF m_brushColor; //画刷颜色
View.cpp中:
m_penColor=RGB(0,0,0);
m_brushColor=RGB(255,255,255);
(2)添加按钮和消息响应函数
void CVectorView::OnPenColor() //设置画笔颜色
void CVectorView::OnBrushColor() //设置画刷颜色
2. 在画布上显示选中图形的属性
在OnDraw()中添加代码,显示属性:
//----------显示图形属性----------
pDC->TextOut(10,10,"画笔颜色");
pDC->TextOut(10,30,"画刷颜色");
CBrush brush1,brush2,*pOldBrush1,*pOldBrush2;
brush1.CreateSolidBrush(m_penColor);
brush2.CreateSolidBrush(m_brushColor);
pOldBrush1=pDC->SelectObject(&brush1);
pDC->Rectangle(80,15,100,25);
pDC->SelectObject(pOldBrush1);
pOldBrush2=pDC->SelectObject(&brush2);
pDC->Rectangle(80,30,100,45);
pDC->SelectObject(pOldBrush2);
3. 保证选中图形的属性实时的显示出来
在SetSelected()中添加代码:
m_penColor=pItem->m_colorLine;
m_brushColor=pItem->m_colorFill;
4. 与属性设置对话框相协调
(1) 首先保证属性对话框要与选中图形的属性信息保持一致
void CVectorView::OnViewProperty()中添加代码如下:
CItem *pItem;
CVectorDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for (int i=0; i<pDoc->m_objItem.GetCount(); i++)
{
pItem=(CItem*)(pDoc->m_objItem.GetAt(i));
if (pItem->m_bSelected)
{
GetSelectedItemsInfo();
}
}
(2) 协调属性显示和属性设置对话框
void CVectorView::SetSelectedItemsInfo(int property) 中添加代码如下:
m_penColor= m_pDlgProperty->m_colorLine;
m_brushColor = m_pDlgProperty->m_colorFill;
二、 画图
1. 添加图形按钮及消息响应:
(1)椭圆
(2)圆角矩形
(3)五边形
(4)六边形
(5)八边形
(6)多个多边形
(7)Bezier曲线
(8)弧线
(9)位图导入按钮及菜单
2. 画图原理:
总的来说就是在屏幕中选好各个控制点的信息,然后代入画图函数当中即可
3. 绘制函数的说明:
(1) 椭圆
BOOL Ellipse( int x1, int y1, int x2, int y2 );
BOOL Ellipse( LPCRECT lpRect );
pDC->Ellipse(m_ptP1.x,m_ptP1.y,m_ptP2.x,m_ptP2.y);
(2) 圆角矩形
BOOL RoundRect( int x1, int y1, int x2, int y2, int x3, int y3 );
BOOL RoundRect( LPCRECT lpRect, POINT point );
pDC->RoundRect(m_ptP1.x,m_ptP1.y,m_ptP2.x,m_ptP2.y,50,50);
(3) 五边形
BOOL Polygon( LPPOINT lpPoints, int nCount );
算法:
void CItem::DrawFivePolygn(CDC *pDC)
{
percentY=(1-sin(0.1*PI))/(1+sin(0.3*PI));
percentX1=0.5-1 / (4 * cos(0.2 * PI));
percentX2=0.5+1 / (4 * cos(0.2 * PI));
pt_Five[0].x=(m_ptP2.x - m_ptP1.x)/2.0 + m_ptP1.x;
pt_Five[0].y=m_ptP1.y;
pt_Five[1].x=m_ptP1.x;
pt_Five[1].y=(m_ptP2.y - m_ptP1.y) * percentY + m_ptP1.y;
pt_Five[2].x=(m_ptP2.x - m_ptP1.x) * percentX1 + m_ptP1.x;
pt_Five[2].y=m_ptP2.y;
pt_Five[3].x=(m_ptP2.x - m_ptP1.x) * percentX2 + m_ptP1.x;
pt_Five[3].y=m_ptP2.y;
pt_Five[4].x=m_ptP2.x;
pt_Five[4].y=(m_ptP2.y - m_ptP1.y) * percentY + m_ptP1.y;
pDC->Polygon(pt_Five,5);
}
(4) 六边形
BOOL Polygon( LPPOINT lpPoints, int nCount );
算法:
void CItem::DrawSixPolygn(CDC *pDC)//画六边形
{
pt_Six[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/2.0;
pt_Six[0].y=m_ptP1.y;
pt_Six[1].x=m_ptP1.x;
pt_Six[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/4.0;
pt_Six[2].x=m_ptP1.x;
pt_Six[2].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)*3/4.0;
pt_Six[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/2.0;
pt_Six[3].y=m_ptP2.y;
pt_Six[4].x=m_ptP2.x;
pt_Six[4].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)*3/4.0;
pt_Six[5].x=m_ptP2.x;
pt_Six[5].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/4.0;
pDC->Polygon(pt_Six,6);
}
(5)八边形
BOOL Polygon( LPPOINT lpPoints, int nCount );
算法:
void CItem::DrawEightPolygn(CDC *pDC)
{
pt_Eight[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[0].y=m_ptP1.y;
pt_Eight[1].x=m_ptP1.x;
pt_Eight[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3.0;
pt_Eight[2].x=m_ptP1.x;
pt_Eight[2].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3.0;
pt_Eight[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[3].y=m_ptP2.y;
pt_Eight[4].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[4].y=m_ptP2.y;
pt_Eight[5].x=m_ptP2.x;
pt_Eight[5].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3;
pt_Eight[6].x=m_ptP2.x;
pt_Eight[6].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3;
pt_Eight[7].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3;
pt_Eight[7].y=m_ptP1.y;
pDC->Polygon(pt_Eight,8);
}
(6)多个多边形
BOOL PolyPolygon( LPPOINT lpPoints, LPINT lpPolyCounts, int nCount );
void CItem::DrawAnyPolygn(CDC *pDC)//画多个多边形
{
pt_Eight[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[0].y=m_ptP1.y;
pt_Eight[1].x=m_ptP1.x;
pt_Eight[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3.0;
pt_Eight[2].x=m_ptP1.x;
pt_Eight[2].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3.0;
pt_Eight[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[3].y=m_ptP2.y;
pt_Eight[4].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3.0;
pt_Eight[4].y=m_ptP2.y;
pt_Eight[5].x=m_ptP2.x;
pt_Eight[5].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3;
pt_Eight[6].x=m_ptP2.x;
pt_Eight[6].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3;
pt_Eight[7].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3;
pt_Eight[7].y=m_ptP1.y;
int arr[2];
arr[0]=5;
arr[1]=3;
pDC->PolyPolygon(pt_Eight,arr,2);
}
(7)Bezier曲线
BOOL PolyBezier( const POINT* lpPoints, int nCount );
pDC->PolyBezier(m_ptP,4);
注:该部分还涉及到控制点的录入,实现方法:
设置控制点个数pointcount=0,在鼠标按下函数中判断pointcount是否小于4(暂时用四个点)并绘制控制点,然后当pointcount=4时完成控制点绘制,将m_bDrawing设为true,在鼠标弹起时形成图形对象,把它加入到对象数组当中即可。
(8)弧线
BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Arc( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
pDC->Arc(CRect(m_ptP1,m_ptP2),m_ptArc[2],m_ptArc[3]);
图 弧线的坐标定位
注:这里也涉及控制点的问题,处理方法与上面完全相同。
(9)饼图:(在程序当中没有实现)
BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );
BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
(10)位图导入按钮及菜单
//下面再讲
三、 位图,文件的操作介绍
void CVectorView::OnFileLoadimage()
{
if(m_nType == ITEM_BITMAP)
{
m_nType = ITEM_EMPTY;
}
else
{
m_nType = ITEM_BITMAP;
}
CFileDialog pCFileDialog(true, NULL, NULL, 0, "位图文件(*.bmp)|*.bmp");
pCFileDialog.m_ofn.lpstrTitle = "打开文件";
if(pCFileDialog.DoModal() != IDOK)
{
return;
}
strfilepath=pCFileDialog.GetPathName();//获取文件路径与名称
//获取文件名
CString filename;
filename=pCFileDialog.GetFileName();
//获取exe文件自身所在文件夹
CString dir;
char filepath[255];
GetModuleFileName(AfxGetInstanceHandle(),filepath,256);
//得到play.exe的路径和文件名
int hf=0;
dir=filepath;
while(dir.Find("//",hf)!=-1)
{
hf=dir.Find("//",hf);
hf=hf+1;
}
int w=dir.GetLength();
dir.Delete(hf,w-hf);
dir=dir+"res//";
//导入文件
CString StrSourceFile=strfilepath;
CString StrDestFolder=dir;
char SourceFile[255+1]=""; //此处必须为字符数组,CString类型是不行的
strcpy(SourceFile,StrSourceFile); //此种方法非常之好
char TargetFolder[255+1]="";
strcpy(TargetFolder,StrDestFolder);
SHFILEOPSTRUCT lpFile;
lpFile.hwnd=GetSafeHwnd();
lpFile.wFunc=FO_COPY;
lpFile.pFrom=SourceFile;
lpFile.pTo=TargetFolder;
lpFile.fFlags=FOF_ALLOWUNDO;
lpFile.fAnyOperationsAborted=FALSE;
lpFile.hNameMappings=NULL;
lpFile.lpszProgressTitle=NULL;
int ReturnValue=SHFileOperation(&lpFile);
if(ReturnValue==0)
{
if(lpFile.fAnyOperationsAborted==TRUE)
MessageBox("导入文件的操作被取消","信息提示",MB_OK+MB_ICONWARNING); //这里导入实际上就是复制,把文件复制到res文件夹当中
else
{
MessageBox("导入文件操作成功","信息提示",MB_OK+MB_ICONWARNING);
m_nType=ITEM_BITMAP;
//新建立一个图形pItem
CItem *pItem;
pItem=new CItem;
pItem->m_nType=m_nType;
pItem->m_ptP1=CPoint(100,100);
pItem->m_ptP2=CPoint(165,155);
pItem->m_bitmapName=dir+filename;
pItem->m_bSelected=true;
AfxMessageBox(pItem->m_bitmapName);
//将pItem加入m_objItem中
CVectorDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDoc->m_objItem.Add(pItem);
//通知pDoc文件内容已经发生改变
pDoc->SetModifiedFlag(true);
DrawAll();
Invalidate(0);
m_nType=ITEM_EMPTY;//一定要注意这里
}
}
else
MessageBox("导入文件操作失败","信息提示",MB_OK+MB_ICONEXCLAMATION);
}
void CItem::DrawBitMap(CDC *pDC) //绘制位图
{
BITMAP bmp;
HBITMAP hBitmap;
CBitmap m_Bitmap;
CDC dcCompatible;
hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),
m_bitmapName,
IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if (hBitmap == NULL)
{
MessageBox(NULL,"Can't find the picture!","ERROR",MB_OK);
exit(0);//退出程序
}
m_Bitmap.Attach(hBitmap);
m_Bitmap.GetBitmap(&bmp);
dcCompatible.CreateCompatibleDC(pDC);
dcCompatible.SelectObject(&m_Bitmap);
pDC->StretchBlt(m_ptP1.x,m_ptP1.y,m_ptP2.x-m_ptP1.x,m_ptP2.y-m_ptP1.y,& dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
dcCompatible.DeleteDC();
}
四、 CRgn类的介绍
区域CRgn类:封装GDI区域。区域是窗口内的一块多边形或椭圆形的区域。CRgn用于设备环境(通常是窗口)内的区域操作。CRgn通常与CDC的有关剪裁(clipping)的成员函数配合使用。
代码示例:
CRgn rgn;
rgn.CreatePolygonRgn(pt_Five,5,ALTERNATE);// nMode是填充模式,可为ALTERNATE或WINDING.
rgn.PtInRegion(point)
五、 Normalize()函数
void CItem::Normalize()//八边形的规则化,仿造矩形的Normalize()函数,保证改变大小是箭头等其他元素的正确性
//在AtKeyPoint()中调用
{
CPoint pt_temp;
if(pt_Eight[0].y>pt_Eight[3].y)
{
pt_temp=pt_Eight[0];
pt_Eight[0]=pt_Eight[3];
pt_Eight[3]=pt_temp;
pt_temp=pt_Eight[7];
pt_Eight[7]=pt_Eight[4];
pt_Eight[4]=pt_temp;
pt_temp=pt_Eight[1];
pt_Eight[1]=pt_Eight[2];
pt_Eight[2]=pt_temp;
pt_temp=pt_Eight[6];
pt_Eight[6]=pt_Eight[5];
pt_Eight[5]=pt_temp;
}
else if(pt_Eight[0].x>pt_Eight[7].x)
{
pt_temp=pt_Eight[0];
pt_Eight[0]=pt_Eight[7];
pt_Eight[7]=pt_temp;
pt_temp=pt_Eight[1];
pt_Eight[1]=pt_Eight[6];
pt_Eight[6]=pt_temp;
pt_temp=pt_Eight[2];
pt_Eight[2]=pt_Eight[5];
pt_Eight[5]=pt_temp;
pt_temp=pt_Eight[3];
pt_Eight[3]=pt_Eight[4];
pt_Eight[4]=pt_temp;
}
}
六、 鼠标的捕获
// void CVectorView::OnLButtonDown(UINT nFlags, CPoint point)
SetCapture();
//void CVectorView::OnLButtonUp(UINT nFlags, CPoint point)
ReleaseCapture();