MFC 多视图同步画图解决方案

来源:互联网 发布:剑网3炮姐捏脸数据 编辑:程序博客网 时间:2024/06/12 21:57
今天看《深入浅出MFC》时,看到要做多视图同步画图问题,此书上刚介绍完单视图画图后,引出多视图画图的问题(多视图是指一个子视图窗口中多个视图区域,由SpliiterWnd分割生成的)。存在相互通知,并特别强调绘图效率的问题。我迫不及待的用自己的想法实现了这个高效率绘图问题。后来看了一下书上的方法,确实也不错,但感觉比我的绘图效率低。我的绘图方法其实是因为书上开始讲的单视图绘图的方法,给了我一个用此方法来提高绘图效率的灵感。

 

单视图画图的基本方法交代:

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////////////////////////////////////////////////////////////////////////

[cpp]
  1. #pragma once  
  2.   
  3. #include "Stroke.h"  
  4.   
  5. class CStroke_MFCDoc : public CDocument  
  6. {  
  7. protected// 仅从序列化创建  
  8.     CStroke_MFCDoc();  
  9.     DECLARE_DYNCREATE(CStroke_MFCDoc)  
  10.   
  11. //数据  
  12. private:  
  13.     //CTypedPtrList<CObList,CStroke*> m_StrokeList;  
  14.     CObList m_StrokeList;//笔画列表  
  15.   
  16.     int m_nPenWidth;//当前笔宽,通过此来调节新创建的笔的笔宽  
  17.     bool bThinPen;//是否是细笔  
  18.     CPen m_Pen;//当前笔  
  19.     CStroke* m_pCurStroke;//当前笔画指针  
  20. public:  
  21.     enum{THIN_PEN=2,THICK_PEN=7};  
  22.   
  23. // 属性  
  24. public:  
  25.   
  26. // 操作  
  27. public:  
  28.     /*CTypedPtrList<CObList,CStroke*>*/CObList& GetStrokeList();  
  29.     void InitDocument();  
  30.     virtual void DeleteContents();  
  31.     CStroke* NewStroke();  
  32.     CPen* GetCurPen();  
  33. // 重写  
  34. public:  
  35.     virtual BOOL OnNewDocument();  
  36.     virtual void Serialize(CArchive& ar);  
  37.   
  38. // 实现  
  39. public:  
  40.     virtual ~CStroke_MFCDoc();  
  41. #ifdef _DEBUG  
  42.     virtual void AssertValid() const;  
  43.     virtual void Dump(CDumpContext& dc) const;  
  44. #endif  
  45.   
  46. protected:  
  47.   
  48. // 生成的消息映射函数  
  49. protected:  
  50.     DECLARE_MESSAGE_MAP()  
  51. public:  
  52.     virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);  
  53.     void ChangePen(void);//在粗笔和细笔之间变化,并返回是否为细笔  
  54.     afx_msg void OnThickPen();  
  55.     afx_msg void OnUpdateThickPen(CCmdUI *pCmdUI);  
  56.     BOOL IsCapture(void);//子视图中是否有捕获鼠标的  
  57.   
  58.     //向除了pWnd外的其他子视图发送相同消息,以实现新建窗口同步  
  59.     BOOL SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point);  
  60.     int GetViewsCount(void);//获得与本文档相关的当前子视图个数  
  61.     CStroke* GetCurStroke(void);//获得当前笔画指针  
  62. };  

//////////////////////////////////////////////////////////////Doc.cpp/////////////////////////////////////////////////////////////////////////////

