1. 数据类 #include <list> class IJxInterface; class CJxDataSet : public CCmdTarget { DECLARE_DYNCREATE(CJxDataSet) CJxDataSet(); // protected constructor used by dynamic creation bool LinkInterface(IJxInterface* pInterface_); bool DelinkInterface(IJxInterface* pInterface_); bool UpdateAllInterfaces(); protected: virtual ~CJxDataSet(); std::list<IJxInterface*> m_views; DECLARE_MESSAGE_MAP() }; #include "DataSet.h" #include "IJxInterface.h" #include <algorithm> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; / // CJxDataSet IMPLEMENT_DYNCREATE(CJxDataSet, CCmdTarget) static void Delink(IJxInterface* _pInf) { ASSERT(_pInf); if (_pInf) _pInf->DelinkToDataset(); } CJxDataSet::CJxDataSet() { } CJxDataSet::~CJxDataSet() { for_each(m_views.begin(), m_views.end(), Delink); } BEGIN_MESSAGE_MAP(CJxDataSet, CCmdTarget) END_MESSAGE_MAP() / // CJxDataSet message handlers bool CJxDataSet::LinkInterface(IJxInterface* pInterface_) { ASSERT(pInterface_); m_views.push_back(pInterface_); return true; } bool CJxDataSet::DelinkInterface(IJxInterface* pInterface_) { if(pInterface_) { m_views.remove(pInterface_); pInterface_->DelinkToDataset(); return true; } return false; } static void UpdateOneInterface(IJxInterface* pInterface_) { ASSERT(pInterface_); pInterface_->OnRefreshByDatasete(); } bool CJxDataSet::UpdateAllInterfaces() { if (m_views.empty()) return false; for_each(m_views.begin(), m_views.end(), UpdateOneInterface); return true; } 2.界面类 #include "DataSet.h" class IJxInterface { public: IJxInterface(); virtual ~IJxInterface(); virtual void OnRefreshByDatasete() = 0; void LinkToDataset(CJxDataSet* pDataset_); CJxDataSet* GetDataSet(){return m_pDataset;} void DelinkToDataset() { ASSERT(m_pDataset); if (m_pDataset) m_pDataset->DelinkInterface(this); m_pDataset = NULL; } protected: CJxDataSet* m_pDataset; }; IJxInterface::IJxInterface() { m_pDataset = NULL; } IJxInterface::~IJxInterface() { if (m_pDataset) m_pDataset->DelinkInterface(this); } void IJxInterface::LinkToDataset(CJxDataSet* pDataset_) { ASSERT(pDataset_); m_pDataset = pDataset_; } 3.粘合类 class CJxDataSet; class IJxInterface; class IJxDataInfConnector { public: IJxDataInfConnector(); virtual ~IJxDataInfConnector(); bool ConnectDataInf(CJxDataSet* pDataSet_, IJxInterface* pInf_); }; IJxDataInfConnector::IJxDataInfConnector() { } IJxDataInfConnector::~IJxDataInfConnector() { } bool IJxDataInfConnector::ConnectDataInf(CJxDataSet* pDataSet_, IJxInterface* pInf_) { ASSERT(pInf_); ASSERT(pDataSet_); if (!pInf_ || !pDataSet_) return false; if (pInf_->GetDataSet()) return false; pDataSet_->LinkInterface(pInf_); pInf_->LinkToDataset(pDataSet_); return true; } 4 具体应用类 class CMyDataSet : public CJxDataSet { public: CMyDataSet(); virtual ~CMyDataSet(); int m_a; protected: DECLARE_MESSAGE_MAP() afx_msg void OnMyCmd(); }; BEGIN_MESSAGE_MAP(CMyDataSet, CJxDataSet) ON_COMMAND(WM_MYCMD, OnMyCmd) END_MESSAGE_MAP() CMyDataSet::CMyDataSet() { m_a = 1; } CMyDataSet::~CMyDataSet() { } void CMyDataSet::OnMyCmd() { m_a++; UpdateAllInterfaces(); } class CMainFrame : public CFrameWnd, public IJxDataInfConnector { public: CMainFrame(); protected: DECLARE_DYNAMIC(CMainFrame) public: CMyDataSet* m_pDataSet; public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); public: virtual ~CMainFrame(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; CChildView m_wndView; protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSetFocus(CWnd *pOldWnd); DECLARE_MESSAGE_MAP() }; CMainFrame::CMainFrame() { m_pDataSet = new CMyDataSet; ConnectDataInf(m_pDataSet, &m_wndView); } CMainFrame::~CMainFrame() { delete m_pDataSet; m_pDataSet = NULL; } void CMainFrame::OnSetFocus(CWnd* pOldWnd) { m_wndView.SetFocus(); } BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE; if (m_pDataSet && m_pDataSet->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE; return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } class CChildView : public CWnd, public IJxInterface { public: CChildView(); public: virtual void OnRefreshByDatasete(); protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); public: virtual ~CChildView(); protected: afx_msg void OnPaint(); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CChildView,CWnd ) //{{AFX_MSG_MAP(CChildView) ON_WM_PAINT() ON_WM_LBUTTONDBLCLK() //}}AFX_MSG_MAP END_MESSAGE_MAP() / // CChildView message handlers BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE; cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); return TRUE; } void CChildView::OnPaint() { CPaintDC dc(this); if (m_pDataset) { int _n = ((CMyDataSet*)m_pDataset)->m_a; CString _str; _str.Format("Hello, %d", _n); dc.TextOut(10, 10, "双击我"); dc.TextOut(100, 100, _str); } } void CChildView::OnRefreshByDatasete() { InvalidateRect(NULL); } void CChildView::OnLButtonDblClk(UINT nFlags, CPoint point) { AfxGetMainWnd()->SendMessage(WM_COMMAND, WM_MYCMD, 0L); }