/***************************************************************************** * * Copyright (c) 1999, KL GROUP INC. All Rights Reserved. * http://www.klgroup.com * * This file is provided for demonstration and educational uses only. * Permission to use, copy, modify and distribute this file for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of KL Group not be used in advertising * or publicity pertaining to this material without the specific, * prior written permission of an authorized representative of * KL Group. * * KL GROUP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. KL GROUP SHALL NOT BE LIABLE FOR ANY * DAMAGES SUFFERED BY USERS AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ // oc3_mvw.cpp : implementation of the COC3_mfcView class // #include "stdafx.h" #include "och3dMFC.cpp" #include "oc3_mfc.h" #include "oc3_mdoc.h" #include "oc3_mvw.h" #include "mainfrm.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView IMPLEMENT_DYNCREATE(COC3_mfcView, CView) BEGIN_MESSAGE_MAP(COC3_mfcView, CView) //{{AFX_MSG_MAP(COC3_mfcView) ON_WM_SIZE() ON_MESSAGE(XRT3DN_REPAINTED, OnOC3Repaint) ON_WM_DESTROY() ON_UPDATE_COMMAND_UI(ID_VIEW_GRIDLINES, OnUpdateViewGridlines) ON_COMMAND(ID_VIEW_GRIDLINES, OnViewGridlines) //}}AFX_MSG_MAP ON_WM_QUERYNEWPALETTE() ON_WM_PALETTECHANGED() ON_MESSAGE(XRT3DN_PALETTECHANGED, OnOC3PaletteChanged) // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView construction/destruction COC3_mfcView::COC3_mfcView() { m_pData = NULL; m_bShowGridlines = FALSE; } COC3_mfcView::~COC3_mfcView() { delete m_pData; } ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView drawing void COC3_mfcView::OnDraw(CDC* pDC) { COC3_mfcDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // if the view needs to be repainted so does the chart // force the chart to repaint itself m_chart.InvalidateRect(NULL, FALSE); } ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView printing BOOL COC3_mfcView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation pInfo->SetMaxPage(3); return DoPreparePrinting(pInfo); } void COC3_mfcView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void COC3_mfcView::OnPrint(CDC* pDC, CPrintInfo* pInfo) { if( pInfo->m_nCurPage == 1) { //Print the chart by passing a device context to WM_PAINT. //The chart is printed at the same size as it appears on the screen. //See INPUTVW.CPP module in the VIEWEX example (in the 16-bit samples). //BLOCK: Set up scale mode { CClientDC dcScreen(NULL); pDC->SetMapMode(MM_ANISOTROPIC); // map 1 screen logical inch to 1 printer (/output) logical inch pDC->SetWindowExt(dcScreen.GetDeviceCaps(LOGPIXELSX), dcScreen.GetDeviceCaps(LOGPIXELSX)); pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSX)); } // We cheat here since some controls do not paint if they are invisible, // so we temporary make set the appropriate visible bits during preview // mode so the controls think they are visible even though they aren't. HWND hWndCheatVisible = NULL; if (!IsWindowVisible()) { // walk up to the top until we find the invisible window for (HWND hWnd = m_hWnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) { ASSERT(hWnd != NULL); DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE); if ((dwStyle & WS_VISIBLE) == 0) { ::SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_VISIBLE); hWndCheatVisible = hWnd; break; } } ASSERT(hWndCheatVisible != NULL); } CPen pen(PS_SOLID, 1, RGB(0,0,0)); // solid black pen CPen* pOldPen = pDC->SelectObject(&pen); ASSERT(pDC->GetWindowOrg() == CPoint(0,0)); PaintChildWindows(m_hWnd, pDC, CPoint(0, 0)); ASSERT(pDC->GetWindowOrg() == CPoint(0,0)); pDC->SelectObject(pOldPen); if (hWndCheatVisible != NULL) ::SetWindowLong(hWndCheatVisible, GWL_STYLE, ::GetWindowLong(hWndCheatVisible, GWL_STYLE) &~ WS_VISIBLE); } else if(pInfo->m_nCurPage == 2) { //Print the chart using the DrawToDC function. //The chart is printed at the same size as it appears on the screen. //BLOCK: Set up scale mode { CClientDC dcScreen(NULL); pDC->SetMapMode(MM_ANISOTROPIC); // map 1 screen logical inch to 1 printer (/output) logical inch pDC->SetWindowExt(dcScreen.GetDeviceCaps(LOGPIXELSX), dcScreen.GetDeviceCaps(LOGPIXELSX)); pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSX)); } CRect rect; m_chart.GetClientRect(rect); ::LPtoDP(pDC->m_hDC, (POINT*)(&rect), 2); m_chart.DrawToDC(pDC->m_hDC, XRT3D_DRAW_ENHMETAFILE, XRT3D_DRAWSCALE_TOFIT, rect.left, rect.top, (rect.right-rect.left), (rect.bottom-rect.top)); } else if(pInfo->m_nCurPage == 3) { //Print the chart using the DrawToDC function. //The chart is printed so that it fills the page in one dimension //and is centered in the other dimension. //The aspect ratio of the chart is maintained (unless pixels don't //have the same aspect ratio on the screen and the printer). CRect rect; m_chart.GetClientRect(rect); //BLOCK: Set up scale mode { int nPageWidth, nPageHeight; int nChartWidth, nChartHeight; long a, b; pDC->SetMapMode(MM_ANISOTROPIC); nPageWidth = pDC->GetDeviceCaps(HORZRES); nPageHeight = pDC->GetDeviceCaps(VERTRES); nChartWidth = rect.right - rect.left; nChartHeight = rect.bottom - rect.top; a = nPageHeight; a *= nChartWidth; b = nPageWidth; b *= nChartHeight; // PH/PW < GH/GW // or PH*GW < PW*GH if(a < b) { // Fill vertically, center horizontally. pDC->SetWindowExt(nChartHeight, nChartHeight); pDC->SetViewportExt(nPageHeight, nPageHeight); pDC->LPtoDP(rect); nChartWidth = rect.right - rect.left; pDC->SetViewportOrg((nPageWidth - nChartWidth) / 2, 0); } else { // Fill horizontally, center vertically. pDC->SetWindowExt(nChartWidth, nChartWidth); pDC->SetViewportExt(nPageWidth, nPageWidth); pDC->LPtoDP(rect); nChartHeight = rect.bottom - rect.top; pDC->SetViewportOrg(0, (nPageHeight - nChartHeight) / 2); } } m_chart.GetClientRect(rect); ::LPtoDP(pDC->m_hDC, (POINT*)(&rect), 2); m_chart.DrawToDC(pDC->m_hDC, XRT3D_DRAW_ENHMETAFILE, XRT3D_DRAWSCALE_TOFIT, rect.left, rect.top, (rect.right-rect.left), (rect.bottom-rect.top)); } } void COC3_mfcView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } // The following code shows the technique of setting up a CDC to do // the appropriate scaling for printing and print preview. // The actual output HDC is then used to draw the individual controls. // This technique sends the WM_PAINT message to the control passing // the HDC as the 'wParam'. This is an alternative painting technique // that most Windows controls and all VB controls support. // This technique has many caveats that make it inappropriate for some // cases. If you find the general technique inappropriate, you can // add special case code to handle the printing of the troublesome // controls. // * If you are using non-VBX custom controls, that do not support // the WM_PAINT technique, they will not be printed // * Some controls may not result in the desired output format // since the controls print in the same fashion as they // are displayed on the screen. // * Some controls assume they are always being displayed on the // screen. This sometimes results in incorrect fonts being // used and bitmaps drawn incorrectly. // * The implementation of control printing does not support // WS_VSCROLL and WS_HSCROLL styles correctly. // * Some printer drivers may fault when painting certain controls. void COC3_mfcView::PaintChildWindows(HWND hWndParent, CDC* pDC, CPoint ptOffset) { for (HWND hWndChild = ::GetTopWindow(hWndParent); hWndChild != NULL; hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) { CRect rect; ::GetWindowRect(hWndChild, rect); // window rect in screen coords ScreenToClient(&rect); // relative to this view HDC hdcOut = pDC->m_hDC; #ifdef _DEBUG CPoint pt = pDC->GetWindowOrg(); ASSERT(pt.x == 0 && pt.y == 0); #endif DWORD dwStyle = ::GetWindowLong(hWndChild, GWL_STYLE); if (dwStyle & (WS_HSCROLL|WS_VSCROLL)) { TRACE("Warning: printing control with scrollbars not supported\n"); } if (dwStyle & WS_BORDER) { // the only case we special case handle - manually drawn border ::Rectangle(hdcOut, rect.left, rect.top, rect.right, rect.bottom); rect.InflateRect(-1,-1); // 1 logical pixel } pDC->SaveDC(); { CPoint pt(ptOffset.x + rect.left, ptOffset.y + rect.top); pDC->LPtoDP(&pt); pDC->OffsetViewportOrg(pt.x, pt.y); // set the viewport origin so that the window origin // can be changed by the control // draw it using a non-virtual HDC ::SendMessage(hWndChild, WM_PAINT, (WPARAM)hdcOut, 0L); } pDC->RestoreDC(-1); if (::GetTopWindow(hWndChild) != NULL) PaintChildWindows(hWndChild, pDC, ptOffset); } } ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView diagnostics #ifdef _DEBUG void COC3_mfcView::AssertValid() const { CView::AssertValid(); } void COC3_mfcView::Dump(CDumpContext& dc) const { CView::Dump(dc); } COC3_mfcDoc* COC3_mfcView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(COC3_mfcDoc))); return (COC3_mfcDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // COC3_mfcView message handlers BOOL COC3_mfcView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { BOOL ret = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); if (ret) { // create a chart window when the view is created ret = m_chart.Create("", WS_CHILD | WS_VISIBLE, rect, this, 0); char *header[] = { "This is a chart!", NULL }; char *label0[] = { "New York", NULL }; char *label1[] = { "Tokyo", NULL }; char *label2[] = { "Mexico", NULL }; Xrt3dLineStyle dot_style = { XRT3D_LPAT_DOTTED, RGB(0,0,0), 1 }; // set some properties, load some data m_chart.SetBackgroundColor(RGB(0xAA,0xBB,0xCC)); m_chart.SetGraphBorderWidth(5); m_chart.SetGraphBorder(XRT3D_BORDER_SHADOW); m_chart.SetGraphBackgroundColor(RGB(0xBB,0xCC,0xDD)); m_chart.SetDataAreaBackgroundColor(RGB(0xDD,0xDD,0xEE)); m_chart.SetSolidSurface(TRUE); m_chart.SetPerspectiveDepth(10); m_chart.SetXRotation(25.8883); m_chart.SetYRotation(0.34); m_chart.SetZRotation(310); m_chart.SetXAnnoMethod(XRT3D_ANNO_VALUE_LABELS); m_chart.SetYAnnoMethod(XRT3D_ANNO_VALUE_LABELS); m_chart.SetHeaderStrings(header); m_chart.SetHeaderBorder(XRT3D_BORDER_ETCHED_IN); m_chart.SetPropString(XRT3D_HEADER_FONT, "Arial,18,Bold"); m_pData = new CChart3DData("pop3d.dat"); m_chart.SetSurfaceData(*m_pData); m_chart.SetZGridLineStyle(&dot_style); m_pLabels[ 0 ] = new CChart3DTextArea(&m_chart); m_pLabels[ 0 ]->SetStrings(label0); m_pLabels[ 0 ]->SetAttachMethod(XRT3D_ATTACH_POINT); m_pLabels[ 0 ]->SetAttachPointX(5.5); m_pLabels[ 0 ]->SetAttachPointY(4.5); m_pLabels[ 0 ]->SetAttachPointZ(15.5); m_pLabels[ 0 ]->SetPlane(XRT3D_YZ_PLANE); m_pLabels[ 1 ] = new CChart3DTextArea(&m_chart); m_pLabels[ 1 ]->SetStrings(label1); m_pLabels[ 1 ]->SetAttachMethod(XRT3D_ATTACH_POINT); m_pLabels[ 1 ]->SetAttachPointX(3.5); m_pLabels[ 1 ]->SetAttachPointY(3); m_pLabels[ 1 ]->SetAttachPointZ(18); m_pLabels[ 1 ]->SetPlane(XRT3D_YZ_PLANE); m_pLabels[ 2 ] = new CChart3DTextArea(&m_chart); m_pLabels[ 2 ]->SetStrings(label2); m_pLabels[ 2 ]->SetAttachMethod(XRT3D_ATTACH_POINT); m_pLabels[ 2 ]->SetAttachPointX(1.5); m_pLabels[ 2 ]->SetAttachPointY(2); m_pLabels[ 2 ]->SetAttachPointZ(8); m_pLabels[ 2 ]->SetPlane(XRT3D_YZ_PLANE); } return (ret); } void COC3_mfcView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); if (IsWindow(m_chart.m_hWnd)) { // If the view has resize then resize the chart if it has been created m_chart.SetWindowPos(&wndTop, 0, 0, cx, cy, SWP_NOZORDER); } } LRESULT COC3_mfcView::OnOC3Repaint(WPARAM wParam, LPARAM lParam) { if (IsWindow(m_chart.m_hWnd)) { RECT rect, chartRect; int nWidth, nHeight; /* make the chart fill the windows client area */ GetClientRect(&rect); ::GetClientRect(m_chart.m_hWnd, &chartRect); nWidth = chartRect.right; nHeight = chartRect.bottom; if (nWidth != rect.right || nHeight != rect.bottom) { /* adjust the window size to fit the chart */ GetParent()->SetWindowPos(&wndTop, 0, 0, nWidth, nHeight, SWP_NOMOVE | SWP_NOZORDER); } } return TRUE; } BOOL COC3_mfcView::OnQueryNewPalette() { return(m_chart.SendMessage(WM_QUERYNEWPALETTE, 0, 0)); } void COC3_mfcView::OnPaletteChanged(CWnd* pFocusWnd) { m_chart.SendMessage(WM_PALETTECHANGED, (WPARAM)pFocusWnd->GetSafeHwnd(), 0); } LRESULT COC3_mfcView::OnOC3PaletteChanged(WPARAM, LPARAM) { CMainFrame* pFrame; CMDIChildWnd* pActiveChild; CView* pActiveView; ASSERT(AfxGetApp()->GetMainWnd()->IsKindOf(RUNTIME_CLASS(CMainFrame))); pFrame = (CMainFrame*)AfxGetApp()->GetMainWnd(); pActiveChild = pFrame->MDIGetActive(); if(!pActiveChild) return 0; pActiveView = pActiveChild->GetActiveView(); if(!pActiveView) return 0; pActiveView->SendMessage(WM_QUERYNEWPALETTE, 0, 0); pFrame->SendMessage(WM_PALETTECHANGED, (WPARAM)(pActiveView->GetSafeHwnd()), 0); return 0; } void COC3_mfcView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { if(bActivate) { // Realize the palette and tell all the other window about it. m_chart.SendMessage(WM_QUERYNEWPALETTE, 0, 0); AfxGetApp()->GetMainWnd()->SendMessage(WM_PALETTECHANGED, (WPARAM)(GetSafeHwnd()), 0); } CView::OnActivateView(bActivate, pActivateView, pDeactiveView); } void COC3_mfcView::OnDestroy() { CView::OnDestroy(); delete m_pLabels[ 0 ]; delete m_pLabels[ 1 ]; delete m_pLabels[ 2 ]; } void COC3_mfcView::OnUpdateViewGridlines(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bShowGridlines); } void COC3_mfcView::OnViewGridlines() { m_bShowGridlines = !m_bShowGridlines; if (m_bShowGridlines) { m_chart.SetZGridLines(XRT3D_XZ_PLANE | XRT3D_YZ_PLANE); } else { m_chart.SetZGridLines(0); } }