[cpp]
  1. #include "stdafx.h"  
  2. #include "Stroke_MFC.h"  
  3.   
  4. #include "Stroke_MFCDoc.h"  
  5. #include "Stroke_MFCView.h"  
  6.   
  7. #ifdef _DEBUG  
  8. #define new DEBUG_NEW  
  9. #endif  
  10.   
  11.   
  12. // CStroke_MFCDoc  
  13.   
  14. IMPLEMENT_DYNCREATE(CStroke_MFCDoc, CDocument)  
  15.   
  16. BEGIN_MESSAGE_MAP(CStroke_MFCDoc, CDocument)  
  17.     ON_COMMAND(ID_THICK_PEN, &CStroke_MFCDoc::OnThickPen)  
  18.     ON_UPDATE_COMMAND_UI(ID_THICK_PEN, &CStroke_MFCDoc::OnUpdateThickPen)  
  19. END_MESSAGE_MAP()  
  20.   
  21.   
  22. // CStroke_MFCDoc 构造/析构  
  23.   
  24. CStroke_MFCDoc::CStroke_MFCDoc()  
  25. {  
  26.     // TODO: 在此添加一次性构造代码  
  27. }  
  28.   
  29. /*CTypedPtrList<CObList,CStroke*>*/CObList& CStroke_MFCDoc::GetStrokeList()  
  30. {  
  31.     return m_StrokeList;  
  32. }  
  33.   
  34. void CStroke_MFCDoc::InitDocument()  
  35. {  
  36.     m_nPenWidth=THIN_PEN;  
  37.     bThinPen=TRUE;  
  38.     m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  39. }  
  40.   
  41. void CStroke_MFCDoc::DeleteContents()  
  42. {  
  43.     while(!m_StrokeList.IsEmpty())  
  44.     {  
  45.         delete m_StrokeList.RemoveHead();  
  46.     }  
  47.     CDocument::DeleteContents();  
  48. }  
  49.   
  50. CStroke* CStroke_MFCDoc::NewStroke()  
  51. {  
  52.     m_pCurStroke=new CStroke(m_nPenWidth);  
  53.     m_StrokeList.AddTail(m_pCurStroke);  
  54.     SetModifiedFlag();  
  55.     return m_pCurStroke;  
  56. }  
  57.   
  58. CPen* CStroke_MFCDoc::GetCurPen()  
  59. {  
  60.     return &m_Pen;  
  61. }  
  62.   
  63. CStroke_MFCDoc::~CStroke_MFCDoc()  
  64. {  
  65. }  
  66.   
  67. BOOL CStroke_MFCDoc::OnNewDocument()  
  68. {  
  69.     if (!CDocument::OnNewDocument())  
  70.         return FALSE;  
  71.   
  72.     // TODO: 在此添加重新初始化代码  
  73.     // (SDI 文档将重用该文档)  
  74.     InitDocument();  
  75.   
  76.     return TRUE;  
  77. }  
  78.   
  79.   
  80.   
  81.   
  82. // CStroke_MFCDoc 序列化  
  83.   
  84. void CStroke_MFCDoc::Serialize(CArchive& ar)  
  85. {  
  86.     if (ar.IsStoring())  
  87.     {  
  88.         // TODO: 在此添加存储代码  
  89.     }  
  90.     else  
  91.     {  
  92.         // TODO: 在此添加加载代码  
  93.     }  
  94.   
  95.     m_StrokeList.Serialize(ar);  
  96. }  
  97.   
  98.   
  99. // CStroke_MFCDoc 诊断  
  100.   
  101. #ifdef _DEBUG  
  102. void CStroke_MFCDoc::AssertValid() const  
  103. {  
  104.     CDocument::AssertValid();  
  105. }  
  106.   
  107. void CStroke_MFCDoc::Dump(CDumpContext& dc) const  
  108. {  
  109.     CDocument::Dump(dc);  
  110. }  
  111. #endif //_DEBUG  
  112.   
  113.   
  114. // CStroke_MFCDoc 命令  
  115.   
  116. BOOL CStroke_MFCDoc::OnOpenDocument(LPCTSTR lpszPathName)  
  117. {  
  118.     if (!CDocument::OnOpenDocument(lpszPathName))  
  119.         return FALSE;  
  120.   
  121.     // TODO:  在此添加您专用的创建代码  
  122.     InitDocument();  
  123.     return TRUE;  
  124. }  
  125.   
  126. void CStroke_MFCDoc::ChangePen(void)  
  127. {  
  128.     m_nPenWidth = bThinPen ? THICK_PEN : THIN_PEN;  
  129.     bThinPen =! bThinPen;  
  130.     m_Pen.DeleteObject();  
  131.     m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  132. }  
  133.   
  134. void CStroke_MFCDoc::OnThickPen()  
  135. {  
  136.     // TODO: 在此添加命令处理程序代码  
  137.     ChangePen();  
  138. }  
  139.   
  140. void CStroke_MFCDoc::OnUpdateThickPen(CCmdUI *pCmdUI)  
  141. {  
  142.     // TODO: 在此添加命令更新用户界面处理程序代码  
  143.     pCmdUI->Enable(!m_StrokeList.IsEmpty());  
  144.     pCmdUI->SetCheck(bThinPen);  
  145. }  
  146.   
  147. BOOL CStroke_MFCDoc::IsCapture(void)  
  148. {  
  149.     POSITION pos = m_viewList.GetHeadPosition();  
  150.     while(NULL != pos)  
  151.     {  
  152.         CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);  
  153.         if(pView->IsCapture())  
  154.             return TRUE;  
  155.     }  
  156.   
  157.     return FALSE;  
  158. }  
  159.   
  160. BOOL CStroke_MFCDoc::SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point)  
  161. {  
  162.     POSITION pos = m_viewList.GetHeadPosition();  
  163.     while(NULL != pos)  
  164.     {  
  165.         CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);  
  166.         if(pView != (CStroke_MFCView*)pWnd)  
  167.             SendMessage(pView->GetSafeHwnd(),message,(WPARAM)0,LPARAM(point.y<<16|point.x));  
  168.     }  
  169.     return TRUE;  
  170. }  
  171.   
  172. int CStroke_MFCDoc::GetViewsCount(void)  
  173. {  
  174.     return m_viewList.GetCount();  
  175. }  
  176.   
  177. CStroke* CStroke_MFCDoc::GetCurStroke(void)  
  178. {  
  179.     return m_pCurStroke;  
  180. }  

 

//////////////////////////////////////////////////////////////view.h///////////////////////////////////////////////////////////////////////////////

[cpp]
  1. #pragma once  
  2. #include "Stroke.h"  
  3.   
  4. class CStroke_MFCView : public CView  
  5. {  
  6. protected// 仅从序列化创建  
  7.     CStroke_MFCView();  
  8.     DECLARE_DYNCREATE(CStroke_MFCView)  
  9.   
  10. //数据  
  11. private:  
  12.     //((CStroke*)&) m_pCurStroke;  
  13.     CPoint m_pointPre;  
  14. // 属性  
  15. public:  
  16.     CStroke_MFCDoc* GetDocument() const;  
  17.   
  18. // 操作  
  19. public:  
  20.   
  21. // 重写  
  22. public:  
  23.     virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图  
  24.     virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  
  25. protected:  
  26.     virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);  
  27.     virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);  
  28.     virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);  
  29.   
  30. // 实现  
  31. public:  
  32.     virtual ~CStroke_MFCView();  
  33. #ifdef _DEBUG  
  34.     virtual void AssertValid() const;  
  35.     virtual void Dump(CDumpContext& dc) const;  
  36. #endif  
  37.   
  38. protected:  
  39.   
  40. // 生成的消息映射函数  
  41. protected:  
  42.     afx_msg void OnFilePrintPreview();  
  43.     afx_msg void OnRButtonUp(UINT nFlags, CPoint point);  
  44.     afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);  
  45.     DECLARE_MESSAGE_MAP()  
  46. public:  
  47.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  48.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  49.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  50.     BOOL IsCapture(void);  
  51. };  
  52.   
  53. #ifndef _DEBUG  // Stroke_MFCView.cpp 中的调试版本  
  54. inline CStroke_MFCDoc* CStroke_MFCView::GetDocument() const  
  55.    { return reinterpret_cast<CStroke_MFCDoc*>(m_pDocument); }  
  56. #endif  

