// System user interface. // #include "stdafx.h" #include #include #include "leocad.h" #include "bmpmenu.h" #include "system.h" #include "defines.h" #include "camera.h" #include "tools.h" #include "file.h" #include "image.h" #include "PieceBar.h" #include "PropsSht.h" #include "PrefSht.h" #include "arraydlg.h" #include "imagedlg.h" #include "groupdlg.h" #include "figdlg.h" #include "seldlg.h" #include "htmldlg.h" #include "stepdlg.h" #include "povdlg.h" #include "terrdlg.h" #include "LibDlg.h" #include "EdGrpDlg.h" #include "AboutDlg.h" #include "categdlg.h" #include "cadbar.h" #include "mainfrm.h" #include "project.h" #include "globals.h" #include "lc_application.h" #include "piece.h" #include "pieceinf.h" // Display a message box when an assert happens. bool lcAssert(const char* FileName, int Line, const char* Expression, const char* Description) { char buf[1024]; sprintf(buf, "Assertion failed on line %d of file %s.\n%s\nDo you want to debug this?", Line, FileName, Description); int ret = AfxMessageBox(buf, MB_YESNOCANCEL|MB_ICONERROR); if (ret == IDYES) DebugBreak(); else if (ret == IDCANCEL) return true; // Disable this assert. return false; } static CMenu menuPopups; static CStepDlg* StepModeless = NULL; static UINT ClipboardFormat = 0; ///////////////////////////////////////////////////////////////////////////// // Static functions static void ShowLastError() { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); MessageBox( NULL, (char*)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION ); LocalFree( lpMsgBuf ); } static CMenu* GetMainMenu(int nIndex) { CWnd* pFrame = AfxGetMainWnd(); if (pFrame == NULL) return NULL; CMenu* pMenu = pFrame->GetMenu(); if (pMenu == NULL) return NULL; return pMenu->GetSubMenu(nIndex); } UINT APIENTRY OFNOpenHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { /* case WM_HELP: { LPHELPINFO lphi = (LPHELPINFO)lParam; if (lphi->iContextType == HELPINFO_WINDOW) // must be for a control WinHelp ((HWND)lphi->hItemHandle, AfxGetApp()->m_pszHelpFilePath, HELP_WM_HELP, (DWORD)(LPVOID)HelpIDs); return TRUE; } break; case WM_CONTEXTMENU: { WinHelp ((HWND)wParam, AfxGetApp()->m_pszHelpFilePath, HELP_CONTEXTMENU, (DWORD)(LPVOID)HelpIDs); return TRUE; } break; */ case WM_INITDIALOG: { RECT rc1, rc2; HWND h = GetParent(hdlg); GetWindowRect(GetDlgItem(h, lst1), &rc1); ScreenToClient(h, (LPPOINT)&rc1); ScreenToClient(h, ((LPPOINT)&rc1)+1); GetWindowRect(hdlg, &rc2); SetWindowPos(hdlg, NULL, 0, 0, 122 + rc1.left, rc2.bottom - rc2.top, SWP_NOMOVE); HBITMAP hbm = CreateColorBitmap(120, 100, GetSysColor(COLOR_BTNFACE)); SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm); GetWindowRect(GetDlgItem(hdlg, IDC_OPENDLG_PREVIEW), &rc1); GetWindowRect(GetDlgItem(hdlg, IDC_OPENDLG_TEXT), &rc2); SetWindowPos(GetDlgItem(hdlg, IDC_OPENDLG_TEXT), NULL, 0, 0, rc1.right - rc1.left, rc2.bottom - rc2.top, SWP_NOMOVE); } break; case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lParam; if (pnmh->code == CDN_FILEOK) { // HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_BITMAP, STM_GETIMAGE, IMAGE_BITMAP, 0); // if (hbmold) // DeleteObject(hbmold); // This avoids an assert _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); pThreadState->m_pAlternateWndInit = NULL; return FALSE; } if (pnmh->code == CDN_SELCHANGE) { char filename[_MAX_PATH]; SendMessage(GetParent(hdlg), CDM_GETFILEPATH, _MAX_PATH, (LPARAM)filename); HBITMAP hbm = NULL; char *p = strrchr(filename, '.'); if ((p && (_stricmp (p+1, "lcd"))) || ((GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY))) { hbm = CreateColorBitmap (120, 100, GetSysColor (COLOR_BTNFACE)); HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm); if (hbmold) DeleteObject(hbmold); return FALSE; } float fv; char id[32]; FileDisk file; file.Open(filename, "rb"); file.Read(id, 32); sscanf(strchr(id, ' '), "%f", &fv); if (fv > 0.4f) { file.Read(&fv, 4); if (fv > 0.7f) { unsigned long dwPosition; file.Seek(-4, SEEK_END); file.Read(&dwPosition, 4); file.Seek(dwPosition, SEEK_SET); if (dwPosition != 0) { if (fv < 1.0f) { BITMAPFILEHEADER bmfHeader; file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)); DWORD nPackedDIBLen = sizeof(BITMAPINFOHEADER) + 36000; HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen); file.Read((LPSTR)hDIB, nPackedDIBLen); BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB; BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB; int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bmiHeader.biBitCount; LPVOID lpDIBBits; if (bmInfo.bmiHeader.biBitCount > 8) lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0)); else lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors); CClientDC dc(NULL); hbm = CreateDIBitmap(dc.m_hDC, &bmiHeader, CBM_INIT, lpDIBBits, &bmInfo, DIB_RGB_COLORS); ::GlobalFree(hDIB); } else { Image image; if (image.FileLoad (file)) { HWND hwndDesktop = GetDesktopWindow(); HDC hdcDesktop = GetDC(hwndDesktop); HDC hdcMem = CreateCompatibleDC(hdcDesktop); hbm = CreateCompatibleBitmap(hdcDesktop, 120, 100); HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); for (int y = 0; y < 100; y++) for (int x = 0; x < 120; x++) { unsigned char* b = image.GetData () + (y*120+x)*3; SetPixelV(hdcMem, x, y, RGB(b[0], b[1], b[2])); } // Clean up SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); ReleaseDC(hwndDesktop, hdcDesktop); } } } } } file.Close(); if (!hbm) hbm = CreateColorBitmap (120, 100, GetSysColor(COLOR_BTNFACE)); HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm); if (hbmold) DeleteObject(hbmold); InvalidateRect(GetDlgItem(hdlg, IDC_OPENDLG_PREVIEW), NULL, TRUE); } } break; case WM_DESTROY: { HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_GETIMAGE, IMAGE_BITMAP, 0); if (hbmold) DeleteObject(hbmold); } break; } return FALSE; } static UINT APIENTRY OFNSaveHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { case WM_INITDIALOG: { int i = theApp.GetProfileInt ("Default", "Save Preview", 0); if (i != 0) CheckDlgButton(hdlg, IDC_SAVEDLG_PREVIEW, BST_CHECKED); } case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lParam; if (pnmh->code == CDN_FILEOK) { int i = 0; if (IsDlgButtonChecked(hdlg, IDC_SAVEDLG_PREVIEW)) i = 1; theApp.WriteProfileInt ("Default", "Save Preview", i); // This avoids an assert _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); pThreadState->m_pAlternateWndInit = NULL; return FALSE; } } } return 0; } static UINT APIENTRY OFNSavePictureHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { case WM_INITDIALOG: { OPENFILENAME* ofn = (OPENFILENAME*)lParam; SetWindowLong(hdlg, GWL_USERDATA, ofn->lCustData); } break; case WM_COMMAND: { if (wParam == IDC_SAVEPICTURE_OPTIONS) { LC_IMAGEDLG_OPTS* opts = (LC_IMAGEDLG_OPTS*)GetWindowLong(hdlg, GWL_USERDATA); CImageDlg dlg(FALSE, opts); dlg.DoModal(); } } break; case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lParam; if (pnmh->code == CDN_FILEOK) { // This avoids an assert _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); pThreadState->m_pAlternateWndInit = NULL; return FALSE; } } } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Wait cursor static int g_nWaitCursorCount; // for wait cursor (>0 => waiting) static HCURSOR g_hcurWaitCursorRestore; // old cursor to restore after wait cursor // 0 => restore, 1=> begin, -1=> end void SystemDoWaitCursor(int nCode) { g_nWaitCursorCount += nCode; if (g_nWaitCursorCount > 0) { HCURSOR hcurWait = ::LoadCursor(NULL, IDC_WAIT); HCURSOR hcurPrev = ::SetCursor(hcurWait); if (nCode > 0 && g_nWaitCursorCount == 1) g_hcurWaitCursorRestore = hcurPrev; } else { // turn everything off g_nWaitCursorCount = 0; // prevent underflow ::SetCursor(g_hcurWaitCursorRestore); } } void Sys_BeginWait () { SystemDoWaitCursor (1); } void Sys_EndWait () { SystemDoWaitCursor (-1); } ///////////////////////////////////////////////////////////////////////////// // Profile Access // returns the store value or default int Sys_ProfileLoadInt(const char* section, const char* entry, const int defaultvalue) { return theApp.GetProfileInt(section, entry, defaultvalue); } // returns true if successful bool Sys_ProfileSaveInt(const char* section, const char* entry, const int value) { return theApp.WriteProfileInt(section, entry, value) ? true : false; } char* Sys_ProfileLoadString(const char* section, const char* entry, const char* defaultvalue) { static CString str; str = theApp.GetProfileString(section, entry, defaultvalue); return (char*)(LPCSTR)str; } bool Sys_ProfileSaveString(const char* section, const char* entry, const char* value) { return theApp.WriteProfileString(section, entry, value) ? true : false; } ///////////////////////////////////////////////////////////////////////////// // User Interface static HBITMAP hbmMenuDot; static const BYTE rgbDot[] = { 0x6, 0xF, 0xF, 0xF, 0x6 }; // simple byte bitmap, 1=> bit on #define DOT_WIDTH 4 #define DOT_HEIGHT 5 void SystemFinish() { DeleteObject(hbmMenuDot); } void SystemInit() { ClipboardFormat = RegisterClipboardFormat(_T("LeoCAD_Data")); // initialize wait cursor state g_nWaitCursorCount = 0; g_hcurWaitCursorRestore = NULL; menuPopups.LoadMenu(IDR_POPUPS); // attempt to load special bitmap, else default to arrow CSize size = GetMenuCheckMarkDimensions(); ASSERT(size.cx > 4 && size.cy > 5); // not too small please if (size.cx > 32) size.cx = 32; int iwRow = (size.cx + 15) >> 4; // # of WORDs per raster line int nShift = (size.cx - DOT_WIDTH) / 2; // # of bits to shift over nShift += ((iwRow * 16) - size.cx); // padding for word alignment if (nShift > 16 - DOT_WIDTH) nShift = 16 - DOT_WIDTH; // maximum shift for 1 word if (size.cy > 32) size.cy = 32; // bitmap 2/4/4/4/2 pixels wide - centered (0 => black) BYTE rgbBitmap[32 * 2 * sizeof(WORD)]; memset(rgbBitmap, 0xff, sizeof(rgbBitmap)); BYTE* pbOut = &rgbBitmap[iwRow * sizeof(WORD) * ((size.cy - (DOT_HEIGHT+1)) >> 1)]; const BYTE* pbIn = rgbDot; for (int y = 0; y < DOT_HEIGHT; y++) { WORD w = (WORD)~(((DWORD)*pbIn++) << nShift); // bitmaps are always hi-lo pbOut[0] = HIBYTE(w); pbOut[1] = LOBYTE(w); pbOut += iwRow * sizeof(WORD); } hbmMenuDot = CreateBitmap(size.cx, size.cy, 1, 1, (LPVOID)&rgbBitmap); if (hbmMenuDot == NULL) { #define OBM_MNARROW 32739 hbmMenuDot = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW)); } } // Viewport menu. void SystemUpdateViewport(int nNew, int nOld) { CMenu* pMenu = GetMainMenu(2); if (!pMenu) return; pMenu = pMenu->GetSubMenu(13); pMenu->CheckMenuItem(nOld + ID_VIEWPORT01, MF_BYCOMMAND | MF_UNCHECKED); pMenu->CheckMenuItem(nNew + ID_VIEWPORT01, MF_BYCOMMAND | MF_CHECKED); } // Action toolbar, popup menu and cursor. void SystemUpdateAction(int nNew, int nOld) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_TOOLS_BAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); CView* pView = pFrame->GetActiveView(); pCtrl->CheckButton(ID_ACTION_SELECT+nOld, FALSE); pCtrl->CheckButton(ID_ACTION_SELECT+nNew, TRUE); // TODO: make sure this works if loading a file from the cmd line. if (pView) pView->SendMessage(WM_LC_SET_CURSOR, nNew); // TODO: update popup context menu // TODO: disable lights if count > 8 } // Current color in the listbox; void SystemUpdateColorList(int nNew) { if (AfxGetMainWnd()) AfxGetMainWnd()->PostMessage (WM_LC_UPDATE_LIST, 0, nNew+1); } void SystemUpdateRenderingMode(bool bBackground, bool bFast) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); // if (bFast) // { // pCtrl->EnableButton(ID_RENDER_BACKGROUND, TRUE); // pCtrl->CheckButton(ID_RENDER_BACKGROUND, bBackground); // } // else { pCtrl->CheckButton(ID_RENDER_BACKGROUND, FALSE); pCtrl->EnableButton(ID_RENDER_BACKGROUND, FALSE); } pCtrl->CheckButton(ID_RENDER_BOX, bFast); } void SystemUpdateUndoRedo(char* undo, char* redo) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); CMenu* pMenu = GetMainMenu(1); char txt[50]; UINT nState; if (pMenu == NULL) return; strcpy(txt, "Undo "); if (undo != NULL) strcat(txt, undo); strcat(txt, "\tCtrl+Z"); nState = pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND); nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR); pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND | MF_STRING | nState, ID_EDIT_UNDO, txt); strcpy(txt, "Redo "); if (redo != NULL) strcat(txt, redo); strcat(txt, "\tCtrl+Y"); nState = pMenu->GetMenuState(ID_EDIT_REDO, MF_BYCOMMAND); nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR); pMenu->ModifyMenu(ID_EDIT_REDO, MF_BYCOMMAND | MF_STRING | nState, ID_EDIT_REDO, txt); pMenu->EnableMenuItem(ID_EDIT_UNDO, MF_BYCOMMAND | (undo ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_EDIT_REDO, MF_BYCOMMAND | (redo ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pCtrl->EnableButton(ID_EDIT_UNDO, undo ? TRUE : FALSE); pCtrl->EnableButton(ID_EDIT_REDO, redo ? TRUE : FALSE); } // Snap menu & toolbar icon void SystemUpdateSnap(const unsigned long nSnap) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); pCtrl->CheckButton(ID_SNAP_ANGLE, (nSnap & LC_DRAW_SNAP_A) != 0); CMenu* pMenu = menuPopups.GetSubMenu(2); pMenu->CheckMenuItem(ID_SNAP_SNAPX, MF_BYCOMMAND | (nSnap & LC_DRAW_SNAP_X ? MF_CHECKED : MF_UNCHECKED)); pMenu->CheckMenuItem(ID_SNAP_SNAPY, MF_BYCOMMAND | (nSnap & LC_DRAW_SNAP_Y ? MF_CHECKED : MF_UNCHECKED)); pMenu->CheckMenuItem(ID_SNAP_SNAPZ, MF_BYCOMMAND | (nSnap & LC_DRAW_SNAP_Z ? MF_CHECKED : MF_UNCHECKED)); pMenu = menuPopups.GetSubMenu(8); pMenu->CheckMenuItem(ID_LOCK_LOCKX, MF_BYCOMMAND | (nSnap & LC_DRAW_LOCK_X ? MF_CHECKED : MF_UNCHECKED)); pMenu->CheckMenuItem(ID_LOCK_LOCKY, MF_BYCOMMAND | (nSnap & LC_DRAW_LOCK_Y ? MF_CHECKED : MF_UNCHECKED)); pMenu->CheckMenuItem(ID_LOCK_LOCKZ, MF_BYCOMMAND | (nSnap & LC_DRAW_LOCK_Z ? MF_CHECKED : MF_UNCHECKED)); SetMenuItemBitmaps(pMenu->m_hMenu, ID_LOCK_2BUTTONS, MF_BYCOMMAND, NULL, hbmMenuDot); SetMenuItemBitmaps(pMenu->m_hMenu, ID_LOCK_3DMOVEMENT, MF_BYCOMMAND, NULL, hbmMenuDot); // TODO: change Snap None & All (or maybe not ?) } void SystemUpdateSelected(unsigned long flags, int SelectedCount, Object* Focus) { CMenu* pMenu; CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); // select all/none/invert/by name pMenu = GetMainMenu(1); if (flags & LC_SEL_NO_PIECES) { pMenu->EnableMenuItem(ID_EDIT_SELECTINVERT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); pMenu->EnableMenuItem(ID_EDIT_SELECTBYNAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); } else { pMenu->EnableMenuItem(ID_EDIT_SELECTINVERT, MF_BYCOMMAND | MF_ENABLED); pMenu->EnableMenuItem(ID_EDIT_SELECTBYNAME, MF_BYCOMMAND | MF_ENABLED); } pMenu->EnableMenuItem(ID_EDIT_SELECTNONE, MF_BYCOMMAND | (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_EDIT_SELECTALL, MF_BYCOMMAND | (flags & LC_SEL_UNSELECTED ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); // cut, copy pMenu->EnableMenuItem(ID_EDIT_CUT, MF_BYCOMMAND | (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_EDIT_COPY, MF_BYCOMMAND | (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pCtrl->EnableButton(ID_EDIT_CUT, flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? TRUE : FALSE); pCtrl->EnableButton(ID_EDIT_COPY, flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? TRUE : FALSE); // mirror/array, hide sel/unsel, unhideall pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_TOOLS_BAR); pCtrl = &pBar->GetToolBarCtrl(); pCtrl->EnableButton(ID_PIECE_ARRAY, flags & LC_SEL_PIECE ? TRUE : FALSE); pCtrl->EnableButton(ID_PIECE_MIRROR, flags & LC_SEL_PIECE ? TRUE : FALSE); pMenu = GetMainMenu(3); pMenu->EnableMenuItem(ID_PIECE_DELETE, MF_BYCOMMAND | (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_COPYKEYS, MF_BYCOMMAND | (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_ARRAY, MF_BYCOMMAND | (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_MIRROR, MF_BYCOMMAND | (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_UNHIDEALL, MF_BYCOMMAND | (flags & LC_SEL_HIDDEN ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_HIDESELECTED, MF_BYCOMMAND | (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_HIDEUNSELECTED, MF_BYCOMMAND | (flags & LC_SEL_UNSELECTED ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); // group pMenu->EnableMenuItem(ID_PIECE_GROUP, MF_BYCOMMAND | (flags & LC_SEL_CANGROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_UNGROUP, MF_BYCOMMAND | (flags & LC_SEL_GROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_ATTACH, MF_BYCOMMAND | ((flags & (LC_SEL_GROUP|LC_SEL_FOCUSGROUP)) == (LC_SEL_GROUP) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_DETACH, MF_BYCOMMAND | (flags & LC_SEL_FOCUSGROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMenu->EnableMenuItem(ID_PIECE_EDITGROUPS, MF_BYCOMMAND | ((flags & LC_SEL_NO_PIECES) == 0 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pCtrl->EnableButton(ID_PIECE_PREVIOUS, flags & LC_SEL_PIECE ? TRUE : FALSE); pCtrl->EnableButton(ID_PIECE_NEXT, flags & LC_SEL_PIECE ? TRUE : FALSE); // Status bar text. if (SelectedCount == 0) { pFrame->SetStatusBarMessage(""); pFrame->SetMessageText(AFX_IDS_IDLEMESSAGE); } else if ((SelectedCount == 1) && (Focus != NULL)) { char Message[256]; if (Focus->IsPiece()) sprintf(Message, "%s (ID: %s)", Focus->GetName(), ((Piece*)Focus)->GetPieceInfo()->m_strName); else strcpy(Message, Focus->GetName()); pFrame->SetStatusBarMessage(Message); pFrame->SetMessageText(Message); } else { char Message[256]; if (SelectedCount == 1) strcpy(Message, "1 Object selected."); else sprintf(Message, "%d Objects selected.", SelectedCount); pFrame->SetStatusBarMessage(Message); pFrame->SetMessageText(Message); } } // Changed current step/frame void SystemUpdateTime(bool bAnimation, int nTime, int nTotal) { // Toolbar CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); pCtrl->EnableButton(ID_VIEW_STEP_NEXT, nTime < nTotal ? TRUE : FALSE); pCtrl->EnableButton(ID_VIEW_STEP_PREVIOUS, nTime > 1 ? TRUE : FALSE); pCtrl->EnableButton(ID_VIEW_STEP_FIRST, nTime != 1 ? TRUE : FALSE); pCtrl->EnableButton(ID_VIEW_STEP_LAST, nTime != nTotal ? TRUE : FALSE); // Main menu CBMPMenu* pMainMenu = (CBMPMenu*)GetMainMenu(2)->GetSubMenu(14); pMainMenu->EnableMenuItem(ID_VIEW_STEP_NEXT, MF_BYCOMMAND | (nTime < nTotal ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMainMenu->EnableMenuItem(ID_VIEW_STEP_PREVIOUS, MF_BYCOMMAND | (nTime > 1 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMainMenu->EnableMenuItem(ID_VIEW_STEP_FIRST, MF_BYCOMMAND | (nTime != 1 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); pMainMenu->EnableMenuItem(ID_VIEW_STEP_LAST, MF_BYCOMMAND | (nTime != nTotal ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); // Status bar char szStep[11]; CStatusBar* pStatusBar = (CStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR); if (bAnimation) sprintf(szStep, "%i/%i", nTime, nTotal); else sprintf(szStep, " Step %i ", nTime); pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_STEP), LPCSTR(szStep)); // Choose step dialog if (StepModeless != NULL) StepModeless->UpdateRange(nTime, nTotal); } void SystemUpdateSnap(unsigned short MoveSnap, unsigned short RotateSnap) { char Text[256], xy[32], z[32]; lcGetActiveProject()->GetSnapDistanceText(xy, z); sprintf(Text, " M: %s %s R: %d ", xy, z, RotateSnap); if (AfxGetMainWnd()) ((CMainFrame*)AfxGetMainWnd())->SetStatusBarPane(ID_INDICATOR_SNAP, Text); } void SystemUpdatePaste(bool enable) { CMenu* pMenu = GetMainMenu(1); CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); if (pMenu != NULL) pMenu->EnableMenuItem(ID_EDIT_PASTE, MF_BYCOMMAND | (enable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); if (pCtrl) pCtrl->EnableButton(ID_EDIT_PASTE, enable ? TRUE : FALSE); } void SystemUpdatePlay(bool play, bool stop) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); pCtrl->EnableButton(ID_ANIMATOR_PLAY, play ? TRUE : FALSE); pCtrl->EnableButton(ID_ANIMATOR_STOP, stop ? TRUE : FALSE); } void SystemUpdateAnimation(bool bAnimation, bool bAddKeys) { // Toolbar CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR); CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl(); pCtrl->CheckButton(ID_ANIMATOR_TOGGLE, bAnimation ? TRUE : FALSE); pCtrl->CheckButton(ID_ANIMATOR_KEY, bAddKeys ? TRUE : FALSE); pCtrl->EnableButton(ID_ANIMATOR_PLAY, bAnimation ? TRUE : FALSE); pCtrl->EnableButton(ID_ANIMATOR_STOP, FALSE); // Menu char* txt; CMenu* pMenu = GetMainMenu(3); UINT nState = pMenu->GetMenuState(ID_PIECE_COPYKEYS, MF_BYCOMMAND); nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR); if (bAnimation) txt = "Copy Keys from Instructions"; else txt = "Copy Keys from Animation"; pMenu->ModifyMenu(ID_PIECE_COPYKEYS, MF_BYCOMMAND | MF_STRING | nState, ID_PIECE_COPYKEYS, txt); } void SystemUpdateCurrentCamera(Camera* pOld, Camera* pNew, Camera* pCamera) { CMenu* Menu = GetMainMenu(2); if (!Menu) return; CBMPMenu* pMainMenu = (CBMPMenu*)Menu->GetSubMenu(13); CMenu* pPopupMenu = menuPopups.GetSubMenu(1)->GetSubMenu(3); int i; for (i = 0; pCamera; i++, pCamera = pCamera->m_pNext) { if (pOld == pCamera) { pPopupMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_UNCHECKED); pMainMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_UNCHECKED); } if (pNew == pCamera) { pPopupMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_CHECKED); pMainMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_CHECKED); SetMenuItemBitmaps(pPopupMenu->m_hMenu, i + ID_CAMERA_FIRST, MF_BYCOMMAND, NULL, hbmMenuDot); SetMenuItemBitmaps(pMainMenu->m_hMenu, i + ID_CAMERA_FIRST, MF_BYCOMMAND, NULL, hbmMenuDot); } } } // Update the list of cameras void SystemUpdateCameraMenu(Camera* pCamera) { CMenu* Menu = GetMainMenu(2); if (!Menu) return; CBMPMenu* pMainMenu = (CBMPMenu*)Menu->GetSubMenu(13); CMenu* pPopupMenu = menuPopups.GetSubMenu(1)->GetSubMenu(3); Camera* pFirst = pCamera; int i; while (pMainMenu->GetMenuItemCount()) pMainMenu->DeleteMenu(0, MF_BYPOSITION); while (pPopupMenu->GetMenuItemCount()) pPopupMenu->DeleteMenu(0, MF_BYPOSITION); for (i = 0; pCamera; i++, pCamera = pCamera->m_pNext) if (i > 6) { pMainMenu->AppendODMenu(pCamera->GetName(), MF_ENABLED, i + ID_CAMERA_FIRST); pPopupMenu->AppendMenu(MF_STRING, i + ID_CAMERA_FIRST, pCamera->GetName()); } if (i > 7) { pMainMenu->AppendODMenu("", MF_SEPARATOR); pPopupMenu->AppendMenu(MF_SEPARATOR); } pCamera = pFirst; for (i = 0; pCamera && (i < 7); i++, pCamera = pCamera->m_pNext) { pMainMenu->AppendODMenu(pCamera->GetName(), MF_ENABLED, i + ID_CAMERA_FIRST); pPopupMenu->AppendMenu(MF_STRING, i + ID_CAMERA_FIRST, pCamera->GetName()); pMainMenu->ChangeMenuItemShortcut("str", i + ID_CAMERA_FIRST); } pMainMenu->AppendODMenu("", MF_SEPARATOR); pPopupMenu->AppendMenu(MF_SEPARATOR); pMainMenu->AppendODMenu("Reset", MF_ENABLED, ID_VIEW_CAMERAS_RESET); pPopupMenu->AppendMenu(MF_STRING, ID_VIEW_CAMERAS_RESET, "Reset"); // pMainMenu->AppendODMenu("Adjust...\t", MF_ENABLED, ID_VIEW_VIEWPOINT); // pPopupMenu->AppendODMenu("Adjust...\t", MF_ENABLED, ID_VIEW_VIEWPOINT); ((CMainFrame*)AfxGetMainWnd())->UpdateMenuAccelerators(); } void SystemUpdateCategories(bool SearchOnly) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CPiecesBar* pBar = (CPiecesBar*)pFrame->GetControlBar(ID_VIEW_PIECES_BAR); pBar->UpdatePiecesTree(SearchOnly); } extern UINT AFXAPI AfxGetFileTitle(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax); extern UINT AFXAPI AfxGetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax); ///////////////////////////////////////////////////////////////////////////// // lpszCanon = C:\MYAPP\DEBUGS\C\TESWIN.C // // cchMax b Result // ------ - --------- // 1- 7 F // 1- 7 T TESWIN.C // 8-14 x TESWIN.C // 15-16 x C:\...\TESWIN.C // 17-23 x C:\...\C\TESWIN.C // 24-25 x C:\...\DEBUGS\C\TESWIN.C // 26+ x C:\MYAPP\DEBUGS\C\TESWIN.C #ifndef _MAC static void AbbreviateName(LPTSTR lpszCanon, int cchMax, BOOL bAtLeastName) { int cchFullPath, cchFileName, cchVolName; const TCHAR* lpszCur; const TCHAR* lpszBase; const TCHAR* lpszFileName; lpszBase = lpszCanon; cchFullPath = lstrlen(lpszCanon); cchFileName = AfxGetFileName(lpszCanon, NULL, 0) - 1; lpszFileName = lpszBase + (cchFullPath-cchFileName); // If cchMax is more than enough to hold the full path name, we're done. // This is probably a pretty common case, so we'll put it first. if (cchMax >= cchFullPath) return; // If cchMax isn't enough to hold at least the basename, we're done if (cchMax < cchFileName) { lstrcpy(lpszCanon, (bAtLeastName) ? lpszFileName : _T("")); return; } // Calculate the length of the volume name. Normally, this is two characters // (e.g., "C:", "D:", etc.), but for a UNC name, it could be more (e.g., // "\\server\share"). // // If cchMax isn't enough to hold at least \...\, the // result is the base filename. lpszCur = lpszBase + 2; // Skip "C:" or leading "\\" if (lpszBase[0] == '\\' && lpszBase[1] == '\\') // UNC pathname { // First skip to the '\' between the server name and the share name, while (*lpszCur != '\\') { lpszCur = _tcsinc(lpszCur); ASSERT(*lpszCur != '\0'); } } // if a UNC get the share name, if a drive get at least one directory ASSERT(*lpszCur == '\\'); // make sure there is another directory, not just c:\filename.ext if (cchFullPath - cchFileName > 3) { lpszCur = _tcsinc(lpszCur); while (*lpszCur != '\\') { lpszCur = _tcsinc(lpszCur); ASSERT(*lpszCur != '\0'); } } ASSERT(*lpszCur == '\\'); cchVolName = lpszCur - lpszBase; if (cchMax < cchVolName + 5 + cchFileName) { lstrcpy(lpszCanon, lpszFileName); return; } // Now loop through the remaining directory components until something // of the form \...\\ fits. // // Assert that the whole filename doesn't fit -- this should have been // handled earlier. ASSERT(cchVolName + (int)lstrlen(lpszCur) > cchMax); while (cchVolName + 4 + (int)lstrlen(lpszCur) > cchMax) { do { lpszCur = _tcsinc(lpszCur); ASSERT(*lpszCur != '\0'); } while (*lpszCur != '\\'); } // Form the resultant string and we're done. lpszCanon[cchVolName] = '\0'; lstrcat(lpszCanon, _T("\\...")); lstrcat(lpszCanon, lpszCur); } #endif static BOOL GetDisplayName(char* filename, CString& strName, LPCTSTR lpszCurDir, int nCurDir, BOOL bAtLeastName) { LPTSTR lpch = strName.GetBuffer(_MAX_PATH); #ifndef _MAC lstrcpy(lpch, filename); // nLenDir is the length of the directory part of the full path int nLenDir = lstrlen(lpch) - (AfxGetFileName(lpch, NULL, 0) - 1); BOOL bSameDir = FALSE; if (nLenDir == nCurDir) { TCHAR chSave = lpch[nLenDir]; lpch[nCurDir] = 0; // terminate at same location as current dir bSameDir = lstrcmpi(lpszCurDir, lpch) == 0; lpch[nLenDir] = chSave; } // copy the full path, otherwise abbreviate the name if (bSameDir) { // copy file name only since directories are same char szTemp[_MAX_PATH]; AfxGetFileTitle(lpch+nCurDir, szTemp, sizeof(szTemp)); lstrcpyn(lpch, szTemp, _MAX_PATH); } else { // strip the extension if the system calls for it char szTemp[_MAX_PATH]; AfxGetFileTitle(lpch+nLenDir, szTemp, sizeof(szTemp)); lstrcpyn(lpch+nLenDir, szTemp, _MAX_PATH-nLenDir); // abbreviate name based on what will fit in limited space AbbreviateName(lpch, 30, bAtLeastName); } #else // for Mac just show the file title name without path AfxGetFileTitle(filename, lpch, _MAX_PATH); #endif strName.ReleaseBuffer(); return TRUE; } void SystemUpdateRecentMenu(char names[4][LC_MAXPATH]) { CBMPMenu* pMenu = (CBMPMenu*)GetMainMenu(0); if (!pMenu) return; UINT nState; pMenu->DeleteMenu(ID_FILE_MRU_FILE2, MF_BYCOMMAND); pMenu->DeleteMenu(ID_FILE_MRU_FILE3, MF_BYCOMMAND); pMenu->DeleteMenu(ID_FILE_MRU_FILE4, MF_BYCOMMAND); if (strlen(names[0]) == 0) { nState = pMenu->GetMenuState(ID_FILE_MRU_FILE1, MF_BYCOMMAND); nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR); pMenu->ModifyMenu(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_STRING | nState, ID_FILE_MRU_FILE1, "Recent File"); pMenu->EnableMenuItem(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); return; } #ifndef _MAC TCHAR szCurDir[_MAX_PATH]; GetCurrentDirectory(_MAX_PATH, szCurDir); int nCurDir = lstrlen(szCurDir); ASSERT(nCurDir >= 0); szCurDir[nCurDir] = '\\'; szCurDir[++nCurDir] = '\0'; #endif CString strName; CString strTemp; for (int i = 0; i < 4; i++) { if (strlen(names[i]) == 0) break; if (!GetDisplayName(names[i], strName, szCurDir, nCurDir, TRUE)) break; // double up any '&' characters so they are not underlined LPCTSTR lpszSrc = strName; LPTSTR lpszDest = strTemp.GetBuffer(strName.GetLength()*2); while (*lpszSrc != 0) { if (*lpszSrc == '&') *lpszDest++ = '&'; if (_istlead(*lpszSrc)) *lpszDest++ = *lpszSrc++; *lpszDest++ = *lpszSrc++; } *lpszDest = 0; strTemp.ReleaseBuffer(); // insert mnemonic + the file name char buf[200]; sprintf(buf, "&%d %s", i+1, strTemp); if (i != 0) { UINT x = pMenu->GetMenuItemCount() - 2; pMenu->InsertMenu(x, MF_BYPOSITION|MF_STRING, ID_FILE_MRU_FILE1 + i, buf); } else { nState = pMenu->GetMenuState(ID_FILE_MRU_FILE1, MF_BYCOMMAND); nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR); pMenu->ModifyMenu(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_STRING | nState, ID_FILE_MRU_FILE1 + i, buf); pMenu->EnableMenuItem(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_ENABLED); } } } // if x = -1, get cursor pos void SystemDoPopupMenu(int nMenu, int x, int y) { CMenu* pPopup; POINT pt; if (x != -1) { pt.x = x; pt.y = y; } else GetCursorPos(&pt); pPopup = menuPopups.GetSubMenu(nMenu); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, AfxGetMainWnd()); } // Private MFC function only sets the title if it's different extern void AFXAPI AfxSetWindowText(HWND, LPCTSTR); void SystemSetWindowCaption(char* caption) { if (!AfxGetMainWnd()) return; AfxSetWindowText(AfxGetMainWnd()->m_hWnd, caption); } int SystemDoMessageBox(char* prompt, int nMode) { return AfxMessageBox(prompt, nMode); } int Sys_MessageBox (const char* text, const char* caption, int type) { return AfxMessageBox(text, type); } extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn); bool SystemDoDialog(int nMode, void* param) { switch (nMode) { case LC_DLG_FILE_OPEN_PROJECT: { CFileDialog dlg(TRUE, "*.lcd", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "LeoCAD Projects (*.lcd)|*.lcd|LDraw Files (*.dat;*.ldr;*.mpd)|*.dat;*.ldr;*.mpd|All Files (*.*)|*.*||", AfxGetMainWnd()); dlg.m_ofn.Flags |= (OFN_ENABLETEMPLATE|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_ENABLEHOOK|OFN_EXPLORER); dlg.m_ofn.hInstance = AfxGetInstanceHandle(); dlg.m_ofn.lpfnHook = OFNOpenHookProc; dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENDLG_TEMPLATE); char *defdir = (char*)param; if (strlen(defdir)) dlg.m_ofn.lpstrInitialDir = defdir; if (dlg.DoModal() == IDOK) { char szFullPath[LC_MAXPATH]; AfxFullPath(szFullPath, dlg.GetPathName()); strcpy((char*)param, szFullPath); return true; } } break; case LC_DLG_FILE_SAVE_PROJECT: { CFileDialog dlg(FALSE, "*.lcd", (char*)param, OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE, "LeoCAD Projects (*.lcd)|*.lcd|LDraw Files (*.dat;*.ldr)|*.dat;*.ldr|All Files (*.*)|*.*||"); dlg.m_ofn.lpfnHook = OFNSaveHookProc; dlg.m_ofn.hInstance = AfxGetInstanceHandle(); dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEDLG_TEMPLATE); if (dlg.DoModal() == IDOK) { char szFullPath[LC_MAXPATH]; AfxFullPath(szFullPath, dlg.GetPathName()); strcpy((char*)param, szFullPath); return true; } } break; case LC_DLG_FILE_MERGE_PROJECT: { CFileDialog dlg(TRUE, "*.lcd", NULL, OFN_HIDEREADONLY|OFN_ENABLETEMPLATE|OFN_FILEMUSTEXIST|OFN_ENABLEHOOK|OFN_EXPLORER, "LeoCAD Projects (*.lcd)|*.lcd|All Files (*.*)|*.*||", AfxGetMainWnd()); dlg.m_ofn.hInstance = AfxGetInstanceHandle(); dlg.m_ofn.lpfnHook = OFNOpenHookProc; dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENDLG_TEMPLATE); dlg.m_ofn.lpstrTitle = "Merge"; char *defdir = (char*)param; if (strlen(defdir)) dlg.m_ofn.lpstrInitialDir = defdir; if (dlg.DoModal() == IDOK) { strcpy((char*)param, dlg.GetPathName()); return true; } } break; case LC_DLG_FILE_OPEN: { LC_FILEOPENDLG_OPTS* opts = (LC_FILEOPENDLG_OPTS*)param; if (opts->type == LC_FILEOPENDLG_DAT) { CString filename; CFileDialog dlg(TRUE, ".dat\0", NULL,OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, "LDraw Files (*.dat)|*.dat|All Files (*.*)|*.*||",NULL); dlg.m_ofn.lpstrFile = filename.GetBuffer(_MAX_PATH * 32); dlg.m_ofn.nMaxFile = _MAX_PATH; dlg.m_ofn.lpstrInitialDir = opts->path; if (dlg.DoModal() == IDOK) { POSITION pos = dlg.GetStartPosition (); int count = 0; while (pos != NULL) { dlg.GetNextPathName (pos); count++; } opts->filenames = (char**)malloc(count*sizeof(char*)); opts->numfiles = count; pos = dlg.GetStartPosition (); count = 0; while (pos != NULL) { CString str = dlg.GetNextPathName (pos); opts->filenames[count] = (char*)malloc(LC_MAXPATH); strcpy (opts->filenames[count], str); count++; } // Get the file path. strcpy (opts->path, opts->filenames[0]); if (strlen (opts->path) > 0) { char* ptr = strrchr(opts->path, '/'); if (ptr == NULL) ptr = strrchr(opts->path, '\\'); if (ptr) { ptr++; *ptr = 0; } } return true; } return false; } else { const char *ext, *filter; if (opts->type == LC_FILEOPENDLG_LCF) { ext = ".lcf\0"; filter = "LeoCAD Category Files (*.lcf)|*.lcf|All Files (*.*)|*.*||"; } else { ext = ".lup\0"; filter = "LeoCAD Library Updates (*.lup)|*.lup|All Files (*.*)|*.*||"; } CFileDialog dlg(TRUE, ext, NULL,OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, NULL); if (dlg.DoModal() == IDOK) { opts->numfiles = 1; opts->filenames = (char**)malloc(LC_MAXPATH); strcpy((char*)opts->filenames, dlg.GetPathName ()); // Get the file path. strcpy(opts->path, (char*)opts->filenames); if (strlen (opts->path) > 0) { char* ptr = strrchr(opts->path, '/'); if (ptr == NULL) ptr = strrchr(opts->path, '\\'); if (ptr) { ptr++; *ptr = 0; } } return true; } return false; } } break; case LC_DLG_FILE_SAVE: { LC_FILESAVEDLG_OPTS* opts = (LC_FILESAVEDLG_OPTS*)param; if (opts->type == LC_FILESAVEDLG_LCF) { CFileDialog dlg(FALSE, ".lcf", NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "LeoCAD Category Files (*.lcf)|*.lcf|All Files (*.*)|*.*||", NULL); if (dlg.DoModal() == IDOK) { strcpy(opts->path, dlg.GetPathName ()); return true; } } return false; } break; case LC_DLG_PICTURE_SAVE: { CFileDialog dlg(FALSE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE|OFN_EXPLORER, "GIF Files (*.gif)|*.gif|JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png|AVI Files (*.avi)|*.avi|All Files (*.*)|*.*||"); DWORD dwImage = theApp.GetProfileInt ("Default", "Image Options", 1|LC_IMAGE_TRANSPARENT); LC_IMAGEDLG_OPTS* opts = (LC_IMAGEDLG_OPTS*)param; opts->width = theApp.GetProfileInt("Default", "Image Width", GetSystemMetrics(SM_CXSCREEN)); opts->height = theApp.GetProfileInt("Default", "Image Height", GetSystemMetrics(SM_CYSCREEN)); opts->imopts.quality = theApp.GetProfileInt("Default", "JPEG Quality", 70); opts->imopts.interlaced = (dwImage & LC_IMAGE_PROGRESSIVE) != 0; opts->imopts.transparent = (dwImage & LC_IMAGE_TRANSPARENT) != 0; opts->imopts.truecolor = (dwImage & LC_IMAGE_HIGHCOLOR) != 0; opts->imopts.pause = (float)theApp.GetProfileInt("Default", "AVI Pause", 100)/100; opts->imopts.format = (unsigned char)(dwImage & ~(LC_IMAGE_MASK)); dlg.m_ofn.hInstance = AfxGetInstanceHandle(); dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEPICTUREDLG_TEMPLATE); dlg.m_ofn.lpfnHook = OFNSavePictureHookProc; dlg.m_ofn.lCustData= (LONG)opts; if (dlg.DoModal() == IDOK) { strcpy(opts->filename, (LPCSTR)dlg.GetPathName()); char ext[5]; if (strlen(opts->filename) == 0) return false; char *p = strrchr(opts->filename, '.'); if (p != NULL) { strcpy(ext, p+1); strlwr(ext); if ((strcmp(ext, "jpg") == 0) || (strcmp(ext, "jpeg") == 0) || (strcmp(ext, "bmp") == 0) || (strcmp(ext, "gif") == 0) || (strcmp(ext, "png") == 0) || (strcmp(ext, "avi") == 0)) return true; } switch (opts->imopts.format) { case LC_IMAGE_BMP: strcat(opts->filename, ".bmp"); break; case LC_IMAGE_GIF: strcat(opts->filename, ".gif"); break; case LC_IMAGE_JPG: strcat(opts->filename, ".jpg"); break; case LC_IMAGE_PNG: strcat(opts->filename, ".png"); break; case LC_IMAGE_AVI: strcat(opts->filename, ".avi"); break; } return true; } } break; case LC_DLG_HTML: { LC_HTMLDLG_OPTS* opts = (LC_HTMLDLG_OPTS*)param; CHTMLDlg dlg(&opts->imdlg); dlg.m_nLayout = opts->singlepage ? 0 : 1; dlg.m_bIndex = opts->index; dlg.m_bImages = opts->images; dlg.m_bListEnd = opts->listend; dlg.m_bListStep = opts->liststep; dlg.m_bHighlight = opts->highlight; dlg.m_bHtmlExt = opts->htmlext; if (dlg.DoModal() == IDOK) { strcpy(opts->path, dlg.m_strFolder); opts->singlepage = (dlg.m_nLayout == 0); opts->index = dlg.m_bIndex == TRUE; opts->images = dlg.m_bImages == TRUE; opts->listend = dlg.m_bListEnd == TRUE; opts->liststep = dlg.m_bListStep == TRUE; opts->highlight = dlg.m_bHighlight == TRUE; opts->htmlext = dlg.m_bHtmlExt == TRUE; return true; } } break; case LC_DLG_POVRAY: { CPOVDlg dlg; if (dlg.DoModal() == IDOK) { LC_POVRAYDLG_OPTS* opts = (LC_POVRAYDLG_OPTS*)param; opts->render = dlg.m_bRender != 0; strcpy(opts->povpath, dlg.m_strPOV); strcpy(opts->outpath, dlg.m_strOut); strcpy(opts->libpath, dlg.m_strLGEO); return true; } } break; case LC_DLG_WAVEFRONT: { CFileDialog dlg(FALSE, "*.obj", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Wavefront Files (*.obj)|*.obj|All Files (*.*)|*.*||", AfxGetMainWnd()); if (dlg.DoModal() == IDOK) { strcpy((char*)param, dlg.GetPathName()); return true; } } break; case LC_DLG_MINIFIG: { CMinifigDlg dlg(param); if (dlg.DoModal() == IDOK) return true; } break; case LC_DLG_ARRAY: { CArrayDlg dlg; if (dlg.DoModal() == IDOK) { LC_ARRAYDLG_OPTS* opts = (LC_ARRAYDLG_OPTS*)param; opts->n1DCount = dlg.m_n1DCount; opts->n2DCount = dlg.m_n2DCount; opts->n3DCount = dlg.m_n3DCount; opts->f2D[0] = dlg.m_f2DX; opts->f2D[1] = dlg.m_f2DY; opts->f2D[2] = dlg.m_f2DZ; opts->f3D[0] = dlg.m_f3DX; opts->f3D[1] = dlg.m_f3DY; opts->f3D[2] = dlg.m_f3DZ; opts->fMove[0] = dlg.m_fMoveX; opts->fMove[1] = dlg.m_fMoveY; opts->fMove[2] = dlg.m_fMoveZ; opts->fRotate[0] = dlg.m_fRotateX; opts->fRotate[1] = dlg.m_fRotateY; opts->fRotate[2] = dlg.m_fRotateZ; opts->nArrayDimension = dlg.m_nArrayDimension; return true; } } break; case LC_DLG_PREFERENCES: { CPreferencesSheet ps; LC_PREFERENCESDLG_OPTS* opts = (LC_PREFERENCESDLG_OPTS*)param; ps.m_PageGeneral.SetOptions(opts->nSaveInterval, opts->nMouse, opts->strPath, opts->strUser); ps.m_PageDetail.SetOptions(opts->nDetail, opts->fLineWidth); ps.m_PageDrawing.SetOptions(opts->nSnap, opts->nAngleSnap, opts->nGridSize); ps.m_PageScene.SetOptions(opts->nScene, opts->fDensity, opts->strBackground, opts->fBackground, opts->fFog, opts->fAmbient, opts->fGrad1, opts->fGrad2); ps.m_PagePrint.SetOptions(opts->strHeader, opts->strFooter); ps.m_PageKeyboard.SetOptions(); if (ps.DoModal() == IDOK) { ps.m_PageGeneral.GetOptions(&opts->nSaveInterval, &opts->nMouse, opts->strPath, opts->strUser); ps.m_PageDetail.GetOptions(&opts->nDetail, &opts->fLineWidth); ps.m_PageDrawing.GetOptions(&opts->nSnap, &opts->nAngleSnap, &opts->nGridSize); ps.m_PageScene.GetOptions(&opts->nScene, &opts->fDensity, opts->strBackground, opts->fBackground, opts->fFog, opts->fAmbient, opts->fGrad1, opts->fGrad2); ps.m_PagePrint.GetOptions(opts->strHeader, opts->strFooter); ps.m_PageKeyboard.GetOptions(); AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_SETTINGS); AfxGetApp()->WriteProfileInt("Settings", "Autosave", opts->nSaveInterval); AfxGetApp()->WriteProfileInt("Default", "Mouse", opts->nMouse); AfxGetApp()->WriteProfileString("Default", "Projects", opts->strPath); return true; } } break; case LC_DLG_PROPERTIES: { CPropertiesSheet ps; LC_PROPERTIESDLG_OPTS* opts = (LC_PROPERTIESDLG_OPTS*)param; ps.SetTitle(opts->strTitle, PSH_PROPTITLE); ps.m_PageSummary.m_strAuthor = opts->strAuthor; ps.m_PageSummary.m_strDescription = opts->strDescription; ps.m_PageSummary.m_strComments = opts->strComments; ps.m_PageGeneral.m_strFilename = opts->strFilename; ps.m_PagePieces.names = opts->names; ps.m_PagePieces.count = opts->count; ps.m_PagePieces.lines = opts->lines; if (ps.DoModal() == IDOK) { strcpy(opts->strAuthor, ps.m_PageSummary.m_strAuthor); strcpy(opts->strDescription, ps.m_PageSummary.m_strDescription); strcpy(opts->strComments, ps.m_PageSummary.m_strComments); return true; } } break; case LC_DLG_TERRAIN: { CTerrainDlg dlg((Terrain*)param, false); if (dlg.DoModal() == IDOK) return true; } break; case LC_DLG_LIBRARY: { CLibraryDlg dlg; dlg.DoModal(); CPiecesBar* pBar = (CPiecesBar*)((CFrameWnd*)AfxGetMainWnd())->GetControlBar(ID_VIEW_PIECES_BAR); pBar->UpdatePiecesTree(false); return true; } break; case LC_DLG_SELECTBYNAME: { CSelectDlg dlg(param); if (dlg.DoModal() == IDOK) return true; } break; case LC_DLG_STEPCHOOSE: { if (StepModeless == NULL) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); CView* pView = pFrame->GetActiveView(); StepModeless = new CStepDlg(&StepModeless, pView); StepModeless->Create(IDD_STEP, pView); int t, l; char buf[30]; strcpy (buf, theApp.GetProfileString("Settings", "Step Dialog")); if (sscanf(buf, "%d, %d", &t, &l) == 2) { CRect rc; StepModeless->GetWindowRect(&rc); StepModeless->SetWindowPos(NULL, min(l, GetSystemMetrics(SM_CXSCREEN)-rc.Width()), min(t, GetSystemMetrics(SM_CYSCREEN)-rc.Height()), 0, 0, SWP_NOZORDER|SWP_NOSIZE); } StepModeless->ShowWindow(SW_SHOW); } else StepModeless->SetActiveWindow(); } break; case LC_DLG_EDITGROUPS: { CEditGroupsDlg dlg((LC_GROUPEDITDLG_OPTS*)param); if (dlg.DoModal() == IDOK) return true; } break; case LC_DLG_GROUP: { CGroupDlg dlg; dlg.m_strName = (char*)param; if (dlg.DoModal() == IDOK) { strcpy((char*)param, dlg.m_strName); return true; } } break; case LC_DLG_EDITCATEGORY: { CCategoryDlg Dlg; LC_CATEGORYDLG_OPTS* Opts = (LC_CATEGORYDLG_OPTS*)param; Dlg.m_Keywords = Opts->Keywords; Dlg.m_Name = Opts->Name; if (Dlg.DoModal() == IDOK) { Opts->Keywords = Dlg.m_Keywords; Opts->Name = Dlg.m_Name; return true; } } break; case LC_DLG_ABOUT: { CAboutDlg dlg; dlg.m_hViewDC = pfnwglGetCurrentDC(); dlg.DoModal(); } break; } return false; } ///////////////////////////////////////////////////////////////////////////// // Memory rendering functions typedef struct { HDC hdc; HDC oldhdc; HGLRC hrc; HGLRC oldhrc; HBITMAP hbm; HBITMAP oldhbm; } LC_RENDER; void* Sys_StartMemoryRender(int width, int height) { LC_RENDER* render = (LC_RENDER*)malloc(sizeof(LC_RENDER)); CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); CView* pView = pFrame->GetActiveView(); CDC* pDC = pView->GetDC(); render->oldhdc = pfnwglGetCurrentDC(); render->oldhrc = pfnwglGetCurrentContext(); render->hdc = CreateCompatibleDC(pDC->m_hDC); // Preparing bitmap header for DIB section BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = width; bi.bmiHeader.biHeight = height; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = width * height * 3; bi.bmiHeader.biXPelsPerMeter = 2925; bi.bmiHeader.biYPelsPerMeter = 2925; // Creating a DIB surface LPVOID lpBits; render->hbm = CreateDIBSection(pDC->GetSafeHdc(), &bi, DIB_RGB_COLORS, (void**)&lpBits, NULL, (DWORD)0); render->oldhbm = (HBITMAP)::SelectObject(render->hdc, render->hbm); PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_BITMAP|PFD_SUPPORT_OPENGL, 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(render->hdc, &pfd); OpenGLDescribePixelFormat(render->hdc, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); OpenGLSetPixelFormat(render->hdc, pixelformat, &pfd); render->hrc = pfnwglCreateContext(render->hdc); pfnwglMakeCurrent(render->hdc, render->hrc); return render; } void Sys_FinishMemoryRender(void* param) { LC_RENDER* render = (LC_RENDER*)param; pfnwglMakeCurrent (render->oldhdc, render->oldhrc); pfnwglDeleteContext(render->hrc); SelectObject(render->hdc, render->oldhbm); DeleteObject(render->hbm); DeleteDC(render->hdc); free(render); } ///////////////////////////////////////////////////////////////////////////// // Main window functions void SystemPieceComboAdd(char* name) { CWnd* pWnd = AfxGetMainWnd(); if (pWnd != NULL) pWnd->PostMessage(WM_LC_ADD_COMBO_STRING, (LPARAM)name); } void SystemCaptureMouse() { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); CView* pView = pFrame->GetActiveView(); pView->SetCapture(); } void SystemReleaseMouse() { ReleaseCapture(); } void SystemExportClipboard(File* clip) { if (clip == NULL) return; HGLOBAL hData = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, clip->GetLength()); void* lpBuffer = GlobalLock(hData); clip->Seek(0, SEEK_SET); clip->Read(lpBuffer, clip->GetLength()); GlobalUnlock(hData); if (OpenClipboard(NULL)) { SetClipboardData(ClipboardFormat, hData); CloseClipboard(); } // else // AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD); } File* SystemImportClipboard() { File* clip = NULL; if (ClipboardFormat != 0) if (OpenClipboard(NULL)) { HANDLE hData = ::GetClipboardData(ClipboardFormat); if (hData != NULL) { clip = new FileMem(); BYTE* lpBuffer = (BYTE*)::GlobalLock(hData); long nBufferSize = ::GlobalSize(hData); clip->Write(lpBuffer, nBufferSize); GlobalUnlock(hData); } // else // AfxMessageBox(IDS_CANNOT_GET_CLIPBOARD_DATA); CloseClipboard(); } // else // AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD); return clip; } bool Sys_KeyDown (int key) { return GetKeyState (KEY_CONTROL) < 0; } void SystemPumpMessages() { MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } long SystemGetTicks() { return GetTickCount(); } void SystemStartProgressBar(int nLower, int nUpper, int nStep, const char* Text) { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CCADStatusBar* pStatusBar = (CCADStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR); pStatusBar->ShowProgressBar(TRUE); pStatusBar->SetProgressBarRange(nLower, nUpper); pStatusBar->SetProgressBarStep(nStep); pStatusBar->SetProgressBarPos(0); ((CMainFrame*)AfxGetMainWnd())->SetStatusBarMessage(Text); ((CMainFrame*)AfxGetMainWnd())->SetMessageText(Text); } void SytemEndProgressBar() { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CCADStatusBar* pStatusBar = (CCADStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR); pStatusBar->ShowProgressBar(FALSE); ((CMainFrame*)AfxGetMainWnd())->SetStatusBarMessage(""); ((CMainFrame*)AfxGetMainWnd())->SetMessageText(AFX_IDS_IDLEMESSAGE); } void SytemStepProgressBar() { CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd(); if (!pFrame) return; CCADStatusBar* pStatusBar = (CCADStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR); pStatusBar->StepProgressBar(); }