大连民族学院
计算机科学与工程学院大作业
作业题目:Ex_A7综合应用
课程名称:Windows编程
实验类型:□演示性 □验证性 □操作性 □设计性 ■综合性
专业:计算计科学与技术 班级:
学生姓名: 学号:实验日期:20##年 11 月 14 日 实验地点:多媒体机房
实验学时:4学时 实验成绩:
指导教师签字: 年 月 日
一. 问题描述
这个实验应用了动态定位法实现了画线的动态定位操作。当鼠标在视图客户区移动时,会出现一个大大的光标(由水平线和垂直线组成),光标的右上角的小窗口显示出当前鼠标的位置,当单击鼠标左键时,在屏幕上出现由小十字点标志,此时再移动鼠标,从当前鼠标位置到前面一个点将绘制一条直线,且该直线随鼠标位置移动而变化,就像一根橡皮条一样,且光标右上角的小窗口显示出这条直线的长度和角度,再单击鼠标左键一条直线将绘制出来……,直到按ESC键结束,一条折线就绘制出来了。为了保证在视图需要更新时,这些线条扔然存在,需要将这些点保存下来,然后再重新绘制。
二. 基本要求
动态定位是交互式图形系统中的最基本的操作,它有橡皮条和牵引两种技术。作业要求按照书上的基本代码逐步实现画线的动态定位操作。
三. 概要设计
该实验分为三部分进行阐述
(1) 光标的生成和实现
(2) 动态小窗口的实现
(3) 直线动态过程实现
功能模块图
四. 详细设计
(1)光标生成和实现
这个部分首先要设置光标第一次显示标志,上一个点的坐标和当前点的坐标。在OnDraw函数中将客户区清为黑色,设置透明背景模式等,在绘制光标函数的成员函数DrawCursor中,确定当前裁剪区的大小,画笔及颜色,设置XOR光栅操作模式,在这个函数中还可以实现绘制水平线,绘制垂直线,恢复原理来的光栅,恢复原来的画笔。接着在用MFC ClassWizard为Cex_A71311View类添加WM_MOUSEMOVE消息映射,实现鼠标的移动,WM_SETCURSOR的消息映射是用来设置光标的,在函数中添加代码SetCursor(NULL)来实现关闭在客户区的光标。这样在视图客户区中就可以看到一个可以移动的大大的光标。
(2)动态小窗口的实现
动态小窗口的实现是通过将内存中相对应的区域填充到原来的小窗口,然后重新绘制小窗口。
(3)直线动态过程实现
开始画线后,可以随意的选择直线两点的所在地,动态的绘制直线,只要不按ESC键,已经画了的线还是存在,可以连续画很多条线,直到按ESC结束,完整的折线出现在屏幕上,然后可以重新绘制新的折线。
五. 编码与调试分析
成员变量:
CPoint m_ptCurPos; //当前点得坐标
CPoint m_ptPrevPos; //上一个点的光标
BOOL m_bCursorFirst; //光标第一次显示标志
BOOL m_bLineStart //判断画线是否开始
CBitmap *m_oldBmp; //用于内存的位图指针
CDC m_dcMem; //定义用于内存环境的设备变量
CStringArray m_strCmdArray; //保存当前绘图命令
鼠标移动代码如下:
void CEx_A71314View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDC* PDC = this->GetDC();
CString strPos;
if(m_bLineStart)
{
int dx=point.x-m_ptPrevPos.x;
int dy=point.y-m_ptPrevPos.y;
double length=sqrt((double)dx*dx+(double)dy*dy);
double angle;
if(dx==0) angle=90.0;
else if(dy==0) angle=0.0;
else angle=180.0*atan((double)dy/(double)dx)/3.14159265;
strPos.Format("%.1f<%.1f",length,angle);
}else
strPos.Format("%d,%d",point.x,point.y);
if (m_bCursorFirst)
{
m_bCursorFirst = FALSE;
m_ptCurPos = point;
DrowCursor(PDC,m_ptCurPos);
DrawInfoWnd(PDC,m_ptCurPos,strPos);
}
else
{
DrowCursor(PDC,m_ptCurPos);
if(m_bLineStart)
DrawXORLine(PDC,m_ptPrevPos,m_ptCurPos);
if(m_dcMem.m_hDC)
{
PDC->BitBlt(m_ptCurPos.x,m_ptCurPos.y-15,80,15,&m_dcMem,m_ptCurPos.x,m_ptCurPos.y-15,SRCCOPY);
}
m_ptCurPos = point;
if(m_bLineStart)
DrawXORLine(PDC,m_ptPrevPos,m_ptCurPos);
DrowCursor(PDC,m_ptCurPos);
DrawInfoWnd(PDC,m_ptCurPos,strPos);
}
CView::OnMouseMove(nFlags, point);
}
六、使用说明
在客户区单击鼠标左键,在屏幕上会出现一个小十字形标志,接着移动鼠标,再在另一个地方单击左键,这样一条直线就出来了。重复上面的步骤,直到按下ESC结束,一条折线就出现在屏幕上了。
七、测试
1、 光标的生成和实现部分:
2、动态小窗口的实现
3、直线动态过程实现
按下exc后:
八、 心得体会
课程设计是培养学生综合运用所学知识、发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.
通过此次作业,我学到了很多东西,不仅之前学习到的内容得到了巩固,自己的动手能力也得到了提高,虽然书上已经把相关的代码给出,但在通过敲代码,我可以清楚的了解到每个细节是如何实现的。例如:DrowCursor(CDC *pDC, CPoint pt)这个函数我最开始函数名就起错了,如果还是按照书本上的代码完全不动就会一直错下去。只能在调用该函数时使用这个“错误”的名字。我深刻的体会到,不管多大的项目,都是由各个小细节构成的。细节决定成败,这可以说是每个IT行业人士都清楚认识到的最重要的一点。
九、 附录(源代码)
#include "stdafx.h"
#include "Ex_A71314.h"
#include "Ex_A71314Doc.h"
#include "Ex_A71314View.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CEx_A71314View, CView)
BEGIN_MESSAGE_MAP(CEx_A71314View, CView)
//{{AFX_MSG_MAP(CEx_A71314View)
ON_WM_MOUSEMOVE()
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
CEx_A71314View::CEx_A71314View()
{
// TODO: add construction code here
m_oldBmp = NULL;
}
CEx_A71314View::~CEx_A71314View()
{
}
BOOL CEx_A71314View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
void CEx_A71314View::OnDraw(CDC* pDC)
{
CEx_A71314Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rcClient;
GetClientRect(rcClient);
if(m_oldBmp){
m_dcMem.SelectObject(m_oldBmp);
}
m_dcMem.DeleteDC();
m_dcMem.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,rcClient.Width(),rcClient.Height());
m_oldBmp=m_dcMem.SelectObject(&bmp);
bmp.DeleteObject();
m_dcMem.FillSolidRect(rcClient,RGB(0,0,0));
int nBkMode=m_dcMem.SetBkMode(TRANSPARENT);
/////////////////
CPen pen(PS_SOLID,3,RGB(0,192,0));
CPen*oldPen=m_dcMem.SelectObject(&pen);
for(int i=0;i { CString str=(CString)m_strCmdArray[i]; CString strCmd; int nIndex=str.Find(","); strCmd =str.Left(nIndex); strCmd.TrimLeft(); strCmd.TrimRight(); CString strData=str.Mid(nIndex+1); int x,y; nIndex=strData.Find(","); x=atol(strData.Left(nIndex)); y=atol(strData.Mid(nIndex+1)); if(strCmd=="MOVETO") m_dcMem.MoveTo(x,y); if(strCmd=="LINETO") m_dcMem.LineTo(x,y); } pDC->BitBlt(0,0,rcClient.Width(),rcClient.Height(),&m_dcMem,0,0,SRCCOPY); m_dcMem.SetBkMode(nBkMode); m_bCursorFirst=TRUE; pDC->FillSolidRect(rcClient,RGB(0,0,0)); m_bCursorFirst = TRUE; pDC->SetBkMode(TRANSPARENT); // TODO: add draw code for native data here } ///////////////////////////////////////////////////////////////////////////// // CEx_A71314View printing BOOL CEx_A71314View::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CEx_A71314View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CEx_A71314View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CEx_A71314View diagnostics #ifdef _DEBUG void CEx_A71314View::AssertValid() const { CView::AssertValid(); } void CEx_A71314View::Dump(CDumpContext& dc) const { CView::Dump(dc); } CEx_A71314Doc* CEx_A71314View::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx_A71314Doc))); return (CEx_A71314Doc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CEx_A71314View message handlers void CEx_A71314View::DrowCursor(CDC *pDC, CPoint pt) { CRect rcClip; pDC->GetClipBox(rcClip); CPen pen(PS_SOLID,1,RGB(128,128,128)); CPen *oldPen =pDC->SelectObject(&pen); int nOldROP =pDC->SetROP2(R2_XORPEN); pDC->MoveTo(rcClip.left,pt.y); pDC->LineTo(rcClip.right,pt.y); pDC->MoveTo(pt.x,rcClip.top); pDC->LineTo(pt.x,rcClip.bottom); pDC->SetROP2(nOldROP); } void CEx_A71314View::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC* PDC = this->GetDC(); CString strPos; if(m_bLineStart) { int dx=point.x-m_ptPrevPos.x; int dy=point.y-m_ptPrevPos.y; double length=sqrt((double)dx*dx+(double)dy*dy); double angle; if(dx==0) angle=90.0; else if(dy==0) angle=0.0; else angle=180.0*atan((double)dy/(double)dx)/3.14159265; strPos.Format("%.1f<%.1f",length,angle); }else strPos.Format("%d,%d",point.x,point.y); if (m_bCursorFirst) { m_bCursorFirst = FALSE; m_ptCurPos = point; DrowCursor(PDC,m_ptCurPos); DrawInfoWnd(PDC,m_ptCurPos,strPos); } else { DrowCursor(PDC,m_ptCurPos); if(m_bLineStart) DrawXORLine(PDC,m_ptPrevPos,m_ptCurPos); if(m_dcMem.m_hDC) { PDC->BitBlt(m_ptCurPos.x,m_ptCurPos.y-15,80,15,&m_dcMem,m_ptCurPos.x,m_ptCurPos.y-15,SRCCOPY); } m_ptCurPos = point; if(m_bLineStart) DrawXORLine(PDC,m_ptPrevPos,m_ptCurPos); DrowCursor(PDC,m_ptCurPos); DrawInfoWnd(PDC,m_ptCurPos,strPos); } CView::OnMouseMove(nFlags, point); } BOOL CEx_A71314View::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: Add your message handler code here and/or call default SetCursor(NULL); return CView::OnSetCursor(pWnd, nHitTest, message); } void CEx_A71314View::DrawInfoWnd(CDC *pDC, CPoint pt, CString strInfo) { CRect rcWnd(pt.x,pt.y-15,pt.x+80,pt.y); pDC->FillSolidRect(rcWnd,RGB(0,0,128)); pDC->Draw3dRect(rcWnd,RGB(255,255,255),RGB(255,255,255)); LOGFONT lfText; memset(&lfText,0,sizeof(LOGFONT)); lfText.lfHeight=-12; lfText.lfCharSet=GB2312_CHARSET; strcpy(lfText.lfFaceName,"宋体"); CFont cf; cf.CreateFontIndirect(&lfText); CFont* oldFont =pDC->SelectObject(&cf); pDC->SetBkColor(RGB(0,0,128)); pDC->SetTextColor(RGB(192,192,0)); pDC->DrawText(strInfo,rcWnd,DT_CENTER|DT_VCENTER|DT_SINGLELINE); pDC->SelectObject(oldFont); cf.DeleteObject(); } void CEx_A71314View::DrawPointFlag(CDC *pDC, CPoint pt) { CPen* oldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN); pDC->MoveTo(pt.x-4,pt.y); pDC->LineTo(pt.x+4,pt.y); pDC->MoveTo(pt.x,pt.y-4); pDC->LineTo(pt.x,pt.y+4); pDC->SelectObject(oldPen); } void CEx_A71314View::DrawXORLine(CDC *pDC, CPoint pt1, CPoint pt2) { CPen pen(PS_SOLID,1,RGB(192,192,128)); CPen* oldPen=pDC->SelectObject(&pen); int nOldROP =pDC->SetROP2(R2_XORPEN); pDC->MoveTo(pt1); pDC->LineTo(pt2); pDC->SetROP2(nOldROP); pDC->SelectObject(oldPen); } void CEx_A71314View::OnInitialUpdate() { CView::OnInitialUpdate(); m_strCmdArray.RemoveAll(); m_bLineStart=FALSE; // TODO: Add your specialized code here and/or call the base class } void CEx_A71314View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_ptPrevPos =point; if(!m_bLineStart) { m_bLineStart=TRUE; CString strCmd; strCmd.Format("MOVETO,%d,%d",point.x,point.y); m_strCmdArray.Add(strCmd); }else{ CString strCmd; strCmd.Format("LINETO,%d,%d",point.x,point.y); m_strCmdArray.Add(strCmd); } DrowCursor(GetDC(),point); DrawPointFlag(GetDC(),point); DrowCursor(GetDC(),point); DrawPointFlag(&m_dcMem,point); CView::OnLButtonDown(nFlags, point); } void CEx_A71314View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if(nChar==VK_ESCAPE) { if(m_bLineStart) { m_bLineStart=FALSE; Invalidate(); } } CView::OnKeyDown(nChar, nRepCnt, nFlags); }