1749 lines
53 KiB
C++
1749 lines
53 KiB
C++
// 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 |