home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / viewcore.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  14KB  |  564 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE2_SEG
  14. #pragma code_seg(AFX_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CView
  24.  
  25. BEGIN_MESSAGE_MAP(CView, CWnd)
  26.     //{{AFX_MSG_MAP(CView)
  27.     ON_WM_PAINT()
  28.     ON_WM_MOUSEACTIVATE()
  29.     ON_WM_CREATE()
  30.     ON_WM_DESTROY()
  31.  
  32.     // Standard commands for split pane
  33.     ON_COMMAND_EX(ID_WINDOW_SPLIT, OnSplitCmd)
  34.     ON_UPDATE_COMMAND_UI(ID_WINDOW_SPLIT, OnUpdateSplitCmd)
  35.  
  36.     // Standard commands for next pane
  37.     ON_UPDATE_COMMAND_UI(ID_NEXT_PANE, OnUpdateNextPaneMenu)
  38.     ON_COMMAND_EX(ID_NEXT_PANE, OnNextPaneCmd)
  39.     ON_UPDATE_COMMAND_UI(ID_PREV_PANE, OnUpdateNextPaneMenu)
  40.     ON_COMMAND_EX(ID_PREV_PANE, OnNextPaneCmd)
  41.     //}}AFX_MSG_MAP
  42.     // special command for Initial Update
  43.     ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
  44. END_MESSAGE_MAP()
  45.  
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CView construction/destruction
  48.  
  49. CView::CView()
  50. {
  51.     m_pDocument = NULL;
  52. }
  53.  
  54. CView::~CView()
  55. {
  56.     if (m_pDocument != NULL)
  57.         m_pDocument->RemoveView(this);
  58. }
  59.  
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CView second phase construction - bind to document
  62.  
  63. BOOL CView::PreCreateWindow(CREATESTRUCT & cs)
  64. {
  65.     ASSERT(cs.style & WS_CHILD);
  66.  
  67.     if (cs.lpszClass == NULL)
  68.     {
  69.         VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  70.         cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
  71.     }
  72.  
  73.     if (afxData.bWin4 && (cs.style & WS_BORDER))
  74.     {
  75.         cs.dwExStyle |= WS_EX_CLIENTEDGE;
  76.         cs.style &= ~WS_BORDER;
  77.     }
  78.  
  79.     return TRUE;
  80. }
  81.  
  82. int CView::OnCreate(LPCREATESTRUCT lpcs)
  83. {
  84.     if (CWnd::OnCreate(lpcs) == -1)
  85.         return -1;
  86.  
  87.     // if ok, wire in the current document
  88.     ASSERT(m_pDocument == NULL);
  89.     CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
  90.  
  91.     // A view should be created in a given context!
  92.     if (pContext != NULL && pContext->m_pCurrentDoc != NULL)
  93.     {
  94.         pContext->m_pCurrentDoc->AddView(this);
  95.         ASSERT(m_pDocument != NULL);
  96.     }
  97.     else
  98.     {
  99.         TRACE0("Warning: Creating a pane with no CDocument.\n");
  100.     }
  101.  
  102.     return 0;   // ok
  103. }
  104.  
  105. void CView::OnDestroy()
  106. {
  107.     CFrameWnd* pFrame = GetParentFrame();
  108.     if (pFrame != NULL && pFrame->GetActiveView() == this)
  109.         pFrame->SetActiveView(NULL);    // deactivate during death
  110.     CWnd::OnDestroy();
  111. }
  112.  
  113. // self destruction
  114. void CView::PostNcDestroy()
  115. {
  116.     // default for views is to allocate them on the heap
  117.     //  the default post-cleanup is to 'delete this'.
  118.     //  never explicitly call 'delete' on a view
  119.     delete this;
  120. }
  121.  
  122. void CView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
  123. {
  124.     if (nAdjustType != 0)
  125.     {
  126.         // allow for special client-edge style
  127.         ::AdjustWindowRectEx(lpClientRect, 0, FALSE, GetExStyle());
  128.  
  129.         // default behavior for in-place editing handles scrollbars
  130.         DWORD dwStyle = GetStyle();
  131.         if (dwStyle & WS_VSCROLL)
  132.         {
  133.             int nAdjust = afxData.cxVScroll;
  134.             if (dwStyle & WS_BORDER)
  135.                 nAdjust -= CX_BORDER;
  136.             lpClientRect->right += nAdjust;
  137.         }
  138.         if (dwStyle & WS_HSCROLL)
  139.         {
  140.             int nAdjust = afxData.cyHScroll;
  141.             if (dwStyle & WS_BORDER)
  142.                 nAdjust -= CY_BORDER;
  143.             lpClientRect->bottom += nAdjust;
  144.         }
  145.         return;
  146.     }
  147.  
  148.     // call default to place borders outside of client rect
  149.     CWnd::CalcWindowRect(lpClientRect, nAdjustType);
  150. }
  151.  
  152. /////////////////////////////////////////////////////////////////////////////
  153. // Command routing
  154.  
  155. BOOL CView::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  156.     AFX_CMDHANDLERINFO* pHandlerInfo)
  157. {
  158.     // first pump through pane
  159.     if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  160.         return TRUE;
  161.  
  162.     // then pump through document
  163.     if (m_pDocument != NULL)
  164.     {
  165.         // special state for saving view before routing to document
  166.         CPushRoutingView push(this);
  167.         return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  168.     }
  169.  
  170.     return FALSE;
  171. }
  172.  
  173. /////////////////////////////////////////////////////////////////////////////
  174. // CView drawing support
  175.  
  176. void CView::OnPaint()
  177. {
  178.     // standard paint routine
  179.     CPaintDC dc(this);
  180.     OnPrepareDC(&dc);
  181.     OnDraw(&dc);
  182. }
  183.  
  184. void CView::OnInitialUpdate()
  185. {
  186.     OnUpdate(NULL, 0, NULL);        // initial update
  187. }
  188.  
  189. void CView::OnUpdate(CView* pSender, LPARAM /*lHint*/, CObject* /*pHint*/)
  190. {
  191.     ASSERT(pSender != this);
  192.     UNUSED(pSender);     // unused in release builds
  193.  
  194.     // invalidate the entire pane, erase background too
  195.     Invalidate(TRUE);
  196. }
  197.  
  198. void CView::OnPrint(CDC* pDC, CPrintInfo*)
  199. {
  200.     ASSERT_VALID(pDC);
  201.  
  202.     // Override and set printing variables based on page number
  203.     OnDraw(pDC);                    // Call Draw
  204. }
  205.  
  206. void CView::OnDraw(CDC*)
  207. {
  208. }
  209.  
  210. /////////////////////////////////////////////////////////////////////////////
  211. // CView selection support
  212.  
  213. BOOL CView::IsSelected(const CObject* pDocItem) const
  214. {
  215.     ASSERT_VALID(pDocItem);
  216.     UNUSED(pDocItem);    // unused in release builds
  217.  
  218.     return FALSE;   // not implemented, so not selected
  219. }
  220.  
  221. void CView::OnActivateView(BOOL bActivate, CView* pActivateView, CView*)
  222. {
  223.     UNUSED(pActivateView);   // unused in release builds
  224.  
  225.     if (bActivate)
  226.     {
  227.         ASSERT(pActivateView == this);
  228.  
  229.         // take the focus if this frame/view/pane is now active
  230.         if (IsTopParentActive())
  231.             SetFocus();
  232.     }
  233. }
  234.  
  235. void CView::OnActivateFrame(UINT /*nState*/, CFrameWnd* /*pFrameWnd*/)
  236. {
  237. }
  238.  
  239. int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
  240. {
  241.     int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
  242.     if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
  243.         return nResult;   // frame does not want to activate
  244.  
  245.     CFrameWnd* pParentFrame = GetParentFrame();
  246.     if (pParentFrame != NULL)
  247.     {
  248.         // eat it if this will cause activation
  249.         ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame));
  250.  
  251.         // either re-activate the current view, or set this view to be active
  252.         CView* pView = pParentFrame->GetActiveView();
  253.         HWND hWndFocus = ::GetFocus();
  254.         if (pView == this &&
  255.             m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus))
  256.         {
  257.             // re-activate this view
  258.             OnActivateView(TRUE, this, this);
  259.         }
  260.         else
  261.         {
  262.             // activate this view
  263.             pParentFrame->SetActiveView(this);
  264.         }
  265.     }
  266.     return nResult;
  267. }
  268.  
  269. /////////////////////////////////////////////////////////////////////////////
  270. // CView scrolling support
  271.  
  272. BOOL CView::OnScroll(UINT /*nScrollCode*/, UINT /*nPos*/, BOOL /*bDoScroll*/)
  273. {
  274.     return FALSE;
  275. }
  276.  
  277. BOOL CView::OnScrollBy(CSize /*sizeScroll*/, BOOL /*bDoScroll*/)
  278. {
  279.     return FALSE;
  280. }
  281.  
  282. /////////////////////////////////////////////////////////////////////////////
  283. // CView drag/drop support
  284.  
  285. DROPEFFECT CView::OnDragScroll(DWORD /*dwKeyState*/, CPoint /*point*/)
  286. {
  287. #ifndef _AFX_NO_OLE_SUPPORT
  288.     return DROPEFFECT_SCROLL; // this means do the default
  289. #else
  290.     return 0;
  291. #endif
  292. }
  293.  
  294. DROPEFFECT CView::OnDragEnter(COleDataObject* /*pDataObject*/,
  295.     DWORD /*dwKeyState*/, CPoint /*point*/)
  296. {
  297.     return 0;   // DROPEFFECT_NONE
  298. }
  299.  
  300. DROPEFFECT CView::OnDragOver(COleDataObject* /*pDataObject*/,
  301.     DWORD /*dwKeyState*/, CPoint /*point*/)
  302. {
  303.     return 0;   // DROPEFFECT_NONE
  304. }
  305.  
  306. BOOL CView::OnDrop(COleDataObject* /*pDataObject*/,
  307.     DROPEFFECT /*dropEffect*/, CPoint /*point*/)
  308. {
  309.     return FALSE;
  310. }
  311.  
  312. DROPEFFECT CView::OnDropEx(COleDataObject* /*pDataObject*/,
  313.     DROPEFFECT /*dropEffect*/, DROPEFFECT /*dropEffectList*/, CPoint /*point*/)
  314. {
  315.     return (DROPEFFECT)-1;  // not implemented
  316. }
  317.  
  318. void CView::OnDragLeave()
  319. {
  320. }
  321.  
  322. /////////////////////////////////////////////////////////////////////////////
  323. // CView splitting commands
  324.  
  325. CSplitterWnd* PASCAL
  326. CView::GetParentSplitter(const CWnd* pWnd, BOOL bAnyState)
  327. {
  328.     CSplitterWnd* pSplitter = (CSplitterWnd*)pWnd->GetParent();
  329.     if (!pSplitter->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
  330.         return NULL;        // not a splitter
  331.     if (!bAnyState)
  332.     {
  333.         // ignore splitters in minimized (iconic) windows
  334.         while ((pWnd = pWnd->GetParent()) != NULL)
  335.             if (pWnd->IsIconic())
  336.                 return NULL;
  337.     }
  338.     return pSplitter;
  339. }
  340.  
  341. CScrollBar* CView::GetScrollBarCtrl(int nBar) const
  342. {
  343.     ASSERT(nBar == SB_HORZ || nBar == SB_VERT);
  344.     if (GetStyle() & ((nBar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL))
  345.     {
  346.         // it has a regular windows style scrollbar (no control)
  347.         return NULL;
  348.     }
  349.  
  350.     CWnd* pParent = GetParentSplitter(this, TRUE);
  351.     if (pParent == NULL)
  352.         return NULL;            // no splitter
  353.  
  354.     UINT nID = _AfxGetDlgCtrlID(m_hWnd);
  355.     if (nID < AFX_IDW_PANE_FIRST || nID > AFX_IDW_PANE_LAST)
  356.         return NULL;            // not a standard pane ID
  357.  
  358.     // appropriate PANE id - look for sibling (splitter, or just frame)
  359.     UINT nIDScroll;
  360.     if (nBar == SB_HORZ)
  361.         nIDScroll = AFX_IDW_HSCROLL_FIRST + (nID - AFX_IDW_PANE_FIRST) % 16;
  362.     else
  363.         nIDScroll = AFX_IDW_VSCROLL_FIRST + (nID - AFX_IDW_PANE_FIRST) / 16;
  364.  
  365.     // return shared scroll bars that are immediate children of splitter
  366.     return (CScrollBar*)pParent->GetDlgItem(nIDScroll);
  367. }
  368.  
  369.  
  370. void CView::OnUpdateSplitCmd(CCmdUI* pCmdUI)
  371. {
  372.     CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE);
  373.     pCmdUI->Enable(pSplitter != NULL && !pSplitter->IsTracking());
  374. }
  375.  
  376. BOOL CView::OnSplitCmd(UINT)
  377. {
  378.     CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE);
  379.     if (pSplitter == NULL)
  380.         return FALSE;
  381.  
  382.     ASSERT(!pSplitter->IsTracking());
  383.     pSplitter->DoKeyboardSplit();
  384.     return TRUE;    // attempted at least
  385. }
  386.  
  387. void CView::OnUpdateNextPaneMenu(CCmdUI* pCmdUI)
  388. {
  389.     ASSERT(pCmdUI->m_nID == ID_NEXT_PANE ||
  390.         pCmdUI->m_nID == ID_PREV_PANE);
  391.     CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE);
  392.     pCmdUI->Enable(pSplitter != NULL &&
  393.         pSplitter->CanActivateNext(pCmdUI->m_nID == ID_PREV_PANE));
  394. }
  395.  
  396. BOOL CView::OnNextPaneCmd(UINT nID)
  397. {
  398.     CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE);
  399.     if (pSplitter == NULL)
  400.         return FALSE;
  401.  
  402.     ASSERT(nID == ID_NEXT_PANE || nID == ID_PREV_PANE);
  403.     pSplitter->ActivateNext(nID == ID_PREV_PANE);
  404.     return TRUE;
  405. }
  406.  
  407. /////////////////////////////////////////////////////////////////////////////
  408. // Printing support virtual functions (others in viewpr.cpp)
  409.  
  410. void CView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  411. {
  412.     ASSERT_VALID(pDC);
  413.     UNUSED(pDC); // unused in release builds
  414.  
  415.     // Default to one page printing if doc length not known
  416.     if (pInfo != NULL)
  417.         pInfo->m_bContinuePrinting =
  418.             (pInfo->GetMaxPage() != 0xffff || (pInfo->m_nCurPage == 1));
  419. }
  420.  
  421. BOOL CView::OnPreparePrinting(CPrintInfo*)
  422. {
  423.     // Do print DC initialization here
  424.     // override and call DoPreparePrinting (in viewprnt.cpp)
  425.  
  426.     return TRUE;
  427. }
  428.  
  429. void CView::OnBeginPrinting(CDC* pDC, CPrintInfo*)
  430. {
  431.     ASSERT_VALID(pDC);
  432.     UNUSED(pDC);     // unused in release builds
  433.  
  434.     // Do printing initialization here
  435. }
  436.  
  437. void CView::OnEndPrinting(CDC* pDC, CPrintInfo*)
  438. {
  439.     ASSERT_VALID(pDC);
  440.     UNUSED(pDC);     // unused in release builds
  441.  
  442.     // Do printing cleanup here
  443. }
  444.  
  445. // OnEndPrintPreview is here for swap tuning reasons
  446. //  (see viewprev.cpp for complete preview mode implementation)
  447. void CView::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo,
  448.             POINT, CPreviewView* pView)
  449. {
  450.     ASSERT_VALID(pDC);
  451.     ASSERT_VALID(pView);
  452.  
  453.     if (pView->m_pPrintView != NULL)
  454.         pView->m_pPrintView->OnEndPrinting(pDC, pInfo);
  455.  
  456.     CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
  457.     ASSERT_VALID(pParent);
  458.  
  459.     // restore the old main window
  460.     pParent->OnSetPreviewMode(FALSE, pView->m_pPreviewState);
  461.  
  462.     // Force active view back to old one
  463.     pParent->SetActiveView(pView->m_pPreviewState->pViewActiveOld);
  464.     if (pParent != GetParentFrame())
  465.         OnActivateView(TRUE, this, this);   // re-activate view in real frame
  466.     pView->DestroyWindow();     // destroy preview view
  467.             // C++ object will be deleted in PostNcDestroy
  468.  
  469.     // restore main frame layout and idle message
  470.     pParent->RecalcLayout();
  471.     pParent->SendMessage(WM_SETMESSAGESTRING, (WPARAM)AFX_IDS_IDLEMESSAGE, 0L);
  472.     pParent->UpdateWindow();
  473. }
  474.  
  475. /////////////////////////////////////////////////////////////////////////////
  476. // CView diagnostics
  477.  
  478. #ifdef _DEBUG
  479. void CView::Dump(CDumpContext& dc) const
  480. {
  481.     CWnd::Dump(dc);
  482.  
  483.     if (m_pDocument != NULL)
  484.         dc << "with document: " << m_pDocument;
  485.     else
  486.         dc << "with no document\n";
  487. }
  488.  
  489. void CView::AssertValid() const
  490. {
  491.     CWnd::AssertValid();
  492. }
  493. #endif //_DEBUG
  494.  
  495. /////////////////////////////////////////////////////////////////////////////
  496. // CCtrlView
  497.  
  498. BEGIN_MESSAGE_MAP(CCtrlView, CView)
  499.     ON_WM_PAINT()
  500. END_MESSAGE_MAP()
  501.  
  502. CCtrlView::CCtrlView(LPCTSTR lpszClass, DWORD dwStyle)
  503. {
  504.     m_strClass = lpszClass;
  505.     m_dwDefaultStyle = dwStyle;
  506. }
  507.  
  508. BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs)
  509. {
  510.     ASSERT(cs.lpszClass == NULL);
  511.     cs.lpszClass = m_strClass;
  512.  
  513.     // initialize common controls
  514.     VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
  515.     AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
  516.  
  517.     // map default CView style to default style
  518.     // WS_BORDER is insignificant
  519.     if ((cs.style | WS_BORDER) == AFX_WS_DEFAULT_VIEW)
  520.         cs.style = m_dwDefaultStyle & (cs.style | ~WS_BORDER);
  521.  
  522.     return CView::PreCreateWindow(cs);
  523. }
  524.  
  525. void CCtrlView::OnDraw(CDC*)
  526. {
  527.     ASSERT(FALSE);
  528. }
  529.  
  530. void CCtrlView::OnPaint()
  531. {
  532.     // this is done to avoid CView::OnPaint
  533.     Default();
  534. }
  535.  
  536. /////////////////////////////////////////////////////////////////////////////
  537. // CCtrlView diagnostics
  538.  
  539. #ifdef _DEBUG
  540. void CCtrlView::Dump(CDumpContext& dc) const
  541. {
  542.     CView::Dump(dc);
  543.     dc << "\nClass Name: " << m_strClass;
  544.     dc << "\nDefault Style: " << (void*)m_dwDefaultStyle;
  545. }
  546.  
  547. void CCtrlView::AssertValid() const
  548. {
  549.     CWnd::AssertValid();
  550.     ASSERT(!m_strClass.IsEmpty());
  551. }
  552. #endif //_DEBUG
  553.  
  554. #ifdef AFX_INIT_SEG
  555. #pragma code_seg(AFX_INIT_SEG)
  556. #endif
  557.  
  558. // IMPLEMENT_DYNAMIC for CView is in wincore.cpp for .OBJ granularity reasons
  559.  
  560. IMPLEMENT_DYNAMIC(CSplitterWnd, CWnd)   // for swap tuning
  561. IMPLEMENT_DYNAMIC(CCtrlView, CView)
  562.  
  563. /////////////////////////////////////////////////////////////////////////////
  564.