//////////////////////////////////////////////////////////////view.cpp////////////////////////////////////////////////////////////////////////////

[cpp]
  1. #include "stdafx.h"  
  2. #include "Stroke_MFC.h"  
  3.   
  4. #include "Stroke_MFCDoc.h"  
  5. #include "Stroke_MFCView.h"  
  6.   
  7. #ifdef _DEBUG  
  8. #define new DEBUG_NEW  
  9. #endif  
  10.   
  11. // CStroke_MFCView  
  12.   
  13. IMPLEMENT_DYNCREATE(CStroke_MFCView, CView)  
  14.   
  15. BEGIN_MESSAGE_MAP(CStroke_MFCView, CView)  
  16.     // 标准打印命令  
  17.     ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)  
  18.     ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)  
  19.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CStroke_MFCView::OnFilePrintPreview)  
  20.     ON_WM_LBUTTONDOWN()  
  21.     ON_WM_LBUTTONUP()  
  22.     ON_WM_MOUSEMOVE()  
  23. END_MESSAGE_MAP()  
  24.   
  25. // CStroke_MFCView 构造/析构  
  26. static int nFirst=0;  
  27.   
  28. CStroke_MFCView::CStroke_MFCView()  
  29. {  
  30.     // TODO: 在此处添加构造代码  
  31. }  
  32.   
  33. CStroke_MFCView::~CStroke_MFCView()  
  34. {  
  35. }  
  36.   
  37. BOOL CStroke_MFCView::PreCreateWindow(CREATESTRUCT& cs)  
  38. {  
  39.     // TODO: 在此处通过修改  
  40.     //  CREATESTRUCT cs 来修改窗口类或样式  
  41.   
  42.     return CView::PreCreateWindow(cs);  
  43. }  
  44.   
  45. // CStroke_MFCView 绘制  
  46.   
  47. void CStroke_MFCView::OnDraw(CDC* pDC)  
  48. {  
  49.     CStroke_MFCDoc* pDoc = GetDocument();  
  50.     ASSERT_VALID(pDoc);  
  51.     if (!pDoc)  
  52.         return;  
  53.   
  54.     // TODO: 在此处为本机数据添加绘制代码  
  55.     /*CTypedPtrList<CObList,CStroke*>*/CObList& pStrokeList = pDoc->GetStrokeList();  
  56.     POSITION pos = pStrokeList.GetHeadPosition();  
  57.     while(NULL != pos)  
  58.     {  
  59.          CStroke* pStroke = (CStroke*)pStrokeList.GetNext(pos);  
  60.          pStroke->Draw(pDC);  
  61.     }  
  62. }  
  63.   
  64.   
  65. // CStroke_MFCView 打印  
  66.   
  67.   
  68. void CStroke_MFCView::OnFilePrintPreview()  
  69. {  
  70.     AFXPrintPreview(this);  
  71. }  
  72.   
  73. BOOL CStroke_MFCView::OnPreparePrinting(CPrintInfo* pInfo)  
  74. {  
  75.     // 默认准备  
  76.     return DoPreparePrinting(pInfo);  
  77. }  
  78.   
  79. void CStroke_MFCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  80. {  
  81.     // TODO: 添加额外的打印前进行的初始化过程  
  82. }  
  83.   
  84. void CStroke_MFCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  85. {  
  86.     // TODO: 添加打印后进行的清理过程  
  87. }  
  88.   
  89. void CStroke_MFCView::OnRButtonUp(UINT nFlags, CPoint point)  
  90. {  
  91.     ClientToScreen(&point);  
  92.     OnContextMenu(this, point);  
  93. }  
  94.   
  95. void CStroke_MFCView::OnContextMenu(CWnd* pWnd, CPoint point)  
  96. {  
  97.     theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);  
  98. }  
  99.   
  100.   
  101. // CStroke_MFCView 诊断  
  102.   
  103. #ifdef _DEBUG  
  104. void CStroke_MFCView::AssertValid() const  
  105. {  
  106.     CView::AssertValid();  
  107. }  
  108.   
  109. void CStroke_MFCView::Dump(CDumpContext& dc) const  
  110. {  
  111.     CView::Dump(dc);  
  112. }  
  113.   
  114. CStroke_MFCDoc* CStroke_MFCView::GetDocument() const // 非调试版本是内联的  
  115. {  
  116.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CStroke_MFCDoc)));  
  117.     return (CStroke_MFCDoc*)m_pDocument;  
  118. }  
  119. #endif //_DEBUG  
  120.   
  121.   
  122. // CStroke_MFCView 消息处理程序  
  123.   
  124. void CStroke_MFCView::OnLButtonDown(UINT nFlags, CPoint point)  
  125. {  
  126.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  127.     if(0 != nFlags)//如果是系统发送的话,由该view唯一创建线条  
  128.     {  
  129.         GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONDOWN,nFlags,point);  
  130.         GetDocument()->NewStroke();  
  131.         GetDocument()->GetCurStroke()->AddPoint(point);  
  132.   
  133.           
  134.     }  
  135.   
  136.     m_pointPre = point;  
  137.     SetCapture();  
  138.   
  139.     CView::OnLButtonDown(nFlags, point);  
  140. }  
  141.   
  142. void CStroke_MFCView::OnLButtonUp(UINT nFlags, CPoint point)  
  143. {  
  144.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  145.     if(!GetDocument()->IsCapture()/*GetCapture() != this*/)  
  146.         return;  
  147.     if(0 != nFlags)  
  148.     {  
  149.         GetDocument()->GetCurStroke()->AddPoint(point);  
  150.         GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONUP,nFlags,point);  
  151.     }  
  152.     CClientDC dc(this);  
  153.     CPen* pCurPen = GetDocument()->GetCurPen();  
  154.     CPen* pOldPen = dc.SelectObject(pCurPen);  
  155.     dc.MoveTo(m_pointPre);  
  156.     dc.LineTo(point);  
  157.     dc.SelectObject(pOldPen);  
  158.   
  159.     ReleaseCapture();  
  160.     CView::OnLButtonUp(nFlags, point);  
  161. }   
  162.   
  163. void CStroke_MFCView::OnMouseMove(UINT nFlags, CPoint point)  
  164. {  
  165.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  166.     if(!GetDocument()->IsCapture()/*GetCapture() != this*/)//如果没有这一句,鼠标移动的时候也会接受消息,但本不应该有这个程序处理的  
  167.         return;  
  168.       
  169.       
  170.     CClientDC dc(this);  
  171.     CPen* pCurPen = GetDocument()->GetCurPen();  
  172.     CPen* pOldPen = dc.SelectObject(pCurPen);  
  173.     dc.MoveTo(m_pointPre);  
  174.     dc.LineTo(point);  
  175.     dc.SelectObject(pOldPen);  
  176.   
  177.     if(0 != nFlags)  
  178.     {  
  179.         GetDocument()->SendBTMsgToOtherViews(this,WM_MOUSEMOVE,nFlags,point);  
  180.         GetDocument()->GetCurStroke()->AddPoint(point);  
  181.               
  182.     }  
  183.     m_pointPre = point;  
  184.     CView::OnMouseMove(nFlags, point);  
  185. }  
  186.   
  187. BOOL CStroke_MFCView::IsCapture(void)  
  188. {  
  189.     return this == GetCapture();  
  190. }  

