home *** CD-ROM | disk | FTP | other *** search
/ Total C++ 2 / TOTALCTWO.iso / borland / tutorole.pak / OWLOLE2.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  16KB  |  645 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Ole tutorial application -- owlole2.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/pch.h>
  6. #include <owl/applicat.h>
  7. #include <owl/decframe.h>
  8. #include <owl/dc.h>
  9. #include <owl/inputdia.h>
  10. #include <owl/opensave.h>
  11. #include <owl/controlb.h>
  12. #include <owl/buttonga.h>
  13. #include <owl/statusba.h>
  14. #include <owl/gdiobjec.h>
  15. #include <owl/chooseco.h>
  16. #include <owl/oleframe.h>
  17. #include <owl/olewindo.h>
  18. #include <ocf/ocstorag.h>
  19. #include <classlib/arrays.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "owlole2.rc"
  23.  
  24. // App registration object
  25. //
  26. static TPointer<TOcRegistrar> Registrar;
  27. DEFINE_APP_DICTIONARY(AppDictionary);
  28.  
  29. #define DocExt   "sp2"  // Scribble Pad #2 document extension
  30.  
  31. REGISTRATION_FORMAT_BUFFER(100)
  32.  
  33. BEGIN_REGISTRATION(AppReg)
  34.   REGDATA(clsid,      "{B6B58B60-B9C3-101B-B3FF-86C8A0834EDE}")
  35.   REGDATA(appname,    "Scribble Pad")
  36. END_REGISTRATION
  37.  
  38. // Register clipboard formats
  39. //
  40. BEGIN_REGISTRATION(DocReg)
  41.   REGDATA(progid,     "Scribble.Pad.2")
  42.   REGDATA(description,"Scribble Pad (Container)")
  43.   REGDATA(extension,  DocExt )
  44.   REGDATA(docfilter,  "*." DocExt)
  45.   REGFORMAT(0, ocrEmbedSource,  ocrContent,  ocrIStorage, ocrGet)
  46.   REGFORMAT(1, ocrMetafilePict, ocrContent,  ocrMfPict|ocrStaticMed, ocrGet)
  47.   REGFORMAT(2, ocrBitmap, ocrContent,  ocrGDI|ocrStaticMed, ocrGet)
  48.   REGFORMAT(3, ocrDib, ocrContent,  ocrHGlobal|ocrStaticMed, ocrGet)
  49.   REGFORMAT(4, ocrLinkSource, ocrContent,  ocrIStream, ocrGet)
  50. END_REGISTRATION
  51.  
  52. TRegLink* RegLinkHead = 0;
  53. TRegLink  DocLink(DocReg, RegLinkHead);
  54. const char ScribbleAppTitle[] = "Scribble";
  55.  
  56. //----------------------------------------------------------------------------
  57.  
  58. typedef TArray<TPoint> TPoints;
  59. typedef TArrayIterator<TPoint> TPointsIterator;
  60.  
  61. class TLine : public TPoints {
  62.   public:
  63.     // Constructor to allow construction from a color and a pen size.
  64.     // Also serves as default constructor.
  65.     TLine(const TColor& color = TColor(0), int penSize = 1) :
  66.       TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
  67.  
  68.     // Functions to modify and query pen attributes.
  69.     int QueryPenSize() const
  70.     {
  71.       return PenSize;
  72.     }
  73.  
  74.     TColor& QueryColor()
  75.     {
  76.       return Color;
  77.     }
  78.  
  79.     void SetPen(const TColor& newColor, int penSize = 0);
  80.     void SetPen(int penSize);
  81.  
  82.     // TLine draws itself.  Returns true if everything went OK.
  83.     virtual bool Draw(TDC&) const;
  84.  
  85.     // The == operator must be defined for the container class, even if unused
  86.     bool operator ==(const TLine& other) const
  87.     {
  88.       return &other == this;
  89.     }
  90.  
  91.     friend ostream& operator <<(ostream& os, const TLine& line);
  92.     friend istream& operator >>(istream& is, TLine& line);
  93.  
  94.   protected:
  95.     int PenSize;
  96.     TColor Color;
  97. };
  98.  
  99. void
  100. TLine::SetPen(int penSize)
  101. {
  102.   if (penSize < 1)
  103.     PenSize = 1;
  104.   else
  105.     PenSize = penSize;
  106. }
  107.  
  108. void
  109. TLine::SetPen(const TColor& newColor, int penSize)
  110. {
  111.   // If penSize isn't the default (0), set PenSize to the new size.
  112.   if (penSize)
  113.     PenSize = penSize;
  114.  
  115.   Color = newColor;
  116. }
  117.  
  118. bool
  119. TLine::Draw(TDC& dc) const
  120. {
  121.   // Set pen for the dc to the values for this line
  122.   TPen pen(Color, PenSize);
  123.   dc.SelectObject(pen);
  124.  
  125.   // Iterates through the points in the line i.
  126.   TPointsIterator j(*this);
  127.   bool first = true;
  128.  
  129.   while (j) {
  130.     TPoint p = j++;
  131.  
  132.     if (!first)
  133.       dc.LineTo(p);
  134.     else {
  135.       dc.MoveTo(p);
  136.       first = false;
  137.     }
  138.   }
  139.   dc.RestorePen();
  140.   return true;
  141. }
  142.  
  143. ostream&
  144. operator <<(ostream& os, const TLine& line)
  145. {
  146.   // Write the number of points in the line
  147.   os << line.GetItemsInContainer();
  148.  
  149.   // Get and write pen attributes.
  150.   os << ' ' << line.Color << ' ' << line.PenSize;
  151.  
  152.   // Get an iterator for the array of points
  153.   TPointsIterator j(line);
  154.  
  155.   // While the iterator is valid (i.e. we haven't run out of points)
  156.   while(j)
  157.     // Write the point from the iterator and increment the array.
  158.     os << j++;
  159.   os << '\n';
  160.  
  161.   // return the stream object
  162.   return os;
  163. }
  164.  
  165. istream&
  166. operator >>(istream& is, TLine& line)
  167. {
  168.   unsigned numPoints;
  169.   is >> numPoints;
  170.  
  171.   COLORREF color;
  172.   int penSize;
  173.   is >> color >> penSize;
  174.   line.SetPen(TColor(color), penSize);
  175.  
  176.   while (numPoints--) {
  177.     TPoint point;
  178.     is >> point;
  179.     line.Add(point);
  180.   }
  181.  
  182.   // return the stream object
  183.   return is;
  184. }
  185.  
  186. //----------------------------------------------------------------------------
  187.  
  188. typedef TArray<TLine> TLines;
  189. typedef TArrayIterator<TLine> TLinesIterator;
  190.  
  191. class TScribbleWindow : public TOleWindow {
  192.   public:
  193.     TScribbleWindow(TWindow* parent, TOpenSaveDialog::TData& fileData);
  194.    ~TScribbleWindow()
  195.     {
  196.       delete Line;
  197.       delete Lines;
  198.     }
  199.  
  200.   protected:
  201.     TPen* Pen;
  202.     TLines* Lines;
  203.     TLine* Line; // To hold a single line at a time that later gets
  204.                  // stuck in Lines
  205.     TOpenSaveDialog::TData& FileData;
  206.     bool IsDirty, IsNewFile;
  207.  
  208.     void GetPenSize(); // GetPenSize always calls Line->SetPen().
  209.  
  210.     // Override member function of TWindow
  211.     void SetupWindow();
  212.     bool CanClose();
  213.  
  214.     // Message response functions
  215.     void EvLButtonDown(uint, TPoint&);
  216.     void EvRButtonDown(uint, TPoint&);
  217.     void EvMouseMove(uint, TPoint&);
  218.     void EvLButtonUp(uint, TPoint&);
  219.     void Paint(TDC&, bool, TRect&);
  220.     void CmFileNew();
  221.     void CmFileOpen();
  222.     void CmFileSave();
  223.     void CmFileSaveAs();
  224.     void CmPenSize();
  225.     void CmPenColor();
  226.     void CmAbout();
  227.     void SaveFile(bool pathChanged);
  228.     void OpenFile();
  229.  
  230.     const char far* EvOcViewTitle(){return ScribbleAppTitle; }
  231.   DECLARE_RESPONSE_TABLE(TScribbleWindow);
  232. };
  233.  
  234. DEFINE_RESPONSE_TABLE1(TScribbleWindow, TOleWindow)
  235.   EV_WM_LBUTTONDOWN,
  236.   EV_WM_RBUTTONDOWN,
  237.   EV_WM_MOUSEMOVE,
  238.   EV_WM_LBUTTONUP,
  239.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  240.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  241.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  242.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  243.   EV_COMMAND(CM_ABOUT, CmAbout),
  244.  
  245.   EV_OC_VIEWTITLE,
  246. END_RESPONSE_TABLE;
  247.  
  248. TScribbleWindow::TScribbleWindow(TWindow* parent, TOpenSaveDialog::TData& fileData)
  249. :
  250.   TOleWindow(parent, 0),
  251.   FileData(fileData)
  252. {
  253.   Lines     = new TLines(5, 0, 5);
  254.   Line      = new TLine(TColor::Black, 1);
  255.   Pen       = 0;
  256.   IsNewFile = true;
  257.   IsDirty   = false;
  258.  
  259.   // Create a OcDocument object to hold the ole parts that we create
  260.   // and a OcView to provide ole services
  261.   //
  262.   CreateOcView(RegLinkHead, false, 0);
  263. }
  264.  
  265. void
  266. TScribbleWindow::SetupWindow()
  267. {
  268.   TOleWindow::SetupWindow();
  269.   if (*FileData.FileName)
  270.     OpenFile();
  271.   else
  272.     SetDocTitle("Untitled", 0);
  273. }
  274.  
  275. bool
  276. TScribbleWindow::CanClose()
  277. {
  278.   if (IsDirty)
  279.     switch (MessageBox("Do you want to save?", "Scribbling has changed",
  280.                        MB_YESNOCANCEL | MB_ICONQUESTION)) {
  281.       case IDCANCEL:
  282.         // Choosing Cancel means to abort the close -- return false.
  283.         return false;
  284.  
  285.       case IDYES:
  286.         // Choosing Yes means to save the drawing, then close.
  287.         CmFileSave();
  288.         break;
  289.  
  290.       case IDNO:
  291.         // Choosing No means don't save the drawing but close.
  292.         // NOTE: Still need to call TOleWindow::CanClose for OLE cleanup
  293.         break;
  294.     }
  295.  
  296.   // Allow TOleWindow to perform OLE document cleanup
  297.   //
  298.   return TOleWindow::CanClose();
  299. }
  300.  
  301. void
  302. TScribbleWindow::EvLButtonDown(uint modKeys, TPoint& point)
  303. {
  304.   TOleWindow::EvLButtonDown(modKeys, point);
  305.  
  306.   if (DragDC && !SelectEmbedded()) {
  307.     SetCapture();
  308.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  309.     DragDC->SelectObject(*Pen);
  310.     DragDC->MoveTo(point);
  311.     Line->Add(point);
  312.     IsDirty = true;
  313.   }
  314. }
  315.  
  316. void
  317. TScribbleWindow::EvRButtonDown(uint modKeys, TPoint& point)
  318. {
  319.   TOleWindow::EvRButtonDown(modKeys, point);
  320.   if (!SelectEmbedded())
  321.     GetPenSize();
  322. }
  323.  
  324. void
  325. TScribbleWindow::EvMouseMove(uint modKeys, TPoint& point)
  326. {
  327.   TOleWindow::EvMouseMove(modKeys, point);
  328.  
  329.   if (DragDC && !SelectEmbedded()) {
  330.     DragDC->LineTo(point);
  331.     Line->Add(point);
  332.   }
  333. }
  334.  
  335. void
  336. TScribbleWindow::EvLButtonUp(uint modKeys, TPoint& point)
  337. {
  338.   if (DragDC) {
  339.     if (!SelectEmbedded()) {
  340.       ReleaseCapture();
  341.       if (Line->GetItemsInContainer() > 1)
  342.         Lines->Add(*Line);
  343.       Line->Flush();
  344.       delete Pen;
  345.       Pen = 0;
  346.     }
  347.   }
  348.   TOleWindow::EvLButtonUp(modKeys, point);
  349. }
  350.  
  351. void
  352. TScribbleWindow::CmPenSize()
  353. {
  354.   GetPenSize();
  355. }
  356.  
  357. void
  358. TScribbleWindow::CmPenColor()
  359. {
  360.   TChooseColorDialog::TData colors;
  361.   static TColor custColors[16] = {
  362.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  363.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  364.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  365.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  366.   };
  367.  
  368.   colors.Flags = CC_RGBINIT;
  369.   colors.Color = TColor(Line->QueryColor());
  370.   colors.CustColors = custColors;
  371.   if (TChooseColorDialog(this, colors).Execute() == IDOK)
  372.     Line->SetPen(colors.Color);
  373. }
  374.  
  375. void
  376. TScribbleWindow::GetPenSize()
  377. {
  378.   char inputText[6];
  379.   int penSize = Line->QueryPenSize();
  380.  
  381.   wsprintf(inputText, "%d", penSize);
  382.   if (TInputDialog(this, "Line Thickness",
  383.                    "Input a new thickness:",
  384.                    inputText,
  385.                    sizeof(inputText)).Execute() == IDOK) {
  386.     penSize = atoi(inputText);
  387.  
  388.     if (penSize < 1)
  389.       penSize = 1;
  390.   }
  391.   Line->SetPen(penSize);
  392. }
  393.  
  394. void
  395. TScribbleWindow::Paint(TDC& dc, bool erase, TRect& rect)
  396. {
  397.   TOleWindow::Paint(dc, erase, rect);
  398.  
  399.   // Iterates through the array of line objects.
  400.   TLinesIterator i(*Lines);
  401.  
  402.   while (i)
  403.     i++.Draw(dc);
  404. }
  405.  
  406. void
  407. TScribbleWindow::CmFileSave()
  408. {
  409.   if (IsNewFile)
  410.     CmFileSaveAs();
  411.   else
  412.     SaveFile(false);
  413. }
  414.  
  415. void
  416. TScribbleWindow::CmFileSaveAs()
  417. {
  418.   if (TFileSaveDialog(this, FileData).Execute() == IDOK)
  419.     SaveFile(true);
  420. }
  421.  
  422. void
  423. TScribbleWindow::CmAbout()
  424. {
  425.   TDialog(this, IDD_ABOUT).Execute();
  426. }
  427.  
  428. void
  429. TScribbleWindow::SaveFile(bool pathChanged)
  430. {
  431.   if (pathChanged && !OcDoc->SaveToFile(FileData.FileName))
  432.     return; // error!
  433.   TOcStorage* storage = OcDoc->GetStorage();
  434.  
  435.   if (!storage) {
  436.     MessageBox("Bogus internal storage problem", "File Error", MB_OK | MB_ICONEXCLAMATION);
  437.   }
  438.   else {
  439.     TOcStream  stream(*storage, "Scribble", true, STGM_READWRITE);
  440.     ostrstream os;
  441.  
  442.     // Write the number of lines in the figure
  443.     os << Lines->GetItemsInContainer();
  444.  
  445.     // Append a description using a resource string
  446.     os << ' ' << string(*GetApplication(), IDS_FILEINFO) << '\n';
  447.  
  448.     // Get an iterator for the array of lines
  449.     TLinesIterator i(*Lines);
  450.  
  451.     // While the iterator is valid (i.e. we haven't run out of lines)
  452.     while (i)
  453.       // Copy the current line from the iterator and increment the array.
  454.       os << i++;
  455.  
  456.     // Set new file and dirty display indicator to false.
  457.     IsNewFile = IsDirty = false;
  458.     if (pathChanged)
  459.       SetDocTitle(FileData.FileName, 0);
  460.  
  461.     OcDoc->SetName(FileData.FileName);
  462.  
  463.     stream.Write(os.str(), os.pcount());
  464.     stream.Commit(STGC_DEFAULT);
  465.  
  466.     OcDoc->SaveParts(0, true);
  467.     OcDoc->GetStorage()->Commit(STGC_DEFAULT);
  468.   }
  469. }
  470.  
  471. void
  472. TScribbleWindow::OpenFile()
  473. {
  474.   try {
  475.     OcDoc->SetStorage(FileData.FileName);
  476.     TOcStorage* storage = OcDoc->GetStorage();
  477.  
  478.     if (!storage)
  479.       MessageBox("Bogus internal storage problem", "File Error", MB_OK | MB_ICONEXCLAMATION);
  480.     else {
  481.       TOcStream   stream(*storage, "Scribble", false, STGM_READWRITE);
  482.  
  483.       // figure out the size of our stream to read, & read it into a buffer
  484.       uint64 size;
  485.       stream.Seek(0, STREAM_SEEK_END, &size);
  486.       char* buff = new char[(int)size.LowPart+10];
  487.       stream.Seek(0, STREAM_SEEK_SET);
  488.       stream.Read(buff, size.LowPart);
  489.  
  490.       // now make the buffer into a input str stream & stream in our objects
  491.       istrstream is(buff, (int)size.LowPart);
  492.       unsigned numLines;
  493.       char fileinfo[100];
  494.  
  495.       Lines->Flush();
  496.       Line->Flush();
  497.  
  498.       is >> numLines;
  499.       is.getline(fileinfo, sizeof(fileinfo));
  500.       SetDocTitle(FileData.FileName, 0);
  501.  
  502.       for (int i = 0; i < numLines; i++) {
  503.         TLine line;
  504.         is >> line;
  505.         Lines->Add(line);
  506.       }
  507.       delete [] buff;
  508.  
  509.       OcDoc->LoadParts();
  510.     }
  511.     IsNewFile = IsDirty = false;
  512.     Invalidate();
  513.   }
  514.   catch(TXBase& xbase) {
  515.     MessageBox(xbase.why().c_str(), "EXCEPTION", MB_OK);
  516.   }
  517. }
  518.  
  519. //----------------------------------------------------------------------------
  520.  
  521. class TScribbleApp : public TApplication, public TOcModule {
  522.   public:
  523.     TScribbleApp();
  524.  
  525.     TUnknown* CreateOleObject(uint32 /*options*/, TRegLink* /*link*/) {return 0;}
  526.  
  527.   protected:
  528.     void InitMainWindow();
  529.     void InitInstance();
  530.  
  531.     void CmFileNew();
  532.     void CmFileOpen();
  533.  
  534.     TOpenSaveDialog::TData FileData;
  535.  
  536.   DECLARE_RESPONSE_TABLE(TScribbleApp);
  537. };
  538.  
  539. DEFINE_RESPONSE_TABLE1(TScribbleApp, TApplication)
  540.   EV_COMMAND(CM_FILENEW, CmFileNew),
  541.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  542. END_RESPONSE_TABLE;
  543.  
  544. TScribbleApp::TScribbleApp()
  545. :
  546.   TApplication(::AppReg["appname"]),
  547.   FileData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  548.            "Scribble Files (*."DocExt")|*."DocExt"|", 0, "", DocExt)
  549. {
  550. }
  551.  
  552. void
  553. TScribbleApp::InitMainWindow()
  554. {
  555.   // Construct the ole decorated frame window
  556.   TOleFrame* frame = new TOleFrame(GetName(), 0, true, this);
  557.  
  558.   // Construct a status bar
  559.   TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  560.  
  561.   // Construct a control bar
  562.   TControlBar* cb = new TControlBar(frame);
  563.   cb->Insert(*new TButtonGadget(CM_FILENEW, CM_FILENEW, TButtonGadget::Command));
  564.   cb->Insert(*new TButtonGadget(CM_FILEOPEN, CM_FILEOPEN, TButtonGadget::Command));
  565.   cb->Insert(*new TButtonGadget(CM_FILESAVE, CM_FILESAVE, TButtonGadget::Command));
  566.   cb->Insert(*new TButtonGadget(CM_FILESAVEAS, CM_FILESAVEAS, TButtonGadget::Command));
  567.   cb->Insert(*new TSeparatorGadget);
  568.   cb->Insert(*new TButtonGadget(CM_PENSIZE, CM_PENSIZE, TButtonGadget::Command));
  569.   cb->Insert(*new TButtonGadget(CM_PENCOLOR, CM_PENCOLOR, TButtonGadget::Command));
  570.   cb->Insert(*new TSeparatorGadget);
  571.   cb->Insert(*new TButtonGadget(CM_ABOUT, CM_ABOUT, TButtonGadget::Command));
  572.   cb->Attr.Id = IDW_TOOLBAR;
  573.  
  574.   // Insert the status bar and control bar into the frame
  575.   frame->Insert(*sb, TDecoratedFrame::Bottom);
  576.   frame->Insert(*cb, TDecoratedFrame::Top);
  577.  
  578.   // Set the menu & icon
  579.   frame->SetMenuDescr(TMenuDescr(IDM_SCRIBBLE));
  580.   frame->SetIcon(this, IDI_TUTORIAL);
  581.  
  582.   // Set the main window
  583.   SetMainWindow(frame);
  584. }
  585.  
  586. //
  587. // Call file new command handler to get the initial new window
  588. //
  589. void
  590. TScribbleApp::InitInstance()
  591. {
  592.   TApplication::InitInstance();
  593.  
  594.   FileData.FileName[0] = 0;
  595.   TWindow* client = new TScribbleWindow(0, FileData);
  596.   TWindow* oldClient = GetMainWindow()->SetClientWindow(client);
  597.   if (oldClient) {
  598.     oldClient->Destroy();
  599.     delete oldClient;
  600.   }
  601. }
  602.  
  603. void
  604. TScribbleApp::CmFileNew()
  605. {
  606.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  607.   if (!scribbleWindow->CanClose())
  608.     return;
  609.  
  610.   FileData.FileName[0] = 0;
  611.   TWindow* client = new TScribbleWindow(0, FileData);
  612.   GetMainWindow()->SetClientWindow(client);
  613.   scribbleWindow->Destroy(0);
  614.   delete scribbleWindow;
  615. }
  616.  
  617. void
  618. TScribbleApp::CmFileOpen()
  619. {
  620.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  621.   if (!scribbleWindow->CanClose())
  622.     return;
  623.  
  624.   if (TFileOpenDialog(GetMainWindow(), FileData).Execute() == IDOK) {
  625.     TWindow* newScribbleWindow = new TScribbleWindow(0, FileData);
  626.     GetMainWindow()->SetClientWindow(newScribbleWindow);
  627.     scribbleWindow->Destroy(0);
  628.     delete scribbleWindow;
  629.   }
  630. }
  631.  
  632. int
  633. OwlMain(int /*argc*/, char* /*argv*/ [])
  634. {
  635.   try {
  636.     Registrar = new TOcRegistrar(::AppReg, TOleFactory<TScribbleApp>(),
  637.                                  TApplication::GetCmdLine());
  638.     return Registrar->Run();
  639.   }
  640.   catch (xmsg& x) {
  641.     ::MessageBox(0, x.why().c_str(), "Scribble App Exception", MB_OK);
  642.   }
  643.   return -1;
  644. }
  645.