// CADView.cpp : implementation of the CCADView class // #include "stdafx.h" #include "LeoCAD.h" #include "CADDoc.h" #include "CADView.h" #include "WheelWnd.h" #include "Tools.h" #include "PrevView.h" #include "project.h" #include "globals.h" #include "system.h" #include "camera.h" #include "view.h" #include "MainFrm.h" #include "PiecePrv.h" #include "lc_application.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif BOOL GLWindowPreTranslateMessage (GLWindow *wnd, MSG *pMsg); ///////////////////////////////////////////////////////////////////////////// // CCADView IMPLEMENT_DYNCREATE(CCADView, CView) BEGIN_MESSAGE_MAP(CCADView, CView) //{{AFX_MSG_MAP(CCADView) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_SETCURSOR() ON_WM_CAPTURECHANGED() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_WM_MOUSEWHEEL() ON_WM_MBUTTONDOWN() ON_WM_TIMER() ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnDropDown) ON_MESSAGE(WM_LC_SET_STEP, OnSetStep) ON_MESSAGE(WM_LC_WHEEL_PAN, OnAutoPan) ON_MESSAGE(WM_LC_SET_CURSOR, OnChangeCursor) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCADView construction/destruction CCADView::CCADView() { m_pPixels = NULL; m_hCursor = NULL; m_pView = NULL; } CCADView::~CCADView() { if (m_pPixels) free (m_pPixels); } BOOL CCADView::PreCreateWindow(CREATESTRUCT& cs) { #define CUSTOM_CLASSNAME _T("LeoCADOpenGLClass") cs.style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS; // call base class PreCreateWindow to get the cs.lpszClass filled in with the MFC default class name if(!CView::PreCreateWindow(cs)) return 0; // Register the window class if it has not already been registered. WNDCLASS wndcls; HINSTANCE hInst = AfxGetInstanceHandle(); // check if our class is registered if(!(::GetClassInfo(hInst, CUSTOM_CLASSNAME, &wndcls))) { // get default MFC class settings if(::GetClassInfo(hInst, cs.lpszClass, &wndcls)) { // set our class name wndcls.lpszClassName = CUSTOM_CLASSNAME; // change settings for your custom class wndcls.style |= CS_OWNDC; wndcls.hbrBackground = NULL; // register class if (!AfxRegisterClass(&wndcls)) AfxThrowResourceException(); } else AfxThrowResourceException(); } // set our class name in CREATESTRUCT cs.lpszClass = CUSTOM_CLASSNAME; return 1; // we're all set } ///////////////////////////////////////////////////////////////////////////// // CCADView drawing void CCADView::OnDraw(CDC* /*pDC*/) { } ///////////////////////////////////////////////////////////////////////////// // CCADView printing // Derived to use our version of the toolbar void CCADView::OnFilePrintPreview() { // In derived classes, implement special window handling here // Be sure to Unhook Frame Window close if hooked. // must not create this on the frame. Must outlive this function CPrintPreviewState* pState = new CPrintPreviewState; pState->lpfnCloseProc = _AfxPreviewCloseProcEx; // DoPrintPreview's return value does not necessarily indicate that // Print preview succeeded or failed, but rather what actions are necessary // at this point. If DoPrintPreview returns TRUE, it means that // OnEndPrintPreview will be (or has already been) called and the // pState structure will be/has been deleted. // If DoPrintPreview returns FALSE, it means that OnEndPrintPreview // WILL NOT be called and that cleanup, including deleting pState // must be done here. if (!DoPrintPreview(IDR_PREVIEW, this, RUNTIME_CLASS(CCADPreviewView), pState)) { // In derived classes, reverse special window handling here for // Preview failure case TRACE0("Error: DoPrintPreview failed.\n"); AfxMessageBox(AFX_IDP_COMMAND_FAILURE); delete pState; // preview failed to initialize, delete State now } } BOOL CCADView::OnPreparePrinting(CPrintInfo* pInfo) { pInfo->m_pPD->m_pd.nMinPage = 1; pInfo->m_pPD->m_pd.hInstance = AfxGetInstanceHandle(); pInfo->m_pPD->m_pd.Flags |= PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOSELECTION | PD_ENABLEPRINTHOOK; pInfo->m_pPD->m_pd.lpfnPrintHook = PrintHookProc; pInfo->m_pPD->m_pd.lCustData = (LONG)AfxGetMainWnd(); int cols = theApp.GetProfileInt("Default", "Print Columns", 1); int rows = theApp.GetProfileInt("Default", "Print Rows", 1); int Max = (lcGetActiveProject()->GetLastStep()/(rows*cols)); if (lcGetActiveProject()->GetLastStep()%(rows*cols) != 0) Max++; pInfo->SetMaxPage(Max); if (pInfo->m_bPreview) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); POSITION pos = pFrame->m_listControlBars.GetHeadPosition(); while (pos != NULL) { CControlBar* pBar = (CControlBar*)pFrame->m_listControlBars.GetNext(pos); CString str; pBar->GetWindowText(str); if (str == _T("Full Screen")) { AfxGetMainWnd()->SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN); break; } } } return DoPreparePrinting(pInfo); } void CCADView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* pInfo) { int cols = theApp.GetProfileInt("Default", "Print Columns", 1); int rows = theApp.GetProfileInt("Default", "Print Rows", 1); int Max = (lcGetActiveProject()->GetLastStep()/(rows*cols)); if (lcGetActiveProject()->GetLastStep()%(rows*cols) != 0) Max++; pInfo->SetMaxPage(Max); } void CCADView::OnPrint(CDC* pDC, CPrintInfo* pInfo) { int cols = theApp.GetProfileInt("Default","Print Columns", 1); int rows = theApp.GetProfileInt("Default","Print Rows", 1); Project* project = lcGetActiveProject(); if (rows < 1) rows = 1; if (cols < 1) cols = 1; CRect rc(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES)); pDC->DPtoLP(&rc); int lpx = pDC->GetDeviceCaps(LOGPIXELSX); int lpy = pDC->GetDeviceCaps(LOGPIXELSY); rc.DeflateRect(lpx*theApp.GetProfileInt("Default","Margin Left", 50)/100, lpy*theApp.GetProfileInt("Default","Margin Top", 50)/100, lpx*theApp.GetProfileInt("Default","Margin Right", 50)/100, lpy*theApp.GetProfileInt("Default","Margin Bottom", 50)/100); int w = rc.Width()/cols, h = rc.Height()/rows; // cell size float viewaspect = (float)m_pView->GetWidth ()/(float)m_pView->GetHeight (); int pw = w, ph = h; // picture int mx = 0, my = 0; // offset if (w < h) { ph = (int) (w / viewaspect); my = (h - ph)/2; } else { pw = (int) (h * viewaspect); mx = (w - pw)/2; } int tw = pw, th = ph; // tile size MEMORYSTATUS MemStat; MemStat.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus(&MemStat); if (DWORD(pw*ph*3) > MemStat.dwTotalPhys) { tw = 512; th = 512; } HDC hMemDC = CreateCompatibleDC(GetDC()->m_hDC); LPBITMAPINFOHEADER lpbi; // Preparing bitmap header for DIB section BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = tw; bi.bmiHeader.biHeight = th; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = tw * th * 3; bi.bmiHeader.biXPelsPerMeter = 2925; bi.bmiHeader.biYPelsPerMeter = 2925; HBITMAP hBm = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, (void **)&lpbi, NULL, (DWORD)0); HBITMAP hBmOld = (HBITMAP)SelectObject(hMemDC, hBm); // Setting up a Pixel format for the DIB surface PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1,PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pixelformat = OpenGLChoosePixelFormat(hMemDC, &pfd); OpenGLDescribePixelFormat (hMemDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); OpenGLSetPixelFormat (hMemDC, pixelformat, &pfd); // Creating OpenGL context HGLRC hmemrc = pfnwglCreateContext(hMemDC); pfnwglMakeCurrent(hMemDC, hmemrc); // if (!pfnwglShareLists(m_hglRC, hmemrc)) // pDoc->RebuildDisplayLists(TRUE); project->RenderInitialize(); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = -MulDiv(50, pDC->GetDeviceCaps(LOGPIXELSY), 72); lf.lfWeight = FW_BOLD; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = PROOF_QUALITY; strcpy (lf.lfFaceName , "Arial"); HFONT font = CreateFontIndirect(&lf); HFONT OldFont = (HFONT)SelectObject(pDC->m_hDC, font); pDC->SetTextAlign(TA_BASELINE|TA_CENTER|TA_NOUPDATECP); float* bg = project->GetBackgroundColor(); pDC->SetTextColor(RGB (1.0f - bg[0], 1.0f - bg[1], 1.0f - bg[2])); pDC->SetBkMode(TRANSPARENT); HPEN hpOld = (HPEN)SelectObject(pDC->m_hDC,(HPEN)GetStockObject(BLACK_PEN)); unsigned short nOldTime = project->m_bAnimation ? project->m_nCurFrame : project->m_nCurStep; UINT nRenderTime = 1+((pInfo->m_nCurPage-1)*rows*cols); int oldSizex = project->m_nViewX; int oldSizey = project->m_nViewY; project->m_nViewX = tw; project->m_nViewY = th; for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) { if (nRenderTime > project->GetLastStep()) continue; if (project->m_bAnimation) project->m_nCurFrame = nRenderTime; else project->m_nCurStep = nRenderTime; project->CalculateStep(); FillRect(hMemDC, CRect(0,th,tw,0), (HBRUSH)GetStockObject(WHITE_BRUSH)); // Tile rendering if (tw != pw) { Camera* pCam = project->m_pCameras; for (int i = LC_CAMERA_MAIN; pCam; pCam = pCam->m_pNext) if (i-- == 0) break; pCam->StartTiledRendering(tw, th, pw, ph, viewaspect); do { project->Render(true); glFinish(); int tr, tc, ctw, cth; pCam->GetTileInfo(&tr, &tc, &ctw, &cth); lpbi = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hBm, 24)); BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); memcpy (&bi.bmiHeader, lpbi, sizeof(BITMAPINFOHEADER)); pDC->SetStretchBltMode(COLORONCOLOR); StretchDIBits(pDC->m_hDC, rc.left+1+(w*c)+mx + tc*tw, rc.top+1+(h*r)+my + tr*th, ctw, cth, 0, 0, ctw, cth, (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY); if (lpbi) GlobalFreePtr(lpbi); } while (pCam->EndTile()); } else { project->Render(true); glFinish(); lpbi = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hBm, 24)); BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); memcpy (&bi.bmiHeader, lpbi, sizeof(BITMAPINFOHEADER)); pDC->SetStretchBltMode(COLORONCOLOR); StretchDIBits(pDC->m_hDC, rc.left+1+(w*c)+mx, rc.top+1+(h*r)+my, w-(2*mx), h-(2*my), 0, 0, pw, ph, (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY); if (lpbi) GlobalFreePtr(lpbi); } // OpenGL Rendering // CCamera* pOld = pDoc->GetActiveCamera(); // pDoc->m_ViewCameras[pDoc->m_nActiveViewport] = pDoc->GetCamera(CAMERA_MAIN); // pDoc->m_ViewCameras[pDoc->m_nActiveViewport] = pOld; DWORD dwPrint = theApp.GetProfileInt("Settings","Print", PRINT_NUMBERS|PRINT_BORDER); if (dwPrint & PRINT_NUMBERS) { char tmp[4]; sprintf (tmp, "%d", nRenderTime); CRect rcNumber (rc); rcNumber.left += (w*c)+(int)(pDC->GetDeviceCaps (LOGPIXELSX)/2); rcNumber.top += (h*r)+(int)(pDC->GetDeviceCaps (LOGPIXELSY)/2); pDC->SetTextAlign (TA_TOP|TA_LEFT|TA_NOUPDATECP); pDC->DrawText(tmp, strlen (tmp), rcNumber, DT_LEFT|DT_TOP|DT_SINGLELINE); } if (dwPrint & PRINT_BORDER) { if (r == 0) { pDC->MoveTo(rc.left+(w*c), rc.top+(h*r)); pDC->LineTo(rc.left+(w*(c+1)), rc.top+(h*r)); } if (c == 0) { pDC->MoveTo(rc.left+(w*c), rc.top+(h*r)); pDC->LineTo(rc.left+(w*c), rc.top+(h*(r+1))); } pDC->MoveTo(rc.left+(w*(c+1)), rc.top+(h*r)); pDC->LineTo(rc.left+(w*(c+1)), rc.top+(h*(r+1))); pDC->MoveTo(rc.left+(w*c), rc.top+(h*(r+1))); pDC->LineTo(rc.left+(w*(c+1)), rc.top+(h*(r+1))); } nRenderTime++; } if (project->m_bAnimation) project->m_nCurFrame = nOldTime; else project->m_nCurStep = (unsigned char)nOldTime; project->m_nViewX = oldSizex; project->m_nViewY = oldSizey; pfnwglMakeCurrent(NULL, NULL); pfnwglDeleteContext(hmemrc); SelectObject(hMemDC, hBmOld); DeleteObject(hBm); DeleteDC(hMemDC); SelectObject(pDC->m_hDC, hpOld); SelectObject(pDC->m_hDC, OldFont); DeleteObject(font); glFinish(); // pfnwglMakeCurrent(m_pDC->m_hDC, m_hglRC); lf.lfHeight = -MulDiv(12, pDC->GetDeviceCaps(LOGPIXELSY), 72); lf.lfWeight = FW_REGULAR; font = CreateFontIndirect(&lf); OldFont = (HFONT)SelectObject(pDC->m_hDC, font); pDC->SetTextColor(RGB (0,0,0)); pDC->SetTextAlign (TA_TOP|TA_LEFT|TA_NOUPDATECP); rc.top -= pDC->GetDeviceCaps(LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Top", 50)/200; rc.bottom += pDC->GetDeviceCaps(LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Bottom", 50)/200; PrintHeader(FALSE, pDC->GetSafeHdc(), rc, pInfo->m_nCurPage, pInfo->GetMaxPage(), FALSE); PrintHeader(TRUE, pDC->GetSafeHdc(), rc, pInfo->m_nCurPage, pInfo->GetMaxPage(), FALSE); SelectObject(pDC->m_hDC, OldFont); DeleteObject(font); } void CCADView::PrintHeader(BOOL bFooter, HDC hDC, CRect rc, UINT nCurPage, UINT nMaxPage, BOOL bCatalog) { Project* project = lcGetActiveProject(); CString str,tmp; UINT nFormat = DT_CENTER; int r; if (bFooter) str = project->m_strFooter; else str = project->m_strHeader; if (str.GetLength()) { while ((r = str.Find("&L")) != -1) { nFormat = DT_LEFT; tmp = str.Left (r); tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&C")) != -1) { nFormat = DT_CENTER; tmp = str.Left (r); tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&R")) != -1) { nFormat = DT_RIGHT; tmp = str.Left (r); tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&F")) != -1) { tmp = str.Left (r); if (bCatalog) tmp += "LeoCAD Pieces Catalog"; else tmp += project->m_strTitle; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&A")) != -1) { tmp = str.Left (r); tmp += project->m_strAuthor; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&N")) != -1) { tmp = str.Left (r); tmp += project->m_strDescription; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&D")) != -1) { char dbuffer [9]; _strdate( dbuffer ); tmp = str.Left (r); tmp += dbuffer; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&T")) != -1) { char tbuffer [9]; _strtime( tbuffer ); tmp = str.Left (r); tmp += tbuffer; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&P")) != -1) { char buf[5]; sprintf (buf, "%d", nCurPage); tmp = str.Left (r); tmp += buf; tmp += str.Right(str.GetLength()-r-2); str = tmp; } while ((r = str.Find("&O")) != -1) { char buf[5]; sprintf (buf, "%d", nMaxPage); tmp = str.Left (r); tmp += buf; tmp += str.Right(str.GetLength()-r-2); str = tmp; } } if (bFooter) nFormat |= DT_BOTTOM|DT_SINGLELINE; else nFormat |= DT_TOP|DT_SINGLELINE; DrawText(hDC, (LPCTSTR)str, str.GetLength(), rc, nFormat); } void CCADView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // pfnwglMakeCurrent(m_pDC->GetSafeHdc(), m_hglRC); } void CCADView::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point, CCADPreviewView* pView) { // 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; CWnd* pNaturalParent = pView->GetParentFrame(); pParent = DYNAMIC_DOWNCAST(CFrameWnd, pNaturalParent); if (pParent == NULL || pParent->IsIconic()) pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd; ASSERT_VALID(pParent); ASSERT_KINDOF(CFrameWnd, 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(); /// pfnwglMakeCurrent(NULL, NULL); /* if (OpenGLGetPixelFormat(m_pDC->GetSafeHdc()) == 0) { delete m_pDC; m_pDC = new CClientDC(this); PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pixelformat = OpenGLChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd); if (pixelformat == 0) { AfxMessageBox("ChoosePixelFormat failed"); } if (OpenGLSetPixelFormat(m_pDC->m_hDC, pixelformat, &pfd) == FALSE) { AfxMessageBox("SetPixelFormat failed"); } } if (pfnwglMakeCurrent(m_pDC->m_hDC, m_hglRC) == FALSE) { LPTSTR lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL); ::MessageBox(NULL, lpMsgBuf, "Error", MB_OK|MB_ICONINFORMATION); LocalFree(lpMsgBuf); } */ InvalidateRect(NULL, FALSE); } BOOL CCADView::DoPrintPreview(UINT nIDResource, CView* pPrintView, CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState) { ASSERT_VALID_IDR(nIDResource); ASSERT_VALID(pPrintView); ASSERT(pPreviewViewClass != NULL); ASSERT(pPreviewViewClass->IsDerivedFrom(RUNTIME_CLASS(CCADPreviewView))); ASSERT(pState != NULL); CFrameWnd* pParent; CWnd* pNaturalParent = pPrintView->GetParentFrame(); pParent = DYNAMIC_DOWNCAST(CFrameWnd, pNaturalParent); if (pParent == NULL || pParent->IsIconic()) pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd; ASSERT_VALID(pParent); ASSERT_KINDOF(CFrameWnd, pParent); CCreateContext context; context.m_pCurrentFrame = pParent; context.m_pCurrentDoc = GetDocument(); context.m_pLastView = this; // Create the preview view object CCADPreviewView* pView = (CCADPreviewView*)pPreviewViewClass->CreateObject(); if (pView == NULL) { TRACE0("Error: Failed to create preview view.\n"); return FALSE; } ASSERT_KINDOF(CCADPreviewView, pView); pView->m_pPreviewState = pState; // save pointer pParent->OnSetPreviewMode(TRUE, pState); // Take over Frame Window // Create the toolbar from the dialog resource pView->m_pToolBar = new CFlatToolBar; if (!pView->m_pToolBar->Create(pParent, WS_CHILD | WS_VISIBLE | CBRS_TOP, AFX_IDW_PREVIEW_BAR) || !pView->m_pToolBar->LoadToolBar(nIDResource)) { TRACE0("Error: Preview could not create toolbar.\n"); pParent->OnSetPreviewMode(FALSE, pState); // restore Frame Window delete pView->m_pToolBar; // not autodestruct yet pView->m_pToolBar = NULL; pView->m_pPreviewState = NULL; // do not delete state structure delete pView; return FALSE; } pView->m_pToolBar->SetBarStyle(pView->m_pToolBar->GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY); /* pView->m_pToolBar = new CDialogBar; if (!pView->m_pToolBar->Create(pParent, MAKEINTRESOURCE(nIDResource), CBRS_TOP, AFX_IDW_PREVIEW_BAR)) { TRACE0("Error: Preview could not create toolbar dialog.\n"); pParent->OnSetPreviewMode(FALSE, pState); // restore Frame Window delete pView->m_pToolBar; // not autodestruct yet pView->m_pToolBar = NULL; pView->m_pPreviewState = NULL; // do not delete state structure delete pView; return FALSE; } */ pView->m_pToolBar->m_bAutoDelete = TRUE; // automatic cleanup // Create the preview view as a child of the App Main Window. This // is a sibling of this view if this is an SDI app. This is NOT a sibling // if this is an MDI app. if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), pParent, AFX_IDW_PANE_FIRST, &context)) { TRACE0("Error: couldn't create preview view for frame.\n"); pParent->OnSetPreviewMode(FALSE, pState); // restore Frame Window pView->m_pPreviewState = NULL; // do not delete state structure delete pView; return FALSE; } // Preview window shown now pState->pViewActiveOld = pParent->GetActiveView(); CCADView* pActiveView = (CCADView*)pParent->GetActiveFrame()->GetActiveView(); if (pActiveView != NULL) pActiveView->OnActivateView(FALSE, pActiveView, pActiveView); if (!pView->SetPrintView((CCADView*)pPrintView)) { pView->OnPreviewClose(); return TRUE; // signal that OnEndPrintPreview was called } pParent->SetActiveView(pView); // set active view - even for MDI // update toolbar and redraw everything pView->m_pToolBar->SendMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE); pParent->RecalcLayout(); // position and size everything pParent->UpdateWindow(); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CCADView diagnostics #ifdef _DEBUG void CCADView::AssertValid() const { CView::AssertValid(); } void CCADView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CCADDoc* CCADView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCADDoc))); return (CCADDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CCADView message handlers int CCADView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; m_pView = new View (lcGetActiveProject(), NULL); m_pView->Create (m_hWnd); m_pView->OnInitialUpdate (); SetTimer (IDT_LC_SAVETIMER, 5000, NULL); return 0; } void CCADView::OnDestroy() { delete m_pView; m_pView = NULL; KillTimer (IDT_LC_SAVETIMER); CView::OnDestroy(); } void CCADView::OnDropDown (NMHDR* pNotifyStruct, LRESULT* pResult) { NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNotifyStruct; RECT rc; ::SendMessage(pNMToolBar->hdr.hwndFrom, TB_GETRECT, (WPARAM)pNMToolBar->iItem, (LPARAM)&rc); CRect rect(rc); rect.top = rect.bottom; ::ClientToScreen(pNMToolBar->hdr.hwndFrom, &rect.TopLeft()); if (pNMToolBar->iItem == ID_SNAP_ON) { POINT pt = { rect.left, rect.top + 1 }; SystemDoPopupMenu(2, pt.x, pt.y); } if (pNMToolBar->iItem == ID_LOCK_ON) { POINT pt = { rect.left, rect.top + 1 }; SystemDoPopupMenu(8, pt.x, pt.y); } *pResult = TBDDRET_DEFAULT; } LONG CCADView::OnChangeCursor(UINT lParam, LONG /*wParam*/) { UINT Cursor; POINT pt; GetCursorPos(&pt); ScreenToClient(&pt); switch (m_pView->GetCursor(pt.x, pt.y)) { case LC_CURSOR_NONE: Cursor = NULL; break; case LC_CURSOR_BRICK: Cursor = IDC_BRICK; break; case LC_CURSOR_LIGHT: Cursor = IDC_LIGHT; break; case LC_CURSOR_SPOTLIGHT: Cursor = IDC_SPOTLIGHT; break; case LC_CURSOR_CAMERA: Cursor = IDC_CAMERA; break; case LC_CURSOR_SELECT: Cursor = IDC_SELECT; break; case LC_CURSOR_SELECT_GROUP: Cursor = IDC_SELECT_GROUP; break; case LC_CURSOR_MOVE: Cursor = IDC_MOVE; break; case LC_CURSOR_ROTATE: Cursor = IDC_ROTATE; break; case LC_CURSOR_ROTATEX: Cursor = IDC_ROTX; break; case LC_CURSOR_ROTATEY: Cursor = IDC_ROTY; break; case LC_CURSOR_DELETE: Cursor = IDC_ERASER; break; case LC_CURSOR_PAINT: Cursor = IDC_PAINT; break; case LC_CURSOR_ZOOM: Cursor = IDC_ZOOM; break; case LC_CURSOR_ZOOM_REGION: Cursor = IDC_ZOOM_REGION; break; case LC_CURSOR_PAN: Cursor = IDC_PAN; break; case LC_CURSOR_ROLL: Cursor = IDC_ROLL; break; case LC_CURSOR_ROTATE_VIEW: Cursor = IDC_ANGLE; break; default: LC_ASSERT_FALSE("Unknown cursor type."); } if (Cursor) { m_hCursor = theApp.LoadCursor(Cursor); SetCursor(m_hCursor); } else m_hCursor = NULL; return TRUE; } BOOL CCADView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (CView::OnSetCursor(pWnd, nHitTest, message)) return TRUE; OnChangeCursor(0, 0); if (m_hCursor) { SetCursor(m_hCursor); return TRUE; } return FALSE; } BOOL CCADView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if (zDelta > 0) lcGetActiveProject()->HandleCommand(LC_VIEW_ZOOMOUT, 0); else lcGetActiveProject()->HandleCommand(LC_VIEW_ZOOMIN, 0); return CView::OnMouseWheel(nFlags, zDelta, pt); } void CCADView::OnMButtonDown(UINT nFlags, CPoint point) { BOOL bCtl = GetKeyState(VK_CONTROL) & 0x8000; if(!bCtl && nFlags == MK_MBUTTON) { CWheelWnd *pwndPanWindow = new CWheelWnd(point); if (!pwndPanWindow->Create(this)) delete pwndPanWindow; } else CView::OnMButtonDown(nFlags, point); } // Notification from the auto-pan window LONG CCADView::OnAutoPan(UINT lParam, LONG wParam) { CPoint pt1(lParam), pt2(wParam); pt2 -= pt1; pt2.y = -pt2.y; unsigned long pt = ((short)pt2.x) | ((unsigned long)(((short)pt2.y) << 16)); lcGetActiveProject()->HandleCommand(LC_VIEW_AUTOPAN, pt); return TRUE; } void CCADView::OnTimer(UINT nIDEvent) { if (nIDEvent == IDT_LC_SAVETIMER) lcGetActiveProject()->CheckAutoSave(); CView::OnTimer(nIDEvent); } // lParam -> new step/frame LONG CCADView::OnSetStep(UINT lParam, LONG /*wParam*/) { if (lParam > 0) lcGetActiveProject()->HandleCommand(LC_VIEW_STEP_SET, lParam); return TRUE; } void CCADView::OnCaptureChanged(CWnd *pWnd) { if (pWnd != this) lcGetActiveProject()->HandleNotify(LC_CAPTURE_LOST, 0); CView::OnCaptureChanged(pWnd); } void CCADView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { char nKey = nChar; switch (nChar) { case VK_NUMPAD0 : case VK_NUMPAD1 : case VK_NUMPAD2 : case VK_NUMPAD3 : case VK_NUMPAD4 : case VK_NUMPAD5 : case VK_NUMPAD6 : case VK_NUMPAD7 : case VK_NUMPAD8 : case VK_NUMPAD9 : { nKey = nChar - VK_NUMPAD0 + 0x30; } break; // select the next/previous piece on the pieces list case VK_HOME: case VK_END: { /* CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd (); CPiecesList& pList = pMain->m_wndPiecesBar.m_wndPiecesList; LV_FINDINFO lvfi; int sel; lvfi.flags = LVFI_PARAM; lvfi.lParam = (LPARAM)pMain->m_wndPiecesBar.m_wndPiecePreview.GetPieceInfo (); sel = pList.FindItem (&lvfi); if (sel != -1) { if (nChar == VK_HOME) sel--; else sel++; pList.SetItemState (sel, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); pList.EnsureVisible (sel, FALSE); } */ } break; } lcGetActiveProject()->OnKeyDown(nKey, GetKeyState (VK_CONTROL) < 0, GetKeyState (VK_SHIFT) < 0); /* switch (nChar) { // HANDLE CTRL if action == pan/zoom case VK_CONTROL: if (m_nCurAction == ACTION_SELECT) { POINT pt; GetCursorPos(&pt); CRect rc; GetWindowRect(rc); if (rc.PtInRect(pt)) OnSetCursor(this, HTCLIENT, 0); } break; */ CView::OnKeyDown(nChar, nRepCnt, nFlags); } void CCADView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { /* if (nChar == VK_CONTROL) { // HANDLE CTRL if action == pan/zoom CCADDoc* pDoc = GetDocument(); if (pDoc->m_nCurAction == ACTION_SELECT) { POINT pt; GetCursorPos(&pt); CRect rc; GetWindowRect(rc); if (rc.PtInRect(pt)) OnSetCursor(this, HTCLIENT, 0); } } */ CView::OnKeyUp(nChar, nRepCnt, nFlags); } void CCADView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { CView::OnActivateView(bActivate, pActivateView, pDeactiveView); /* if (IsWindowEnabled()) { if (bActivate) { if (m_pPixels) free (m_pPixels); m_pPixels = NULL; } else { if (m_pPixels) free (m_pPixels); CCADDoc* pDoc = GetDocument(); m_pPixels = malloc(pDoc->m_szView.cx * pDoc->m_szView.cy * sizeof(GLubyte) * 4); if (!m_pPixels) return; glReadPixels(0, 0, pDoc->m_szView.cx, pDoc->m_szView.cy, GL_RGBA, GL_UNSIGNED_BYTE, m_pPixels); } } */ } LRESULT CCADView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if (m_pView) { MSG msg; msg.message = message; msg.wParam = wParam; msg.lParam = lParam; if (GLWindowPreTranslateMessage(m_pView, &msg)) return TRUE; } return CView::WindowProc(message, wParam, lParam); }