MFC 多视图同步画图解决方案
来源:互联网 发布:剑网3炮姐捏脸数据 编辑:程序博客网 时间:2024/06/12 21:57
单视图画图的基本方法交代:
1:通过CStroke类(派生于COjbect,以实现序列化),记录一次笔画的所有点信息,以及笔画宽度,并完成相应绘画工作(笔画就是鼠标左键按下,画图,到左键松开)。
2:Doc通过建立CObList,来保存本次绘画的所有笔画。在保存文件时进行序列化。
3:View的OnDraw函数通过遍历CObList的每个对象,完成所有笔画的现实工作。
4:直接通过OnLButtonDown,OnLButtonUp,OnMouseMove即时来完成绘图,并在此保存笔画信息。
就是因为第4点,让我想到一个高效率绘图方法。
首先介绍书上的方法:
书上采用UpdateAllView函数通知其他子视图其他视图进行重画,因为UpdateAllView引发子视图调用OnUpdate,然后在OnUpdate里面利用UpdateAllView传递过来的pHint来设定所需重画的最小矩形区域。以提高绘画效率。
这里我需要说明:为什么要提高绘画效率,因为传统的方法是通过UpdateAllViews来通知子视图重画全部区域,但设想要实现即时绘画,鼠标移动的消息可是很多啊,如果在这个情况下不断地UpdateAllViews 可想屏幕会多卡。
而我的思路是:基本可以概括为,发送相同消息给兄弟视图,让兄弟视图利用OnLButtonDown,OnLButtonUp,OnMouseMove里本身的即时绘图来实现即时绘画。
////////////////////////////////////////////////////////////////////思路简介//////////////////////////////////////////////////////////////////////
////用CStroke类记录一次笔画过程中的点,以及点所对应的线的粗度 ////
////由当前(激活的)视图负责点记录,并向其他兄弟视图发送相同消息(带有nFlags标记),来使得其它子视图是负责 ////
////当前(激活的)视图在自己鼠标消息中绘画。 ////
///其他视图通过nFlags标记位判断此消息是兄弟视图发送的消息,还是windows发送的消息以区别对待。如果是兄弟消息那么就不 ///
////用保存绘画信息(因为绘画信息只保留一份就可以,由当前(激活的)视图负责记录) ,只负责即时绘画就可以。如果是windows///
/////的那么此兄弟视图目前成为了当前(激活的视图)。 ////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
不过这样的设计会牵扯到如下两个问题:
1:如何区分windows消息和兄弟视图发送的消息?
2:如何实现数据的单一副本,而不会存在每个子视图一份数据(因为笔画的数据创建,添加是在OnLButtonDown,OnLButtonUp,
OnMouseMove里完成),所以不能照搬单视图的方法。
解决方式:
1:其他视图通过nFlags标记位判断此消息是兄弟视图发送的消息,还是windows发送的消息以区别对待。
2:由鼠标激活的视图完成笔画数据创建,以及添加工作。其他视图是负责绘画。
解决完上面两方面就可以完成多视图同步高效率绘画问题。下面是我所设计的数据和函数:
//////////////////////////////////////////////////////////////////Doc.h////////////////////////////////////////////////////////////////////////
- #pragma once
- #include "Stroke.h"
- class CStroke_MFCDoc : public CDocument
- {
- protected: // 仅从序列化创建
- CStroke_MFCDoc();
- DECLARE_DYNCREATE(CStroke_MFCDoc)
- //数据
- private:
- //CTypedPtrList<CObList,CStroke*> m_StrokeList;
- CObList m_StrokeList;//笔画列表
- int m_nPenWidth;//当前笔宽,通过此来调节新创建的笔的笔宽
- bool bThinPen;//是否是细笔
- CPen m_Pen;//当前笔
- CStroke* m_pCurStroke;//当前笔画指针
- public:
- enum{THIN_PEN=2,THICK_PEN=7};
- // 属性
- public:
- // 操作
- public:
- /*CTypedPtrList<CObList,CStroke*>*/CObList& GetStrokeList();
- void InitDocument();
- virtual void DeleteContents();
- CStroke* NewStroke();
- CPen* GetCurPen();
- // 重写
- public:
- virtual BOOL OnNewDocument();
- virtual void Serialize(CArchive& ar);
- // 实现
- public:
- virtual ~CStroke_MFCDoc();
- #ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
- #endif
- protected:
- // 生成的消息映射函数
- protected:
- DECLARE_MESSAGE_MAP()
- public:
- virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
- void ChangePen(void);//在粗笔和细笔之间变化,并返回是否为细笔
- afx_msg void OnThickPen();
- afx_msg void OnUpdateThickPen(CCmdUI *pCmdUI);
- BOOL IsCapture(void);//子视图中是否有捕获鼠标的
- //向除了pWnd外的其他子视图发送相同消息,以实现新建窗口同步
- BOOL SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point);
- int GetViewsCount(void);//获得与本文档相关的当前子视图个数
- CStroke* GetCurStroke(void);//获得当前笔画指针
- };
//////////////////////////////////////////////////////////////Doc.cpp/////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Stroke_MFC.h"
- #include "Stroke_MFCDoc.h"
- #include "Stroke_MFCView.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // CStroke_MFCDoc
- IMPLEMENT_DYNCREATE(CStroke_MFCDoc, CDocument)
- BEGIN_MESSAGE_MAP(CStroke_MFCDoc, CDocument)
- ON_COMMAND(ID_THICK_PEN, &CStroke_MFCDoc::OnThickPen)
- ON_UPDATE_COMMAND_UI(ID_THICK_PEN, &CStroke_MFCDoc::OnUpdateThickPen)
- END_MESSAGE_MAP()
- // CStroke_MFCDoc 构造/析构
- CStroke_MFCDoc::CStroke_MFCDoc()
- {
- // TODO: 在此添加一次性构造代码
- }
- /*CTypedPtrList<CObList,CStroke*>*/CObList& CStroke_MFCDoc::GetStrokeList()
- {
- return m_StrokeList;
- }
- void CStroke_MFCDoc::InitDocument()
- {
- m_nPenWidth=THIN_PEN;
- bThinPen=TRUE;
- m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- }
- void CStroke_MFCDoc::DeleteContents()
- {
- while(!m_StrokeList.IsEmpty())
- {
- delete m_StrokeList.RemoveHead();
- }
- CDocument::DeleteContents();
- }
- CStroke* CStroke_MFCDoc::NewStroke()
- {
- m_pCurStroke=new CStroke(m_nPenWidth);
- m_StrokeList.AddTail(m_pCurStroke);
- SetModifiedFlag();
- return m_pCurStroke;
- }
- CPen* CStroke_MFCDoc::GetCurPen()
- {
- return &m_Pen;
- }
- CStroke_MFCDoc::~CStroke_MFCDoc()
- {
- }
- BOOL CStroke_MFCDoc::OnNewDocument()
- {
- if (!CDocument::OnNewDocument())
- return FALSE;
- // TODO: 在此添加重新初始化代码
- // (SDI 文档将重用该文档)
- InitDocument();
- return TRUE;
- }
- // CStroke_MFCDoc 序列化
- void CStroke_MFCDoc::Serialize(CArchive& ar)
- {
- if (ar.IsStoring())
- {
- // TODO: 在此添加存储代码
- }
- else
- {
- // TODO: 在此添加加载代码
- }
- m_StrokeList.Serialize(ar);
- }
- // CStroke_MFCDoc 诊断
- #ifdef _DEBUG
- void CStroke_MFCDoc::AssertValid() const
- {
- CDocument::AssertValid();
- }
- void CStroke_MFCDoc::Dump(CDumpContext& dc) const
- {
- CDocument::Dump(dc);
- }
- #endif //_DEBUG
- // CStroke_MFCDoc 命令
- BOOL CStroke_MFCDoc::OnOpenDocument(LPCTSTR lpszPathName)
- {
- if (!CDocument::OnOpenDocument(lpszPathName))
- return FALSE;
- // TODO: 在此添加您专用的创建代码
- InitDocument();
- return TRUE;
- }
- void CStroke_MFCDoc::ChangePen(void)
- {
- m_nPenWidth = bThinPen ? THICK_PEN : THIN_PEN;
- bThinPen =! bThinPen;
- m_Pen.DeleteObject();
- m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- }
- void CStroke_MFCDoc::OnThickPen()
- {
- // TODO: 在此添加命令处理程序代码
- ChangePen();
- }
- void CStroke_MFCDoc::OnUpdateThickPen(CCmdUI *pCmdUI)
- {
- // TODO: 在此添加命令更新用户界面处理程序代码
- pCmdUI->Enable(!m_StrokeList.IsEmpty());
- pCmdUI->SetCheck(bThinPen);
- }
- BOOL CStroke_MFCDoc::IsCapture(void)
- {
- POSITION pos = m_viewList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);
- if(pView->IsCapture())
- return TRUE;
- }
- return FALSE;
- }
- BOOL CStroke_MFCDoc::SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point)
- {
- POSITION pos = m_viewList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);
- if(pView != (CStroke_MFCView*)pWnd)
- SendMessage(pView->GetSafeHwnd(),message,(WPARAM)0,LPARAM(point.y<<16|point.x));
- }
- return TRUE;
- }
- int CStroke_MFCDoc::GetViewsCount(void)
- {
- return m_viewList.GetCount();
- }
- CStroke* CStroke_MFCDoc::GetCurStroke(void)
- {
- return m_pCurStroke;
- }
//////////////////////////////////////////////////////////////view.h///////////////////////////////////////////////////////////////////////////////
- #pragma once
- #include "Stroke.h"
- class CStroke_MFCView : public CView
- {
- protected: // 仅从序列化创建
- CStroke_MFCView();
- DECLARE_DYNCREATE(CStroke_MFCView)
- //数据
- private:
- //((CStroke*)&) m_pCurStroke;
- CPoint m_pointPre;
- // 属性
- public:
- CStroke_MFCDoc* GetDocument() const;
- // 操作
- public:
- // 重写
- public:
- virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
- virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
- protected:
- virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
- virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
- virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
- // 实现
- public:
- virtual ~CStroke_MFCView();
- #ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
- #endif
- protected:
- // 生成的消息映射函数
- protected:
- afx_msg void OnFilePrintPreview();
- afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
- afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
- DECLARE_MESSAGE_MAP()
- public:
- afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
- afx_msg void OnMouseMove(UINT nFlags, CPoint point);
- BOOL IsCapture(void);
- };
- #ifndef _DEBUG // Stroke_MFCView.cpp 中的调试版本
- inline CStroke_MFCDoc* CStroke_MFCView::GetDocument() const
- { return reinterpret_cast<CStroke_MFCDoc*>(m_pDocument); }
- #endif
//////////////////////////////////////////////////////////////view.cpp////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Stroke_MFC.h"
- #include "Stroke_MFCDoc.h"
- #include "Stroke_MFCView.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // CStroke_MFCView
- IMPLEMENT_DYNCREATE(CStroke_MFCView, CView)
- BEGIN_MESSAGE_MAP(CStroke_MFCView, CView)
- // 标准打印命令
- ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
- ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
- ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CStroke_MFCView::OnFilePrintPreview)
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- ON_WM_MOUSEMOVE()
- END_MESSAGE_MAP()
- // CStroke_MFCView 构造/析构
- static int nFirst=0;
- CStroke_MFCView::CStroke_MFCView()
- {
- // TODO: 在此处添加构造代码
- }
- CStroke_MFCView::~CStroke_MFCView()
- {
- }
- BOOL CStroke_MFCView::PreCreateWindow(CREATESTRUCT& cs)
- {
- // TODO: 在此处通过修改
- // CREATESTRUCT cs 来修改窗口类或样式
- return CView::PreCreateWindow(cs);
- }
- // CStroke_MFCView 绘制
- void CStroke_MFCView::OnDraw(CDC* pDC)
- {
- CStroke_MFCDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (!pDoc)
- return;
- // TODO: 在此处为本机数据添加绘制代码
- /*CTypedPtrList<CObList,CStroke*>*/CObList& pStrokeList = pDoc->GetStrokeList();
- POSITION pos = pStrokeList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke* pStroke = (CStroke*)pStrokeList.GetNext(pos);
- pStroke->Draw(pDC);
- }
- }
- // CStroke_MFCView 打印
- void CStroke_MFCView::OnFilePrintPreview()
- {
- AFXPrintPreview(this);
- }
- BOOL CStroke_MFCView::OnPreparePrinting(CPrintInfo* pInfo)
- {
- // 默认准备
- return DoPreparePrinting(pInfo);
- }
- void CStroke_MFCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: 添加额外的打印前进行的初始化过程
- }
- void CStroke_MFCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: 添加打印后进行的清理过程
- }
- void CStroke_MFCView::OnRButtonUp(UINT nFlags, CPoint point)
- {
- ClientToScreen(&point);
- OnContextMenu(this, point);
- }
- void CStroke_MFCView::OnContextMenu(CWnd* pWnd, CPoint point)
- {
- theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
- }
- // CStroke_MFCView 诊断
- #ifdef _DEBUG
- void CStroke_MFCView::AssertValid() const
- {
- CView::AssertValid();
- }
- void CStroke_MFCView::Dump(CDumpContext& dc) const
- {
- CView::Dump(dc);
- }
- CStroke_MFCDoc* CStroke_MFCView::GetDocument() const // 非调试版本是内联的
- {
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CStroke_MFCDoc)));
- return (CStroke_MFCDoc*)m_pDocument;
- }
- #endif //_DEBUG
- // CStroke_MFCView 消息处理程序
- void CStroke_MFCView::OnLButtonDown(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- if(0 != nFlags)//如果是系统发送的话,由该view唯一创建线条
- {
- GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONDOWN,nFlags,point);
- GetDocument()->NewStroke();
- GetDocument()->GetCurStroke()->AddPoint(point);
- }
- m_pointPre = point;
- SetCapture();
- CView::OnLButtonDown(nFlags, point);
- }
- void CStroke_MFCView::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- if(!GetDocument()->IsCapture()/*GetCapture() != this*/)
- return;
- if(0 != nFlags)
- {
- GetDocument()->GetCurStroke()->AddPoint(point);
- GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONUP,nFlags,point);
- }
- CClientDC dc(this);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- ReleaseCapture();
- CView::OnLButtonUp(nFlags, point);
- }
- void CStroke_MFCView::OnMouseMove(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- if(!GetDocument()->IsCapture()/*GetCapture() != this*/)//如果没有这一句,鼠标移动的时候也会接受消息,但本不应该有这个程序处理的
- return;
- CClientDC dc(this);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- if(0 != nFlags)
- {
- GetDocument()->SendBTMsgToOtherViews(this,WM_MOUSEMOVE,nFlags,point);
- GetDocument()->GetCurStroke()->AddPoint(point);
- }
- m_pointPre = point;
- CView::OnMouseMove(nFlags, point);
- }
- BOOL CStroke_MFCView::IsCapture(void)
- {
- return this == GetCapture();
- }
//////////////////////////////////////////////////////////////CStroke.h//////////////////////////////////////////////////////////////////////////
- #pragma once
- #include "afx.h"
- class CStroke :
- public CObject
- {
- int m_nPenWidth;
- CArray<CPoint,CPoint> m_pointArray;
- public:
- CStroke(void);
- CStroke(int nPenWidth);
- void AddPoint(CPoint point);
- void Draw(CDC* pDC);
- void virtual Serialize(CArchive& ar);
- DECLARE_SERIAL(CStroke)
- ~CStroke(void);
- };
//////////////////////////////////////////////////////////////CStroke.cpp////////////////////////////////////////////////////////////////////////
- #include "StdAfx.h"
- #include "Stroke.h"
- IMPLEMENT_SERIAL(CStroke,CObject,1);
- CStroke::CStroke(void)
- {
- m_nPenWidth=2;
- }
- CStroke::CStroke(int nPenWidth)
- {
- m_nPenWidth=nPenWidth;
- }
- void CStroke::AddPoint(CPoint point)
- {
- m_pointArray.Add(point);
- }
- void CStroke::Draw(CDC* pDC)
- {
- CPen pen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- CPen* pOldPen=pDC->SelectObject(&pen);
- int size=m_pointArray.GetSize();
- if(size>0)
- {
- pDC->MoveTo(m_pointArray[0]);
- for(int i=1;i<size;i++)
- pDC->LineTo(m_pointArray[i]);
- }
- pDC->SelectObject(pOldPen);
- }
- void CStroke::Serialize(CArchive& ar)
- {
- if(ar.IsStoring())
- {
- ar<<m_nPenWidth;
- }
- else
- {
- ar>>m_nPenWidth;
- }
- m_pointArray.Serialize(ar);
- }
- CStroke::~CStroke(void)
- {
- }
在滚动窗口中使显示时,为了使激活视图(被鼠标激活的)和兄弟视图在逻辑上同步,必须让激活视图完成两个任务。
1:进行设备坐标绘画。
2:逻辑坐标添加点信息
注意设备坐标只是在绘图上使用,而文件保存的是逻辑坐标。
兄弟视图要完成的任务只有,完成逻辑坐标绘画。这就和激活视图有着既然相反的绘画方式。
滚动窗口的响应代码:
//////////////////////////////////////////////////////////////////Doc.h////////////////////////////////////////////////////////////////////////
- // Stroke_MFCDoc.h : CStroke_MFCDoc 类的接口
- //
- #pragma once
- #include "Stroke.h"
- class CStroke_MFCDoc : public CDocument
- {
- protected: // 仅从序列化创建
- CStroke_MFCDoc();
- DECLARE_DYNCREATE(CStroke_MFCDoc)
- CRect rc;
- //数据
- private:
- //CTypedPtrList<CObList,CStroke*> m_StrokeList;
- CObList m_StrokeList;//笔画列表
- int m_nPenWidth;//当前笔宽,通过此来调节新创建的笔的笔宽
- bool bThinPen;//是否是细笔
- CPen m_Pen;//当前笔
- CStroke* m_pCurStroke;//当前笔画指针
- int m_nThinPen;//细笔
- int m_nThickPen;//粗笔
- CSize m_sizeDoc;
- // 属性
- public:
- // 操作
- public:
- /*CTypedPtrList<CObList,CStroke*>*/CObList& GetStrokeList();
- void InitDocument();
- virtual void DeleteContents();
- CStroke* NewStroke();
- CPen* GetCurPen();
- CSize GetSize() const {return m_sizeDoc;}
- // 重写
- public:
- virtual BOOL OnNewDocument();
- virtual void Serialize(CArchive& ar);
- // 实现
- public:
- virtual ~CStroke_MFCDoc();
- #ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
- #endif
- protected:
- // 生成的消息映射函数
- protected:
- DECLARE_MESSAGE_MAP()
- public:
- virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
- void ChangePen(void);//在粗笔和细笔之间变化,并返回是否为细笔
- afx_msg void OnThickPen();
- afx_msg void OnUpdateThickPen(CCmdUI *pCmdUI);
- BOOL IsCapture(void);//子视图中是否有捕获鼠标的
- //向除了pWnd外的其他子视图发送相同消息,以实现新建窗口同步
- BOOL SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point);
- int GetViewsCount(void);//获得与本文档相关的当前子视图个数
- CStroke* GetCurStroke(void);//获得当前笔画指针
- afx_msg void OnPenWidth();
- void UpdatePen(void);
- };
//////////////////////////////////////////////////////////////////Doc.cpp////////////////////////////////////////////////////////////////////////
- // Stroke_MFCDoc.cpp : CStroke_MFCDoc 类的实现
- //
- #include "stdafx.h"
- #include "Stroke_MFC.h"
- #include "Stroke_MFCDoc.h"
- #include "Stroke_MFCView.h"
- #include "PenWidthDialog.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // CStroke_MFCDoc
- IMPLEMENT_DYNCREATE(CStroke_MFCDoc, CDocument)
- BEGIN_MESSAGE_MAP(CStroke_MFCDoc, CDocument)
- ON_COMMAND(ID_THICK_PEN, &CStroke_MFCDoc::OnThickPen)
- ON_UPDATE_COMMAND_UI(ID_THICK_PEN, &CStroke_MFCDoc::OnUpdateThickPen)
- ON_COMMAND(ID_PEN_WIDTH, &CStroke_MFCDoc::OnPenWidth)
- END_MESSAGE_MAP()
- // CStroke_MFCDoc 构造/析构
- CStroke_MFCDoc::CStroke_MFCDoc()
- {
- // TODO: 在此添加一次性构造代码
- }
- /*CTypedPtrList<CObList,CStroke*>*/CObList& CStroke_MFCDoc::GetStrokeList()
- {
- return m_StrokeList;
- }
- void CStroke_MFCDoc::InitDocument()
- {
- m_nPenWidth = /*THIN_PEN*/m_nThinPen=2;
- m_nThickPen = 5;
- bThinPen=TRUE;
- m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- m_sizeDoc.SetSize(800,900);
- }
- void CStroke_MFCDoc::DeleteContents()
- {
- while(!m_StrokeList.IsEmpty())
- {
- delete m_StrokeList.RemoveHead();
- }
- CDocument::DeleteContents();
- }
- CStroke* CStroke_MFCDoc::NewStroke()
- {
- m_pCurStroke=new CStroke(m_nPenWidth);
- m_StrokeList.AddTail(m_pCurStroke);
- SetModifiedFlag();
- return m_pCurStroke;
- }
- CPen* CStroke_MFCDoc::GetCurPen()
- {
- return &m_Pen;
- }
- CStroke_MFCDoc::~CStroke_MFCDoc()
- {
- }
- BOOL CStroke_MFCDoc::OnNewDocument()
- {
- if (!CDocument::OnNewDocument())
- return FALSE;
- // TODO: 在此添加重新初始化代码
- // (SDI 文档将重用该文档)
- InitDocument();
- return TRUE;
- }
- // CStroke_MFCDoc 序列化
- void CStroke_MFCDoc::Serialize(CArchive& ar)
- {
- if (ar.IsStoring())
- {
- // TODO: 在此添加存储代码
- }
- else
- {
- // TODO: 在此添加加载代码
- }
- m_StrokeList.Serialize(ar);
- }
- // CStroke_MFCDoc 诊断
- #ifdef _DEBUG
- void CStroke_MFCDoc::AssertValid() const
- {
- CDocument::AssertValid();
- }
- void CStroke_MFCDoc::Dump(CDumpContext& dc) const
- {
- CDocument::Dump(dc);
- }
- #endif //_DEBUG
- // CStroke_MFCDoc 命令
- BOOL CStroke_MFCDoc::OnOpenDocument(LPCTSTR lpszPathName)
- {
- if (!CDocument::OnOpenDocument(lpszPathName))
- return FALSE;
- // TODO: 在此添加您专用的创建代码
- InitDocument();
- return TRUE;
- }
- void CStroke_MFCDoc::ChangePen(void)
- {
- m_nPenWidth = bThinPen ? /*THICK_PEN*/m_nThickPen : m_nThinPen;
- bThinPen =! bThinPen;
- m_Pen.DeleteObject();
- m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- }
- void CStroke_MFCDoc::OnThickPen()
- {
- // TODO: 在此添加命令处理程序代码
- ChangePen();
- }
- void CStroke_MFCDoc::OnUpdateThickPen(CCmdUI *pCmdUI)
- {
- // TODO: 在此添加命令更新用户界面处理程序代码
- //pCmdUI->Enable(!m_StrokeList.IsEmpty());
- pCmdUI->SetCheck(bThinPen);
- }
- BOOL CStroke_MFCDoc::IsCapture(void)
- {
- POSITION pos = m_viewList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);
- if(pView->IsCapture())
- return TRUE;
- }
- return FALSE;
- }
- BOOL CStroke_MFCDoc::SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point)
- {
- POSITION pos = m_viewList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);
- if(pView != (CStroke_MFCView*)pWnd)
- SendMessage(pView->GetSafeHwnd(),message,(WPARAM)0x10000000,LPARAM(point.y<<16|point.x));
- }
- return TRUE;
- }
- int CStroke_MFCDoc::GetViewsCount(void)
- {
- return m_viewList.GetCount();
- }
- CStroke* CStroke_MFCDoc::GetCurStroke(void)
- {
- return m_pCurStroke;
- }
- void CStroke_MFCDoc::OnPenWidth()
- {
- // TODO: 在此添加命令处理程序代码
- CPenWidthDialog dlg;
- dlg.m_nThickPen = m_nThickPen;
- dlg.m_nThinPen = m_nThinPen;
- if(IDOK == dlg.DoModal())
- {
- m_nThickPen = dlg.m_nThickPen;
- m_nThinPen = dlg.m_nThinPen;
- UpdatePen();
- }
- }
- void CStroke_MFCDoc::UpdatePen(void)
- {
- m_nPenWidth = bThinPen ? m_nThinPen : m_nThickPen;
- m_Pen.DeleteObject();
- m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
- }
//////////////////////////////////////////////////////////////////view.h////////////////////////////////////////////////////////////////////////
- // Stroke_MFCView.h : CStroke_MFCView 类的接口
- //
- #pragma once
- #include "Stroke.h"
- class CStroke_MFCView : public /*CView*/CScrollView
- {
- protected: // 仅从序列化创建
- CStroke_MFCView();
- DECLARE_DYNCREATE(CStroke_MFCView)
- //数据
- private:
- //((CStroke*)&) m_pCurStroke;
- CPoint m_pointPre;
- // 属性
- public:
- CStroke_MFCDoc* GetDocument() const;
- // 操作
- public:
- // 重写
- public:
- virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
- virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
- protected:
- virtual void OnInitialUpdate(); // 构造后第一次调用
- virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
- virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
- virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
- // 实现
- public:
- virtual ~CStroke_MFCView();
- #ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
- #endif
- protected:
- // 生成的消息映射函数
- protected:
- afx_msg void OnFilePrintPreview();
- afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
- afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
- DECLARE_MESSAGE_MAP()
- public:
- afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
- afx_msg void OnMouseMove(UINT nFlags, CPoint point);
- BOOL IsCapture(void);
- //void DPToLP(CClientDC* pDC,CPoint& point);
- };
- #ifndef _DEBUG // Stroke_MFCView.cpp 中的调试版本
- inline CStroke_MFCDoc* CStroke_MFCView::GetDocument() const
- { return reinterpret_cast<CStroke_MFCDoc*>(m_pDocument); }
- #endif
//////////////////////////////////////////////////////////////////view.cpp////////////////////////////////////////////////////////////////////////
- // Stroke_MFCView.cpp : CStroke_MFCView 类的实现
- //
- #include "stdafx.h"
- #include "Stroke_MFC.h"
- #include "Stroke_MFCDoc.h"
- #include "Stroke_MFCView.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // CStroke_MFCView
- IMPLEMENT_DYNCREATE(CStroke_MFCView, /*CView*/CScrollView)
- BEGIN_MESSAGE_MAP(CStroke_MFCView, /*CView*/CScrollView)
- // 标准打印命令
- ON_COMMAND(ID_FILE_PRINT, &/*CView*/CScrollView::OnFilePrint)
- ON_COMMAND(ID_FILE_PRINT_DIRECT, &/*CView*/CScrollView::OnFilePrint)
- ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CStroke_MFCView::OnFilePrintPreview)
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- ON_WM_MOUSEMOVE()
- END_MESSAGE_MAP()
- // CStroke_MFCView 构造/析构
- static int nFirst=0;
- CStroke_MFCView::CStroke_MFCView()
- {
- // TODO: 在此处添加构造代码
- }
- CStroke_MFCView::~CStroke_MFCView()
- {
- }
- BOOL CStroke_MFCView::PreCreateWindow(CREATESTRUCT& cs)
- {
- // TODO: 在此处通过修改
- // CREATESTRUCT cs 来修改窗口类或样式
- return CView::PreCreateWindow(cs);
- }
- void CStroke_MFCView::OnInitialUpdate()
- {
- CScrollView::OnInitialUpdate();
- // TODO: 计算此视图的合计大小
- SetScrollSizes(MM_TEXT, GetDocument()->GetSize());
- }
- // CStroke_MFCView 绘制
- void CStroke_MFCView::OnDraw(CDC* pDC)
- {
- CStroke_MFCDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (!pDoc)
- return;
- // TODO: 在此处为本机数据添加绘制代码
- /*CTypedPtrList<CObList,CStroke*>*/CObList& pStrokeList = pDoc->GetStrokeList();
- POSITION pos = pStrokeList.GetHeadPosition();
- while(NULL != pos)
- {
- CStroke* pStroke = (CStroke*)pStrokeList.GetNext(pos);
- pStroke->Draw(pDC);
- }
- }
- // CStroke_MFCView 打印
- void CStroke_MFCView::OnFilePrintPreview()
- {
- AFXPrintPreview(this);
- }
- BOOL CStroke_MFCView::OnPreparePrinting(CPrintInfo* pInfo)
- {
- // 默认准备
- return DoPreparePrinting(pInfo);
- }
- void CStroke_MFCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: 添加额外的打印前进行的初始化过程
- }
- void CStroke_MFCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: 添加打印后进行的清理过程
- }
- void CStroke_MFCView::OnRButtonUp(UINT nFlags, CPoint point)
- {
- ClientToScreen(&point);
- OnContextMenu(this, point);
- }
- void CStroke_MFCView::OnContextMenu(CWnd* pWnd, CPoint point)
- {
- theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
- }
- // CStroke_MFCView 诊断
- #ifdef _DEBUG
- void CStroke_MFCView::AssertValid() const
- {
- CView::AssertValid();
- }
- void CStroke_MFCView::Dump(CDumpContext& dc) const
- {
- CView::Dump(dc);
- }
- CStroke_MFCDoc* CStroke_MFCView::GetDocument() const // 非调试版本是内联的
- {
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CStroke_MFCDoc)));
- return (CStroke_MFCDoc*)m_pDocument;
- }
- #endif //_DEBUG
- // CStroke_MFCView 消息处理程序
- void CStroke_MFCView::OnLButtonDown(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- m_pointPre = point;
- if(0x10000000 != nFlags)//如果是系统发送的话,由该view唯一创建线条
- {
- GetDocument()->NewStroke();
- //将设备坐标转换成逻辑坐标保存起来
- CClientDC dc(this);
- OnPrepareDC(&dc);
- dc.DPtoLP(&point);
- GetDocument()->GetCurStroke()->AddPoint(point);
- //必须将逻辑坐标转换完后才能发送,使得兄弟视图画的不是设备坐标而是逻辑坐标
- GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONDOWN,nFlags,point);
- SetCapture();
- }
- CView::OnLButtonDown(nFlags, point);
- }
- void CStroke_MFCView::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- if(!GetDocument()->IsCapture()/*GetCapture() != this*/)
- return;
- if(0x10000000 != nFlags)
- {
- CClientDC dc(this);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- OnPrepareDC(&dc);
- dc.DPtoLP(&point);
- GetDocument()->GetCurStroke()->AddPoint(point);
- GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONUP,nFlags,point);
- ReleaseCapture();
- }
- else
- {
- CClientDC dc(this);
- OnPrepareDC(&dc);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- }
- CView::OnLButtonUp(nFlags, point);
- }
- void CStroke_MFCView::OnMouseMove(UINT nFlags, CPoint point)
- {
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- if(!GetDocument()->IsCapture()/*GetCapture() != this*/)//如果没有这一句,鼠标移动的时候也会接受消息,但本不应该有这个程序处理的
- return;
- if(0x10000000 != nFlags)
- {
- CClientDC dc(this);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- m_pointPre = point;
- OnPrepareDC(&dc);
- dc.DPtoLP(&point);
- GetDocument()->GetCurStroke()->AddPoint(point);
- GetDocument()->SendBTMsgToOtherViews(this,WM_MOUSEMOVE,nFlags,point);
- }
- else//如果是兄弟发来的消息,那么自己应该会逻辑坐标。而不是设备坐标
- {
- CClientDC dc(this);
- OnPrepareDC(&dc);
- CPen* pCurPen = GetDocument()->GetCurPen();
- CPen* pOldPen = dc.SelectObject(pCurPen);
- dc.MoveTo(m_pointPre);
- dc.LineTo(point);
- dc.SelectObject(pOldPen);
- m_pointPre = point;
- }
- CView::OnMouseMove(nFlags, point);
- }
- BOOL CStroke_MFCView::IsCapture(void)
- {
- return this == GetCapture();
- }
- MFC 多视图同步画图解决方案
- MFC 多视图同步画图解决方案
- MFC 多视图同步画图解决方案
- MFC 画图
- MFC画图
- MFC画图
- MFC画图
- MFC画图
- MFC画图
- MFC画图
- MFC 画图
- MFC画图
- MFC画图
- MFC画图
- 深入浅出 MFC多视图
- MFC 多视图
- 深入浅出 MFC多视图
- 深入浅出 MFC多视图
- HDU 2111 Saving HDU
- MySQL 临时目录
- UrlRewriter url 地址重写
- xilinx 不能自动安装USB 驱动
- C++ Bridge 设计模式
- MFC 多视图同步画图解决方案
- 经纬财富:大连白银支撑与压力位六大分析法
- js控制双击修改内容
- Solr开发<转>
- Android应用崩溃后异常捕获并重启
- Linux系统编程(4)——文件与IO之ioctl函数
- Apache Commons Chain简明手册
- 线程池的介绍及简单实现
- "服务器 '' 上的 MSDTC 不可用。"