// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFX_CORE2_SEG #pragma code_seg(AFX_CORE2_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CView BEGIN_MESSAGE_MAP(CView, CWnd) //{{AFX_MSG_MAP(CView) ON_WM_PAINT() ON_WM_MOUSEACTIVATE() ON_WM_CREATE() ON_WM_DESTROY() // Standard commands for split pane ON_COMMAND_EX(ID_WINDOW_SPLIT, OnSplitCmd) ON_UPDATE_COMMAND_UI(ID_WINDOW_SPLIT, OnUpdateSplitCmd) // Standard commands for next pane ON_UPDATE_COMMAND_UI(ID_NEXT_PANE, OnUpdateNextPaneMenu) ON_COMMAND_EX(ID_NEXT_PANE, OnNextPaneCmd) ON_UPDATE_COMMAND_UI(ID_PREV_PANE, OnUpdateNextPaneMenu) ON_COMMAND_EX(ID_PREV_PANE, OnNextPaneCmd) //}}AFX_MSG_MAP // special command for Initial Update ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CView construction/destruction CView::CView() { m_pDocument = NULL; } CView::~CView() { if (m_pDocument != NULL) m_pDocument->RemoveView(this); } ///////////////////////////////////////////////////////////////////////////// // CView second phase construction - bind to document BOOL CView::PreCreateWindow(CREATESTRUCT & cs) { ASSERT(cs.style & WS_CHILD); if (cs.lpszClass == NULL) { VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background } if (afxData.bWin4 && (cs.style & WS_BORDER)) { cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; } return TRUE; } int CView::OnCreate(LPCREATESTRUCT lpcs) { if (CWnd::OnCreate(lpcs) == -1) return -1; // if ok, wire in the current document ASSERT(m_pDocument == NULL); CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams; // A view should be created in a given context! if (pContext != NULL && pContext->m_pCurrentDoc != NULL) { pContext->m_pCurrentDoc->AddView(this); ASSERT(m_pDocument != NULL); } else { TRACE0("Warning: Creating a pane with no CDocument.\n"); } return 0; // ok } void CView::OnDestroy() { CFrameWnd* pFrame = GetParentFrame(); if (pFrame != NULL && pFrame->GetActiveView() == this) pFrame->SetActiveView(NULL); // deactivate during death CWnd::OnDestroy(); } // self destruction void CView::PostNcDestroy() { // default for views is to allocate them on the heap // the default post-cleanup is to 'delete this'. // never explicitly call 'delete' on a view delete this; } void CView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType) { if (nAdjustType != 0) { // allow for special client-edge style ::AdjustWindowRectEx(lpClientRect, 0, FALSE, GetExStyle()); // default behavior for in-place editing handles scrollbars DWORD dwStyle = GetStyle(); if (dwStyle & WS_VSCROLL) { int nAdjust = afxData.cxVScroll; if (dwStyle & WS_BORDER) nAdjust -= CX_BORDER; lpClientRect->right += nAdjust; } if (dwStyle & WS_HSCROLL) { int nAdjust = afxData.cyHScroll; if (dwStyle & WS_BORDER) nAdjust -= CY_BORDER; lpClientRect->bottom += nAdjust; } return; } // call default to place borders outside of client rect CWnd::CalcWindowRect(lpClientRect, nAdjustType); } ///////////////////////////////////////////////////////////////////////////// // Command routing BOOL CView::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // first pump through pane if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE; // then pump through document if (m_pDocument != NULL) { // special state for saving view before routing to document CPushRoutingView push(this); return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // CView drawing support void CView::OnPaint() { // standard paint routine CPaintDC dc(this); OnPrepareDC(&dc); OnDraw(&dc); } void CView::OnInitialUpdate() { OnUpdate(NULL, 0, NULL); // initial update } void CView::OnUpdate(CView* pSender, LPARAM /*lHint*/, CObject* /*pHint*/) { ASSERT(pSender != this); UNUSED(pSender); // unused in release builds // invalidate the entire pane, erase background too Invalidate(TRUE); } void CView::OnPrint(CDC* pDC, CPrintInfo*) { ASSERT_VALID(pDC); // Override and set printing variables based on page number OnDraw(pDC); // Call Draw } void CView::OnDraw(CDC*) { } ///////////////////////////////////////////////////////////////////////////// // CView selection support BOOL CView::IsSelected(const CObject* pDocItem) const { ASSERT_VALID(pDocItem); UNUSED(pDocItem); // unused in release builds return FALSE; // not implemented, so not selected } void CView::OnActivateView(BOOL bActivate, CView* pActivateView, CView*) { UNUSED(pActivateView); // unused in release builds if (bActivate) { ASSERT(pActivateView == this); // take the focus if this frame/view/pane is now active if (IsTopParentActive()) SetFocus(); } } void CView::OnActivateFrame(UINT /*nState*/, CFrameWnd* /*pFrameWnd*/) { } int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) { int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message); if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT) return nResult; // frame does not want to activate CFrameWnd* pParentFrame = GetParentFrame(); if (pParentFrame != NULL) { // eat it if this will cause activation ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame)); // either re-activate the current view, or set this view to be active CView* pView = pParentFrame->GetActiveView(); HWND hWndFocus = ::GetFocus(); if (pView == this && m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus)) { // re-activate this view OnActivateView(TRUE, this, this); } else { // activate this view pParentFrame->SetActiveView(this); } } return nResult; } ///////////////////////////////////////////////////////////////////////////// // CView scrolling support BOOL CView::OnScroll(UINT /*nScrollCode*/, UINT /*nPos*/, BOOL /*bDoScroll*/) { return FALSE; } BOOL CView::OnScrollBy(CSize /*sizeScroll*/, BOOL /*bDoScroll*/) { return FALSE; } ///////////////////////////////////////////////////////////////////////////// // CView drag/drop support DROPEFFECT CView::OnDragScroll(DWORD /*dwKeyState*/, CPoint /*point*/) { #ifndef _AFX_NO_OLE_SUPPORT return DROPEFFECT_SCROLL; // this means do the default #else return 0; #endif } DROPEFFECT CView::OnDragEnter(COleDataObject* /*pDataObject*/, DWORD /*dwKeyState*/, CPoint /*point*/) { return 0; // DROPEFFECT_NONE } DROPEFFECT CView::OnDragOver(COleDataObject* /*pDataObject*/, DWORD /*dwKeyState*/, CPoint /*point*/) { return 0; // DROPEFFECT_NONE } BOOL CView::OnDrop(COleDataObject* /*pDataObject*/, DROPEFFECT /*dropEffect*/, CPoint /*point*/) { return FALSE; } DROPEFFECT CView::OnDropEx(COleDataObject* /*pDataObject*/, DROPEFFECT /*dropEffect*/, DROPEFFECT /*dropEffectList*/, CPoint /*point*/) { return (DROPEFFECT)-1; // not implemented } void CView::OnDragLeave() { } ///////////////////////////////////////////////////////////////////////////// // CView splitting commands CSplitterWnd* PASCAL CView::GetParentSplitter(const CWnd* pWnd, BOOL bAnyState) { CSplitterWnd* pSplitter = (CSplitterWnd*)pWnd->GetParent(); if (!pSplitter->IsKindOf(RUNTIME_CLASS(CSplitterWnd))) return NULL; // not a splitter if (!bAnyState) { // ignore splitters in minimized (iconic) windows while ((pWnd = pWnd->GetParent()) != NULL) if (pWnd->IsIconic()) return NULL; } return pSplitter; } CScrollBar* CView::GetScrollBarCtrl(int nBar) const { ASSERT(nBar == SB_HORZ || nBar == SB_VERT); if (GetStyle() & ((nBar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL)) { // it has a regular windows style scrollbar (no control) return NULL; } CWnd* pParent = GetParentSplitter(this, TRUE); if (pParent == NULL) return NULL; // no splitter UINT nID = _AfxGetDlgCtrlID(m_hWnd); if (nID < AFX_IDW_PANE_FIRST || nID > AFX_IDW_PANE_LAST) return NULL; // not a standard pane ID // appropriate PANE id - look for sibling (splitter, or just frame) UINT nIDScroll; if (nBar == SB_HORZ) nIDScroll = AFX_IDW_HSCROLL_FIRST + (nID - AFX_IDW_PANE_FIRST) % 16; else nIDScroll = AFX_IDW_VSCROLL_FIRST + (nID - AFX_IDW_PANE_FIRST) / 16; // return shared scroll bars that are immediate children of splitter return (CScrollBar*)pParent->GetDlgItem(nIDScroll); } void CView::OnUpdateSplitCmd(CCmdUI* pCmdUI) { CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE); pCmdUI->Enable(pSplitter != NULL && !pSplitter->IsTracking()); } BOOL CView::OnSplitCmd(UINT) { CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE); if (pSplitter == NULL) return FALSE; ASSERT(!pSplitter->IsTracking()); pSplitter->DoKeyboardSplit(); return TRUE; // attempted at least } void CView::OnUpdateNextPaneMenu(CCmdUI* pCmdUI) { ASSERT(pCmdUI->m_nID == ID_NEXT_PANE || pCmdUI->m_nID == ID_PREV_PANE); CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE); pCmdUI->Enable(pSplitter != NULL && pSplitter->CanActivateNext(pCmdUI->m_nID == ID_PREV_PANE)); } BOOL CView::OnNextPaneCmd(UINT nID) { CSplitterWnd* pSplitter = GetParentSplitter(this, FALSE); if (pSplitter == NULL) return FALSE; ASSERT(nID == ID_NEXT_PANE || nID == ID_PREV_PANE); pSplitter->ActivateNext(nID == ID_PREV_PANE); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // Printing support virtual functions (others in viewpr.cpp) void CView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { ASSERT_VALID(pDC); UNUSED(pDC); // unused in release builds // Default to one page printing if doc length not known if (pInfo != NULL) pInfo->m_bContinuePrinting = (pInfo->GetMaxPage() != 0xffff || (pInfo->m_nCurPage == 1)); } BOOL CView::OnPreparePrinting(CPrintInfo*) { // Do print DC initialization here // override and call DoPreparePrinting (in viewprnt.cpp) return TRUE; } void CView::OnBeginPrinting(CDC* pDC, CPrintInfo*) { ASSERT_VALID(pDC); UNUSED(pDC); // unused in release builds // Do printing initialization here } void CView::OnEndPrinting(CDC* pDC, CPrintInfo*) { ASSERT_VALID(pDC); UNUSED(pDC); // unused in release builds // Do printing cleanup here } // OnEndPrintPreview is here for swap tuning reasons // (see viewprev.cpp for complete preview mode implementation) void CView::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT, CPreviewView* pView) { ASSERT_VALID(pDC); ASSERT_VALID(pView); if (pView->m_pPrintView != NULL) pView->m_pPrintView->OnEndPrinting(pDC, pInfo); CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd()); ASSERT_VALID(pParent); // restore the old main window pParent->OnSetPreviewMode(FALSE, pView->m_pPreviewState); // Force active view back to old one pParent->SetActiveView(pView->m_pPreviewState->pViewActiveOld); if (pParent != GetParentFrame()) OnActivateView(TRUE, this, this); // re-activate view in real frame pView->DestroyWindow(); // destroy preview view // C++ object will be deleted in PostNcDestroy // restore main frame layout and idle message pParent->RecalcLayout(); pParent->SendMessage(WM_SETMESSAGESTRING, (WPARAM)AFX_IDS_IDLEMESSAGE, 0L); pParent->UpdateWindow(); } ///////////////////////////////////////////////////////////////////////////// // CView diagnostics #ifdef _DEBUG void CView::Dump(CDumpContext& dc) const { CWnd::Dump(dc); if (m_pDocument != NULL) dc << "with document: " << m_pDocument; else dc << "with no document\n"; } void CView::AssertValid() const { CWnd::AssertValid(); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CCtrlView BEGIN_MESSAGE_MAP(CCtrlView, CView) ON_WM_PAINT() END_MESSAGE_MAP() CCtrlView::CCtrlView(LPCTSTR lpszClass, DWORD dwStyle) { m_strClass = lpszClass; m_dwDefaultStyle = dwStyle; } BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs) { ASSERT(cs.lpszClass == NULL); cs.lpszClass = m_strClass; // initialize common controls VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG)); AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG); // map default CView style to default style // WS_BORDER is insignificant if ((cs.style | WS_BORDER) == AFX_WS_DEFAULT_VIEW) cs.style = m_dwDefaultStyle & (cs.style | ~WS_BORDER); return CView::PreCreateWindow(cs); } void CCtrlView::OnDraw(CDC*) { ASSERT(FALSE); } void CCtrlView::OnPaint() { // this is done to avoid CView::OnPaint Default(); } ///////////////////////////////////////////////////////////////////////////// // CCtrlView diagnostics #ifdef _DEBUG void CCtrlView::Dump(CDumpContext& dc) const { CView::Dump(dc); dc << "\nClass Name: " << m_strClass; dc << "\nDefault Style: " << (void*)m_dwDefaultStyle; } void CCtrlView::AssertValid() const { CWnd::AssertValid(); ASSERT(!m_strClass.IsEmpty()); } #endif //_DEBUG #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif // IMPLEMENT_DYNAMIC for CView is in wincore.cpp for .OBJ granularity reasons IMPLEMENT_DYNAMIC(CSplitterWnd, CWnd) // for swap tuning IMPLEMENT_DYNAMIC(CCtrlView, CView) /////////////////////////////////////////////////////////////////////////////