Leaked source code of windows server 2003
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.

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