//////////////////////////////////////////////////////////////CStroke.h//////////////////////////////////////////////////////////////////////////

[cpp]
  1. #pragma once  
  2. #include "afx.h"  
  3.   
  4. class CStroke :  
  5.     public CObject  
  6. {  
  7.     int m_nPenWidth;  
  8.     CArray<CPoint,CPoint> m_pointArray;  
  9. public:  
  10.     CStroke(void);  
  11.     CStroke(int nPenWidth);  
  12.     void AddPoint(CPoint point);  
  13.     void Draw(CDC* pDC);  
  14.     void virtual Serialize(CArchive& ar);  
  15.     DECLARE_SERIAL(CStroke)  
  16.     ~CStroke(void);  
  17. };  

//////////////////////////////////////////////////////////////CStroke.cpp////////////////////////////////////////////////////////////////////////

[cpp]
  1. #include "StdAfx.h"  
  2. #include "Stroke.h"  
  3.   
  4. IMPLEMENT_SERIAL(CStroke,CObject,1);  
  5.   
  6. CStroke::CStroke(void)  
  7. {  
  8.     m_nPenWidth=2;  
  9. }  
  10.   
  11. CStroke::CStroke(int nPenWidth)  
  12. {  
  13.     m_nPenWidth=nPenWidth;  
  14. }  
  15.   
  16. void CStroke::AddPoint(CPoint point)  
  17. {  
  18.     m_pointArray.Add(point);  
  19. }  
  20.   
  21. void CStroke::Draw(CDC* pDC)  
  22. {  
  23.     CPen pen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  24.     CPen* pOldPen=pDC->SelectObject(&pen);  
  25.     int size=m_pointArray.GetSize();  
  26.     if(size>0)  
  27.     {  
  28.         pDC->MoveTo(m_pointArray[0]);  
  29.         for(int i=1;i<size;i++)  
  30.             pDC->LineTo(m_pointArray[i]);  
  31.     }  
  32.     pDC->SelectObject(pOldPen);  
  33. }  
  34.   
  35. void CStroke::Serialize(CArchive& ar)  
  36. {  
  37.     if(ar.IsStoring())  
  38.     {  
  39.         ar<<m_nPenWidth;  
  40.     }  
  41.     else  
  42.     {  
  43.         ar>>m_nPenWidth;  
  44.     }  
  45.   
  46.     m_pointArray.Serialize(ar);  
  47. }  
  48.   
  49. CStroke::~CStroke(void)  
  50. {  
  51. }  

 

在滚动窗口中使显示时,为了使激活视图(被鼠标激活的)和兄弟视图在逻辑上同步,必须让激活视图完成两个任务。

1:进行设备坐标绘画。

2:逻辑坐标添加点信息

注意设备坐标只是在绘图上使用,而文件保存的是逻辑坐标。

 

兄弟视图要完成的任务只有,完成逻辑坐标绘画。这就和激活视图有着既然相反的绘画方式。

滚动窗口的响应代码:

//////////////////////////////////////////////////////////////////Doc.h////////////////////////////////////////////////////////////////////////

