home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / TUTOROLE.PAK / OWLOLE3.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  18.9 KB  |  757 lines

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