Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1748 lines
53 KiB

  1. // pbrush.cpp : Defines the class behaviors for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "global.h"
  5. #include "pbrush.h"
  6. #include "pbrusfrm.h"
  7. #include "ipframe.h"
  8. #include "pbrusdoc.h"
  9. #include "pbrusvw.h"
  10. #include "bmobject.h"
  11. #include "imgsuprt.h"
  12. #include "imgwnd.h"
  13. #include "imgwell.h"
  14. #include "imgtools.h"
  15. #include "ferr.h"
  16. #include "cmpmsg.h"
  17. #include "settings.h"
  18. #include "undo.h"
  19. #include "colorsrc.h"
  20. #include "printres.h"
  21. #include "loadimag.h"
  22. #include "image.h"
  23. #include <dlgs.h>
  24. #include <shlobj.h>
  25. #include "ofn.h"
  26. #include "imaging.h"
  27. // turn on visibility of GIF filter
  28. #define GIF_SUPPORT
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static char BASED_CODE THIS_FILE[] = __FILE__;
  32. #endif
  33. typedef BOOL(WINAPI* SHSPECPATH)(HWND,LPTSTR,int,BOOL);
  34. #include "memtrace.h"
  35. BOOL NEAR g_bShowAllFiles = FALSE;
  36. #ifdef USE_MIRRORING
  37. HINSTANCE ghInstGDI32=NULL;
  38. DWORD WINAPI PBGetLayoutPreNT5(HDC hdc) {
  39. return 0; // No mirroring on systems before NT5 or W98-CS
  40. }
  41. DWORD (WINAPI *PBGetLayout) (HDC hdc) = &PBGetLayoutInit;
  42. DWORD WINAPI PBGetLayoutInit(HDC hdc) {
  43. PBGetLayout = (DWORD (WINAPI *) (HDC hdc)) GetProcAddress(ghInstGDI32, "GetLayout");
  44. if (!PBGetLayout) {
  45. PBGetLayout = PBGetLayoutPreNT5;
  46. }
  47. return PBGetLayout(hdc);
  48. }
  49. //// RESetLayout - Set layout of DC
  50. //
  51. // Sets layout flags in an NT5/W98 or later DC.
  52. DWORD WINAPI PBSetLayoutPreNT5(HDC hdc, DWORD dwLayout) {
  53. return 0; // No mirroring on systems before NT5 or W98-CS
  54. }
  55. DWORD (WINAPI *PBSetLayout) (HDC hdc, DWORD dwLayout) = &PBSetLayoutInit;
  56. DWORD WINAPI PBSetLayoutInit(HDC hdc, DWORD dwLayout) {
  57. PBSetLayout = (DWORD (WINAPI *) (HDC hdc, DWORD dwLayout)) GetProcAddress(ghInstGDI32, "SetLayout");
  58. if (!PBSetLayout) {
  59. PBSetLayout = PBSetLayoutPreNT5;
  60. }
  61. return PBSetLayout(hdc, dwLayout);
  62. }
  63. #endif
  64. /***************************************************************************/
  65. // CPBApp
  66. BEGIN_MESSAGE_MAP(CPBApp, CWinApp)
  67. //{{AFX_MSG_MAP(CPBApp)
  68. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  69. // NOTE - the ClassWizard will add and remove mapping macros here.
  70. // DO NOT EDIT what you see in these blocks of generated code!
  71. //}}AFX_MSG_MAP
  72. // Standard file based document commands
  73. ON_COMMAND(ID_FILE_NEW, OnFileNew)
  74. ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  75. // Standard print setup command
  76. ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
  77. END_MESSAGE_MAP()
  78. /***************************************************************************/
  79. // CPBApp construction
  80. CPBApp::CPBApp()
  81. {
  82. // TODO: add construction code here,
  83. // Place all significant initialization in InitInstance
  84. #ifdef _DEBUG
  85. m_bLogUndo = FALSE;
  86. #endif
  87. // This is the minimum amount of free memory we like to have
  88. // (NOTE: These are overwritten by ReadInitFile)
  89. m_dwLowMemoryBytes = 1024L * 2200;
  90. m_nLowGdiPercent = 10;
  91. m_nLowUserPercent = 10;
  92. m_nFileErrorCause = 0; // from CFileException::m_cause
  93. m_wEmergencyFlags = 0;
  94. m_tickLastWarning = 0;
  95. m_iCurrentUnits = 0;
  96. m_bShowStatusbar = TRUE;
  97. m_bShowThumbnail = FALSE;
  98. m_bShowTextToolbar = TRUE;
  99. m_bShowIconToolbar = TRUE;
  100. m_bEmbedded = FALSE;
  101. m_bLinked = FALSE;
  102. m_bHidden = FALSE;
  103. m_bActiveApp = FALSE;
  104. m_bPenSystem = FALSE;
  105. m_bPaletted = FALSE;
  106. m_pPalette = NULL;
  107. m_bPrintOnly = FALSE;
  108. #ifdef PCX_SUPPORT
  109. m_bPCXfile = FALSE;
  110. #endif
  111. m_rectFloatThumbnail.SetRectEmpty();
  112. m_rectMargins.SetRect(MARGINS_DEFAULT, MARGINS_DEFAULT, MARGINS_DEFAULT,
  113. MARGINS_DEFAULT);
  114. m_bCenterHorizontally = TRUE;
  115. m_bCenterVertically = TRUE;
  116. m_bScaleFitTo = FALSE;
  117. m_nAdjustToPercent = 100;
  118. m_nFitToPagesWide = 1;
  119. m_nFitToPagesTall = 1;
  120. m_pwndInPlaceFrame = NULL;
  121. m_hwndInPlaceApp = NULL;
  122. m_pColors = NULL;
  123. m_iColors = 0;
  124. for (int index = 0; index < nSysBrushes + nOurBrushes; index++)
  125. {
  126. m_pbrSysColors[index] = NULL;
  127. }
  128. m_nFilters = 0;
  129. m_guidFltType = NULL;
  130. m_guidFltTypeUsed = WiaImgFmt_UNDEFINED;
  131. m_nFilterInIdx = -1; // default is All Pictures
  132. m_nFilterOutIdx = 1;
  133. #ifdef USE_MIRRORING
  134. ghInstGDI32 = GetModuleHandle(TEXT("gdi32.dll"));
  135. #endif
  136. }
  137. /***************************************************************************/
  138. // CPBApp destruction
  139. CPBApp::~CPBApp()
  140. {
  141. delete [] m_guidFltType;
  142. }
  143. /***************************************************************************/
  144. // The one and only CPBApp object
  145. CPBApp theApp;
  146. // This identifier was generated to be statistically unique for your app.
  147. // You may change it if you prefer to choose a specific identifier.
  148. const CLSID BASED_CODE CLSID_Paint =
  149. { 0xd3e34b21, 0x9d75, 0x101a, { 0x8c, 0x3d, 0x0, 0xaa, 0x0, 0x1a, 0x16, 0x52 } };
  150. const CLSID BASED_CODE CLSID_PaintBrush =
  151. { 0x0003000A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
  152. /***************************************************************************/
  153. // Stolen from WordPad
  154. BOOL MatchOption(LPTSTR lpsz, LPTSTR lpszOption)
  155. {
  156. if (lpsz[0] == TEXT('-') || lpsz[0] == TEXT('/'))
  157. {
  158. lpsz++;
  159. if (lstrcmpi(lpsz, lpszOption) == 0)
  160. return TRUE;
  161. }
  162. return FALSE;
  163. }
  164. void CPBApp::ParseCommandLine()
  165. {
  166. BOOL bPrintTo = FALSE;
  167. #ifdef UNICODE
  168. int argcw;
  169. LPWSTR *argvw;
  170. argvw = CommandLineToArgvW (GetCommandLine (), &argcw);
  171. #define ARGV argvw
  172. #define ARGC argcw
  173. #else
  174. #define ARGV __argv
  175. #define ARGC __argc
  176. #endif
  177. // start at 1 -- the first is the exe
  178. for (int i=1; i< ARGC; i++)
  179. {
  180. if (MatchOption(ARGV[i], TEXT("pt")))
  181. bPrintTo = m_bPrintOnly = TRUE;
  182. else if (MatchOption(ARGV[i], TEXT("p")))
  183. m_bPrintOnly = TRUE;
  184. else if (MatchOption(ARGV[i], TEXT("wia")))
  185. m_bWiaCallback = TRUE;
  186. else if (m_bWiaCallback && m_strWiaDeviceId.IsEmpty())
  187. m_strWiaDeviceId = ARGV[i];
  188. else if (m_bWiaCallback && m_strWiaEventId.IsEmpty())
  189. m_strWiaEventId = ARGV[i];
  190. // else if (MatchOption(__argv[i], "t"))
  191. // m_bForceTextMode = TRUE;
  192. // else if (MatchOption(__argv[i], "Embedding"))
  193. // m_bEmbedded = TRUE;
  194. // else if (MatchOption(__argv[i], "Automation"))
  195. // m_bEmbedded = TRUE;
  196. else if (m_strDocName.IsEmpty())
  197. m_strDocName = ARGV[i];
  198. else if (bPrintTo && m_strPrinterName.IsEmpty())
  199. m_strPrinterName = ARGV[i];
  200. else if (bPrintTo && m_strDriverName.IsEmpty())
  201. m_strDriverName = ARGV[i];
  202. else if (bPrintTo && m_strPortName.IsEmpty())
  203. m_strPortName = ARGV[i];
  204. else
  205. {
  206. ASSERT(FALSE);
  207. }
  208. }
  209. #ifdef UNICODE
  210. GlobalFree (argvw);
  211. #endif
  212. }
  213. void GetShortModuleFileName(HINSTANCE hInst, LPTSTR pszName, UINT uLen)
  214. {
  215. TCHAR szLongName[_MAX_PATH];
  216. GetModuleFileName(hInst, szLongName, _MAX_PATH);
  217. // APPCOMPAT GSPN sometimes fails on UNC's. Try this until that is tracked down
  218. lstrcpyn(pszName, szLongName, uLen);
  219. if (!GetShortPathName(szLongName, pszName, uLen))
  220. {
  221. GetLastError();
  222. }
  223. }
  224. #if 0
  225. // Pulling self-registration out. This is to be done once during setup only
  226. void CPBApp::RegisterShell(CSingleDocTemplate *pDocTemplate)
  227. {
  228. const struct
  229. {
  230. LPCTSTR pszActionID;
  231. LPCTSTR pszCommand;
  232. } aActions[] =
  233. {
  234. { TEXT("Open") , TEXT("\"%s\" \"%%1\"") },
  235. { TEXT("Print") , TEXT("\"%s\" /p \"%%1\"") },
  236. { TEXT("PrintTo"), TEXT("\"%s\" /pt \"%%1\" \"%%2\" \"%%3\" \"%%4\"") },
  237. } ;
  238. // We now need quotes around the file name, and MFC doesn't do this
  239. CString strTypeID;
  240. if (!pDocTemplate->GetDocString(strTypeID, CDocTemplate::regFileTypeId))
  241. {
  242. return;
  243. }
  244. strTypeID += TEXT("\\shell");
  245. CRegKey rkShellInfo(HKEY_CLASSES_ROOT, strTypeID);
  246. if (!(HKEY)rkShellInfo)
  247. {
  248. return;
  249. }
  250. TCHAR szFile[MAX_PATH];
  251. ::GetShortModuleFileName(AfxGetInstanceHandle(), szFile, ARRAYSIZE(szFile));
  252. int i;
  253. for (i=0; i<ARRAYSIZE(aActions); ++i)
  254. {
  255. CRegKey rkAction(rkShellInfo, aActions[i].pszActionID);
  256. if (!(HKEY)rkAction)
  257. {
  258. continue;
  259. }
  260. // Note I do not set the name of the action; I will need to add this
  261. // if I use anything other than "Open", "Print", or "PrintTo"
  262. TCHAR szCommand[MAX_PATH + 80];
  263. wsprintf(szCommand, aActions[i].pszCommand, szFile);
  264. RegSetValue(rkAction, TEXT("command"), REG_SZ, szCommand, 0);
  265. }
  266. // Set the OLE server for PBrush objects
  267. CRegKey rkPBrushInfo(HKEY_CLASSES_ROOT, TEXT("PBrush\\protocol\\StdFileEditing\\server"));
  268. if ((HKEY)rkPBrushInfo)
  269. {
  270. RegSetValue(rkPBrushInfo, TEXT(""), REG_SZ, szFile, 0);
  271. }
  272. }
  273. #endif
  274. /***************************************************************************/
  275. // CPBApp initialization
  276. BOOL CPBApp::InitInstance()
  277. {
  278. SetRegistryKey( IDS_REGISTRY_PATH );
  279. if (m_pszProfileName)
  280. {
  281. free((void*)m_pszProfileName);
  282. }
  283. m_pszProfileName = _tcsdup(TEXT("Paint"));
  284. HDC hdc = ::GetDC( NULL );
  285. ASSERT( hdc != NULL );
  286. GetSystemSettings( CDC::FromHandle( hdc ) );
  287. ::ReleaseDC( NULL, hdc );
  288. // Because we cannot LoadString when these strings are needed (in
  289. // WarnUserOfEmergency) load them here in private member variables
  290. // of CTheApp...
  291. //
  292. m_strEmergencyNoMem.LoadString ( IDS_ERROR_NOMEMORY );
  293. m_strEmergencyLowMem.LoadString( IDS_ERROR_LOWMEMORY );
  294. // Initialize OLE 2.0 libraries
  295. if (! AfxOleInit())
  296. {
  297. AfxMessageBox( IDP_OLE_INIT_FAILED );
  298. return FALSE;
  299. }
  300. // disable the annoying "server busy" dialog that pops up
  301. // during long blocking WIA calls
  302. COleMessageFilter* pFilter = AfxOleGetMessageFilter();
  303. ASSERT( pFilter );
  304. if (pFilter)
  305. {
  306. pFilter->EnableNotRespondingDialog(FALSE);
  307. pFilter->EnableBusyDialog(FALSE);
  308. }
  309. // Standard initialization
  310. // If you are not using these features and wish to reduce the size
  311. // of your final executable, you should remove from the following
  312. // the specific initialization routines you do not need.
  313. // SetDialogBkColor(); // Set dialog background color to gray
  314. LoadProfileSettings(); // Load standard INI file options (including MRU)
  315. InitCustomData();
  316. if (! g_pColors)
  317. {
  318. g_pColors = new CColors;
  319. if (! g_pColors->GetColorCount())
  320. {
  321. theApp.SetMemoryEmergency();
  322. return -1;
  323. }
  324. }
  325. // Register the application's document templates. Document templates
  326. // serve as the connection between documents, frame windows and views.
  327. CSingleDocTemplate* pDocTemplate;
  328. pDocTemplate = new CSingleDocTemplate( ID_MAINFRAME,
  329. RUNTIME_CLASS( CPBDoc ),
  330. RUNTIME_CLASS( CPBFrame ), // main SDI frame window
  331. RUNTIME_CLASS( CPBView ) );
  332. pDocTemplate->SetServerInfo( IDR_SRVR_EMBEDDED, IDR_SRVR_INPLACE,
  333. RUNTIME_CLASS( CInPlaceFrame ),
  334. RUNTIME_CLASS( CPBView ) );
  335. AddDocTemplate( pDocTemplate );
  336. // Connect the COleTemplateServer to the document template.
  337. // The COleTemplateServer creates new documents on behalf
  338. // of requesting OLE containers by using information
  339. // specified in the document template.
  340. m_server.ConnectTemplate( CLSID_Paint, pDocTemplate, TRUE );
  341. // Note: SDI applications register server objects only if /Embedding
  342. // or /Automation is present on the command line.
  343. #if 0
  344. // Pulling self-registration out. This is to be done once during setup only
  345. RegisterShell(pDocTemplate);
  346. #endif
  347. m_bEmbedded = RunEmbedded();
  348. // Parse the command line to see if launched as OLE server
  349. if (m_bEmbedded || RunAutomated())
  350. {
  351. // Register all OLE server (factories) as running. This enables the
  352. // OLE 2.0 libraries to create objects from other applications.
  353. COleTemplateServer::RegisterAll();
  354. // Application was run with /Embedding or /Automation. Don't show the
  355. // main window in this case.
  356. return TRUE;
  357. }
  358. #if 0
  359. // Pulling self-registration out. This is to be done once during setup only
  360. // When a server application is launched stand-alone, it is a good idea
  361. // to update the system registry in case it has been damaged.
  362. m_server.UpdateRegistry( OAT_INPLACE_SERVER );
  363. #endif
  364. ParseCommandLine();
  365. if (m_bWiaCallback)
  366. {
  367. USES_CONVERSION;
  368. GUID guidEventId;
  369. ASSERT(!m_strWiaEventId.IsEmpty() && !m_strWiaDeviceId.IsEmpty());
  370. // check that we have received the WIA_EVENT_DEVICE_CONNECTED event and
  371. // a valid device id. If not, we should exit before going any further
  372. if (m_strWiaEventId.IsEmpty() ||
  373. m_strWiaDeviceId.IsEmpty() ||
  374. CLSIDFromString((LPOLESTR) T2COLE(m_strWiaEventId), &guidEventId) != S_OK ||
  375. guidEventId != WIA_EVENT_DEVICE_CONNECTED)
  376. {
  377. return FALSE;
  378. }
  379. }
  380. // simple command line parsing
  381. if (m_strDocName.IsEmpty())
  382. {
  383. // create a new (empty) document
  384. OnFileNew();
  385. }
  386. else
  387. {
  388. CString sExt = GetExtension( m_strDocName );
  389. if (sExt.IsEmpty())
  390. {
  391. if (pDocTemplate->GetDocString( sExt, CDocTemplate::filterExt )
  392. && ! sExt.IsEmpty())
  393. m_strDocName += sExt;
  394. }
  395. WIN32_FIND_DATA finddata;
  396. HANDLE hFind = FindFirstFile(m_strDocName, &finddata);
  397. if (hFind != INVALID_HANDLE_VALUE)
  398. {
  399. FindClose(hFind);
  400. // Find the file name and replace it with the long file name
  401. int iBS = m_strDocName.ReverseFind(TEXT('\\'));
  402. if (iBS == -1)
  403. {
  404. iBS = m_strDocName.ReverseFind(TEXT(':'));
  405. }
  406. // HACK: Notice this is correct even if iBS==-1
  407. ++iBS;
  408. // Resize the memory string
  409. m_strDocName.GetBuffer(iBS);
  410. m_strDocName.ReleaseBuffer(iBS);
  411. m_strDocName += finddata.cFileName;
  412. }
  413. OpenDocumentFile( m_strDocName );
  414. }
  415. if (m_pMainWnd)
  416. {
  417. m_pMainWnd->DragAcceptFiles();
  418. if (m_bWiaCallback)
  419. {
  420. // select the device and post a message to popup the WIA dialog
  421. ((CPBFrame*)m_pMainWnd)->m_pMgr->Select(m_strWiaDeviceId);
  422. m_pMainWnd->PostMessage(WM_COMMAND, ID_FILE_SCAN_NEW, 0);
  423. }
  424. }
  425. return TRUE;
  426. }
  427. /***************************************************************************/
  428. int CPBApp::ExitInstance()
  429. {
  430. CustomExit(); // clean up in customiz
  431. CleanupImages();
  432. if (g_pColors)
  433. {
  434. delete g_pColors;
  435. g_pColors = NULL;
  436. }
  437. if (m_fntStatus.m_hObject != NULL)
  438. m_fntStatus.DeleteObject();
  439. ResetSysBrushes();
  440. CTracker::CleanUpTracker();
  441. return CWinApp::ExitInstance();
  442. }
  443. /***************************************************************************/
  444. void CPBApp::GetSystemSettings( CDC* pdc )
  445. {
  446. NONCLIENTMETRICS ncMetrics;
  447. ncMetrics.cbSize = sizeof( NONCLIENTMETRICS );
  448. if (SystemParametersInfo( SPI_GETNONCLIENTMETRICS,
  449. sizeof( NONCLIENTMETRICS ),
  450. &ncMetrics, 0 ))
  451. {
  452. if (m_fntStatus.m_hObject != NULL)
  453. m_fntStatus.DeleteObject();
  454. m_fntStatus.CreateFontIndirect( &ncMetrics.lfMenuFont );
  455. }
  456. ScreenDeviceInfo.iWidthinMM = pdc->GetDeviceCaps( HORZSIZE );
  457. ScreenDeviceInfo.iHeightinMM = pdc->GetDeviceCaps( VERTSIZE );
  458. ScreenDeviceInfo.iWidthinPels = pdc->GetDeviceCaps( HORZRES );
  459. ScreenDeviceInfo.iHeightinPels = pdc->GetDeviceCaps( VERTRES );
  460. ScreenDeviceInfo.ixPelsPerINCH = pdc->GetDeviceCaps( LOGPIXELSX );
  461. ScreenDeviceInfo.iyPelsPerINCH = pdc->GetDeviceCaps( LOGPIXELSY );
  462. /* get the pels per decameter '.1' rounded */
  463. ScreenDeviceInfo.ixPelsPerDM = (int)(((((long)ScreenDeviceInfo.iWidthinPels * 1000L) / (long)ScreenDeviceInfo.iWidthinMM ) + 5L) / 10);
  464. ScreenDeviceInfo.iyPelsPerDM = (int)(((((long)ScreenDeviceInfo.iHeightinPels * 1000L) / (long)ScreenDeviceInfo.iHeightinMM) + 5L) / 10);
  465. ScreenDeviceInfo.ixPelsPerMM = (ScreenDeviceInfo.ixPelsPerDM + 50) / 100;
  466. ScreenDeviceInfo.iyPelsPerMM = (ScreenDeviceInfo.iyPelsPerDM + 50) / 100;
  467. ScreenDeviceInfo.iWidthinINCH = (int)(((long)ScreenDeviceInfo.iWidthinMM * 100L / 245L + 5L) / 10L); //24.5 mm to the inch
  468. ScreenDeviceInfo.iHeightinINCH = (int)(((long)ScreenDeviceInfo.iHeightinMM * 100L / 245L + 5L) / 10L);
  469. ScreenDeviceInfo.iBitsPixel = pdc->GetDeviceCaps( BITSPIXEL );
  470. ScreenDeviceInfo.iPlanes = pdc->GetDeviceCaps( PLANES );
  471. m_cxFrame = GetSystemMetrics( SM_CXFRAME );
  472. m_cyFrame = GetSystemMetrics( SM_CYFRAME );
  473. m_cxBorder = GetSystemMetrics( SM_CXBORDER );
  474. m_cyBorder = GetSystemMetrics( SM_CYBORDER );
  475. m_cyCaption = GetSystemMetrics( SM_CYSMCAPTION );
  476. m_bPenSystem = GetSystemMetrics( SM_PENWINDOWS )? TRUE: FALSE;
  477. m_bPaletted = (pdc->GetDeviceCaps( RASTERCAPS ) & RC_PALETTE);
  478. m_bMonoDevice = ((ScreenDeviceInfo.iBitsPixel
  479. * ScreenDeviceInfo.iPlanes) == 1);
  480. SetErrorMode( SEM_NOOPENFILEERRORBOX );
  481. }
  482. /***************************************************************************/
  483. CPoint CPBApp::CheckWindowPosition( CPoint ptPosition, CSize& sizeWindow )
  484. {
  485. CPoint ptNew = ptPosition;
  486. sizeWindow.cx = max( sizeWindow.cx, 0 );
  487. sizeWindow.cy = max( sizeWindow.cy, 0 );
  488. if (sizeWindow.cx
  489. && sizeWindow.cy)
  490. {
  491. sizeWindow.cx = min( sizeWindow.cx, ScreenDeviceInfo.iWidthinPels );
  492. sizeWindow.cy = min( sizeWindow.cy, ScreenDeviceInfo.iHeightinPels );
  493. }
  494. ptNew.x = max( ptNew.x, 0 );
  495. ptNew.y = max( ptNew.y, 0 );
  496. if (ptNew.x
  497. && ptNew.y)
  498. {
  499. if (ptNew.x >= ScreenDeviceInfo.iWidthinPels)
  500. ptNew.x = ScreenDeviceInfo.iWidthinPels - sizeWindow.cx;
  501. if (ptNew.y >= ScreenDeviceInfo.iHeightinPels)
  502. ptNew.y = ScreenDeviceInfo.iHeightinPels - sizeWindow.cy;
  503. }
  504. return ptNew;
  505. }
  506. /***************************************************************************/
  507. void CPBApp::WinHelp( DWORD dwData, UINT nCmd /* = HELP_CONTEXT */ )
  508. {
  509. // This app has been converted to use HtmlHelp. This is a safety to prevent someone
  510. // from accidentally adding WinHelp calls for proceedural help
  511. ASSERT( (nCmd != HELP_FINDER) && (nCmd != HELP_INDEX) && (nCmd != HELP_CONTENTS) );
  512. CWinApp::WinHelp( dwData, nCmd );
  513. }
  514. /***************************************************************************/
  515. BOOL CPBApp::OnIdle( LONG lCount )
  516. {
  517. if (m_bHidden)
  518. return CWinApp::OnIdle( lCount );
  519. if (! lCount)
  520. {
  521. if (CheckForEmergency())
  522. {
  523. TryToFreeMemory();
  524. WarnUserOfEmergency();
  525. }
  526. if (m_nFileErrorCause != CFileException::none && m_pMainWnd)
  527. {
  528. CWnd* pWnd = AfxGetMainWnd();
  529. pWnd->PostMessage( WM_USER + 1001 );
  530. }
  531. }
  532. extern void IdleImage();
  533. IdleImage();
  534. return CWinApp::OnIdle(lCount) || lCount <= 4;
  535. }
  536. /***************************************************************************/
  537. // Map a file error code to a string id.
  538. struct FERRID
  539. {
  540. int ferr;
  541. int ids;
  542. } mpidsferr[] =
  543. {
  544. { ferrIllformedGroup, IDS_ERROR_BOGUSFILE },
  545. { ferrReadFailed, IDS_ERROR_BOGUSFILE }, // error while reading a file or file corupt
  546. { ferrIllformedFile, IDS_ERROR_BOGUSFILE }, // not a valid palette file or zero length pcx file
  547. { ferrCantProcNewExeHdr, IDS_ERROR_EXE_HDR },
  548. { ferrCantProcOldExeHdr, IDS_ERROR_EXE_HDR },
  549. { ferrBadMagicNewExe, IDS_ERROR_EXE_HDRMZ },
  550. { ferrBadMagicOldExe, IDS_ERROR_EXE_HDRMZ },
  551. { ferrNotWindowsExe, IDS_ERROR_EXE_HDRNW },
  552. { ferrExeWinVer3, IDS_ERROR_EXE_HDRWV },
  553. { ferrNotValidRc, IDS_ERROR_NOTVALID_RC },
  554. { ferrNotValidExe, IDS_ERROR_NOTVALID_EXE },
  555. { ferrNotValidRes, IDS_ERROR_NOTVALID_RES },
  556. { ferrNotValidBmp, IDS_ERROR_NOTVALID_BMP }, // invalid bitmap
  557. { ferrNotValidIco, IDS_ERROR_NOTVALID_ICO },
  558. { ferrNotValidCur, IDS_ERROR_NOTVALID_CUR },
  559. { ferrRcInvalidExt, IDS_ERROR_RCPROB },
  560. { ferrFileAlreadyOpen, IDS_ERROR_COMPEX },
  561. { ferrExeTooLarge, IDS_ERROR_EXE_ALIGN },
  562. { ferrCantCopyOldToNew, IDS_ERROR_EXE_SAVE },
  563. { ferrReadLoad, IDS_ERROR_READLOAD },
  564. { ferrExeAlloc, IDS_ERROR_EXE_ALLOC },
  565. { ferrExeInUse, IDS_ERROR_EXE_INUSE },
  566. { ferrExeEmpty, IDS_ERROR_EXE_EMPTY },
  567. { ferrGroup, IDS_ERROR_GROUP },
  568. { ferrResSave, IDS_ERROR_RES_SAVE },
  569. { ferrSaveOverOpen, IDS_ERROR_SAVEOVEROPEN },
  570. { ferrSaveOverReadOnly, IDS_ERROR_SAVERO },
  571. { ferrCantDetermineType, IDS_ERROR_WHAAAT }, // bad pcx file
  572. { ferrSameName, IDS_ERROR_SAMENAME },
  573. { ferrSaveAborted, IDS_ERROR_SAVE_ABORTED },
  574. { ferrLooksLikeNtRes, IDS_ERROR_NT_RES },
  575. { ferrCantSaveReadOnly, IDS_ERROR_CANT_SAVERO }, // trying to save over a read only file
  576. };
  577. int IdsFromFerr(int ferr)
  578. {
  579. if (ferr < ferrFirst)
  580. return IDS_ERROR_FILE + ferr; // was an exception cause
  581. for (int i = 0; i < sizeof (mpidsferr) / sizeof (FERRID); i++)
  582. {
  583. if (mpidsferr[i].ferr == ferr)
  584. return mpidsferr[i].ids;
  585. }
  586. ASSERT(FALSE); // You forgot to stick an entry in the above table!
  587. return 0;
  588. }
  589. /***************************************************************************/
  590. // Display a message box informing the user of a file related exception.
  591. // The format of the box is something like:
  592. //
  593. // <file name>
  594. // <operation failed>
  595. // <reason>
  596. //
  597. // <file name> describes what file has the problem, <operation files>
  598. // indicated what kind of thing failed (e.g. "Cannot save file"), and
  599. // <reason> provides more information about why the operation failed
  600. // (e.g. "Disk full").
  601. //
  602. // All the parameters must have been setup previously via a call to
  603. // CWinApp::SetFileError().
  604. //
  605. void CPBApp::FileErrorMessageBox( void )
  606. {
  607. static BOOL bInUse = FALSE;
  608. if (m_nFileErrorCause != CFileException::none && ! bInUse)
  609. {
  610. bInUse = TRUE;
  611. CString strOperation;
  612. VERIFY( strOperation.LoadString( m_uOperation ) );
  613. CString strReason;
  614. VERIFY( strReason.LoadString( IdsFromFerr( m_nFileErrorCause ) ) );
  615. CString strFmt;
  616. CString strMsg;
  617. if (m_sLastFile.IsEmpty())
  618. {
  619. strFmt.LoadString(IDS_FORMATERR_NOFILE);
  620. strMsg.Format(strFmt, (LPCTSTR)strOperation, (LPCTSTR)strReason);
  621. }
  622. else
  623. {
  624. strFmt.LoadString(IDS_FORMATERR_FILE);
  625. strMsg.Format(strFmt, (LPCTSTR)m_sLastFile, (LPCTSTR)strOperation, (LPCTSTR)strReason);
  626. }
  627. AfxMessageBox( strMsg, MB_TASKMODAL | MB_OK | MB_ICONEXCLAMATION );
  628. bInUse = FALSE;
  629. }
  630. m_nFileErrorCause = CFileException::none;
  631. }
  632. /***************************************************************************/
  633. void CPBApp::SetFileError( UINT uOperation, int nCause, LPCTSTR lpszFile )
  634. {
  635. m_nFileErrorCause = nCause;
  636. m_uOperation = uOperation;
  637. if (lpszFile)
  638. m_sLastFile = lpszFile;
  639. }
  640. /***************************************************************************/
  641. // Memory/resource emergency handling functions
  642. void CPBApp::SetMemoryEmergency(BOOL bFailed)
  643. {
  644. TRACE(TEXT("Memory emergency!\n"));
  645. m_wEmergencyFlags |= memoryEmergency | warnEmergency;
  646. if (bFailed)
  647. m_wEmergencyFlags |= failedEmergency;
  648. }
  649. /***************************************************************************/
  650. void CPBApp::SetGdiEmergency(BOOL bFailed)
  651. {
  652. TRACE(TEXT("GDI emergency!\n"));
  653. m_wEmergencyFlags |= gdiEmergency | warnEmergency;
  654. if (bFailed)
  655. m_wEmergencyFlags |= failedEmergency;
  656. }
  657. /***************************************************************************/
  658. void CPBApp::SetUserEmergency(BOOL bFailed)
  659. {
  660. TRACE(TEXT("USER emergency!\n"));
  661. m_wEmergencyFlags |= userEmergency | warnEmergency;
  662. if (bFailed)
  663. m_wEmergencyFlags |= failedEmergency;
  664. }
  665. /***************************************************************************/
  666. void CPBApp::WarnUserOfEmergency()
  667. {
  668. if ((m_wEmergencyFlags & warnEmergency) == 0)
  669. {
  670. // We have nothing to warn the user about!
  671. return;
  672. }
  673. if ((m_wEmergencyFlags & failedEmergency) == 0 &&
  674. GetTickCount() < m_tickLastWarning + ticksBetweenWarnings)
  675. {
  676. // We've warned the user recently, so keep quiet for now...
  677. // The warning flag is cleared so we don't just warn the
  678. // user after the delay is up unless another emergency
  679. // occurs AFTER then...
  680. m_wEmergencyFlags &= ~warnEmergency;
  681. return;
  682. }
  683. // Don't go invoking message boxes when we're not the active app!
  684. if (! m_bActiveApp)
  685. return;
  686. const TCHAR* szMsg = (m_wEmergencyFlags & failedEmergency) != 0 ?
  687. m_strEmergencyNoMem : m_strEmergencyLowMem;
  688. if (AfxMessageBox(szMsg, MB_TASKMODAL | MB_OK | MB_ICONSTOP) == IDOK)
  689. {
  690. m_wEmergencyFlags &= ~(warnEmergency | failedEmergency);
  691. m_tickLastWarning = GetTickCount();
  692. }
  693. #ifdef _DEBUG
  694. else
  695. TRACE(TEXT("Emergency warning message box failed!\n"));
  696. #endif
  697. // Update status bar warning message...
  698. if ( ::IsWindow( ((CPBFrame*)m_pMainWnd)->m_statBar.m_hWnd ) )
  699. ((CPBFrame*)m_pMainWnd)->m_statBar.Invalidate(FALSE);
  700. }
  701. /***************************************************************************/
  702. void CPBApp::TryToFreeMemory()
  703. {
  704. // We are in a memory/resource emergency state! Add things to this
  705. // function to flush caches and do anything else to free up memory
  706. // we don't really need to be using right now...
  707. if (m_wEmergencyFlags & memoryEmergency)
  708. {
  709. CPBDoc* pDoc = (CPBDoc*)((CFrameWnd*)AfxGetMainWnd())->GetActiveDocument();
  710. if (pDoc && pDoc->m_pBitmapObj && ! pDoc->m_pBitmapObj->IsDirty()
  711. && pDoc->m_pBitmapObj->m_hThing)
  712. pDoc->m_pBitmapObj->Free();
  713. }
  714. if (m_wEmergencyFlags & gdiEmergency)
  715. {
  716. // theUndo.Flush();
  717. ResetSysBrushes();
  718. }
  719. }
  720. /***************************************************************************/
  721. // App command to run the dialog
  722. void CPBApp::OnAppAbout()
  723. {
  724. CString sTitle;
  725. CString sBrag;
  726. HICON hIcon = LoadIcon( ID_MAINFRAME );
  727. sTitle.LoadString( AFX_IDS_APP_TITLE );
  728. sBrag.LoadString( IDS_PerContractSoDontChange );
  729. ShellAbout( AfxGetMainWnd()->GetSafeHwnd(), sTitle, sBrag, hIcon );
  730. if (hIcon != NULL)
  731. ::DestroyIcon( hIcon );
  732. }
  733. /***************************************************************************/
  734. void CPBApp::SetDeviceHandles(HANDLE hDevNames, HANDLE hDevMode)
  735. {
  736. // The old ones should already be freed
  737. m_hDevNames = hDevNames;
  738. m_hDevMode = hDevMode;
  739. }
  740. /***************************************************************************/
  741. #if 0
  742. class CFileOpenSaveDlg : public CFileDialog
  743. {
  744. public:
  745. BOOL m_bOpenFile;
  746. CFileOpenSaveDlg( BOOL bOpenFileDialog );
  747. virtual void OnLBSelChangedNotify( UINT nIDBox, UINT iCurSel, UINT nCode );
  748. DECLARE_MESSAGE_MAP()
  749. };
  750. /***************************************************************************/
  751. BEGIN_MESSAGE_MAP(CFileOpenSaveDlg, CFileDialog)
  752. END_MESSAGE_MAP()
  753. /***************************************************************************/
  754. CFileOpenSaveDlg::CFileOpenSaveDlg( BOOL bOpenFileDialog )
  755. :CFileDialog( bOpenFileDialog )
  756. {
  757. m_bOpenFile = bOpenFileDialog;
  758. }
  759. /***************************************************************************/
  760. void CFileOpenSaveDlg::OnLBSelChangedNotify( UINT nIDBox, UINT iCurSel, UINT nCode )
  761. {
  762. if (! m_bOpenFile && iCurSel <= 5 && nIDBox == cmb1
  763. && nCode == CD_LBSELCHANGE)
  764. {
  765. // change in the file type
  766. CWnd* pText = GetDlgItem( edt1 );
  767. CWnd* pType = GetDlgItem( cmb1 );
  768. CString sFname;
  769. CString sDfltExt;
  770. switch (iCurSel)
  771. {
  772. #ifdef PCX_SUPPORT
  773. case 4:
  774. sDfltExt.LoadString( IDS_EXTENSION_PCX );
  775. break;
  776. #endif
  777. case 5:
  778. sDfltExt.LoadString( IDS_EXTENSION_ICO );
  779. break;
  780. default:
  781. sDfltExt.LoadString( IDS_EXTENSION_BMP );
  782. break;
  783. }
  784. pText->GetWindowText( sFname );
  785. if (sDfltExt.CompareNoCase( GetExtension( sFname ) ))
  786. {
  787. sFname = StripExtension( sFname ) + sDfltExt;
  788. pText->SetWindowText( sFname );
  789. }
  790. }
  791. }
  792. #endif //0
  793. /***************************************************************************/
  794. extern BOOL AFXAPI AfxFullPath( LPTSTR lpszPathOut, LPCTSTR lpszFileIn );
  795. CDocument*
  796. CPBApp::OpenDocumentFile(
  797. LPCTSTR lpszFileName
  798. )
  799. {
  800. CancelToolMode(FALSE);
  801. TCHAR szPath[_MAX_PATH];
  802. AfxFullPath( szPath, lpszFileName );
  803. return(m_pDocManager->OpenDocumentFile(szPath));
  804. // CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
  805. //
  806. // ASSERT( pTemplate->IsKindOf( RUNTIME_CLASS( CDocTemplate ) ) );
  807. //
  808. // return pTemplate->OpenDocumentFile( szPath );
  809. }
  810. void CancelToolMode(BOOL bSelectionCommand)
  811. {
  812. if (bSelectionCommand)
  813. {
  814. // Check if a selection tool is the current one
  815. if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL)
  816. || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL))
  817. {
  818. // Don't try canceling the mode, since the command works on a
  819. // selection
  820. return;
  821. }
  822. }
  823. // Just select the current tool again to reset everything
  824. CImgTool *pImgTool = CImgTool::GetCurrent();
  825. if (pImgTool)
  826. {
  827. pImgTool->Select();
  828. }
  829. }
  830. /***************************************************************************/
  831. // CPBApp commands
  832. void CPBApp::OnFileNew()
  833. {
  834. CancelToolMode(FALSE);
  835. CWinApp::OnFileNew();
  836. }
  837. void CPBApp::OnFileOpen()
  838. {
  839. CancelToolMode(FALSE);
  840. // prompt the user (with all document templates)
  841. CString newName;
  842. int iColor = 0;
  843. if (! DoPromptFileName( newName, AFX_IDS_OPENFILE,
  844. OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
  845. TRUE, iColor, FALSE ))
  846. return; // open cancelled
  847. #ifdef PCX_SUPPORT
  848. m_bPCXfile = (iColor == 4);
  849. #endif
  850. CPBDoc* pDoc = (CPBDoc*)((CFrameWnd*)AfxGetMainWnd())->GetActiveDocument();
  851. // prompt to save the current document if it was modified
  852. if (pDoc && pDoc->SaveModified())
  853. {
  854. pDoc->SetModifiedFlag(FALSE);
  855. if (OpenDocumentFile( newName )==NULL)
  856. {
  857. // attempt to open a file failed, so make sure any new doc just
  858. // created in the process gets destroyed
  859. POSITION tPos = GetFirstDocTemplatePosition();
  860. CDocTemplate* pTemplate = GetNextDocTemplate(tPos);
  861. POSITION dPos = pTemplate->GetFirstDocPosition ();
  862. CPBDoc *pDoc= (CPBDoc *)(pTemplate->GetNextDoc(dPos));
  863. if (pDoc->m_pBitmapObjNew)
  864. {
  865. delete pDoc->m_pBitmapObjNew;
  866. pDoc->m_pBitmapObjNew =NULL;
  867. }
  868. OnFileNew(); // then start anew...
  869. }
  870. }
  871. }
  872. /****************************************************************************/
  873. // prompt for file name - used for open and save as
  874. BOOL CPBApp::DoPromptFileName( CString& fileName, UINT nIDSTitle, DWORD lFlags,
  875. BOOL bOpenFileDialog, int& iColors, BOOL bOnlyBmp )
  876. {
  877. COpenFileName dlgFile( bOpenFileDialog );
  878. ASSERT(dlgFile.m_pofn);
  879. if (!dlgFile.m_pofn)
  880. return FALSE;
  881. CString title;
  882. VERIFY( title.LoadString( nIDSTitle ) );
  883. lFlags |= OFN_EXPLORER;
  884. if (!bOpenFileDialog)
  885. lFlags |= OFN_OVERWRITEPROMPT;
  886. dlgFile.m_pofn->Flags |= lFlags;
  887. dlgFile.m_pofn->Flags &= ~OFN_SHOWHELP;
  888. CString strFilter;
  889. // CString strDefault;
  890. CDocTemplate* pTemplate = NULL;
  891. POSITION pos = m_pDocManager->GetFirstDocTemplatePosition();
  892. if (pos != NULL)
  893. pTemplate = m_pDocManager->GetNextDocTemplate(pos);
  894. CString strFilterExt;
  895. CString strFilterName;
  896. CString strAllPictureFiles;
  897. ASSERT(pTemplate != NULL);
  898. pTemplate->GetDocString( strFilterExt , CDocTemplate::filterExt );
  899. pTemplate->GetDocString( strFilterName, CDocTemplate::filterName );
  900. ASSERT( strFilterExt[0] == TEXT('.') );
  901. // set the default extension
  902. // strDefault = ((const TCHAR*)strFilterExt) + 1; // skip the '.'
  903. // dlgFile.m_pofn->nFilterIndex = iColors + 1; // 1 based number
  904. dlgFile.m_pofn->lpstrDefExt = ((LPCTSTR)strFilterExt) + 1; // skip the '.'
  905. if (bOpenFileDialog)
  906. {
  907. // add to filter
  908. strFilter = strFilterName;
  909. strFilter += _T('\0'); // next string please
  910. strFilter += _T("*") + strFilterExt;
  911. VERIFY(strFilterExt.LoadString(IDS_EXTENSION_DIB));
  912. strFilter += _T(";*") + strFilterExt;
  913. strAllPictureFiles += _T(";*") + strFilterExt;
  914. VERIFY(strFilterExt.LoadString(IDS_EXTENSION_BMP));
  915. strAllPictureFiles += _T(";*") + strFilterExt;
  916. VERIFY(strFilterExt.LoadString(IDS_EXTENSION_RLE));
  917. strFilter += _T(";*") + strFilterExt;
  918. strFilter += _T('\0'); // next string please
  919. dlgFile.m_pofn->nMaxCustFilter++;
  920. }
  921. else
  922. {
  923. for (int i = IDS_BMP_MONO; i <= IDS_BMP_TRUECOLOR; i++)
  924. {
  925. strFilterName.LoadString( i );
  926. // add to filter
  927. strFilter += strFilterName;
  928. strFilter += _T('\0'); // next string please
  929. strFilter += _T("*") + strFilterExt;
  930. strFilter += _T('\0'); // next string please
  931. dlgFile.m_pofn->nMaxCustFilter++;
  932. }
  933. }
  934. // get a list of GDI+ codecs (if available)
  935. Gdiplus::ImageCodecInfo *pCodecs = 0;
  936. UINT nCodecs = 0;
  937. if (bOpenFileDialog)
  938. {
  939. GetGdiplusDecoders(&nCodecs, &pCodecs);
  940. }
  941. else
  942. {
  943. GetGdiplusEncoders(&nCodecs, &pCodecs);
  944. }
  945. if (nCodecs && !bOnlyBmp)
  946. {
  947. delete [] m_guidFltType;
  948. m_guidFltType = new GUID[nCodecs];
  949. m_nFilters = 0;
  950. for (UINT i = 0; i < nCodecs; ++i)
  951. {
  952. if (pCodecs[i].FormatID != WiaImgFmt_BMP &&
  953. pCodecs[i].FormatID != WiaImgFmt_EMF &&
  954. pCodecs[i].FormatID != WiaImgFmt_WMF) // GDI+ does not handle WMF/EMF well
  955. {
  956. m_guidFltType[m_nFilters++] = pCodecs[i].FormatID;
  957. strFilter += pCodecs[i].FormatDescription;
  958. strFilter += _T(" (");
  959. strFilter += pCodecs[i].FilenameExtension;
  960. strFilter += _T(')');
  961. strFilter += _T('\0'); // next string please
  962. strFilter += pCodecs[i].FilenameExtension;
  963. strFilter += _T('\0'); // next string please
  964. strAllPictureFiles += _T(';');
  965. strAllPictureFiles += pCodecs[i].FilenameExtension;
  966. dlgFile.m_pofn->nMaxCustFilter++;
  967. }
  968. }
  969. LocalFree(pCodecs);
  970. }
  971. else
  972. {
  973. //
  974. // get list of all installed filters and add those to the list...
  975. //
  976. delete [] m_guidFltType;
  977. m_guidFltType = new GUID[16]; // max # of filters
  978. TCHAR name[128];
  979. TCHAR ext[sizeof("jpg;*.jpeg") + 1];
  980. BOOL bImageAPI;
  981. for (int i=0, j=0; !bOnlyBmp && GetInstalledFilters(bOpenFileDialog,
  982. i, name, sizeof(name), ext, sizeof(ext), NULL, 0, bImageAPI); i++)
  983. {
  984. if (!bImageAPI)
  985. {
  986. continue;
  987. }
  988. if (ext[0] == 0 || name[0] == 0)
  989. continue;
  990. // if there are multiple extensions, take the first one...
  991. PTSTR pComma = _tcschr(ext, _T(','));
  992. if (pComma)
  993. *pComma = 0;
  994. PTSTR pSemiColon = _tcschr(ext, _T(';'));
  995. if (pSemiColon)
  996. *pSemiColon = 0;
  997. PTSTR pSpace = _tcschr(ext, _T(' '));
  998. if (pSpace)
  999. *pSpace = 0;
  1000. if (lstrlen(ext) > 3)
  1001. continue;
  1002. // dont show these, we already handle these
  1003. if (lstrcmpi(ext,_T("bmp")) == 0 ||
  1004. lstrcmpi(ext,_T("dib")) == 0 ||
  1005. lstrcmpi(ext,_T("rle")) == 0)
  1006. continue;
  1007. #ifndef GIF_SUPPORT
  1008. if (lstrcmpi(ext, _T("gif") == 0)
  1009. {
  1010. continue;
  1011. }
  1012. #endif
  1013. #if 0 // only use known good filters
  1014. if (!g_bShowAllFiles &&
  1015. (GetKeyState(VK_SHIFT) & 0x8000) == 0 &&
  1016. lstrcmpi(ext,_T("pcx")) != 0)
  1017. continue;
  1018. #endif
  1019. // save a list of available filter types
  1020. if (lstrcmpi(ext,_T("gif")) == 0)
  1021. {
  1022. m_guidFltType[j++] = WiaImgFmt_GIF;
  1023. }
  1024. else if (lstrcmpi(ext,_T("jpg")) == 0)
  1025. {
  1026. m_guidFltType[j++] = WiaImgFmt_JPEG;
  1027. _tcscat (ext, _T(";*.jpeg"));
  1028. }
  1029. #ifdef SUPPORT_ALL_FILTERS
  1030. else if (lstrcmpi(ext,_T("png")) == 0)
  1031. {
  1032. #ifdef PNG_SUPPORT
  1033. m_guidFltType[j++] = WiaImgFmt_PNG;
  1034. #else
  1035. continue;
  1036. #endif // PNG_SUPPORT
  1037. }
  1038. else if (lstrcmpi(ext,_T("pcd")) == 0)
  1039. {
  1040. m_guidFltType[j++] = WiaImgFmt_PHOTOCD;
  1041. }
  1042. /*else if (lstrcmpi(ext,_T("pic")) == 0)
  1043. {
  1044. m_guidFltType[j++] = IFLT_PICT;
  1045. _tcscat(ext, _T(";*.pict"));
  1046. }
  1047. else if (lstrcmpi(ext,_T("tga")) == 0)
  1048. {
  1049. m_iflFltType[j++] = IFLT_TGA;
  1050. }*/
  1051. else if (lstrcmpi(ext,_T("tif")) == 0)
  1052. {
  1053. m_guidFltType[j++] = WiaImgFmt_TIFF;
  1054. _tcscat(ext, _T(";*.tiff"));
  1055. }
  1056. else
  1057. {
  1058. m_guidFltType[j++] = WiaImgFmt_UNDEFINED;
  1059. }
  1060. #else
  1061. else continue;
  1062. #endif
  1063. // add to filter
  1064. strFilter += name;
  1065. strFilter += _T(" ( *.");
  1066. strFilter += ext;
  1067. strFilter += _T(" )");
  1068. strFilter += _T('\0'); // next string please
  1069. strFilter += _T("*.");
  1070. strFilter += ext;
  1071. strFilter += _T('\0'); // next string please
  1072. strAllPictureFiles = strAllPictureFiles + _T(";*.")+ext;
  1073. dlgFile.m_pofn->nMaxCustFilter++;
  1074. }
  1075. }
  1076. if (!bOnlyBmp && bOpenFileDialog)
  1077. {
  1078. // append "All Picture Files" only if opening a file
  1079. VERIFY(strFilterName.LoadString(IDS_TYPE_ALLPICTURES));
  1080. strFilter+= strFilterName;
  1081. strFilter += _T('\0');
  1082. strFilter += strAllPictureFiles;
  1083. strFilter += _T('\0');
  1084. dlgFile.m_pofn->nMaxCustFilter++;
  1085. if (m_nFilterInIdx == -1)
  1086. {
  1087. m_nFilterInIdx = dlgFile.m_pofn->nMaxCustFilter;
  1088. }
  1089. // append the "*.*" filter only if "Open"ing a file
  1090. VERIFY( strFilterName.LoadString( IDS_TYPE_ALLFILES ) );
  1091. strFilter += strFilterName;
  1092. strFilter += _T('\0'); // next string please
  1093. strFilter += _T("*.*");
  1094. strFilter += _T('\0'); // last string
  1095. dlgFile.m_pofn->nMaxCustFilter++;
  1096. }
  1097. // prompt the user with the appropriate filter pre-selected
  1098. if (bOpenFileDialog)
  1099. {
  1100. dlgFile.m_pofn->nFilterIndex = m_nFilterInIdx;
  1101. }
  1102. else
  1103. {
  1104. DWORD dwIndex;
  1105. if (m_guidFltTypeUsed != WiaImgFmt_UNDEFINED &&
  1106. (dwIndex = GetFilterIndex(m_guidFltTypeUsed))) // has an export filter?
  1107. dlgFile.m_pofn->nFilterIndex = dwIndex + 4; // skip the first 4 BMP types
  1108. else if (m_nFilterOutIdx >= 4)
  1109. dlgFile.m_pofn->nFilterIndex = m_nFilterOutIdx;
  1110. else
  1111. dlgFile.m_pofn->nFilterIndex = iColors + 1; // 1 based number
  1112. }
  1113. dlgFile.m_pofn->lpstrFilter = strFilter;
  1114. dlgFile.m_pofn->hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
  1115. dlgFile.m_pofn->hInstance = AfxGetResourceHandle();
  1116. dlgFile.m_pofn->lpstrTitle = title;
  1117. dlgFile.m_pofn->lpstrFile = fileName.GetBuffer(_MAX_PATH);
  1118. dlgFile.m_pofn->nMaxFile = _MAX_PATH;
  1119. TCHAR szInitPath[MAX_PATH];
  1120. ::LoadString (GetModuleHandle (NULL), AFX_IDS_UNTITLED, szInitPath, MAX_PATH);
  1121. //
  1122. // Look in "My Documents" on NT 5, Win98, and later.
  1123. //
  1124. if (!theApp.GetLastFile() || !*(theApp.GetLastFile()))
  1125. {
  1126. static SHSPECPATH pfnSpecialPath = NULL;
  1127. if (!pfnSpecialPath)
  1128. {
  1129. #ifdef UNICODE
  1130. pfnSpecialPath = (SHSPECPATH)GetProcAddress (
  1131. GetModuleHandle(_T("shell32.dll")),
  1132. "SHGetSpecialFolderPathW");
  1133. #else
  1134. pfnSpecialPath = (SHSPECPATH)GetProcAddress (
  1135. GetModuleHandle(_T("shell32.dll")),
  1136. "SHGetSpecialFolderPathA");
  1137. #endif //UNICODE
  1138. }
  1139. if (pfnSpecialPath)
  1140. {
  1141. (pfnSpecialPath)(NULL, szInitPath, CSIDL_MYPICTURES, FALSE);
  1142. dlgFile.m_pofn->lpstrInitialDir = szInitPath;
  1143. }
  1144. }
  1145. BOOL bRet = dlgFile.DoModal() == IDOK? TRUE : FALSE;
  1146. fileName.ReleaseBuffer();
  1147. // keep track of the filter selected by the user
  1148. if (bOpenFileDialog)
  1149. m_nFilterInIdx = dlgFile.m_pofn->nFilterIndex;
  1150. else
  1151. m_nFilterOutIdx = dlgFile.m_pofn->nFilterIndex;
  1152. iColors = (int)dlgFile.m_pofn->nFilterIndex - 1;
  1153. CString sExt = dlgFile.m_pofn->lpstrFile + dlgFile.m_pofn->nFileExtension;
  1154. #ifdef ICO_SUPPORT
  1155. if (! bOpenFileDialog && dlgFile.m_pofn->nFileExtension)
  1156. // did the user try to sneak a icon extension past us
  1157. if (! sExt.CompareNoCase( ((const TCHAR *)strFilterExt) + 1 ))
  1158. iColors = 5;
  1159. #endif
  1160. return bRet;
  1161. }
  1162. DWORD CPBApp::GetFilterIndex( REFGUID guidFltType )
  1163. {
  1164. for (int i = 0; i < m_nFilters; i++)
  1165. if (m_guidFltType[i] == guidFltType)
  1166. return i+1;
  1167. return 0;
  1168. }
  1169. // fix the file extension based on export filter selected - used for save as
  1170. void CPBApp::FixExtension( CString& fileName, int iflFltType )
  1171. {
  1172. CString sDfltExt;
  1173. switch (iflFltType)
  1174. {
  1175. case IFLT_GIF:
  1176. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_GIF ));
  1177. break;
  1178. case IFLT_JPEG:
  1179. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_JPEG ));
  1180. break;
  1181. case IFLT_PCD:
  1182. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PCD ));
  1183. break;
  1184. case IFLT_PCX:
  1185. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PCX ));
  1186. break;
  1187. case IFLT_PICT:
  1188. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PICT ));
  1189. break;
  1190. #ifdef PNG_SUPPORT
  1191. case IFLT_PNG:
  1192. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_PNG ));
  1193. break;
  1194. #endif // PNG_SUPPORT
  1195. case IFLT_TGA:
  1196. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_TGA ));
  1197. break;
  1198. case IFLT_TIFF:
  1199. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_TIFF ));
  1200. break;
  1201. case IFLT_UNKNOWN: // unknown or unsupported file type
  1202. default:
  1203. VERIFY(sDfltExt.LoadString( IDS_EXTENSION_BMP ));
  1204. break;
  1205. }
  1206. if (sDfltExt.CompareNoCase( GetExtension( (LPCTSTR)fileName ) ))
  1207. {
  1208. fileName = StripExtension( fileName ) + sDfltExt;
  1209. }
  1210. }
  1211. #if 0
  1212. // Pulling self-registration out. This is to be done once during setup only
  1213. /***************************************************************************/
  1214. // Mostly stolen from MFC
  1215. // I made no attempt to strip out stuff I do not actually use
  1216. // I just modified this so it used short module file name
  1217. //
  1218. //////////////////////////////////////////////////////////////////////////////
  1219. // data for UpdateRegistry functionality
  1220. // %1 - class ID
  1221. // %2 - class name
  1222. // %3 - executable path
  1223. // %4 - short type name
  1224. // %5 - long type name
  1225. // %6 - long application name
  1226. // %7 - icon index
  1227. static const TCHAR sz00[] = TEXT("%2\0") TEXT("%5");
  1228. static const TCHAR sz01[] = TEXT("%2\\CLSID\0") TEXT("%1");
  1229. static const TCHAR sz02[] = TEXT("%2\\Insertable\0") TEXT("");
  1230. static const TCHAR sz03[] = TEXT("%2\\protocol\\StdFileEditing\\verb\\0\0") TEXT("&Edit");
  1231. static const TCHAR sz04[] = TEXT("%2\\protocol\\StdFileEditing\\server\0") TEXT("%3");
  1232. static const TCHAR sz05[] = TEXT("CLSID\\%1\0") TEXT("%5");
  1233. static const TCHAR sz06[] = TEXT("CLSID\\%1\\ProgID\0") TEXT("%2");
  1234. #ifndef _USRDLL
  1235. static const TCHAR sz07[] = TEXT("CLSID\\%1\\InprocHandler32\0") TEXT("ole32.dll");
  1236. static const TCHAR sz08[] = TEXT("CLSID\\%1\\LocalServer32\0") TEXT("%3");
  1237. #else
  1238. static const TCHAR sz07[] = TEXT("\0") TEXT("");
  1239. static const TCHAR sz08[] = TEXT("CLSID\\%1\\InProcServer32\0") TEXT("%3");
  1240. #endif
  1241. static const TCHAR sz09[] = TEXT("CLSID\\%1\\Verb\\0\0") TEXT("&Edit,0,2");
  1242. static const TCHAR sz10[] = TEXT("CLSID\\%1\\Verb\\1\0") TEXT("&Open,0,2");
  1243. static const TCHAR sz11[] = TEXT("CLSID\\%1\\Insertable\0") TEXT("");
  1244. static const TCHAR sz12[] = TEXT("CLSID\\%1\\AuxUserType\\2\0") TEXT("%4");
  1245. static const TCHAR sz13[] = TEXT("CLSID\\%1\\AuxUserType\\3\0") TEXT("%6");
  1246. static const TCHAR sz14[] = TEXT("CLSID\\%1\\DefaultIcon\0") TEXT("%3,%7");
  1247. static const TCHAR sz15[] = TEXT("CLSID\\%1\\MiscStatus\0") TEXT("32");
  1248. // registration for OAT_INPLACE_SERVER
  1249. static const LPCTSTR rglpszInPlaceRegister[] =
  1250. {
  1251. sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12,
  1252. sz13, sz15, NULL
  1253. };
  1254. // registration for OAT_SERVER
  1255. static const LPCTSTR rglpszServerRegister[] =
  1256. {
  1257. sz00, sz02, sz03, sz05, sz09, sz11, sz12,
  1258. sz13, sz15, NULL
  1259. };
  1260. // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER
  1261. static const LPCTSTR rglpszServerOverwrite[] =
  1262. {
  1263. sz01, sz04, sz06, sz07, sz08, sz14, NULL
  1264. };
  1265. // registration for OAT_CONTAINER
  1266. static const LPCTSTR rglpszContainerRegister[] =
  1267. {
  1268. sz00, sz05, NULL
  1269. };
  1270. // overwrite entries for OAT_CONTAINER
  1271. static const LPCTSTR rglpszContainerOverwrite[] =
  1272. {
  1273. sz01, sz06, sz07, sz08, sz14, NULL
  1274. };
  1275. // registration for OAT_DISPATCH_OBJECT
  1276. static const LPCTSTR rglpszDispatchRegister[] =
  1277. {
  1278. sz00, sz05, NULL
  1279. };
  1280. // overwrite entries for OAT_CONTAINER
  1281. static const LPCTSTR rglpszDispatchOverwrite[] =
  1282. {
  1283. sz01, sz06, sz08, NULL
  1284. };
  1285. struct STANDARD_ENTRY
  1286. {
  1287. const LPCTSTR* rglpszRegister;
  1288. const LPCTSTR* rglpszOverwrite;
  1289. };
  1290. static const STANDARD_ENTRY rgStdEntries[] =
  1291. {
  1292. { rglpszInPlaceRegister, rglpszServerOverwrite },
  1293. { rglpszServerRegister, rglpszServerOverwrite },
  1294. { rglpszContainerRegister, rglpszContainerOverwrite },
  1295. { rglpszDispatchRegister, rglpszDispatchOverwrite }
  1296. };
  1297. /////////////////////////////////////////////////////////////////////////////
  1298. // Special registration for apps that wish not to use REGLOAD
  1299. BOOL AFXAPI PBOleRegisterServerClass(
  1300. REFCLSID clsid, LPCTSTR lpszClassName,
  1301. LPCTSTR lpszShortTypeName, LPCTSTR lpszLongTypeName,
  1302. OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite)
  1303. {
  1304. ASSERT(AfxIsValidString(lpszClassName));
  1305. ASSERT(AfxIsValidString(lpszShortTypeName));
  1306. ASSERT(*lpszShortTypeName != 0);
  1307. ASSERT(AfxIsValidString(lpszLongTypeName));
  1308. ASSERT(*lpszLongTypeName != 0);
  1309. ASSERT(nAppType == OAT_INPLACE_SERVER || nAppType == OAT_SERVER ||
  1310. nAppType == OAT_CONTAINER || nAppType == OAT_DISPATCH_OBJECT);
  1311. // use standard registration entries if non given
  1312. if (rglpszRegister == NULL)
  1313. rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister;
  1314. if (rglpszOverwrite == NULL)
  1315. rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite;
  1316. LPTSTR rglpszSymbols[7];
  1317. // 0 - class ID
  1318. // 1 - class name
  1319. // 2 - executable path
  1320. // 3 - short type name
  1321. // 4 - long type name
  1322. // 5 - long application name
  1323. // 6 - icon index
  1324. // convert the CLSID to a string
  1325. LPWSTR lpszClassID;
  1326. ::StringFromCLSID(clsid, &lpszClassID);
  1327. if (lpszClassID == NULL)
  1328. {
  1329. TRACE0("Warning: StringFromCLSID failed in AfxOleRegisterServerName --\n");
  1330. TRACE0("\tperhaps AfxOleInit() has not been called.\n");
  1331. return FALSE;
  1332. }
  1333. #ifdef UNICODE
  1334. rglpszSymbols[0] = lpszClassID;
  1335. #else
  1336. int cc = WideCharToMultiByte (CP_ACP, 0, lpszClassID, -1,
  1337. (LPSTR)&rglpszSymbols[0], 0,
  1338. NULL, NULL);
  1339. rglpszSymbols[0] = (LPSTR)new char[cc];
  1340. WideCharToMultiByte (CP_ACP, 0, lpszClassID, -1,
  1341. rglpszSymbols[0], cc,
  1342. NULL, NULL);
  1343. #endif // UNICODE
  1344. rglpszSymbols[1] = (LPTSTR)lpszClassName;
  1345. // get path name to server
  1346. TCHAR szPathName[_MAX_PATH];
  1347. LPTSTR pszTemp = szPathName;
  1348. ::GetShortModuleFileName(AfxGetInstanceHandle(), pszTemp, _MAX_PATH);
  1349. rglpszSymbols[2] = szPathName;
  1350. // fill in rest of symbols
  1351. rglpszSymbols[3] = (LPTSTR)lpszShortTypeName;
  1352. rglpszSymbols[4] = (LPTSTR)lpszLongTypeName;
  1353. rglpszSymbols[5] = (LPTSTR)AfxGetAppName(); // will usually be long, readable name
  1354. LPCTSTR lpszIconIndex;
  1355. HICON hIcon = ExtractIcon(AfxGetInstanceHandle(), szPathName, 1);
  1356. if (hIcon != NULL)
  1357. {
  1358. lpszIconIndex = TEXT("1");
  1359. DestroyIcon(hIcon);
  1360. }
  1361. else
  1362. {
  1363. lpszIconIndex = TEXT("0");
  1364. }
  1365. rglpszSymbols[6] = (LPTSTR)lpszIconIndex;
  1366. // update the registry with helper function
  1367. BOOL bResult;
  1368. bResult = AfxOleRegisterHelper(rglpszRegister, (LPCTSTR*)rglpszSymbols, 7, FALSE);
  1369. if (bResult && rglpszOverwrite != NULL)
  1370. bResult = AfxOleRegisterHelper(rglpszOverwrite, (LPCTSTR*)rglpszSymbols, 7, TRUE);
  1371. // free memory for class ID
  1372. ASSERT(lpszClassID != NULL);
  1373. AfxFreeTaskMem(lpszClassID);
  1374. #ifndef UNICODE
  1375. delete[](LPSTR)rglpszSymbols[0];
  1376. #endif
  1377. return bResult;
  1378. }
  1379. void CPBTemplateServer::UpdateRegistry(OLE_APPTYPE nAppType,
  1380. LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite)
  1381. {
  1382. ASSERT(m_pDocTemplate != NULL);
  1383. // get registration info from doc template string
  1384. CString strServerName;
  1385. CString strLocalServerName;
  1386. CString strLocalShortName;
  1387. if (!m_pDocTemplate->GetDocString(strServerName,
  1388. CDocTemplate::regFileTypeId) || strServerName.IsEmpty())
  1389. {
  1390. TRACE0("Error: not enough information in DocTemplate to register OLE server.\n");
  1391. return;
  1392. }
  1393. if (!m_pDocTemplate->GetDocString(strLocalServerName,
  1394. CDocTemplate::regFileTypeName))
  1395. strLocalServerName = strServerName; // use non-localized name
  1396. if (!m_pDocTemplate->GetDocString(strLocalShortName,
  1397. CDocTemplate::fileNewName))
  1398. strLocalShortName = strLocalServerName; // use long name
  1399. ASSERT(strServerName.Find(TEXT(' ')) == -1); // no spaces allowed
  1400. // place entries in system registry
  1401. if (!PBOleRegisterServerClass(m_clsid, strServerName, strLocalShortName,
  1402. strLocalServerName, nAppType, rglpszRegister, rglpszOverwrite))
  1403. {
  1404. // not fatal (don't fail just warn)
  1405. TRACE0("mspaint: Unable to register server class.\n");
  1406. }
  1407. }
  1408. #endif