[cpp]
  1. // Stroke_MFCDoc.h : CStroke_MFCDoc 类的接口  
  2. //  
  3.   
  4.   
  5. #pragma once  
  6.   
  7. #include "Stroke.h"  
  8.   
  9. class CStroke_MFCDoc : public CDocument  
  10. {  
  11. protected// 仅从序列化创建  
  12.     CStroke_MFCDoc();  
  13.     DECLARE_DYNCREATE(CStroke_MFCDoc)  
  14.     CRect rc;  
  15. //数据  
  16. private:  
  17.     //CTypedPtrList<CObList,CStroke*> m_StrokeList;  
  18.     CObList m_StrokeList;//笔画列表  
  19.   
  20.     int m_nPenWidth;//当前笔宽,通过此来调节新创建的笔的笔宽  
  21.     bool bThinPen;//是否是细笔  
  22.     CPen m_Pen;//当前笔  
  23.     CStroke* m_pCurStroke;//当前笔画指针  
  24.   
  25.     int m_nThinPen;//细笔  
  26.     int m_nThickPen;//粗笔  
  27.   
  28.     CSize m_sizeDoc;  
  29.   
  30. // 属性  
  31. public:  
  32.   
  33. // 操作  
  34. public:  
  35.     /*CTypedPtrList<CObList,CStroke*>*/CObList& GetStrokeList();  
  36.     void InitDocument();  
  37.     virtual void DeleteContents();  
  38.     CStroke* NewStroke();  
  39.     CPen* GetCurPen();  
  40.     CSize GetSize() const {return m_sizeDoc;}  
  41. // 重写  
  42. public:  
  43.     virtual BOOL OnNewDocument();  
  44.     virtual void Serialize(CArchive& ar);  
  45.   
  46. // 实现  
  47. public:  
  48.     virtual ~CStroke_MFCDoc();  
  49. #ifdef _DEBUG  
  50.     virtual void AssertValid() const;  
  51.     virtual void Dump(CDumpContext& dc) const;  
  52. #endif  
  53.   
  54. protected:  
  55.   
  56. // 生成的消息映射函数  
  57. protected:  
  58.     DECLARE_MESSAGE_MAP()  
  59. public:  
  60.     virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);  
  61.     void ChangePen(void);//在粗笔和细笔之间变化,并返回是否为细笔  
  62.     afx_msg void OnThickPen();  
  63.     afx_msg void OnUpdateThickPen(CCmdUI *pCmdUI);  
  64.     BOOL IsCapture(void);//子视图中是否有捕获鼠标的  
  65.   
  66.     //向除了pWnd外的其他子视图发送相同消息,以实现新建窗口同步  
  67.     BOOL SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point);  
  68.     int GetViewsCount(void);//获得与本文档相关的当前子视图个数  
  69.     CStroke* GetCurStroke(void);//获得当前笔画指针  
  70.     afx_msg void OnPenWidth();  
  71.     void UpdatePen(void);  
  72. };  

//////////////////////////////////////////////////////////////////Doc.cpp////////////////////////////////////////////////////////////////////////

