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

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