home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / oletutor.pak / OWLOLE2.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  16KB  |  640 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Ole tutorial application -- owlole2.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/owlpch.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(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(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, TPoint&)
  318. {
  319.   GetPenSize();
  320. }
  321.  
  322. void
  323. TScribbleWindow::EvMouseMove(uint modKeys, TPoint& point)
  324. {
  325.   TOleWindow::EvMouseMove(modKeys, point);
  326.  
  327.   if (DragDC && !SelectEmbedded()) {
  328.     DragDC->LineTo(point);
  329.     Line->Add(point);
  330.   }
  331. }
  332.  
  333. void
  334. TScribbleWindow::EvLButtonUp(uint modKeys, TPoint& point)
  335. {
  336.   if (DragDC) {
  337.     if (!SelectEmbedded()) {
  338.       ReleaseCapture();
  339.       if (Line->GetItemsInContainer() > 1)
  340.         Lines->Add(*Line);
  341.       Line->Flush();
  342.       delete Pen;
  343.       Pen = 0;
  344.     }
  345.   }
  346.   TOleWindow::EvLButtonUp(modKeys, point);
  347. }
  348.  
  349. void
  350. TScribbleWindow::CmPenSize()
  351. {
  352.   GetPenSize();
  353. }
  354.  
  355. void
  356. TScribbleWindow::CmPenColor()
  357. {
  358.   TChooseColorDialog::TData colors;
  359.   static TColor custColors[16] = {
  360.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  361.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  362.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  363.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  364.   };
  365.  
  366.   colors.Flags = CC_RGBINIT;
  367.   colors.Color = TColor(Line->QueryColor());
  368.   colors.CustColors = custColors;
  369.   if (TChooseColorDialog(this, colors).Execute() == IDOK)
  370.     Line->SetPen(colors.Color);
  371. }
  372.  
  373. void
  374. TScribbleWindow::GetPenSize()
  375. {
  376.   char inputText[6];
  377.   int penSize = Line->QueryPenSize();
  378.  
  379.   wsprintf(inputText, "%d", penSize);
  380.   if (TInputDialog(this, "Line Thickness",
  381.                    "Input a new thickness:",
  382.                    inputText,
  383.                    sizeof(inputText)).Execute() == IDOK) {
  384.     penSize = atoi(inputText);
  385.  
  386.     if (penSize < 1)
  387.       penSize = 1;
  388.   }
  389.   Line->SetPen(penSize);
  390. }
  391.  
  392. void
  393. TScribbleWindow::Paint(TDC& dc, bool erase, TRect& rect)
  394. {
  395.   TOleWindow::Paint(dc, erase, rect);
  396.  
  397.   // Iterates through the array of line objects.
  398.   TLinesIterator i(*Lines);
  399.  
  400.   while (i)
  401.     i++.Draw(dc);
  402. }
  403.  
  404. void
  405. TScribbleWindow::CmFileSave()
  406. {
  407.   if (IsNewFile)
  408.     CmFileSaveAs();
  409.   else
  410.     SaveFile(false);
  411. }
  412.  
  413. void
  414. TScribbleWindow::CmFileSaveAs()
  415. {
  416.   if (TFileSaveDialog(this, FileData).Execute() == IDOK)
  417.     SaveFile(true);
  418. }
  419.  
  420. void
  421. TScribbleWindow::CmAbout()
  422. {
  423.   TDialog(this, IDD_ABOUT).Execute();
  424. }
  425.  
  426. void
  427. TScribbleWindow::SaveFile(bool pathChanged)
  428. {
  429.   if (pathChanged && !OcDoc->SaveToFile(FileData.FileName))
  430.     return; // error!
  431.   TOcStorage* storage = OcDoc->GetStorage();
  432.  
  433.   if (!storage) {
  434.     MessageBox("Bogus internal storage problem", "File Error", MB_OK | MB_ICONEXCLAMATION);
  435.   }
  436.   else {
  437.     TOcStream  stream(*storage, "Scribble", true, STGM_READWRITE);
  438.     ostrstream os;
  439.  
  440.     // Write the number of lines in the figure
  441.     os << Lines->GetItemsInContainer();
  442.  
  443.     // Append a description using a resource string
  444.     os << ' ' << string(*GetApplication(), IDS_FILEINFO) << '\n';
  445.  
  446.     // Get an iterator for the array of lines
  447.     TLinesIterator i(*Lines);
  448.  
  449.     // While the iterator is valid (i.e. we haven't run out of lines)
  450.     while (i)
  451.       // Copy the current line from the iterator and increment the array.
  452.       os << i++;
  453.  
  454.     // Set new file and dirty display indicator to false.
  455.     IsNewFile = IsDirty = false;
  456.     if (pathChanged)
  457.       SetDocTitle(FileData.FileName, 0);
  458.  
  459.     OcDoc->SetName(FileData.FileName);
  460.  
  461.     stream.Write(os.str(), os.pcount());
  462.     stream.Commit(STGC_DEFAULT);
  463.  
  464.     OcDoc->SaveParts(0, true);
  465.     OcDoc->GetStorage()->Commit(STGC_DEFAULT);
  466.   }
  467. }
  468.  
  469. void
  470. TScribbleWindow::OpenFile()
  471. {
  472.   try {
  473.     OcDoc->SetStorage(FileData.FileName);
  474.     TOcStorage* storage = OcDoc->GetStorage();
  475.  
  476.     if (!storage)
  477.       MessageBox("Bogus internal storage problem", "File Error", MB_OK | MB_ICONEXCLAMATION);
  478.     else {
  479.       TOcStream   stream(*storage, "Scribble", false, STGM_READWRITE);
  480.  
  481.       // figure out the size of our stream to read, & read it into a buffer
  482.       uint64 size;
  483.       stream.Seek(0, STREAM_SEEK_END, &size);
  484.       char* buff = new char[(int)size.LowPart+10]; 
  485.       stream.Seek(0, STREAM_SEEK_SET);
  486.       stream.Read(buff, size.LowPart);
  487.  
  488.       // now make the buffer into a input str stream & stream in our objects
  489.       istrstream is(buff, (int)size.LowPart);
  490.       unsigned numLines;
  491.       char fileinfo[100];
  492.  
  493.       Lines->Flush();
  494.       Line->Flush();
  495.  
  496.       is >> numLines;
  497.       is.getline(fileinfo, sizeof(fileinfo));
  498.       SetDocTitle(FileData.FileName, 0);
  499.  
  500.       for (int i = 0; i < numLines; i++) {
  501.         TLine line;
  502.         is >> line;
  503.         Lines->Add(line);
  504.       }
  505.       delete [] buff;
  506.  
  507.       OcDoc->LoadParts();
  508.     }
  509.     IsNewFile = IsDirty = false;
  510.     Invalidate();
  511.   }
  512.   catch(TXBase& xbase) {
  513.     MessageBox(xbase.why().c_str(), "EXCEPTION", MB_OK);
  514.   }
  515. }
  516.  
  517. //----------------------------------------------------------------------------
  518.  
  519. class TScribbleApp : public TApplication, public TOcModule {
  520.   public:
  521.     TScribbleApp();
  522.  
  523.     TUnknown* CreateOleObject(uint32 /*options*/, TRegLink* /*link*/) {return 0;}
  524.  
  525.   protected:
  526.     void InitMainWindow();
  527.     void InitInstance();
  528.  
  529.     void CmFileNew();
  530.     void CmFileOpen();
  531.  
  532.     TOpenSaveDialog::TData FileData;
  533.  
  534.   DECLARE_RESPONSE_TABLE(TScribbleApp);
  535. };
  536.  
  537. DEFINE_RESPONSE_TABLE(TScribbleApp)
  538.   EV_COMMAND(CM_FILENEW, CmFileNew),
  539.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  540. END_RESPONSE_TABLE;
  541.  
  542. TScribbleApp::TScribbleApp()
  543. :
  544.   TApplication(::AppReg["appname"]),
  545.   FileData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  546.            "Scribble Files (*."DocExt")|*."DocExt"|", 0, "", DocExt)
  547. {
  548. }
  549.  
  550. void
  551. TScribbleApp::InitMainWindow()
  552. {
  553.   // Construct the ole decorated frame window
  554.   TOleFrame* frame = new TOleFrame(GetName(), 0, true, this);
  555.  
  556.   // Construct a status bar
  557.   TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  558.  
  559.   // Construct a control bar
  560.   TControlBar* cb = new TControlBar(frame);
  561.   cb->Insert(*new TButtonGadget(CM_FILENEW, CM_FILENEW, TButtonGadget::Command));
  562.   cb->Insert(*new TButtonGadget(CM_FILEOPEN, CM_FILEOPEN, TButtonGadget::Command));
  563.   cb->Insert(*new TButtonGadget(CM_FILESAVE, CM_FILESAVE, TButtonGadget::Command));
  564.   cb->Insert(*new TButtonGadget(CM_FILESAVEAS, CM_FILESAVEAS, TButtonGadget::Command));
  565.   cb->Insert(*new TSeparatorGadget);
  566.   cb->Insert(*new TButtonGadget(CM_PENSIZE, CM_PENSIZE, TButtonGadget::Command));
  567.   cb->Insert(*new TButtonGadget(CM_PENCOLOR, CM_PENCOLOR, TButtonGadget::Command));
  568.   cb->Insert(*new TSeparatorGadget);
  569.   cb->Insert(*new TButtonGadget(CM_ABOUT, CM_ABOUT, TButtonGadget::Command));
  570.   cb->Attr.Id = IDW_TOOLBAR;
  571.  
  572.   // Insert the status bar and control bar into the frame
  573.   frame->Insert(*sb, TDecoratedFrame::Bottom);
  574.   frame->Insert(*cb, TDecoratedFrame::Top);
  575.  
  576.   // Set the main window and its menu
  577.   SetMainWindow(frame);
  578.   GetMainWindow()->SetMenuDescr(TMenuDescr(IDM_SCRIBBLE));
  579. }
  580.  
  581. //
  582. // Call file new command handler to get the initial new window
  583. //
  584. void
  585. TScribbleApp::InitInstance()
  586. {
  587.   TApplication::InitInstance();
  588.  
  589.   FileData.FileName[0] = 0;
  590.   TWindow* client = new TScribbleWindow(0, FileData);
  591.   TWindow* oldClient = GetMainWindow()->SetClientWindow(client);
  592.   if (oldClient) {
  593.     oldClient->Destroy();
  594.     delete oldClient;
  595.   }
  596. }
  597.  
  598. void
  599. TScribbleApp::CmFileNew()
  600. {
  601.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  602.   if (!scribbleWindow->CanClose())
  603.     return;
  604.  
  605.   FileData.FileName[0] = 0;
  606.   TWindow* client = new TScribbleWindow(0, FileData);
  607.   GetMainWindow()->SetClientWindow(client);
  608.   scribbleWindow->Destroy(0);
  609.   delete scribbleWindow;
  610. }
  611.  
  612. void
  613. TScribbleApp::CmFileOpen()
  614. {
  615.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  616.   if (!scribbleWindow->CanClose())
  617.     return;
  618.  
  619.   if (TFileOpenDialog(GetMainWindow(), FileData).Execute() == IDOK) {
  620.     TWindow* newScribbleWindow = new TScribbleWindow(0, FileData);
  621.     GetMainWindow()->SetClientWindow(newScribbleWindow);
  622.     scribbleWindow->Destroy(0);
  623.     delete scribbleWindow;
  624.   }
  625. }
  626.  
  627. int
  628. OwlMain(int /*argc*/, char* /*argv*/ [])
  629. {
  630.   try {
  631.     Registrar = new TOcRegistrar(::AppReg, TOleFactory<TScribbleApp>(),
  632.                                  TApplication::GetCmdLine());
  633.     return Registrar->Run();
  634.   }
  635.   catch (xmsg& x) {
  636.     ::MessageBox(0, x.why().c_str(), "Scribble App Exception", MB_OK);
  637.   }
  638.   return -1;
  639. }
  640.