[cpp]
  1. // Stroke_MFCDoc.cpp : CStroke_MFCDoc 类的实现  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "Stroke_MFC.h"  
  6.   
  7. #include "Stroke_MFCDoc.h"  
  8. #include "Stroke_MFCView.h"  
  9. #include "PenWidthDialog.h"  
  10.   
  11. #ifdef _DEBUG  
  12. #define new DEBUG_NEW  
  13. #endif  
  14.   
  15.   
  16. // CStroke_MFCDoc  
  17.   
  18. IMPLEMENT_DYNCREATE(CStroke_MFCDoc, CDocument)  
  19.   
  20. BEGIN_MESSAGE_MAP(CStroke_MFCDoc, CDocument)  
  21.     ON_COMMAND(ID_THICK_PEN, &CStroke_MFCDoc::OnThickPen)  
  22.     ON_UPDATE_COMMAND_UI(ID_THICK_PEN, &CStroke_MFCDoc::OnUpdateThickPen)  
  23.     ON_COMMAND(ID_PEN_WIDTH, &CStroke_MFCDoc::OnPenWidth)  
  24. END_MESSAGE_MAP()  
  25.   
  26.   
  27. // CStroke_MFCDoc 构造/析构  
  28.   
  29. CStroke_MFCDoc::CStroke_MFCDoc()  
  30. {  
  31.     // TODO: 在此添加一次性构造代码  
  32. }  
  33.   
  34. /*CTypedPtrList<CObList,CStroke*>*/CObList& CStroke_MFCDoc::GetStrokeList()  
  35. {  
  36.     return m_StrokeList;  
  37. }  
  38.   
  39. void CStroke_MFCDoc::InitDocument()  
  40. {  
  41.     m_nPenWidth = /*THIN_PEN*/m_nThinPen=2;  
  42.     m_nThickPen = 5;  
  43.     bThinPen=TRUE;  
  44.     m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  45.   
  46.     m_sizeDoc.SetSize(800,900);  
  47. }  
  48.   
  49. void CStroke_MFCDoc::DeleteContents()  
  50. {  
  51.     while(!m_StrokeList.IsEmpty())  
  52.     {  
  53.         delete m_StrokeList.RemoveHead();  
  54.     }  
  55.     CDocument::DeleteContents();  
  56. }  
  57.   
  58. CStroke* CStroke_MFCDoc::NewStroke()  
  59. {  
  60.     m_pCurStroke=new CStroke(m_nPenWidth);  
  61.     m_StrokeList.AddTail(m_pCurStroke);  
  62.     SetModifiedFlag();  
  63.     return m_pCurStroke;  
  64. }  
  65.   
  66. CPen* CStroke_MFCDoc::GetCurPen()  
  67. {  
  68.     return &m_Pen;  
  69. }  
  70.   
  71. CStroke_MFCDoc::~CStroke_MFCDoc()  
  72. {  
  73. }  
  74.   
  75. BOOL CStroke_MFCDoc::OnNewDocument()  
  76. {  
  77.     if (!CDocument::OnNewDocument())  
  78.         return FALSE;  
  79.   
  80.     // TODO: 在此添加重新初始化代码  
  81.     // (SDI 文档将重用该文档)  
  82.     InitDocument();  
  83.   
  84.     return TRUE;  
  85. }  
  86.   
  87.   
  88.   
  89.   
  90. // CStroke_MFCDoc 序列化  
  91.   
  92. void CStroke_MFCDoc::Serialize(CArchive& ar)  
  93. {  
  94.     if (ar.IsStoring())  
  95.     {  
  96.         // TODO: 在此添加存储代码  
  97.     }  
  98.     else  
  99.     {  
  100.         // TODO: 在此添加加载代码  
  101.     }  
  102.   
  103.     m_StrokeList.Serialize(ar);  
  104. }  
  105.   
  106.   
  107. // CStroke_MFCDoc 诊断  
  108.   
  109. #ifdef _DEBUG  
  110. void CStroke_MFCDoc::AssertValid() const  
  111. {  
  112.     CDocument::AssertValid();  
  113. }  
  114.   
  115. void CStroke_MFCDoc::Dump(CDumpContext& dc) const  
  116. {  
  117.     CDocument::Dump(dc);  
  118. }  
  119. #endif //_DEBUG  
  120.   
  121.   
  122. // CStroke_MFCDoc 命令  
  123.   
  124. BOOL CStroke_MFCDoc::OnOpenDocument(LPCTSTR lpszPathName)  
  125. {  
  126.     if (!CDocument::OnOpenDocument(lpszPathName))  
  127.         return FALSE;  
  128.   
  129.     // TODO:  在此添加您专用的创建代码  
  130.     InitDocument();  
  131.     return TRUE;  
  132. }  
  133.   
  134. void CStroke_MFCDoc::ChangePen(void)  
  135. {  
  136.     m_nPenWidth = bThinPen ? /*THICK_PEN*/m_nThickPen : m_nThinPen;  
  137.     bThinPen =! bThinPen;  
  138.     m_Pen.DeleteObject();  
  139.     m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  140. }  
  141.   
  142. void CStroke_MFCDoc::OnThickPen()  
  143. {  
  144.     // TODO: 在此添加命令处理程序代码  
  145.     ChangePen();  
  146. }  
  147.   
  148. void CStroke_MFCDoc::OnUpdateThickPen(CCmdUI *pCmdUI)  
  149. {  
  150.     // TODO: 在此添加命令更新用户界面处理程序代码  
  151.     //pCmdUI->Enable(!m_StrokeList.IsEmpty());  
  152.     pCmdUI->SetCheck(bThinPen);  
  153. }  
  154.   
  155. BOOL CStroke_MFCDoc::IsCapture(void)  
  156. {  
  157.     POSITION pos = m_viewList.GetHeadPosition();  
  158.     while(NULL != pos)  
  159.     {  
  160.         CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);  
  161.         if(pView->IsCapture())  
  162.             return TRUE;  
  163.     }  
  164.   
  165.     return FALSE;  
  166. }  
  167.   
  168. BOOL CStroke_MFCDoc::SendBTMsgToOtherViews(CWnd* pWnd,UINT message,UINT nFlags, CPoint point)  
  169. {  
  170.     POSITION pos = m_viewList.GetHeadPosition();  
  171.     while(NULL != pos)  
  172.     {  
  173.         CStroke_MFCView* pView = (CStroke_MFCView*)m_viewList.GetNext(pos);  
  174.         if(pView != (CStroke_MFCView*)pWnd)  
  175.             SendMessage(pView->GetSafeHwnd(),message,(WPARAM)0x10000000,LPARAM(point.y<<16|point.x));  
  176.     }  
  177.     return TRUE;  
  178. }  
  179.   
  180. int CStroke_MFCDoc::GetViewsCount(void)  
  181. {  
  182.     return m_viewList.GetCount();  
  183. }  
  184.   
  185. CStroke* CStroke_MFCDoc::GetCurStroke(void)  
  186. {  
  187.     return m_pCurStroke;  
  188. }  
  189.   
  190. void CStroke_MFCDoc::OnPenWidth()  
  191. {  
  192.     // TODO: 在此添加命令处理程序代码  
  193.     CPenWidthDialog dlg;  
  194.     dlg.m_nThickPen = m_nThickPen;  
  195.     dlg.m_nThinPen = m_nThinPen;  
  196.   
  197.     if(IDOK == dlg.DoModal())  
  198.     {  
  199.         m_nThickPen = dlg.m_nThickPen;  
  200.         m_nThinPen = dlg.m_nThinPen;  
  201.         UpdatePen();  
  202.     }  
  203. }  
  204.   
  205. void CStroke_MFCDoc::UpdatePen(void)  
  206. {  
  207.     m_nPenWidth = bThinPen ? m_nThinPen : m_nThickPen;  
  208.     m_Pen.DeleteObject();  
  209.     m_Pen.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));  
  210. }  

//////////////////////////////////////////////////////////////////view.h////////////////////////////////////////////////////////////////////////

