// pbrush.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "global.h" #include "pbrush.h" #include "pbrusfrm.h" #include "ipframe.h" #include "pbrusdoc.h" #include "pbrusvw.h" #include "bmobject.h" #include "imgsuprt.h" #include "imgwnd.h" #include "imgwell.h" #include "imgtools.h" #include "ferr.h" #include "cmpmsg.h" #include "settings.h" #include "undo.h" #include "colorsrc.h" #include "printres.h" #include "loadimag.h" #include #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #include "memtrace.h" BOOL NEAR g_bShowAllFiles = FALSE; /***************************************************************************/ // CPBApp BEGIN_MESSAGE_MAP(CPBApp, CWinApp) //{{AFX_MSG_MAP(CPBApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP // Standard file based document commands ON_COMMAND(ID_FILE_NEW, OnFileNew) ON_COMMAND(ID_FILE_OPEN, OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() /***************************************************************************/ // CPBApp construction CPBApp::CPBApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance #ifdef _DEBUG m_bLogUndo = FALSE; #endif // This is the minimum amount of free memory we like to have // (NOTE: These are overwritten by ReadInitFile) m_dwLowMemoryBytes = 1024L * 2200; m_nLowGdiPercent = 10; m_nLowUserPercent = 10; m_nFileErrorCause = 0; // from CFileException::m_cause m_wEmergencyFlags = 0; m_tickLastWarning = 0; m_iCurrentUnits = 0; m_bShowStatusbar = TRUE; m_bShowThumbnail = FALSE; m_bShowTextToolbar = TRUE; m_bShowIconToolbar = TRUE; m_bThumbnailDocked = TRUE; m_bEmbedded = FALSE; m_bLinked = FALSE; m_bHidden = FALSE; m_bActiveApp = FALSE; m_bPenSystem = FALSE; m_bPaletted = FALSE; m_pPalette = NULL; m_bPrintOnly = FALSE; #ifdef PCX_SUPPORT m_bPCXfile = FALSE; #endif m_rectFloatThumbnail.SetRectEmpty(); m_rectDockThumbnail.SetRectEmpty(); m_rectMargins.SetRect(MARGINS_DEFAULT, MARGINS_DEFAULT, MARGINS_DEFAULT, MARGINS_DEFAULT); m_pwndInPlaceFrame = NULL; m_hwndInPlaceApp = NULL; m_pColors = NULL; m_iColors = 0; for (int index = 0; index < nSysBrushes + nOurBrushes; index++) m_pbrSysColors[index] = NULL; } /***************************************************************************/ // The one and only CPBApp object CPBApp NEAR theApp; // This identifier was generated to be statistically unique for your app. // You may change it if you prefer to choose a specific identifier. const CLSID BASED_CODE CLSID_Paint = { 0xd3e34b21, 0x9d75, 0x101a, { 0x8c, 0x3d, 0x0, 0xaa, 0x0, 0x1a, 0x16, 0x52 } }; const CLSID BASED_CODE CLSID_PaintBrush = { 0x0003000A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; /***************************************************************************/ // Stolen from WordPad BOOL MatchOption(LPTSTR lpsz, LPTSTR lpszOption) { if (lpsz[0] == TEXT('-') || lpsz[0] == TEXT('/')) { lpsz++; if (lstrcmpi(lpsz, lpszOption) == 0) return TRUE; } return FALSE; } void CPBApp::ParseCommandLine() { BOOL bPrintTo = FALSE; #ifdef UNICODE int argcw; LPWSTR *argvw; argvw = CommandLineToArgvW (GetCommandLine (), &argcw); #define ARGV argvw #define ARGC argcw #else #define ARGV __argv #define ARGC __argc #endif // start at 1 -- the first is the exe for (int i=1; i< ARGC; i++) { if (MatchOption(ARGV[i], TEXT("pt"))) bPrintTo = m_bPrintOnly = TRUE; else if (MatchOption(ARGV[i], TEXT("p"))) m_bPrintOnly = TRUE; // else if (MatchOption(__argv[i], "t")) // m_bForceTextMode = TRUE; // else if (MatchOption(__argv[i], "Embedding")) // m_bEmbedded = TRUE; // else if (MatchOption(__argv[i], "Automation")) // m_bEmbedded = TRUE; else if (m_strDocName.IsEmpty()) m_strDocName = ARGV[i]; else if (bPrintTo && m_strPrinterName.IsEmpty()) m_strPrinterName = ARGV[i]; else if (bPrintTo && m_strDriverName.IsEmpty()) m_strDriverName = ARGV[i]; else if (bPrintTo && m_strPortName.IsEmpty()) m_strPortName = ARGV[i]; else { ASSERT(FALSE); } } #ifdef UNICODE GlobalFree (argvw); #endif } void GetShortModuleFileName(HINSTANCE hInst, LPTSTR pszName, UINT uLen) { TCHAR szLongName[_MAX_PATH]; GetModuleFileName(hInst, szLongName, _MAX_PATH); #pragma message("GSMFN: Remove this hack!") // BUGBUG: GSPN sometimes fails on UNC's. Try this until that is tracked // down lstrcpyn(pszName, szLongName, uLen); if (!GetShortPathName(szLongName, pszName, uLen)) { GetLastError(); } } void CPBApp::RegisterShell(CSingleDocTemplate *pDocTemplate) { const struct { LPCTSTR pszActionID; LPCTSTR pszCommand; } aActions[] = { { TEXT("Open") , TEXT("\"%s\" \"%%1\"") }, { TEXT("Print") , TEXT("\"%s\" /p \"%%1\"") }, { TEXT("PrintTo"), TEXT("\"%s\" /pt \"%%1\" \"%%2\" \"%%3\" \"%%4\"") }, } ; // We now need quotes around the file name, and MFC doesn't do this CString strTypeID; if (!pDocTemplate->GetDocString(strTypeID, CDocTemplate::regFileTypeId)) { return; } strTypeID += TEXT("\\shell"); CRegKey rkShellInfo(HKEY_CLASSES_ROOT, strTypeID); if (!(HKEY)rkShellInfo) { return; } TCHAR szFile[MAX_PATH]; ::GetShortModuleFileName(AfxGetInstanceHandle(), szFile, ARRAYSIZE(szFile)); int i; for (i=0; iGetColorCount()) { theApp.SetMemoryEmergency(); return -1; } } // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views. CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( ID_MAINFRAME, RUNTIME_CLASS( CPBDoc ), RUNTIME_CLASS( CPBFrame ), // main SDI frame window RUNTIME_CLASS( CPBView ) ); pDocTemplate->SetServerInfo( IDR_SRVR_EMBEDDED, IDR_SRVR_INPLACE, RUNTIME_CLASS( CInPlaceFrame ), RUNTIME_CLASS( CPBView ) ); AddDocTemplate( pDocTemplate ); // Connect the COleTemplateServer to the document template. // The COleTemplateServer creates new documents on behalf // of requesting OLE containers by using information // specified in the document template. m_server.ConnectTemplate( CLSID_Paint, pDocTemplate, TRUE ); // Note: SDI applications register server objects only if /Embedding // or /Automation is present on the command line. RegisterShell(pDocTemplate); m_bEmbedded = RunEmbedded(); // Parse the command line to see if launched as OLE server if (m_bEmbedded || RunAutomated()) { // Register all OLE server (factories) as running. This enables the // OLE 2.0 libraries to create objects from other applications. COleTemplateServer::RegisterAll(); // Application was run with /Embedding or /Automation. Don't show the // main window in this case. return TRUE; } // When a server application is launched stand-alone, it is a good idea // to update the system registry in case it has been damaged. m_server.UpdateRegistry( OAT_INPLACE_SERVER ); ParseCommandLine(); // simple command line parsing if (m_strDocName.IsEmpty()) { // create a new (empty) document OnFileNew(); } else { CString sExt = GetExtension( m_strDocName ); if (sExt.IsEmpty()) { if (pDocTemplate->GetDocString( sExt, CDocTemplate::filterExt ) && ! sExt.IsEmpty()) m_strDocName += sExt; } WIN32_FIND_DATA finddata; HANDLE hFind = FindFirstFile(m_strDocName, &finddata); if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); // Find the file name and replace it with the long file name int iBS = m_strDocName.ReverseFind(TEXT('\\')); if (iBS == -1) { iBS = m_strDocName.ReverseFind(TEXT(':')); } // HACK: Notice this is correct even if iBS==-1 ++iBS; // Resize the memory string m_strDocName.GetBuffer(iBS); m_strDocName.ReleaseBuffer(iBS); m_strDocName += finddata.cFileName; } OpenDocumentFile( m_strDocName ); } if (m_pMainWnd) m_pMainWnd->DragAcceptFiles(); return TRUE; } /***************************************************************************/ int CPBApp::ExitInstance() { CustomExit(); // clean up in customiz CleanupImages(); if (g_pColors) { delete g_pColors; g_pColors = NULL; } if (m_fntStatus.m_hObject != NULL) m_fntStatus.DeleteObject(); ResetSysBrushes(); CTracker::CleanUpTracker(); // // Work-around MFC bug - delete the tool tips and NULL // them so we don't crash after inplace activation // _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); CToolTipCtrl* pToolTip = pThreadState->m_pToolTip; if (NULL != pToolTip) { pToolTip->DestroyWindow(); delete pToolTip; pThreadState->m_pToolTip = NULL ; } return CWinApp::ExitInstance(); } /***************************************************************************/ void CPBApp::GetSystemSettings( CDC* pdc ) { NONCLIENTMETRICS ncMetrics; ncMetrics.cbSize = sizeof( NONCLIENTMETRICS ); if (SystemParametersInfo( SPI_GETNONCLIENTMETRICS, sizeof( NONCLIENTMETRICS ), &ncMetrics, 0 )) { if (m_fntStatus.m_hObject != NULL) m_fntStatus.DeleteObject(); m_fntStatus.CreateFontIndirect( &ncMetrics.lfMenuFont ); } ScreenDeviceInfo.iWidthinMM = pdc->GetDeviceCaps( HORZSIZE ); ScreenDeviceInfo.iHeightinMM = pdc->GetDeviceCaps( VERTSIZE ); ScreenDeviceInfo.iWidthinPels = pdc->GetDeviceCaps( HORZRES ); ScreenDeviceInfo.iHeightinPels = pdc->GetDeviceCaps( VERTRES ); ScreenDeviceInfo.ixPelsPerINCH = pdc->GetDeviceCaps( LOGPIXELSX ); ScreenDeviceInfo.iyPelsPerINCH = pdc->GetDeviceCaps( LOGPIXELSY ); /* get the pels per decameter '.1' rounded */ ScreenDeviceInfo.ixPelsPerDM = (int)(((((long)ScreenDeviceInfo.iWidthinPels * 1000L) / (long)ScreenDeviceInfo.iWidthinMM ) + 5L) / 10); ScreenDeviceInfo.iyPelsPerDM = (int)(((((long)ScreenDeviceInfo.iHeightinPels * 1000L) / (long)ScreenDeviceInfo.iHeightinMM) + 5L) / 10); ScreenDeviceInfo.ixPelsPerMM = (ScreenDeviceInfo.ixPelsPerDM + 50) / 100; ScreenDeviceInfo.iyPelsPerMM = (ScreenDeviceInfo.iyPelsPerDM + 50) / 100; ScreenDeviceInfo.iWidthinINCH = (int)(((long)ScreenDeviceInfo.iWidthinMM * 100L / 245L + 5L) / 10L); //24.5 mm to the inch ScreenDeviceInfo.iHeightinINCH = (int)(((long)ScreenDeviceInfo.iHeightinMM * 100L / 245L + 5L) / 10L); ScreenDeviceInfo.iBitsPixel = pdc->GetDeviceCaps( BITSPIXEL ); ScreenDeviceInfo.iPlanes = pdc->GetDeviceCaps( PLANES ); m_cxFrame = GetSystemMetrics( SM_CXFRAME ); m_cyFrame = GetSystemMetrics( SM_CYFRAME ); m_cxBorder = GetSystemMetrics( SM_CXBORDER ); m_cyBorder = GetSystemMetrics( SM_CYBORDER ); m_cyCaption = GetSystemMetrics( SM_CYSMCAPTION ); m_bPenSystem = GetSystemMetrics( SM_PENWINDOWS )? TRUE: FALSE; m_bPaletted = (pdc->GetDeviceCaps( RASTERCAPS ) & RC_PALETTE); m_bMonoDevice = ((ScreenDeviceInfo.iBitsPixel * ScreenDeviceInfo.iPlanes) == 1); SetErrorMode( SEM_NOOPENFILEERRORBOX ); } /***************************************************************************/ CPoint CPBApp::CheckWindowPosition( CPoint ptPosition, CSize& sizeWindow ) { CPoint ptNew = ptPosition; sizeWindow.cx = max( sizeWindow.cx, 0 ); sizeWindow.cy = max( sizeWindow.cy, 0 ); if (sizeWindow.cx && sizeWindow.cy) { sizeWindow.cx = min( sizeWindow.cx, ScreenDeviceInfo.iWidthinPels ); sizeWindow.cy = min( sizeWindow.cy, ScreenDeviceInfo.iHeightinPels ); } ptNew.x = max( ptNew.x, 0 ); ptNew.y = max( ptNew.y, 0 ); if (ptNew.x && ptNew.y) { if (ptNew.x >= ScreenDeviceInfo.iWidthinPels) ptNew.x = ScreenDeviceInfo.iWidthinPels - sizeWindow.cx; if (ptNew.y >= ScreenDeviceInfo.iHeightinPels) ptNew.y = ScreenDeviceInfo.iHeightinPels - sizeWindow.cy; } return ptNew; } /***************************************************************************/ void CPBApp::WinHelp( DWORD dwData, UINT nCmd /* = HELP_CONTEXT */ ) { CWinApp::WinHelp( dwData, nCmd ); } /***************************************************************************/ BOOL CPBApp::OnIdle( LONG lCount ) { if (m_bHidden) return CWinApp::OnIdle( lCount ); if (! lCount) { if (CheckForEmergency()) { TryToFreeMemory(); WarnUserOfEmergency(); } if (m_nFileErrorCause != CFileException::none && m_pMainWnd) { CWnd* pWnd = AfxGetMainWnd(); pWnd->PostMessage( WM_USER + 1001 ); } } extern void IdleImage(); IdleImage(); return CWinApp::OnIdle(lCount) || lCount <= 4; } /***************************************************************************/ // Map a file error code to a string id. struct FERRID { int ferr; int ids; } mpidsferr[] = { { ferrIllformedGroup, IDS_ERROR_BOGUSFILE }, { ferrReadFailed, IDS_ERROR_BOGUSFILE }, // error while reading a file or file corupt { ferrIllformedFile, IDS_ERROR_BOGUSFILE }, // not a valid palette file or zero length pcx file { ferrCantProcNewExeHdr, IDS_ERROR_EXE_HDR }, { ferrCantProcOldExeHdr, IDS_ERROR_EXE_HDR }, { ferrBadMagicNewExe, IDS_ERROR_EXE_HDRMZ }, { ferrBadMagicOldExe, IDS_ERROR_EXE_HDRMZ }, { ferrNotWindowsExe, IDS_ERROR_EXE_HDRNW }, { ferrExeWinVer3, IDS_ERROR_EXE_HDRWV }, { ferrNotValidRc, IDS_ERROR_NOTVALID_RC }, { ferrNotValidExe, IDS_ERROR_NOTVALID_EXE }, { ferrNotValidRes, IDS_ERROR_NOTVALID_RES }, { ferrNotValidBmp, IDS_ERROR_NOTVALID_BMP }, // invalid bitmap { ferrNotValidIco, IDS_ERROR_NOTVALID_ICO }, { ferrNotValidCur, IDS_ERROR_NOTVALID_CUR }, { ferrRcInvalidExt, IDS_ERROR_RCPROB }, { ferrFileAlreadyOpen, IDS_ERROR_COMPEX }, { ferrExeTooLarge, IDS_ERROR_EXE_ALIGN }, { ferrCantCopyOldToNew, IDS_ERROR_EXE_SAVE }, { ferrReadLoad, IDS_ERROR_READLOAD }, { ferrExeAlloc, IDS_ERROR_EXE_ALLOC }, { ferrExeInUse, IDS_ERROR_EXE_INUSE }, { ferrExeEmpty, IDS_ERROR_EXE_EMPTY }, { ferrGroup, IDS_ERROR_GROUP }, { ferrResSave, IDS_ERROR_RES_SAVE }, { ferrSaveOverOpen, IDS_ERROR_SAVEOVEROPEN }, { ferrSaveOverReadOnly, IDS_ERROR_SAVERO }, { ferrCantDetermineType, IDS_ERROR_WHAAAT }, // bad pcx file { ferrSameName, IDS_ERROR_SAMENAME }, { ferrSaveAborted, IDS_ERROR_SAVE_ABORTED }, { ferrLooksLikeNtRes, IDS_ERROR_NT_RES }, { ferrCantSaveReadOnly, IDS_ERROR_CANT_SAVERO }, // trying to save over a read only file }; int IdsFromFerr(int ferr) { if (ferr < ferrFirst) return IDS_ERROR_FILE + ferr; // was an exception cause for (int i = 0; i < sizeof (mpidsferr) / sizeof (FERRID); i += 1) { if (mpidsferr[i].ferr == ferr) return mpidsferr[i].ids; } ASSERT(FALSE); // You forgot to stick an entry in the above table! return 0; } /***************************************************************************/ // Display a message box informing the user of a file related exception. // The format of the box is something like: // // // // // // describes what file has the problem, // indicated what kind of thing failed (e.g. "Cannot save file"), and // provides more information about why the operation failed // (e.g. "Disk full"). // // All the parameters must have been setup previously via a call to // CWinApp::SetFileError(). // void CPBApp::FileErrorMessageBox( void ) { static BOOL bInUse = FALSE; if (m_nFileErrorCause != CFileException::none && ! bInUse) { bInUse = TRUE; CString strOperation; VERIFY( strOperation.LoadString( m_uOperation ) ); CString strReason; VERIFY( strReason.LoadString( IdsFromFerr( m_nFileErrorCause ) ) ); TCHAR szMsg[256]; if (m_sLastFile.IsEmpty()) wsprintf( szMsg, TEXT("%s\n%s"), (LPCTSTR)strOperation, (LPCTSTR)strReason ); else wsprintf( szMsg, TEXT("%s\n%s\n%s"), (LPCTSTR)m_sLastFile, (LPCTSTR)strOperation, (LPCTSTR)strReason ); AfxMessageBox( szMsg, MB_TASKMODAL | MB_OK | MB_ICONEXCLAMATION ); bInUse = FALSE; } m_nFileErrorCause = CFileException::none; } /***************************************************************************/ void CPBApp::SetFileError( UINT uOperation, int nCause, LPCTSTR lpszFile ) { m_nFileErrorCause = nCause; m_uOperation = uOperation; if (lpszFile) m_sLastFile = lpszFile; } /***************************************************************************/ // Memory/resource emergency handling functions void CPBApp::SetMemoryEmergency(BOOL bFailed) { TRACE(TEXT("Memory emergency!\n")); m_wEmergencyFlags |= memoryEmergency | warnEmergency; if (bFailed) m_wEmergencyFlags |= failedEmergency; } /***************************************************************************/ void CPBApp::SetGdiEmergency(BOOL bFailed) { TRACE(TEXT("GDI emergency!\n")); m_wEmergencyFlags |= gdiEmergency | warnEmergency; if (bFailed) m_wEmergencyFlags |= failedEmergency; } /***************************************************************************/ void CPBApp::SetUserEmergency(BOOL bFailed) { TRACE(TEXT("USER emergency!\n")); m_wEmergencyFlags |= userEmergency | warnEmergency; if (bFailed) m_wEmergencyFlags |= failedEmergency; } /***************************************************************************/ void CPBApp::WarnUserOfEmergency() { if ((m_wEmergencyFlags & warnEmergency) == 0) { // We have nothing to warn the user about! return; } if ((m_wEmergencyFlags & failedEmergency) == 0 && GetTickCount() < m_tickLastWarning + ticksBetweenWarnings) { // We've warned the user recently, so keep quiet for now... // The warning flag is cleared so we don't just warn the // user after the delay is up unless another emergency // occurs AFTER then... m_wEmergencyFlags &= ~warnEmergency; return; } // Don't go invoking message boxes when we're not the active app! if (! m_bActiveApp) return; const TCHAR* szMsg = (m_wEmergencyFlags & failedEmergency) != 0 ? m_strEmergencyNoMem : m_strEmergencyLowMem; if (AfxMessageBox(szMsg, MB_TASKMODAL | MB_OK | MB_ICONSTOP) == IDOK) { m_wEmergencyFlags &= ~(warnEmergency | failedEmergency); m_tickLastWarning = GetTickCount(); } #ifdef _DEBUG else TRACE(TEXT("Emergency warning message box failed!\n")); #endif // Update status bar warning message... if ( ::IsWindow( ((CPBFrame*)m_pMainWnd)->m_statBar.m_hWnd ) ) ((CPBFrame*)m_pMainWnd)->m_statBar.Invalidate(FALSE); } /***************************************************************************/ void CPBApp::TryToFreeMemory() { // We are in a memory/resource emergency state! Add things to this // function to flush caches and do anything else to free up memory // we don't really need to be using right now... if (m_wEmergencyFlags & memoryEmergency) { CPBDoc* pDoc = (CPBDoc*)((CFrameWnd*)AfxGetMainWnd())->GetActiveDocument(); if (pDoc && pDoc->m_pBitmapObj && ! pDoc->m_pBitmapObj->IsDirty() && pDoc->m_pBitmapObj->m_lpvThing) pDoc->m_pBitmapObj->Free(); } if (m_wEmergencyFlags & gdiEmergency) { // theUndo.Flush(); ResetSysBrushes(); } } /***************************************************************************/ // App command to run the dialog void CPBApp::OnAppAbout() { CString sTitle; CString sBrag; HICON hIcon = LoadIcon( ID_MAINFRAME ); sTitle.LoadString( AFX_IDS_APP_TITLE ); sBrag.LoadString( IDS_PerContractSoDontChange ); ShellAbout( AfxGetMainWnd()->GetSafeHwnd(), sTitle, sBrag, hIcon ); if (hIcon != NULL) ::DestroyIcon( hIcon ); } /***************************************************************************/ void CPBApp::SetDeviceHandles(HANDLE hDevNames, HANDLE hDevMode) { // The old ones should already be freed m_hDevNames = hDevNames; m_hDevMode = hDevMode; } /***************************************************************************/ class CFileOpenSaveDlg : public CFileDialog { public: BOOL m_bOpenFile; CFileOpenSaveDlg( BOOL bOpenFileDialog ); virtual void OnLBSelChangedNotify( UINT nIDBox, UINT iCurSel, UINT nCode ); DECLARE_MESSAGE_MAP() }; /***************************************************************************/ BEGIN_MESSAGE_MAP(CFileOpenSaveDlg, CFileDialog) END_MESSAGE_MAP() /***************************************************************************/ CFileOpenSaveDlg::CFileOpenSaveDlg( BOOL bOpenFileDialog ) :CFileDialog( bOpenFileDialog ) { m_bOpenFile = bOpenFileDialog; } /***************************************************************************/ void CFileOpenSaveDlg::OnLBSelChangedNotify( UINT nIDBox, UINT iCurSel, UINT nCode ) { if (! m_bOpenFile && iCurSel <= 5 && nIDBox == cmb1 && nCode == CD_LBSELCHANGE) { // change in the file type CWnd* pText = GetDlgItem( edt1 ); CWnd* pType = GetDlgItem( cmb1 ); CString sFname; CString sDfltExt; switch (iCurSel) { #ifdef PCX_SUPPORT case 4: sDfltExt.LoadString( IDS_EXTENSION_PCX ); break; #endif case 5: sDfltExt.LoadString( IDS_EXTENSION_ICO ); break; default: sDfltExt.LoadString( IDS_EXTENSION_BMP ); break; } pText->GetWindowText( sFname ); if (sDfltExt.CompareNoCase( GetExtension( sFname ) )) { sFname = StripExtension( sFname ) + sDfltExt; pText->SetWindowText( sFname ); } } } /***************************************************************************/ extern BOOL AFXAPI AfxFullPath( LPTSTR lpszPathOut, LPCTSTR lpszFileIn ); CDocument* CPBApp::OpenDocumentFile( LPCTSTR lpszFileName ) { CancelToolMode(FALSE); TCHAR szPath[_MAX_PATH]; AfxFullPath( szPath, lpszFileName ); return(m_pDocManager->OpenDocumentFile(szPath)); // CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead(); // // ASSERT( pTemplate->IsKindOf( RUNTIME_CLASS( CDocTemplate ) ) ); // // return pTemplate->OpenDocumentFile( szPath ); } void CancelToolMode(BOOL bSelectionCommand) { if (bSelectionCommand) { // Check if a selection tool is the current one if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL) || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)) { // Don't try canceling the mode, since the command works on a // selection return; } } // Just select the current tool again to reset everything CImgTool *pImgTool = CImgTool::GetCurrent(); if (pImgTool) { pImgTool->Select(); } } /***************************************************************************/ // CPBApp commands void CPBApp::OnFileNew() { CancelToolMode(FALSE); CWinApp::OnFileNew(); } void CPBApp::OnFileOpen() { CancelToolMode(FALSE); // prompt the user (with all document templates) CString newName; int iColor = 0; if (! DoPromptFileName( newName, AFX_IDS_OPENFILE, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, iColor )) return; // open cancelled #ifdef PCX_SUPPORT m_bPCXfile = (iColor == 4); #endif OpenDocumentFile( newName ); } /****************************************************************************/ // prompt for file name - used for open and save as BOOL CPBApp::DoPromptFileName( CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, int& iColors ) { CFileOpenSaveDlg dlgFile( bOpenFileDialog ); CString title; VERIFY( title.LoadString( nIDSTitle ) ); lFlags |= OFN_EXPLORER; dlgFile.m_ofn.Flags |= lFlags; dlgFile.m_ofn.Flags &= ~OFN_SHOWHELP; CString strFilter; CString strDefault; CDocTemplate* pTemplate = NULL; POSITION pos = m_pDocManager->GetFirstDocTemplatePosition(); if (pos != NULL) pTemplate = m_pDocManager->GetNextDocTemplate(pos); CString strFilterExt; CString strFilterName; ASSERT(pTemplate != NULL); pTemplate->GetDocString( strFilterExt , CDocTemplate::filterExt ); pTemplate->GetDocString( strFilterName, CDocTemplate::filterName ); ASSERT( strFilterExt[0] == TEXT('.') ); // start the default extension strDefault = ((const TCHAR*)strFilterExt) + 1; // skip the '.' dlgFile.m_ofn.nFilterIndex = iColors + 1; // 1 based number if (bOpenFileDialog) { // add to filter strFilter += strFilterName; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*") + strFilterExt; strFilter += (TCHAR)TEXT('\0'); // next string please dlgFile.m_ofn.nMaxCustFilter++; #ifdef PCX_SUPPORT strFilterExt.LoadString( IDS_EXTENSION_PCX ); strFilterName.LoadString( IDS_PCX_FILTER_NAME ); // add to filter strFilter += strFilterName; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*") + strFilterExt; strFilter += (TCHAR)TEXT('\0'); // next string please dlgFile.m_ofn.nMaxCustFilter++; #endif // // get list of all installed filters and add those to the list... // TCHAR name[128]; TCHAR ext[10]; for (int i=0; GetFilterInfo(i, name, sizeof(name)/sizeof(TCHAR), ext, sizeof(ext)/sizeof(TCHAR),NULL,0); i++) { if (ext[0] == 0 || name[0] == 0) continue; if (lstrlen(ext) > 3) continue; // dont show these, we already handle these if (lstrcmpi(ext,TEXT("bmp")) == 0 || lstrcmpi(ext,TEXT("dib")) == 0 || lstrcmpi(ext,TEXT("rle")) == 0) continue; #if 1 // only use known good filters if (!g_bShowAllFiles && (GetKeyState(VK_SHIFT) & 0x8000) == 0 && lstrcmpi(ext,TEXT("pcx")) != 0) continue; #endif // add to filter strFilter += name; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*."); strFilter += ext; strFilter += (TCHAR)TEXT('\0'); // next string please dlgFile.m_ofn.nMaxCustFilter++; } } else { for (int i = IDS_BMP_MONO; i <= IDS_BMP_TRUECOLOR; i++) { strFilterName.LoadString( i ); // add to filter strFilter += strFilterName; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*") + strFilterExt; strFilter += (TCHAR)TEXT('\0'); // next string please dlgFile.m_ofn.nMaxCustFilter++; } #ifdef PCX_SUPPORT strFilterExt.LoadString( IDS_EXTENSION_PCX ); strFilterName.LoadString( IDS_PCX_FILTER_NAME ); // add to filter strFilter += strFilterName; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*") + strFilterExt; strFilter += (TCHAR)TEXT('\0'); // next string please dlgFile.m_ofn.nMaxCustFilter++; if (theApp.m_bPCXfile) dlgFile.m_ofn.nFilterIndex = i-IDS_BMP_MONO+1; // 1 based number #endif } // set the default extension dlgFile.m_ofn.lpstrDefExt = (LPTSTR)(const TCHAR*)(strDefault); // append the "*.*" all files filter VERIFY( strFilterName.LoadString( IDS_TYPE_ALLFILES ) ); strFilter += strFilterName; strFilter += (TCHAR)TEXT('\0'); // next string please strFilter += TEXT("*.*"); strFilter += (TCHAR)TEXT('\0'); // last string dlgFile.m_ofn.nMaxCustFilter++; dlgFile.m_ofn.lpstrFilter = strFilter; dlgFile.m_ofn.hwndOwner = AfxGetMainWnd()->GetSafeHwnd(); dlgFile.m_ofn.lpstrTitle = title; dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH); BOOL bRet = dlgFile.DoModal() == IDOK? TRUE : FALSE; #ifdef _DEBUG if (!bRet) { TCHAR buf[100]; wsprintf (buf, TEXT("DoModal error: %d\n"), CommDlgExtendedError ()); OutputDebugString (buf); } #endif fileName.ReleaseBuffer(); iColors = (int)dlgFile.m_ofn.nFilterIndex - 1; CString sExt = dlgFile.GetFileExt(); #ifdef ICO_SUPPORT if (! bOpenFileDialog && dlgFile.m_ofn.nFileExtension) // did the user try to sneak a icon extension past us if (! sExt.CompareNoCase( ((const TCHAR *)strFilterExt) + 1 )) iColors = 5; #endif #ifdef PCX_SUPPORT if (bOpenFileDialog && iColors == 1) iColors = 4; // or a pcx extension past us strFilterExt.LoadString( IDS_EXTENSION_PCX ); if (! sExt.CompareNoCase( ((const TCHAR *)strFilterExt) + 1 )) iColors = 4; #endif return bRet; } /***************************************************************************/ // Mostly stolen from MFC // I made no attempt to strip out stuff I do not actually use // I just modified this so it used short module file name // ////////////////////////////////////////////////////////////////////////////// // data for UpdateRegistry functionality // %1 - class ID // %2 - class name // %3 - executable path // %4 - short type name // %5 - long type name // %6 - long application name // %7 - icon index static const TCHAR sz00[] = TEXT("%2\0") TEXT("%5"); static const TCHAR sz01[] = TEXT("%2\\CLSID\0") TEXT("%1"); static const TCHAR sz02[] = TEXT("%2\\Insertable\0") TEXT(""); static const TCHAR sz03[] = TEXT("%2\\protocol\\StdFileEditing\\verb\\0\0") TEXT("&Edit"); static const TCHAR sz04[] = TEXT("%2\\protocol\\StdFileEditing\\server\0") TEXT("%3"); static const TCHAR sz05[] = TEXT("CLSID\\%1\0") TEXT("%5"); static const TCHAR sz06[] = TEXT("CLSID\\%1\\ProgID\0") TEXT("%2"); #ifndef _USRDLL static const TCHAR sz07[] = TEXT("CLSID\\%1\\InprocHandler32\0") TEXT("ole32.dll"); static const TCHAR sz08[] = TEXT("CLSID\\%1\\LocalServer32\0") TEXT("%3"); #else static const TCHAR sz07[] = TEXT("\0") TEXT(""); static const TCHAR sz08[] = TEXT("CLSID\\%1\\InProcServer32\0") TEXT("%3"); #endif static const TCHAR sz09[] = TEXT("CLSID\\%1\\Verb\\0\0") TEXT("&Edit,0,2"); static const TCHAR sz10[] = TEXT("CLSID\\%1\\Verb\\1\0") TEXT("&Open,0,2"); static const TCHAR sz11[] = TEXT("CLSID\\%1\\Insertable\0") TEXT(""); static const TCHAR sz12[] = TEXT("CLSID\\%1\\AuxUserType\\2\0") TEXT("%4"); static const TCHAR sz13[] = TEXT("CLSID\\%1\\AuxUserType\\3\0") TEXT("%6"); static const TCHAR sz14[] = TEXT("CLSID\\%1\\DefaultIcon\0") TEXT("%3,%7"); static const TCHAR sz15[] = TEXT("CLSID\\%1\\MiscStatus\0") TEXT("32"); // registration for OAT_INPLACE_SERVER static const LPCTSTR rglpszInPlaceRegister[] = { sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12, sz13, sz15, NULL }; // registration for OAT_SERVER static const LPCTSTR rglpszServerRegister[] = { sz00, sz02, sz03, sz05, sz09, sz11, sz12, sz13, sz15, NULL }; // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER static const LPCTSTR rglpszServerOverwrite[] = { sz01, sz04, sz06, sz07, sz08, sz14, NULL }; // registration for OAT_CONTAINER static const LPCTSTR rglpszContainerRegister[] = { sz00, sz05, NULL }; // overwrite entries for OAT_CONTAINER static const LPCTSTR rglpszContainerOverwrite[] = { sz01, sz06, sz07, sz08, sz14, NULL }; // registration for OAT_DISPATCH_OBJECT static const LPCTSTR rglpszDispatchRegister[] = { sz00, sz05, NULL }; // overwrite entries for OAT_CONTAINER static const LPCTSTR rglpszDispatchOverwrite[] = { sz01, sz06, sz08, NULL }; struct STANDARD_ENTRY { const LPCTSTR* rglpszRegister; const LPCTSTR* rglpszOverwrite; }; static const STANDARD_ENTRY rgStdEntries[] = { { rglpszInPlaceRegister, rglpszServerOverwrite }, { rglpszServerRegister, rglpszServerOverwrite }, { rglpszContainerRegister, rglpszContainerOverwrite }, { rglpszDispatchRegister, rglpszDispatchOverwrite } }; ///////////////////////////////////////////////////////////////////////////// // Special registration for apps that wish not to use REGLOAD BOOL AFXAPI PBOleRegisterServerClass( REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName, LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite) { ASSERT(AfxIsValidString(lpszClassName)); ASSERT(AfxIsValidString(lpszShortTypeName)); ASSERT(*lpszShortTypeName != 0); ASSERT(AfxIsValidString(lpszLongTypeName)); ASSERT(*lpszLongTypeName != 0); ASSERT(nAppType == OAT_INPLACE_SERVER || nAppType == OAT_SERVER || nAppType == OAT_CONTAINER || nAppType == OAT_DISPATCH_OBJECT); // use standard registration entries if non given if (rglpszRegister == NULL) rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister; if (rglpszOverwrite == NULL) rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite; LPCTSTR rglpszSymbols[7]; // 0 - class ID // 1 - class name // 2 - executable path // 3 - short type name // 4 - long type name // 5 - long application name // 6 - icon index // convert the CLSID to a string LPTSTR lpszClassID; ::StringFromCLSID(clsid, &lpszClassID); if (lpszClassID == NULL) { TRACE0("Warning: StringFromCLSID failed in AfxOleRegisterServerName --\n"); TRACE0("\tperhaps AfxOleInit() has not been called.\n"); return FALSE; } rglpszSymbols[0] = lpszClassID; rglpszSymbols[1] = lpszClassName; // get path name to server TCHAR szPathName[_MAX_PATH]; LPTSTR pszTemp = szPathName; ::GetShortModuleFileName(AfxGetInstanceHandle(), pszTemp, _MAX_PATH); rglpszSymbols[2] = szPathName; // fill in rest of symbols rglpszSymbols[3] = lpszShortTypeName; rglpszSymbols[4] = lpszLongTypeName; rglpszSymbols[5] = AfxGetAppName(); // will usually be long, readable name LPCTSTR lpszIconIndex; HICON hIcon = ExtractIcon(AfxGetInstanceHandle(), szPathName, 1); if (hIcon != NULL) { lpszIconIndex = TEXT("1"); DestroyIcon(hIcon); } else { lpszIconIndex = TEXT("0"); } rglpszSymbols[6] = lpszIconIndex; // update the registry with helper function BOOL bResult; bResult = AfxOleRegisterHelper(rglpszRegister, rglpszSymbols, 7, FALSE); if (bResult && rglpszOverwrite != NULL) bResult = AfxOleRegisterHelper(rglpszOverwrite, rglpszSymbols, 7, TRUE); // free memory for class ID ASSERT(lpszClassID != NULL); AfxFreeTaskMem(lpszClassID); return bResult; } void CPBTemplateServer::UpdateRegistry(OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite) { ASSERT(m_pDocTemplate != NULL); // get registration info from doc template string CString strServerName; CString strLocalServerName; CString strLocalShortName; if (!m_pDocTemplate->GetDocString(strServerName, CDocTemplate::regFileTypeId) || strServerName.IsEmpty()) { TRACE0("Error: not enough information in DocTemplate to register OLE server.\n"); return; } if (!m_pDocTemplate->GetDocString(strLocalServerName, CDocTemplate::regFileTypeName)) strLocalServerName = strServerName; // use non-localized name if (!m_pDocTemplate->GetDocString(strLocalShortName, CDocTemplate::fileNewName)) strLocalShortName = strLocalServerName; // use long name ASSERT(strServerName.Find(TEXT(' ')) == -1); // no spaces allowed // place entries in system registry if (!PBOleRegisterServerClass(m_clsid, strServerName, strLocalShortName, strLocalServerName, nAppType, rglpszRegister, rglpszOverwrite)) { // not fatal (don't fail just warn) AfxMessageBox(AFX_IDP_FAILED_TO_AUTO_REGISTER); } }