|
|
// 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 "image.h"
#include <dlgs.h>
#include <shlobj.h>
#include "ofn.h"
#include "imaging.h"
// turn on visibility of GIF filter
#define GIF_SUPPORT
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__; #endif
typedef BOOL(WINAPI* SHSPECPATH)(HWND,LPTSTR,int,BOOL);
#include "memtrace.h"
BOOL NEAR g_bShowAllFiles = FALSE;
#ifdef USE_MIRRORING
HINSTANCE ghInstGDI32=NULL;
DWORD WINAPI PBGetLayoutPreNT5(HDC hdc) { return 0; // No mirroring on systems before NT5 or W98-CS
}
DWORD (WINAPI *PBGetLayout) (HDC hdc) = &PBGetLayoutInit;
DWORD WINAPI PBGetLayoutInit(HDC hdc) {
PBGetLayout = (DWORD (WINAPI *) (HDC hdc)) GetProcAddress(ghInstGDI32, "GetLayout");
if (!PBGetLayout) { PBGetLayout = PBGetLayoutPreNT5; }
return PBGetLayout(hdc);
}
//// RESetLayout - Set layout of DC
//
// Sets layout flags in an NT5/W98 or later DC.
DWORD WINAPI PBSetLayoutPreNT5(HDC hdc, DWORD dwLayout) { return 0; // No mirroring on systems before NT5 or W98-CS
}
DWORD (WINAPI *PBSetLayout) (HDC hdc, DWORD dwLayout) = &PBSetLayoutInit;
DWORD WINAPI PBSetLayoutInit(HDC hdc, DWORD dwLayout) {
PBSetLayout = (DWORD (WINAPI *) (HDC hdc, DWORD dwLayout)) GetProcAddress(ghInstGDI32, "SetLayout");
if (!PBSetLayout) { PBSetLayout = PBSetLayoutPreNT5; }
return PBSetLayout(hdc, dwLayout);
} #endif
/***************************************************************************/ // 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_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_rectMargins.SetRect(MARGINS_DEFAULT, MARGINS_DEFAULT, MARGINS_DEFAULT, MARGINS_DEFAULT);
m_bCenterHorizontally = TRUE; m_bCenterVertically = TRUE; m_bScaleFitTo = FALSE; m_nAdjustToPercent = 100; m_nFitToPagesWide = 1; m_nFitToPagesTall = 1;
m_pwndInPlaceFrame = NULL; m_hwndInPlaceApp = NULL;
m_pColors = NULL; m_iColors = 0;
for (int index = 0; index < nSysBrushes + nOurBrushes; index++) { m_pbrSysColors[index] = NULL; }
m_nFilters = 0; m_guidFltType = NULL; m_guidFltTypeUsed = WiaImgFmt_UNDEFINED; m_nFilterInIdx = -1; // default is All Pictures
m_nFilterOutIdx = 1;
#ifdef USE_MIRRORING
ghInstGDI32 = GetModuleHandle(TEXT("gdi32.dll")); #endif
}
/***************************************************************************/ // CPBApp destruction
CPBApp::~CPBApp() { delete [] m_guidFltType; }
/***************************************************************************/ // The one and only CPBApp object
CPBApp 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], TEXT("wia"))) m_bWiaCallback = TRUE; else if (m_bWiaCallback && m_strWiaDeviceId.IsEmpty()) m_strWiaDeviceId = ARGV[i]; else if (m_bWiaCallback && m_strWiaEventId.IsEmpty()) m_strWiaEventId = ARGV[i]; // 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);
// APPCOMPAT GSPN sometimes fails on UNC's. Try this until that is tracked down
lstrcpyn(pszName, szLongName, uLen);
if (!GetShortPathName(szLongName, pszName, uLen)) { GetLastError(); } }
#if 0
// Pulling self-registration out. This is to be done once during setup only
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; i<ARRAYSIZE(aActions); ++i) { CRegKey rkAction(rkShellInfo, aActions[i].pszActionID); if (!(HKEY)rkAction) { continue; }
// Note I do not set the name of the action; I will need to add this
// if I use anything other than "Open", "Print", or "PrintTo"
TCHAR szCommand[MAX_PATH + 80]; wsprintf(szCommand, aActions[i].pszCommand, szFile);
RegSetValue(rkAction, TEXT("command"), REG_SZ, szCommand, 0); }
// Set the OLE server for PBrush objects
CRegKey rkPBrushInfo(HKEY_CLASSES_ROOT, TEXT("PBrush\\protocol\\StdFileEditing\\server")); if ((HKEY)rkPBrushInfo) { RegSetValue(rkPBrushInfo, TEXT(""), REG_SZ, szFile, 0); } }
#endif
/***************************************************************************/ // CPBApp initialization
BOOL CPBApp::InitInstance() { SetRegistryKey( IDS_REGISTRY_PATH ); if (m_pszProfileName) { free((void*)m_pszProfileName); } m_pszProfileName = _tcsdup(TEXT("Paint"));
HDC hdc = ::GetDC( NULL );
ASSERT( hdc != NULL );
GetSystemSettings( CDC::FromHandle( hdc ) );
::ReleaseDC( NULL, hdc );
// Because we cannot LoadString when these strings are needed (in
// WarnUserOfEmergency) load them here in private member variables
// of CTheApp...
//
m_strEmergencyNoMem.LoadString ( IDS_ERROR_NOMEMORY ); m_strEmergencyLowMem.LoadString( IDS_ERROR_LOWMEMORY );
// Initialize OLE 2.0 libraries
if (! AfxOleInit()) { AfxMessageBox( IDP_OLE_INIT_FAILED ); return FALSE; }
// disable the annoying "server busy" dialog that pops up
// during long blocking WIA calls
COleMessageFilter* pFilter = AfxOleGetMessageFilter();
ASSERT( pFilter );
if (pFilter) { pFilter->EnableNotRespondingDialog(FALSE); pFilter->EnableBusyDialog(FALSE); }
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
// SetDialogBkColor(); // Set dialog background color to gray
LoadProfileSettings(); // Load standard INI file options (including MRU)
InitCustomData();
if (! g_pColors) { g_pColors = new CColors;
if (! g_pColors->GetColorCount()) { 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.
#if 0
// Pulling self-registration out. This is to be done once during setup only
RegisterShell(pDocTemplate); #endif
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; }
#if 0
// Pulling self-registration out. This is to be done once during setup only
// 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 ); #endif
ParseCommandLine();
if (m_bWiaCallback) { USES_CONVERSION; GUID guidEventId;
ASSERT(!m_strWiaEventId.IsEmpty() && !m_strWiaDeviceId.IsEmpty());
// check that we have received the WIA_EVENT_DEVICE_CONNECTED event and
// a valid device id. If not, we should exit before going any further
if (m_strWiaEventId.IsEmpty() || m_strWiaDeviceId.IsEmpty() || CLSIDFromString((LPOLESTR) T2COLE(m_strWiaEventId), &guidEventId) != S_OK || guidEventId != WIA_EVENT_DEVICE_CONNECTED) { return FALSE; } }
// 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();
if (m_bWiaCallback) { // select the device and post a message to popup the WIA dialog
((CPBFrame*)m_pMainWnd)->m_pMgr->Select(m_strWiaDeviceId); m_pMainWnd->PostMessage(WM_COMMAND, ID_FILE_SCAN_NEW, 0); } }
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();
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 */ ) { // This app has been converted to use HtmlHelp. This is a safety to prevent someone
// from accidentally adding WinHelp calls for proceedural help
ASSERT( (nCmd != HELP_FINDER) && (nCmd != HELP_INDEX) && (nCmd != HELP_CONTENTS) );
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++) { 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:
//
// <file name>
// <operation failed>
// <reason>
//
// <file name> describes what file has the problem, <operation files>
// indicated what kind of thing failed (e.g. "Cannot save file"), and
// <reason> 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 ) ) );
CString strFmt; CString strMsg;
if (m_sLastFile.IsEmpty()) { strFmt.LoadString(IDS_FORMATERR_NOFILE); strMsg.Format(strFmt, (LPCTSTR)strOperation, (LPCTSTR)strReason); } else { strFmt.LoadString(IDS_FORMATERR_FILE); strMsg.Format(strFmt, (LPCTSTR)m_sLastFile, (LPCTSTR)strOperation, (LPCTSTR)strReason); } AfxMessageBox( strMsg, 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_hThing) 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; }
/***************************************************************************/
#if 0
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 ); } } }
#endif //0
/***************************************************************************/
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, FALSE )) return; // open cancelled
#ifdef PCX_SUPPORT
m_bPCXfile = (iColor == 4); #endif
CPBDoc* pDoc = (CPBDoc*)((CFrameWnd*)AfxGetMainWnd())->GetActiveDocument();
// prompt to save the current document if it was modified
if (pDoc && pDoc->SaveModified()) { pDoc->SetModifiedFlag(FALSE);
if (OpenDocumentFile( newName )==NULL) { // attempt to open a file failed, so make sure any new doc just
// created in the process gets destroyed
POSITION tPos = GetFirstDocTemplatePosition(); CDocTemplate* pTemplate = GetNextDocTemplate(tPos); POSITION dPos = pTemplate->GetFirstDocPosition (); CPBDoc *pDoc= (CPBDoc *)(pTemplate->GetNextDoc(dPos));
if (pDoc->m_pBitmapObjNew) { delete pDoc->m_pBitmapObjNew; pDoc->m_pBitmapObjNew =NULL; } OnFileNew(); // then start anew...
} } }
/****************************************************************************/ // prompt for file name - used for open and save as
BOOL CPBApp::DoPromptFileName( CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, int& iColors, BOOL bOnlyBmp ) { COpenFileName dlgFile( bOpenFileDialog );
ASSERT(dlgFile.m_pofn);
if (!dlgFile.m_pofn) return FALSE;
CString title;
VERIFY( title.LoadString( nIDSTitle ) );
lFlags |= OFN_EXPLORER;
if (!bOpenFileDialog) lFlags |= OFN_OVERWRITEPROMPT;
dlgFile.m_pofn->Flags |= lFlags; dlgFile.m_pofn->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; CString strAllPictureFiles;
ASSERT(pTemplate != NULL);
pTemplate->GetDocString( strFilterExt , CDocTemplate::filterExt ); pTemplate->GetDocString( strFilterName, CDocTemplate::filterName );
ASSERT( strFilterExt[0] == TEXT('.') );
// set the default extension
// strDefault = ((const TCHAR*)strFilterExt) + 1; // skip the '.'
// dlgFile.m_pofn->nFilterIndex = iColors + 1; // 1 based number
dlgFile.m_pofn->lpstrDefExt = ((LPCTSTR)strFilterExt) + 1; // skip the '.'
if (bOpenFileDialog) { // add to filter
strFilter = strFilterName; strFilter += _T('\0'); // next string please
strFilter += _T("*") + strFilterExt; VERIFY(strFilterExt.LoadString(IDS_EXTENSION_DIB)); strFilter += _T(";*") + strFilterExt; strAllPictureFiles += _T(";*") + strFilterExt; VERIFY(strFilterExt.LoadString(IDS_EXTENSION_BMP)); strAllPictureFiles += _T(";*") + strFilterExt; VERIFY(strFilterExt.LoadString(IDS_EXTENSION_RLE)); strFilter += _T(";*") + strFilterExt; strFilter += _T('\0'); // next string please
dlgFile.m_pofn->nMaxCustFilter++; } else { for (int i = IDS_BMP_MONO; i <= IDS_BMP_TRUECOLOR; i++) { strFilterName.LoadString( i );
// add to filter
strFilter += strFilterName;
strFilter += _T('\0'); // next string please
strFilter += _T("*") + strFilterExt; strFilter += _T('\0'); // next string please
dlgFile.m_pofn->nMaxCustFilter++; } }
// get a list of GDI+ codecs (if available)
Gdiplus::ImageCodecInfo *pCodecs = 0; UINT nCodecs = 0;
if (bOpenFileDialog) { GetGdiplusDecoders(&nCodecs, &pCodecs); } else { GetGdiplusEncoders(&nCodecs, &pCodecs); }
if (nCodecs && !bOnlyBmp) { delete [] m_guidFltType; m_guidFltType = new GUID[nCodecs]; m_nFilters = 0;
for (UINT i = 0; i < nCodecs; ++i) { if (pCodecs[i].FormatID != WiaImgFmt_BMP && pCodecs[i].FormatID != WiaImgFmt_EMF && pCodecs[i].FormatID != WiaImgFmt_WMF) // GDI+ does not handle WMF/EMF well
{ m_guidFltType[m_nFilters++] = pCodecs[i].FormatID;
strFilter += pCodecs[i].FormatDescription; strFilter += _T(" ("); strFilter += pCodecs[i].FilenameExtension; strFilter += _T(')'); strFilter += _T('\0'); // next string please
strFilter += pCodecs[i].FilenameExtension; strFilter += _T('\0'); // next string please
strAllPictureFiles += _T(';'); strAllPictureFiles += pCodecs[i].FilenameExtension;
dlgFile.m_pofn->nMaxCustFilter++; } }
LocalFree(pCodecs); } else { //
// get list of all installed filters and add those to the list...
//
delete [] m_guidFltType; m_guidFltType = new GUID[16]; // max # of filters
TCHAR name[128]; TCHAR ext[sizeof("jpg;*.jpeg") + 1]; BOOL bImageAPI;
for (int i=0, j=0; !bOnlyBmp && GetInstalledFilters(bOpenFileDialog, i, name, sizeof(name), ext, sizeof(ext), NULL, 0, bImageAPI); i++) { if (!bImageAPI) { continue; } if (ext[0] == 0 || name[0] == 0) continue;
// if there are multiple extensions, take the first one...
PTSTR pComma = _tcschr(ext, _T(',')); if (pComma) *pComma = 0;
PTSTR pSemiColon = _tcschr(ext, _T(';')); if (pSemiColon) *pSemiColon = 0;
PTSTR pSpace = _tcschr(ext, _T(' ')); if (pSpace) *pSpace = 0;
if (lstrlen(ext) > 3) continue;
// dont show these, we already handle these
if (lstrcmpi(ext,_T("bmp")) == 0 || lstrcmpi(ext,_T("dib")) == 0 || lstrcmpi(ext,_T("rle")) == 0) continue; #ifndef GIF_SUPPORT
if (lstrcmpi(ext, _T("gif") == 0) { continue; }
#endif
#if 0 // only use known good filters
if (!g_bShowAllFiles && (GetKeyState(VK_SHIFT) & 0x8000) == 0 && lstrcmpi(ext,_T("pcx")) != 0) continue; #endif
// save a list of available filter types
if (lstrcmpi(ext,_T("gif")) == 0) { m_guidFltType[j++] = WiaImgFmt_GIF; } else if (lstrcmpi(ext,_T("jpg")) == 0) { m_guidFltType[j++] = WiaImgFmt_JPEG; _tcscat (ext, _T(";*.jpeg")); } #ifdef SUPPORT_ALL_FILTERS
else if (lstrcmpi(ext,_T("png")) == 0) { #ifdef PNG_SUPPORT
m_guidFltType[j++] = WiaImgFmt_PNG; #else
continue; #endif // PNG_SUPPORT
}
else if (lstrcmpi(ext,_T("pcd")) == 0) { m_guidFltType[j++] = WiaImgFmt_PHOTOCD; } /*else if (lstrcmpi(ext,_T("pic")) == 0)
{ m_guidFltType[j++] = IFLT_PICT; _tcscat(ext, _T(";*.pict")); } else if (lstrcmpi(ext,_T("tga")) == 0) { m_iflFltType[j++] = IFLT_TGA; }*/ else if (lstrcmpi(ext,_T("tif")) == 0) { m_guidFltType[j++] = WiaImgFmt_TIFF; _tcscat(ext, _T(";*.tiff")); } else { m_guidFltType[j++] = WiaImgFmt_UNDEFINED; } #else
else continue; #endif
// add to filter
strFilter += name; strFilter += _T(" ( *."); strFilter += ext; strFilter += _T(" )"); strFilter += _T('\0'); // next string please
strFilter += _T("*."); strFilter += ext; strFilter += _T('\0'); // next string please
strAllPictureFiles = strAllPictureFiles + _T(";*.")+ext; dlgFile.m_pofn->nMaxCustFilter++; } }
if (!bOnlyBmp && bOpenFileDialog) { // append "All Picture Files" only if opening a file
VERIFY(strFilterName.LoadString(IDS_TYPE_ALLPICTURES)); strFilter+= strFilterName; strFilter += _T('\0'); strFilter += strAllPictureFiles; strFilter += _T('\0'); dlgFile.m_pofn->nMaxCustFilter++;
if (m_nFilterInIdx == -1) { m_nFilterInIdx = dlgFile.m_pofn->nMaxCustFilter; }
// append the "*.*" filter only if "Open"ing a file
VERIFY( strFilterName.LoadString( IDS_TYPE_ALLFILES ) );
strFilter += strFilterName; strFilter += _T('\0'); // next string please
strFilter += _T("*.*"); strFilter += _T('\0'); // last string
dlgFile.m_pofn->nMaxCustFilter++;
}
// prompt the user with the appropriate filter pre-selected
if (bOpenFileDialog) { dlgFile.m_pofn->nFilterIndex = m_nFilterInIdx; } else { DWORD dwIndex; if (m_guidFltTypeUsed != WiaImgFmt_UNDEFINED && (dwIndex = GetFilterIndex(m_guidFltTypeUsed))) // has an export filter?
dlgFile.m_pofn->nFilterIndex = dwIndex + 4; // skip the first 4 BMP types
else if (m_nFilterOutIdx >= 4) dlgFile.m_pofn->nFilterIndex = m_nFilterOutIdx; else dlgFile.m_pofn->nFilterIndex = iColors + 1; // 1 based number
} dlgFile.m_pofn->lpstrFilter = strFilter; dlgFile.m_pofn->hwndOwner = AfxGetMainWnd()->GetSafeHwnd(); dlgFile.m_pofn->hInstance = AfxGetResourceHandle(); dlgFile.m_pofn->lpstrTitle = title; dlgFile.m_pofn->lpstrFile = fileName.GetBuffer(_MAX_PATH); dlgFile.m_pofn->nMaxFile = _MAX_PATH; TCHAR szInitPath[MAX_PATH]; ::LoadString (GetModuleHandle (NULL), AFX_IDS_UNTITLED, szInitPath, MAX_PATH); //
// Look in "My Documents" on NT 5, Win98, and later.
//
if (!theApp.GetLastFile() || !*(theApp.GetLastFile())) { static SHSPECPATH pfnSpecialPath = NULL; if (!pfnSpecialPath) {
#ifdef UNICODE
pfnSpecialPath = (SHSPECPATH)GetProcAddress ( GetModuleHandle(_T("shell32.dll")), "SHGetSpecialFolderPathW"); #else
pfnSpecialPath = (SHSPECPATH)GetProcAddress ( GetModuleHandle(_T("shell32.dll")), "SHGetSpecialFolderPathA"); #endif //UNICODE
} if (pfnSpecialPath) { (pfnSpecialPath)(NULL, szInitPath, CSIDL_MYPICTURES, FALSE); dlgFile.m_pofn->lpstrInitialDir = szInitPath; }
}
BOOL bRet = dlgFile.DoModal() == IDOK? TRUE : FALSE; fileName.ReleaseBuffer();
// keep track of the filter selected by the user
if (bOpenFileDialog) m_nFilterInIdx = dlgFile.m_pofn->nFilterIndex; else m_nFilterOutIdx = dlgFile.m_pofn->nFilterIndex;
iColors = (int)dlgFile.m_pofn->nFilterIndex - 1;
CString sExt = dlgFile.m_pofn->lpstrFile + dlgFile.m_pofn->nFileExtension;
#ifdef ICO_SUPPORT
if (! bOpenFileDialog && dlgFile.m_pofn->nFileExtension) // did the user try to sneak a icon extension past us
if (! sExt.CompareNoCase( ((const TCHAR *)strFilterExt) + 1 )) iColors = 5; #endif
return bRet; }
DWORD CPBApp::GetFilterIndex( REFGUID guidFltType ) { for (int i = 0; i < m_nFilters; i++) if (m_guidFltType[i] == guidFltType) return i+1;
return 0; }
// fix the file extension based on export filter selected - used for save as
void CPBApp::FixExtension( CString& fileName, int iflFltType ) { CString sDfltExt;
switch (iflFltType) { case IFLT_GIF: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_GIF )); break;
case IFLT_JPEG: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_JPEG )); break;
case IFLT_PCD: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PCD )); break;
case IFLT_PCX: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PCX )); break;
case IFLT_PICT: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PICT )); break; #ifdef PNG_SUPPORT
case IFLT_PNG: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PNG )); break; #endif // PNG_SUPPORT
case IFLT_TGA: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_TGA )); break;
case IFLT_TIFF: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_TIFF )); break;
case IFLT_UNKNOWN: // unknown or unsupported file type
default: VERIFY(sDfltExt.LoadString( IDS_EXTENSION_BMP )); break; }
if (sDfltExt.CompareNoCase( GetExtension( (LPCTSTR)fileName ) )) { fileName = StripExtension( fileName ) + sDfltExt; } }
#if 0
// Pulling self-registration out. This is to be done once during setup only
/***************************************************************************/
// 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;
LPTSTR 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
LPWSTR lpszClassID; ::StringFromCLSID(clsid, &lpszClassID); if (lpszClassID == NULL) { TRACE0("Warning: StringFromCLSID failed in AfxOleRegisterServerName --\n"); TRACE0("\tperhaps AfxOleInit() has not been called.\n"); return FALSE; } #ifdef UNICODE
rglpszSymbols[0] = lpszClassID; #else
int cc = WideCharToMultiByte (CP_ACP, 0, lpszClassID, -1, (LPSTR)&rglpszSymbols[0], 0, NULL, NULL); rglpszSymbols[0] = (LPSTR)new char[cc]; WideCharToMultiByte (CP_ACP, 0, lpszClassID, -1, rglpszSymbols[0], cc, NULL, NULL);
#endif // UNICODE
rglpszSymbols[1] = (LPTSTR)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] = (LPTSTR)lpszShortTypeName; rglpszSymbols[4] = (LPTSTR)lpszLongTypeName; rglpszSymbols[5] = (LPTSTR)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] = (LPTSTR)lpszIconIndex;
// update the registry with helper function
BOOL bResult; bResult = AfxOleRegisterHelper(rglpszRegister, (LPCTSTR*)rglpszSymbols, 7, FALSE); if (bResult && rglpszOverwrite != NULL) bResult = AfxOleRegisterHelper(rglpszOverwrite, (LPCTSTR*)rglpszSymbols, 7, TRUE);
// free memory for class ID
ASSERT(lpszClassID != NULL); AfxFreeTaskMem(lpszClassID); #ifndef UNICODE
delete[](LPSTR)rglpszSymbols[0]; #endif
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)
TRACE0("mspaint: Unable to register server class.\n"); } }
#endif
|