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.

1071 lines
29 KiB

  1. // pbrusdoc.cpp : implementation of the CPBDoc class
  2. //
  3. #include "stdafx.h"
  4. #include "global.h"
  5. #include "pbrush.h"
  6. #include "pbrusdoc.h"
  7. #include "pbrusfrm.h"
  8. #include "pbrusvw.h"
  9. #include "srvritem.h"
  10. #include "bmobject.h"
  11. #include "imgwnd.h"
  12. #include "imgsuprt.h"
  13. #include "imgwnd.h"
  14. #include "imgbrush.h"
  15. #include "imgbrush.h"
  16. #include "imgwell.h"
  17. #include "imgtools.h"
  18. #include "imgdlgs.h"
  19. #include "tedit.h"
  20. #include "t_text.h"
  21. #include "undo.h"
  22. #include "cmpmsg.h"
  23. #include "ferr.h"
  24. #include "loadimag.h"
  25. #include "saveimag.h"
  26. #include "colorsrc.h"
  27. #include "props.h"
  28. #include <shlobj.h>
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  32. #endif
  33. IMPLEMENT_DYNCREATE(CPBDoc, COleServerDoc)
  34. #include "memtrace.h"
  35. /***************************************************************************/
  36. // CPBDoc
  37. BEGIN_MESSAGE_MAP(CPBDoc, COleServerDoc)
  38. //{{AFX_MSG_MAP(CPBDoc)
  39. ON_COMMAND(ID_FILE_SAVE_COPY_AS, OnFileSaveCopyAs)
  40. ON_COMMAND(ID_FILE_SEND, OnFileSendMail)
  41. ON_COMMAND(ID_FILE_UPDATE, MyOnFileUpdate)
  42. ON_UPDATE_COMMAND_UI(ID_FILE_SEND, OnUpdateFileSendMail)
  43. //}}AFX_MSG_MAP
  44. END_MESSAGE_MAP()
  45. BEGIN_INTERFACE_MAP(CPBDoc, COleServerDoc)
  46. INTERFACE_PART(CPBDoc, IID_IPersistStorage, PBPersistStg)
  47. END_INTERFACE_MAP()
  48. /***************************************************************************/
  49. // CPBDoc construction/destruction
  50. CPBDoc::CPBDoc()
  51. {
  52. m_bObjectLoaded = FALSE;
  53. m_pBitmapObj = NULL;
  54. m_pBitmapObjNew = NULL;
  55. m_bNewDoc = TRUE;
  56. m_bPaintFormat = FALSE;
  57. m_bNonBitmapFile= FALSE;
  58. m_bSaveViaFilter= FALSE;
  59. m_bManualTruncate= FALSE;
  60. m_bHasSeenAFileError= FALSE;
  61. }
  62. /***************************************************************************/
  63. CPBDoc::~CPBDoc()
  64. {
  65. if (m_pBitmapObj)
  66. delete m_pBitmapObj;
  67. }
  68. /***************************************************************************/
  69. //
  70. // SetDibHandle replaces the current image with the DIB
  71. // indicated by hdib
  72. //
  73. void CPBDoc::SetDibHandle (HGLOBAL hDib)
  74. {
  75. CWaitCursor DisplayWaitCursor;
  76. if (m_pBitmapObj->ReadResource (hDib))
  77. {
  78. m_pBitmapObj->ReLoadImage (this);
  79. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) GlobalLock(hDib);
  80. if (lpbi)
  81. {
  82. if (lpbi->biBitCount == 1)
  83. {
  84. m_pBitmapObj->SetIntProp (P_Colors, 1);
  85. }
  86. GlobalUnlock(hDib);
  87. }
  88. m_pBitmapObj->SetDirty( TRUE );
  89. SetModifiedFlag( TRUE );
  90. if (theApp.m_bEmbedded)
  91. NotifyChanged();
  92. }
  93. }
  94. BOOL CPBDoc::OnNewDocument()
  95. {
  96. if (! Finish())
  97. return FALSE;
  98. m_bObjectLoaded = FALSE;
  99. m_bNewDoc = TRUE;
  100. m_bNonBitmapFile= FALSE;
  101. m_bSaveViaFilter= FALSE;
  102. m_sName.Empty();
  103. g_bUseTrans = FALSE;
  104. crTrans = TRANS_COLOR_NONE;
  105. theApp.m_sCurFile.Empty();
  106. if (! CreateNewDocument()
  107. || ! COleServerDoc::OnNewDocument())
  108. {
  109. if (m_pBitmapObjNew)
  110. {
  111. delete m_pBitmapObjNew;
  112. m_pBitmapObjNew = 0;
  113. }
  114. return FALSE;
  115. }
  116. return TRUE;
  117. }
  118. /***************************************************************************/
  119. BOOL CPBDoc::OnOpenDocument( const TCHAR* pszPathName )
  120. {
  121. m_bObjectLoaded = FALSE;
  122. m_bNonBitmapFile= FALSE;
  123. m_bSaveViaFilter= FALSE;
  124. g_bUseTrans = FALSE;
  125. crTrans = TRANS_COLOR_NONE;
  126. theApp.m_sCurFile = pszPathName;
  127. if (pszPathName != NULL)
  128. {
  129. if (theApp.m_bEmbedded)
  130. theApp.m_bLinked = TRUE;
  131. m_bNewDoc = FALSE;
  132. m_sName = pszPathName;
  133. #ifdef PCX_SUPPORT
  134. if (! theApp.m_bPCXfile)
  135. {
  136. CString cStrExt = GetExtension( pszPathName );
  137. CString cStrPCXExt;
  138. cStrPCXExt.LoadString( IDS_EXTENSION_PCX );
  139. // is it a PCX extension?
  140. theApp.m_bPCXfile = ! cStrExt.CompareNoCase( cStrPCXExt );
  141. }
  142. #endif
  143. // preset the file name in case of errors.
  144. theApp.SetFileError( IDS_ERROR_OPEN, CFileException::none, pszPathName );
  145. }
  146. else
  147. {
  148. m_bNewDoc = TRUE; /* not really but we don't have a name */
  149. m_sName.Empty();
  150. }
  151. #ifdef _DEBUG
  152. if (theApp.m_bEmbedded)
  153. TRACE( TEXT("MSPaint Open %s Document.\n"), (theApp.m_bLinked? TEXT("Linked"): TEXT("Embedded")) );
  154. #endif
  155. if (! CreateNewDocument())
  156. return FALSE;
  157. return COleServerDoc::OnOpenDocument( pszPathName );
  158. }
  159. /***************************************************************************/
  160. BOOL CPBDoc::OnSaveDocument( const TCHAR* pszPathName )
  161. {
  162. ASSERT( m_pBitmapObj != NULL );
  163. if (! Finish() || ! COleServerDoc::OnSaveDocument( pszPathName ))
  164. return FALSE;
  165. // Set the name if the thing doesn't have a name yet...
  166. if (m_pBitmapObj->m_bTempName && pszPathName != NULL)
  167. {
  168. m_pBitmapObj->m_bTempName = FALSE;
  169. }
  170. m_pBitmapObj->SetDirty( FALSE );
  171. theApp.m_sCurFile = pszPathName;
  172. return TRUE;
  173. }
  174. /***************************************************************************/
  175. CFile* CPBDoc::GetFile(LPCTSTR lpszFileName, UINT nOpenFlags,
  176. CFileException* pError)
  177. {
  178. // While saving a file, MFC opens the file with CREATE_ALWAYS flag.
  179. // But this wipes out the file summary info that the user has spent so much time editing (!)
  180. // We don't want that, so we will open the file with the OPEN_ALWAYS flag,
  181. // which does not disturb the summary info. But if the new file is shorter
  182. // than the old file, we need to manually truncate the file. So when we are
  183. // done, we will SetEndOfFile() in CPBDoc::ReleaseFile()
  184. // modeCreate maps to CREATE_ALWAYS
  185. // modeCreate + modeNoTruncate maps to OPEN_ALWAYS
  186. // So if MFC calls us with modeCreate only, we will also set modeNoTruncate
  187. m_bManualTruncate =
  188. (nOpenFlags & CFile::modeCreate) &&
  189. !(nOpenFlags & CFile::modeNoTruncate);
  190. if (m_bManualTruncate)
  191. nOpenFlags |= CFile::modeNoTruncate;
  192. // If we modify a file, the shell somehow cannot detect this and cannot
  193. // update the thumbnails view. So we will be nice and notify the shell
  194. if (nOpenFlags & (CFile::modeWrite | CFile::modeReadWrite))
  195. {
  196. // we should notify the shell if we are changing (writing to) a file
  197. // determine the type of notification
  198. WIN32_FIND_DATA fd;
  199. HANDLE hFind = FindFirstFile(lpszFileName, &fd);
  200. if (hFind != INVALID_HANDLE_VALUE)
  201. {
  202. // If the file previously exists, this means we will be updating it
  203. m_wChangeNotifyEventId = SHCNE_UPDATEITEM;
  204. FindClose(hFind);
  205. }
  206. else
  207. {
  208. // otherwise we will be creating a new file
  209. m_wChangeNotifyEventId = SHCNE_CREATE;
  210. }
  211. }
  212. else
  213. {
  214. // if we are only reading the file, no need for a notification
  215. m_wChangeNotifyEventId = 0;
  216. }
  217. // Copy MFC's implementation of CDocument::GetFile()
  218. // With one exception, do not use the CMirrorFile mess...
  219. CFile* pFile = new CFile;
  220. ASSERT(pFile != NULL);
  221. if (!pFile->Open(lpszFileName, nOpenFlags, pError))
  222. {
  223. delete pFile;
  224. pFile = NULL;
  225. }
  226. return pFile;
  227. }
  228. void CPBDoc::ReleaseFile(CFile* pFile, BOOL bAbort)
  229. {
  230. // manually set the end of file if needed
  231. if (m_bManualTruncate)
  232. {
  233. SetEndOfFile((HANDLE) pFile->m_hFile);
  234. }
  235. // cache the file name before the file object gets deleted
  236. CString strFileName = pFile->GetFilePath();
  237. // call the parent
  238. CDocument::ReleaseFile(pFile, bAbort);
  239. // notify the shell if needed
  240. if (m_wChangeNotifyEventId != 0)
  241. {
  242. SHChangeNotify(m_wChangeNotifyEventId, SHCNF_PATH, strFileName, 0);
  243. }
  244. }
  245. /***************************************************************************/
  246. void CPBDoc::ReportSaveLoadException(LPCTSTR lpszPathName, CException* e,
  247. BOOL bSaving, UINT nIDPDefault)
  248. {
  249. if(m_bHasSeenAFileError) {
  250. m_bHasSeenAFileError = FALSE;
  251. } else {
  252. // the app doesn't know about the error so let mfc complain
  253. COleServerDoc::ReportSaveLoadException(lpszPathName, e, bSaving,
  254. nIDPDefault);
  255. }
  256. }
  257. /***************************************************************************/
  258. BOOL CPBDoc::CanCloseFrame( CFrameWnd* pFrame )
  259. {
  260. TRACE3("CanCloseFrame: %d %s %s\n",m_bNonBitmapFile, (LPCTSTR)GetTitle(), (LPCTSTR)GetPathName());
  261. if (! Finish() || ! COleServerDoc::CanCloseFrame( pFrame ))
  262. return FALSE;
  263. theUndo.Flush();
  264. return TRUE;
  265. }
  266. /***************************************************************************/
  267. BOOL CPBDoc::SaveModified()
  268. {
  269. TRACE2("SaveModified %d %s\n", IsModified(), (LPCTSTR)GetPathName());
  270. return COleServerDoc::SaveModified();
  271. }
  272. /***************************************************************************/
  273. BOOL CPBDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
  274. {
  275. CancelToolMode(FALSE);
  276. BOOL bCannotSaveInCurrentFormat = m_bNonBitmapFile &&
  277. !GetClsidOfEncoder(theApp.m_guidFltTypeUsed, NULL);
  278. int iColors = m_pBitmapObj->m_nColors;
  279. int iOldColors = iColors;
  280. CString newName = lpszPathName;
  281. if (bCannotSaveInCurrentFormat || newName.IsEmpty())
  282. {
  283. CDocTemplate* pTemplate = GetDocTemplate();
  284. ASSERT(pTemplate != NULL);
  285. newName = m_strPathName;
  286. if (bReplace && newName.IsEmpty())
  287. {
  288. newName = m_strTitle;
  289. // check for dubious filename
  290. int iBad = newName.FindOneOf(_T("#%;/\\"));
  291. if (iBad != -1)
  292. newName.ReleaseBuffer(iBad);
  293. // append the default suffix if there is one
  294. CString strExt;
  295. if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&
  296. !strExt.IsEmpty())
  297. {
  298. ASSERT(strExt[0] == '.');
  299. newName += strExt;
  300. }
  301. }
  302. // If the filename is not null,
  303. // drop the extension in prompt a la Internet Explorer, and let
  304. // the Save As dialog append one appropriately.
  305. if (GetName(newName) != _T(""))
  306. {
  307. newName = StripExtension(newName);
  308. }
  309. if (!theApp.DoPromptFileName(newName,
  310. bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,
  311. OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, iColors, FALSE))
  312. return FALSE; // don't even attempt to save
  313. // check if any color reduction will be performed, including the
  314. // case of saving any 24-bit image to 8 bit GIF.
  315. if (((iOldColors < 4 && iColors < iOldColors)||
  316. (iOldColors == 3 && iColors >=4 &&
  317. WiaImgFmt_GIF == theApp.m_guidFltType[iColors-4])) &&
  318. AfxMessageBox(IDS_WARNING_COLORSAVE, MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
  319. {
  320. // abort immediately if the user didn't confirm the operation
  321. return FALSE;
  322. }
  323. if (iColors < 4 && iColors >= 0)
  324. {
  325. m_bNonBitmapFile = FALSE;
  326. m_bSaveViaFilter = FALSE;
  327. m_pBitmapObj->m_nSaveColors = iColors;
  328. theApp.m_guidFltTypeUsed = WiaImgFmt_UNDEFINED;
  329. }
  330. else
  331. {
  332. m_bNonBitmapFile = TRUE;
  333. m_bSaveViaFilter = TRUE;
  334. theApp.m_guidFltTypeUsed = theApp.m_guidFltType[iColors-4];
  335. //theApp.FixExtension (newName, theApp.m_guidFltTypeUsed);
  336. }
  337. }
  338. CWaitCursor wait;
  339. #ifdef ICO_SUPPORT
  340. m_pBitmapObj->m_bSaveIcon = (iColors == 5);
  341. if (m_pBitmapObj->m_bSaveIcon)
  342. {
  343. m_pBitmapObj->Free();
  344. m_pBitmapObj->Export(newName);
  345. m_pBitmapObj->m_bSaveIcon = FALSE; // always reset after use
  346. m_pBitmapObj->Free();
  347. return TRUE;
  348. }
  349. #endif
  350. BOOL bSavedDifferentFormat = (iColors != m_pBitmapObj->m_nColors);
  351. if (bSavedDifferentFormat)
  352. m_pBitmapObj->Free();
  353. if (!OnSaveDocument(newName))
  354. {
  355. if (lpszPathName == NULL)
  356. {
  357. // be sure to delete the file
  358. TRY
  359. {
  360. CFile::Remove( newName );
  361. }
  362. CATCH_ALL(e)
  363. {
  364. TRACE0( "Warning: failed to delete file after failed SaveAs\n" );
  365. }
  366. END_CATCH_ALL
  367. }
  368. return FALSE;
  369. }
  370. if (bSavedDifferentFormat)
  371. {
  372. m_pBitmapObj->ReLoadImage( this );
  373. //
  374. // We only want the first 16 color chips for 16 color images
  375. //
  376. g_pColors->ResetColors ((iColors==1)?16:256);
  377. }
  378. // reset the title and change the document name
  379. if (bReplace)
  380. SetPathName(newName);
  381. //
  382. // MFC sets the modified flag when user invokes OnFileSaveCopyAs.
  383. // Then if the user exits paint the storage in the container is never
  384. // updated because paint thinks it's already done it.
  385. // So after saving, set the dirty flag to true
  386. if (!lpszPathName && !bReplace)
  387. {
  388. SetModifiedFlag(TRUE);
  389. }
  390. return TRUE;
  391. }
  392. /***************************************************************************/
  393. // CPBDoc server implementation
  394. COleServerItem* CPBDoc::OnGetEmbeddedItem()
  395. {
  396. // OnGetEmbeddedItem is called by the framework to get the COleServerItem
  397. // that is associated with the document. It is only called when necessary.
  398. CPBSrvrItem* pItem = new CPBSrvrItem( this );
  399. ASSERT_VALID( pItem );
  400. return pItem;
  401. }
  402. /***************************************************************************/
  403. COleServerItem* CPBDoc::OnGetLinkedItem( LPCTSTR lpszItemName )
  404. {
  405. ASSERT_VALID( m_pBitmapObj );
  406. // look in current list first
  407. COleServerItem* pItem = COleServerDoc::OnGetLinkedItem( lpszItemName );
  408. if (pItem)
  409. return pItem;
  410. pItem = new CPBSrvrItem( this );
  411. ASSERT_VALID( pItem );
  412. // return new item that matches lpszItemName
  413. return pItem;
  414. }
  415. /***************************************************************************/
  416. // CPBDoc serialization
  417. BOOL CPBDoc::SerializeBitmap(CArchive& ar, CBitmapObj* pBitmapCur,
  418. CBitmapObj* pBitmapNew, BOOL bOLEObject)
  419. {
  420. BOOL success = FALSE;
  421. if (ar.IsStoring())
  422. {
  423. // Always write the PBrush OLE format
  424. CBitmapObj::PBResType rtType = !bOLEObject ? CBitmapObj::rtFile :
  425. CBitmapObj::rtPBrushOLEObj;
  426. if (!m_bSaveViaFilter)
  427. {
  428. success = pBitmapCur->WriteResource( ar.GetFile(), rtType );
  429. }
  430. else if (!bOLEObject && theApp.m_guidFltTypeUsed != WiaImgFmt_UNDEFINED)
  431. {
  432. // in order for the filter export interface to work, here we
  433. // close the file first after saving its name, so that a filter
  434. // can open it later to do the export...
  435. CString str = ar.GetFile()->GetFilePath();
  436. ar.GetFile()->Close();
  437. success = SaveDIBToFile( str, theApp.m_guidFltTypeUsed, pBitmapCur );
  438. if (!success)
  439. {
  440. theApp.SetFileError (IDS_ERROR_SAVE, ferrSaveAborted);
  441. }
  442. // now reopen the file again as if nothing had really happened
  443. // (any mode option can be used since the file will be closed
  444. // immediately after return)
  445. CFileException fe;
  446. ar.GetFile()->Open(str, CFile::modeRead | CFile::shareExclusive, &fe);
  447. }
  448. }
  449. else
  450. {
  451. CBitmapObj::PBResType rtType = !bOLEObject ? CBitmapObj::rtFile :
  452. m_bPaintFormat ? CBitmapObj::rtPaintOLEObj :
  453. CBitmapObj::rtPBrushOLEObj;
  454. success = pBitmapNew->ReadResource( ar.GetFile(), rtType );
  455. //
  456. // if we cant open the file, lets try using a filter.
  457. //
  458. if (success)
  459. {
  460. m_bNonBitmapFile = FALSE;
  461. m_bSaveViaFilter = FALSE;
  462. }
  463. else if (!bOLEObject)
  464. {
  465. HGLOBAL hDib;
  466. if (hDib = LoadDIBFromFile(theApp.GetLastFile(), &theApp.m_guidFltTypeUsed))
  467. {
  468. success = pBitmapNew->ReadResource(hDib);
  469. if (success)
  470. {
  471. // we loaded a non .bmp file
  472. m_bNonBitmapFile = TRUE;
  473. m_bSaveViaFilter = TRUE;
  474. // set no error
  475. theApp.SetFileError(0, CFileException::none);
  476. }
  477. }
  478. else
  479. {
  480. theApp.SetFileError(IDS_ERROR_READLOAD,
  481. ferrNotValidBmp);
  482. }
  483. }
  484. }
  485. return(success);
  486. }
  487. void CPBDoc::Serialize( CArchive& ar )
  488. {
  489. m_bObjectLoaded = SerializeBitmap(ar, m_pBitmapObj, m_pBitmapObjNew, FALSE);
  490. if (!m_bObjectLoaded) // much less than ideal but oh well
  491. {
  492. theApp.FileErrorMessageBox ();
  493. m_bHasSeenAFileError = TRUE;
  494. // let mfc know so it can tidy up internally...
  495. AfxThrowFileException(CFileException::invalidFile);
  496. }
  497. }
  498. void CPBDoc::OLESerialize( CArchive& ar )
  499. {
  500. m_bObjectLoaded = SerializeBitmap(ar, m_pBitmapObj, m_pBitmapObjNew, TRUE);
  501. if (!m_bObjectLoaded) // much less than ideal but oh well
  502. {
  503. // let mfc know so it can tidy up internally...
  504. AfxThrowFileException(CFileException::invalidFile);
  505. }
  506. }
  507. STDMETHODIMP CPBDoc::XPBPersistStg::QueryInterface(
  508. REFIID iid, LPVOID* ppvObj)
  509. {
  510. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  511. return pThis->ExternalQueryInterface(&iid, ppvObj);
  512. }
  513. STDMETHODIMP_(ULONG) CPBDoc::XPBPersistStg::AddRef()
  514. {
  515. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  516. return pThis->ExternalAddRef();
  517. }
  518. STDMETHODIMP_(ULONG) CPBDoc::XPBPersistStg::Release()
  519. {
  520. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  521. return pThis->ExternalRelease();
  522. }
  523. STDMETHODIMP CPBDoc::XPBPersistStg::GetClassID(LPCLSID pclsid)
  524. {
  525. // Always return the CLSID for PBrush
  526. *pclsid = CLSID_PaintBrush;
  527. return(NOERROR);
  528. }
  529. STDMETHODIMP CPBDoc::XPBPersistStg::IsDirty()
  530. {
  531. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  532. return(pThis->m_xPersistStorage.IsDirty());
  533. }
  534. STDMETHODIMP CPBDoc::XPBPersistStg::InitNew(LPSTORAGE pstg)
  535. {
  536. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  537. return(pThis->m_xPersistStorage.InitNew(pstg));
  538. }
  539. STDMETHODIMP CPBDoc::XPBPersistStg::Load(LPSTORAGE pstg)
  540. {
  541. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  542. return(pThis->m_xPersistStorage.Load(pstg));
  543. }
  544. STDMETHODIMP CPBDoc::XPBPersistStg::Save(LPSTORAGE pstg, BOOL bSameAsLoad)
  545. {
  546. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  547. return(pThis->m_xPersistStorage.Save(pstg, bSameAsLoad));
  548. }
  549. STDMETHODIMP CPBDoc::XPBPersistStg::SaveCompleted(LPSTORAGE pstg)
  550. {
  551. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  552. return(pThis->m_xPersistStorage.SaveCompleted(pstg));
  553. }
  554. STDMETHODIMP CPBDoc::XPBPersistStg::HandsOffStorage()
  555. {
  556. METHOD_PROLOGUE_EX(CPBDoc, PBPersistStg)
  557. return(pThis->m_xPersistStorage.HandsOffStorage());
  558. }
  559. #define NO_CPP_EXCEPTION(x) x
  560. static const TCHAR szOle10Native[] = TEXT("\1Ole10Native");
  561. static const TCHAR szOle10ItemName[] = TEXT("\1Ole10ItemName");
  562. /////////////////////////////////////////////////////////////////////////////
  563. // Helpers for saving to IStorage based files
  564. // (these are used in the 'docfile' implementation as well as for servers)
  565. static const TCHAR szContents[] = TEXT("Contents");
  566. void CPBDoc::SaveToStorage(CObject* pObject)
  567. {
  568. ASSERT(m_lpRootStg != NULL);
  569. // create Contents stream
  570. COleStreamFile file;
  571. CFileException fe;
  572. if (!file.CreateStream(m_lpRootStg, szOle10Native,
  573. CFile::modeWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
  574. {
  575. AfxThrowFileException(fe.m_cause, fe.m_lOsError);
  576. }
  577. // save to Contents stream
  578. CArchive saveArchive(&file, CArchive::store | CArchive::bNoFlushOnDelete);
  579. saveArchive.m_pDocument = this;
  580. saveArchive.m_bForceFlat = FALSE;
  581. TRY
  582. {
  583. // save the contents
  584. if (pObject != NULL)
  585. pObject->Serialize(saveArchive);
  586. else
  587. OLESerialize(saveArchive);
  588. saveArchive.Close();
  589. file.Close();
  590. if (pObject != NULL)
  591. {
  592. if (file.CreateStream(m_lpRootStg, szOle10ItemName,
  593. CFile::modeWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
  594. {
  595. LPCTSTR szItemName;
  596. DWORD dwLen;
  597. CString strItemName = ((CPBSrvrItem*)pObject)->GetItemName();
  598. if (strItemName.IsEmpty())
  599. {
  600. szItemName = TEXT("");
  601. dwLen = 1;
  602. }
  603. else
  604. {
  605. szItemName = strItemName;
  606. dwLen = lstrlen(szItemName) + 1;
  607. }
  608. file.Write( &dwLen, sizeof( dwLen ));
  609. file.Write( &szItemName, dwLen);
  610. file.Close();
  611. }
  612. }
  613. SCODE sc;
  614. // Always write the CLSID for PBrush
  615. sc = WriteClassStg(m_lpRootStg, CLSID_PaintBrush);
  616. if (sc != NOERROR)
  617. AfxThrowOleException(sc);
  618. sc = WriteFmtUserTypeStg(m_lpRootStg, (WORD)RegisterClipboardFormat(TEXT("PBrush")),
  619. L"PBrush");
  620. if (sc != NOERROR)
  621. AfxThrowOleException(sc);
  622. // commit the root storage
  623. sc = m_lpRootStg->Commit(STGC_ONLYIFCURRENT);
  624. if (sc != NOERROR)
  625. AfxThrowOleException(sc);
  626. }
  627. CATCH_ALL(e)
  628. {
  629. file.Abort(); // will not throw an exception
  630. CommitItems(FALSE); // abort save in progress
  631. NO_CPP_EXCEPTION(saveArchive.Abort());
  632. THROW_LAST();
  633. }
  634. END_CATCH_ALL
  635. }
  636. void CPBDoc::LoadFromStorage()
  637. {
  638. ASSERT(m_lpRootStg != NULL);
  639. // open Contents stream
  640. COleStreamFile file;
  641. CFileException fe;
  642. if (file.OpenStream(m_lpRootStg, szOle10Native,
  643. CFile::modeReadWrite|CFile::shareExclusive, &fe))
  644. {
  645. m_bPaintFormat = FALSE;
  646. }
  647. else if (file.OpenStream(m_lpRootStg, szContents,
  648. CFile::modeReadWrite|CFile::shareExclusive, &fe))
  649. {
  650. m_bPaintFormat = TRUE;
  651. }
  652. else
  653. {
  654. AfxThrowFileException(fe.m_cause, fe.m_lOsError);
  655. }
  656. // load it with CArchive (loads from Contents stream)
  657. CArchive loadArchive(&file, CArchive::load | CArchive::bNoFlushOnDelete);
  658. loadArchive.m_pDocument = this;
  659. loadArchive.m_bForceFlat = FALSE;
  660. TRY
  661. {
  662. OLESerialize(loadArchive); // load main contents
  663. loadArchive.Close();
  664. file.Close();
  665. }
  666. CATCH_ALL(e)
  667. {
  668. file.Abort(); // will not throw an exception
  669. DeleteContents(); // removed failed contents
  670. NO_CPP_EXCEPTION(loadArchive.Abort());
  671. THROW_LAST();
  672. }
  673. END_CATCH_ALL
  674. }
  675. /***************************************************************************/
  676. // CPBDoc diagnostics
  677. #ifdef _DEBUG
  678. void CPBDoc::AssertValid() const
  679. {
  680. COleServerDoc::AssertValid();
  681. }
  682. void CPBDoc::Dump(CDumpContext& dc) const
  683. {
  684. COleServerDoc::Dump(dc);
  685. }
  686. #endif //_DEBUG
  687. /***************************************************************************/
  688. // CPBDoc commands
  689. BOOL CPBDoc::CreateNewDocument()
  690. {
  691. CBitmapObj* pBitmapObj = NULL;
  692. //
  693. // If we have a window already, reset the color squares.
  694. // every doc starts with a white background
  695. //
  696. pBitmapObj = new CBitmapObj;
  697. pBitmapObj->MakeEmpty();
  698. if (AfxGetMainWnd())
  699. {
  700. g_pColors->ResetColors(256);
  701. }
  702. if (! pBitmapObj)
  703. return FALSE;
  704. m_pBitmapObjNew = pBitmapObj;
  705. pBitmapObj->m_bTempName = m_bNewDoc;
  706. pBitmapObj->m_bDirty = FALSE;
  707. theUndo.Flush();
  708. return TRUE;
  709. }
  710. /***************************************************************************/
  711. BOOL CPBDoc::Finish()
  712. {
  713. CImgTool* pImgTool = CImgTool::GetCurrent();
  714. if (pImgTool != NULL && CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  715. {
  716. POSITION pos = GetFirstViewPosition();
  717. ((CTextTool*)pImgTool)->CloseTextTool( ((CPBView*)GetNextView( pos ))->m_pImgWnd );
  718. }
  719. CommitSelection( FALSE );
  720. if (m_pBitmapObj == NULL)
  721. return TRUE;
  722. if (! m_pBitmapObj->SaveResource( TRUE ))
  723. return FALSE;
  724. if (m_pBitmapObj->IsDirty())
  725. {
  726. SetModifiedFlag();
  727. if (theApp.m_bEmbedded)
  728. NotifyChanged();
  729. }
  730. return TRUE;
  731. }
  732. /***************************************************************************/
  733. BOOL CPBDoc::SaveTheDocument()
  734. {
  735. if (IsModified() || m_bNonBitmapFile)
  736. OnFileSave();
  737. return TRUE;
  738. }
  739. /***************************************************************************/
  740. void CPBDoc::OnShowControlBars(CFrameWnd *pFrame, BOOL bShow)
  741. {
  742. POSITION pos = GetFirstViewPosition();
  743. CPBView* pView = (CPBView*)(GetNextView( pos ));
  744. if ( bShow )
  745. {
  746. pView->SetTools();
  747. if ( pView->m_pImgWnd &&
  748. pView->m_pImgWnd->GetZoom() > 1 )
  749. pView->ShowThumbNailView();
  750. }
  751. else
  752. {
  753. pView->HideThumbNailView();
  754. }
  755. // FEATURE: What I should do is add an OnShowControlBars member to
  756. // CImgTool, but that's too big a change for right now
  757. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  758. {
  759. CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
  760. pTextTool->OnShowControlBars(bShow);
  761. }
  762. COleServerDoc::OnShowControlBars(pFrame,bShow);
  763. }
  764. class CCB : public CControlBar
  765. {
  766. public:
  767. void ForceDelayed(void);
  768. };
  769. void CCB::ForceDelayed(void)
  770. {
  771. if (!this)
  772. {
  773. return;
  774. }
  775. BOOL bVis = GetStyle() & WS_VISIBLE;
  776. UINT swpFlags = 0;
  777. if ((m_nStateFlags & delayHide) && bVis)
  778. swpFlags = SWP_HIDEWINDOW;
  779. else if ((m_nStateFlags & delayShow) && !bVis)
  780. swpFlags = SWP_SHOWWINDOW;
  781. m_nStateFlags &= ~(delayShow|delayHide);
  782. if (swpFlags != 0)
  783. {
  784. SetWindowPos(NULL, 0, 0, 0, 0, swpFlags|
  785. SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  786. }
  787. }
  788. class CFW : public CFrameWnd
  789. {
  790. public:
  791. void ForceDelayed(void);
  792. };
  793. void CFW::ForceDelayed(void)
  794. {
  795. if (!this)
  796. {
  797. return;
  798. }
  799. POSITION pos = m_listControlBars.GetHeadPosition();
  800. while (pos != NULL)
  801. {
  802. // show/hide the next control bar
  803. CCB* pBar = (CCB*)m_listControlBars.GetNext(pos);
  804. pBar->ForceDelayed();
  805. }
  806. }
  807. class COIPF : public COleIPFrameWnd
  808. {
  809. public:
  810. void ForceDelayed(void);
  811. };
  812. void COIPF::ForceDelayed(void)
  813. {
  814. if (!this)
  815. {
  816. return;
  817. }
  818. ((CFW*)m_pMainFrame)->ForceDelayed();
  819. ((CFW*)m_pDocFrame )->ForceDelayed();
  820. }
  821. void CPBDoc::OnDeactivateUI(BOOL bUndoable)
  822. {
  823. COleServerDoc::OnDeactivateUI(bUndoable);
  824. POSITION pos = GetFirstViewPosition();
  825. CPBView* pView = (CPBView*)(GetNextView( pos ));
  826. CancelToolMode (FALSE);
  827. if (pView != NULL)
  828. {
  829. pView->HideThumbNailView();
  830. COIPF* pFrame = (COIPF*)m_pInPlaceFrame;
  831. pFrame->ForceDelayed();
  832. }
  833. }
  834. //
  835. // We override OnUpdateDocument to ignore the modified flag. Certain MFC paths
  836. // set the modified flag inappropriately, causing data loss.
  837. BOOL CPBDoc::OnUpdateDocument ()
  838. {
  839. // save a server document -> update
  840. TRY
  841. {
  842. SaveEmbedding();
  843. }
  844. CATCH_ALL(e)
  845. {
  846. AfxMessageBox(AFX_IDP_FAILED_TO_UPDATE);
  847. #ifndef _AFX_OLD_EXCEPTIONS
  848. e->Delete();
  849. #endif
  850. return FALSE;
  851. }
  852. END_CATCH_ALL
  853. return TRUE;
  854. }
  855. void CPBDoc::MyOnFileUpdate ()
  856. {
  857. CancelToolMode (FALSE);
  858. OnFileUpdate();
  859. }