mirror of
https://github.com/leozide/leocad
synced 2024-12-27 21:58:37 +01:00
722 lines
18 KiB
C++
722 lines
18 KiB
C++
#include "lc_global.h"
|
|
#include "LeoCAD.h"
|
|
#include <WindowsX.h>
|
|
|
|
#include "CADDoc.h"
|
|
#include "CADView.h"
|
|
#include "Tools.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_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_SET_CURSOR, OnChangeCursor)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCADView construction/destruction
|
|
|
|
CCADView::CCADView()
|
|
{
|
|
m_hCursor = NULL;
|
|
m_pView = NULL;
|
|
}
|
|
|
|
CCADView::~CCADView()
|
|
{
|
|
}
|
|
|
|
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()
|
|
{
|
|
#ifndef SHARED_HANDLERS
|
|
AFXPrintPreview(this);
|
|
#endif
|
|
}
|
|
|
|
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)
|
|
{
|
|
CFrameWndEx* pFrame = (CFrameWndEx*)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
|
|
|
|
if (tw > 1024 || th > 1024)
|
|
tw = th = 1024;
|
|
|
|
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);
|
|
|
|
GL_DisableVertexBufferObject();
|
|
|
|
View view(project, project->m_ActiveView);
|
|
view.SetCamera(project->m_ActiveView->mCamera, false);
|
|
view.CreateFromBitmap(hMemDC);
|
|
view.MakeCurrent();
|
|
view.OnSize(tw, th);
|
|
project->AddView(&view);
|
|
|
|
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);
|
|
|
|
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 (pw > tw || ph > th)
|
|
{
|
|
Camera* pCam = view.mCamera;
|
|
pCam->StartTiledRendering(tw, th, pw, ph, viewaspect);
|
|
do
|
|
{
|
|
project->Render(&view, 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);
|
|
|
|
int y = 0;
|
|
|
|
if (ph > th && tr != 0)
|
|
y = tr * th - (th - ph % th);
|
|
|
|
StretchDIBits(pDC->m_hDC, rc.left+1+(w*c)+mx + tc*tw, rc.top+1+(h*r)+my + y, 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(&view, 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);
|
|
}
|
|
|
|
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)
|
|
{
|
|
pDC->MoveTo(rc.left+(w*c), rc.top+(h*r));
|
|
pDC->LineTo(rc.left+(w*(c+1)), rc.top+(h*r));
|
|
|
|
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;
|
|
|
|
view.DestroyContext();
|
|
SelectObject(hMemDC, hBmOld);
|
|
DeleteObject(hBm);
|
|
DeleteDC(hMemDC);
|
|
GL_EnableVertexBufferObject();
|
|
|
|
SelectObject(pDC->m_hDC, hpOld);
|
|
SelectObject(pDC->m_hDC, OldFont);
|
|
DeleteObject(font);
|
|
glFinish();
|
|
|
|
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);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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;
|
|
|
|
Project* project = lcGetActiveProject();
|
|
|
|
m_pView = new View(project, project->m_ActiveView);
|
|
if (project->m_ActiveView)
|
|
m_pView->SetCamera(project->m_ActiveView->mCamera, false);
|
|
else
|
|
m_pView->SetDefaultCamera();
|
|
m_pView->CreateFromWindow(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;
|
|
|
|
switch (m_pView->GetCursor())
|
|
{
|
|
case LC_CURSOR_DEFAULT: 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;
|
|
}
|
|
|
|
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;
|
|
|
|
if (nChar >= VK_NUMPAD0 && nChar <= VK_NUMPAD9)
|
|
{
|
|
nKey = nChar - VK_NUMPAD0 + '0';
|
|
}
|
|
|
|
// Update cursor for multiple selection.
|
|
if (nChar == VK_CONTROL)
|
|
{
|
|
if (lcGetActiveProject()->GetCurAction() == LC_ACTION_SELECT)
|
|
{
|
|
POINT pt;
|
|
|
|
GetCursorPos(&pt);
|
|
CRect rc;
|
|
GetWindowRect(rc);
|
|
|
|
if (rc.PtInRect(pt))
|
|
OnSetCursor(this, HTCLIENT, 0);
|
|
}
|
|
}
|
|
|
|
lcGetActiveProject()->OnKeyDown(nKey, GetKeyState(VK_CONTROL) < 0, GetKeyState(VK_SHIFT) < 0);
|
|
|
|
CView::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CCADView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
// Update cursor for multiple selection.
|
|
if (nChar == VK_CONTROL)
|
|
{
|
|
if (lcGetActiveProject()->GetCurAction() == LC_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)
|
|
{
|
|
// if (pActivateView && pActivateView->IsKindOf(RUNTIME_CLASS(CCADView)))
|
|
// lcGetActiveProject()->SetActiveView(((CCADView*)pActivateView)->m_pView);
|
|
|
|
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
|
|
}
|
|
|
|
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);
|
|
}
|