[cpp] view plaincopyprint?
  1. // Stroke_MFCView.h : CStroke_MFCView 类的接口  
  2. //  
  3.   
  4.   
  5. #pragma once  
  6. #include "Stroke.h"  
  7.   
  8. class CStroke_MFCView : public /*CView*/CScrollView  
  9. {  
  10. protected// 仅从序列化创建  
  11.     CStroke_MFCView();  
  12.     DECLARE_DYNCREATE(CStroke_MFCView)  
  13.   
  14. //数据  
  15. private:  
  16.     //((CStroke*)&) m_pCurStroke;  
  17.     CPoint m_pointPre;  
  18. // 属性  
  19. public:  
  20.     CStroke_MFCDoc* GetDocument() const;  
  21.   
  22. // 操作  
  23. public:  
  24.   
  25. // 重写  
  26. public:  
  27.     virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图  
  28.     virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  
  29. protected:  
  30.     virtual void OnInitialUpdate(); // 构造后第一次调用  
  31.     virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);  
  32.     virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);  
  33.     virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);  
  34.   
  35. // 实现  
  36. public:  
  37.     virtual ~CStroke_MFCView();  
  38. #ifdef _DEBUG  
  39.     virtual void AssertValid() const;  
  40.     virtual void Dump(CDumpContext& dc) const;  
  41. #endif  
  42.   
  43. protected:  
  44.   
  45. // 生成的消息映射函数  
  46. protected:  
  47.     afx_msg void OnFilePrintPreview();  
  48.     afx_msg void OnRButtonUp(UINT nFlags, CPoint point);  
  49.     afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);  
  50.     DECLARE_MESSAGE_MAP()  
  51. public:  
  52.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  53.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  54.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  55.     BOOL IsCapture(void);  
  56.     //void DPToLP(CClientDC* pDC,CPoint& point);  
  57. };  
  58.   
  59. #ifndef _DEBUG  // Stroke_MFCView.cpp 中的调试版本  
  60. inline CStroke_MFCDoc* CStroke_MFCView::GetDocument() const  
  61.    { return reinterpret_cast<CStroke_MFCDoc*>(m_pDocument); }  
  62. #endif  

//////////////////////////////////////////////////////////////////view.cpp////////////////////////////////////////////////////////////////////////

[cpp]
  1. // Stroke_MFCView.cpp : CStroke_MFCView 类的实现  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "Stroke_MFC.h"  
  6.   
  7. #include "Stroke_MFCDoc.h"  
  8. #include "Stroke_MFCView.h"  
  9.   
  10. #ifdef _DEBUG  
  11. #define new DEBUG_NEW  
  12. #endif  
  13.   
  14. // CStroke_MFCView  
  15.   
  16. IMPLEMENT_DYNCREATE(CStroke_MFCView, /*CView*/CScrollView)  
  17.   
  18. BEGIN_MESSAGE_MAP(CStroke_MFCView, /*CView*/CScrollView)  
  19.     // 标准打印命令  
  20.     ON_COMMAND(ID_FILE_PRINT, &/*CView*/CScrollView::OnFilePrint)  
  21.     ON_COMMAND(ID_FILE_PRINT_DIRECT, &/*CView*/CScrollView::OnFilePrint)  
  22.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CStroke_MFCView::OnFilePrintPreview)  
  23.     ON_WM_LBUTTONDOWN()  
  24.     ON_WM_LBUTTONUP()  
  25.     ON_WM_MOUSEMOVE()  
  26. END_MESSAGE_MAP()  
  27.   
  28. // CStroke_MFCView 构造/析构  
  29. static int nFirst=0;  
  30.   
  31. CStroke_MFCView::CStroke_MFCView()  
  32. {  
  33.     // TODO: 在此处添加构造代码  
  34. }  
  35.   
  36. CStroke_MFCView::~CStroke_MFCView()  
  37. {  
  38. }  
  39.   
  40. BOOL CStroke_MFCView::PreCreateWindow(CREATESTRUCT& cs)  
  41. {  
  42.     // TODO: 在此处通过修改  
  43.     //  CREATESTRUCT cs 来修改窗口类或样式  
  44.   
  45.     return CView::PreCreateWindow(cs);  
  46. }  
  47.   
  48. void CStroke_MFCView::OnInitialUpdate()  
  49. {  
  50.     CScrollView::OnInitialUpdate();  
  51.   
  52.     // TODO: 计算此视图的合计大小  
  53.   
  54.     SetScrollSizes(MM_TEXT, GetDocument()->GetSize());  
  55. }  
  56.   
  57. // CStroke_MFCView 绘制  
  58.   
  59. void CStroke_MFCView::OnDraw(CDC* pDC)  
  60. {  
  61.     CStroke_MFCDoc* pDoc = GetDocument();  
  62.     ASSERT_VALID(pDoc);  
  63.     if (!pDoc)  
  64.         return;  
  65.   
  66.     // TODO: 在此处为本机数据添加绘制代码  
  67.     /*CTypedPtrList<CObList,CStroke*>*/CObList& pStrokeList = pDoc->GetStrokeList();  
  68.     POSITION pos = pStrokeList.GetHeadPosition();  
  69.     while(NULL != pos)  
  70.     {  
  71.          CStroke* pStroke = (CStroke*)pStrokeList.GetNext(pos);  
  72.          pStroke->Draw(pDC);  
  73.     }  
  74. }  
  75.   
  76.   
  77. // CStroke_MFCView 打印  
  78.   
  79.   
  80. void CStroke_MFCView::OnFilePrintPreview()  
  81. {  
  82.     AFXPrintPreview(this);  
  83. }  
  84.   
  85. BOOL CStroke_MFCView::OnPreparePrinting(CPrintInfo* pInfo)  
  86. {  
  87.     // 默认准备  
  88.     return DoPreparePrinting(pInfo);  
  89. }  
  90.   
  91. void CStroke_MFCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  92. {  
  93.     // TODO: 添加额外的打印前进行的初始化过程  
  94. }  
  95.   
  96. void CStroke_MFCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  97. {  
  98.     // TODO: 添加打印后进行的清理过程  
  99. }  
  100.   
  101. void CStroke_MFCView::OnRButtonUp(UINT nFlags, CPoint point)  
  102. {  
  103.     ClientToScreen(&point);  
  104.     OnContextMenu(this, point);  
  105. }  
  106.   
  107. void CStroke_MFCView::OnContextMenu(CWnd* pWnd, CPoint point)  
  108. {  
  109.     theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);  
  110. }  
  111.   
  112.   
  113. // CStroke_MFCView 诊断  
  114.   
  115. #ifdef _DEBUG  
  116. void CStroke_MFCView::AssertValid() const  
  117. {  
  118.     CView::AssertValid();  
  119. }  
  120.   
  121. void CStroke_MFCView::Dump(CDumpContext& dc) const  
  122. {  
  123.     CView::Dump(dc);  
  124. }  
  125.   
  126. CStroke_MFCDoc* CStroke_MFCView::GetDocument() const // 非调试版本是内联的  
  127. {  
  128.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CStroke_MFCDoc)));  
  129.     return (CStroke_MFCDoc*)m_pDocument;  
  130. }  
  131. #endif //_DEBUG  
  132.   
  133.   
  134. // CStroke_MFCView 消息处理程序  
  135.   
  136. void CStroke_MFCView::OnLButtonDown(UINT nFlags, CPoint point)  
  137. {  
  138.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  139.     m_pointPre = point;  
  140.       
  141.   
  142.     if(0x10000000 != nFlags)//如果是系统发送的话,由该view唯一创建线条  
  143.     {     
  144.         GetDocument()->NewStroke();  
  145.   
  146.         //将设备坐标转换成逻辑坐标保存起来  
  147.         CClientDC dc(this);  
  148.         OnPrepareDC(&dc);  
  149.         dc.DPtoLP(&point);  
  150.   
  151.         GetDocument()->GetCurStroke()->AddPoint(point);  
  152.   
  153.         //必须将逻辑坐标转换完后才能发送,使得兄弟视图画的不是设备坐标而是逻辑坐标  
  154.         GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONDOWN,nFlags,point);  
  155.         SetCapture();  
  156.     }  
  157.     CView::OnLButtonDown(nFlags, point);  
  158. }  
  159.   
  160. void CStroke_MFCView::OnLButtonUp(UINT nFlags, CPoint point)  
  161. {  
  162.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  163.     if(!GetDocument()->IsCapture()/*GetCapture() != this*/)  
  164.         return;  
  165.   
  166.     if(0x10000000 != nFlags)  
  167.     {  
  168.         CClientDC dc(this);  
  169.         CPen* pCurPen = GetDocument()->GetCurPen();  
  170.         CPen* pOldPen = dc.SelectObject(pCurPen);  
  171.         dc.MoveTo(m_pointPre);  
  172.         dc.LineTo(point);  
  173.         dc.SelectObject(pOldPen);  
  174.   
  175.         OnPrepareDC(&dc);  
  176.         dc.DPtoLP(&point);  
  177.   
  178.         GetDocument()->GetCurStroke()->AddPoint(point);  
  179.         GetDocument()->SendBTMsgToOtherViews(this,WM_LBUTTONUP,nFlags,point);  
  180.         ReleaseCapture();  
  181.     }  
  182.     else  
  183.     {  
  184.         CClientDC dc(this);  
  185.         OnPrepareDC(&dc);  
  186.   
  187.         CPen* pCurPen = GetDocument()->GetCurPen();  
  188.         CPen* pOldPen = dc.SelectObject(pCurPen);  
  189.         dc.MoveTo(m_pointPre);  
  190.         dc.LineTo(point);  
  191.         dc.SelectObject(pOldPen);  
  192.     }  
  193.   
  194.     CView::OnLButtonUp(nFlags, point);  
  195. }   
  196.   
  197. void CStroke_MFCView::OnMouseMove(UINT nFlags, CPoint point)  
  198. {  
  199.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  200.     if(!GetDocument()->IsCapture()/*GetCapture() != this*/)//如果没有这一句,鼠标移动的时候也会接受消息,但本不应该有这个程序处理的  
  201.         return;  
  202.       
  203.       
  204.   
  205.   
  206.     if(0x10000000 != nFlags)  
  207.     {  
  208.         CClientDC dc(this);  
  209.         CPen* pCurPen = GetDocument()->GetCurPen();  
  210.         CPen* pOldPen = dc.SelectObject(pCurPen);  
  211.         dc.MoveTo(m_pointPre);  
  212.         dc.LineTo(point);  
  213.         dc.SelectObject(pOldPen);  
  214.   
  215.         m_pointPre = point;  
  216.   
  217.         OnPrepareDC(&dc);  
  218.         dc.DPtoLP(&point);  
  219.   
  220.         GetDocument()->GetCurStroke()->AddPoint(point);  
  221.         GetDocument()->SendBTMsgToOtherViews(this,WM_MOUSEMOVE,nFlags,point);              
  222.     }  
  223.     else//如果是兄弟发来的消息,那么自己应该会逻辑坐标。而不是设备坐标  
  224.     {  
  225.         CClientDC dc(this);  
  226.         OnPrepareDC(&dc);  
  227.         CPen* pCurPen = GetDocument()->GetCurPen();  
  228.         CPen* pOldPen = dc.SelectObject(pCurPen);  
  229.         dc.MoveTo(m_pointPre);  
  230.         dc.LineTo(point);  
  231.         dc.SelectObject(pOldPen);  
  232.   
  233.         m_pointPre = point;  
  234.     }  
  235.   
  236.     CView::OnMouseMove(nFlags, point);  
  237. }  
  238.   
  239. BOOL CStroke_MFCView::IsCapture(void)  
  240. {  
  241.     return this == GetCapture();  
  242. }  

0 0