home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / STEP18.PAK / STEP18DV.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  47.4 KB  |  2,046 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1994 by Borland International
  3. //   Tutorial application -- step18dv.cpp
  4. //   Automation Container Server example
  5. //----------------------------------------------------------------------------
  6.  
  7. #define NO_VBX_PICTURES // So that vivbx.h's LPPICTURE does not conflict with
  8.                         // olectl's LPPICTURE
  9.  
  10. #include <owl/pch.h>
  11. #include <owl/dc.h>
  12. #include <owl/inputdia.h>
  13. #include <owl/chooseco.h>
  14. #include <owl/gdiobjec.h>
  15. #include <owl/docmanag.h>
  16. #include <owl/listbox.h>
  17. #include <owl/controlb.h>
  18. #include <owl/buttonga.h>
  19. #include <owl/scroller.h>  // scrolling support
  20. #include <classlib/arrays.h>
  21. #include <owl/olemdifr.h>
  22. #include <owl/oledoc.h>
  23. #include <owl/oleview.h>
  24. #include <owl/edit.rh>
  25. #include <owl/opensave.h>
  26. #include <owl/messageb.h>
  27. #include <ocf/automacr.h>
  28. #include <ocf/ocdata.h>
  29. #include <ocf/ocremvie.h>
  30. #include <ocf/ocreg.h>
  31. #include "step18dv.h"
  32. #include "step18.h"
  33. #include "step18dv.rc"
  34. #include <olectl.h>
  35. #include <tchar.h>
  36.  
  37. const char  DocContent[] = "All";
  38. const char  DrawPadFormat[] = "DrawPad";
  39.  
  40. BEGIN_REGISTRATION(DocReg)
  41.   REGDATA(progid,     "DrawPad.Drawing.18")
  42.   REGDATA(description,"DrawPad (Step18--AutoContServer) Drawing")
  43.   REGDATA(menuname,   "Drawing")
  44.   REGDATA(extension,  "p18")
  45.   REGDATA(docfilter,  "*.p18")
  46.   REGDOCFLAGS(dtAutoOpen | dtAutoDelete | dtUpdateDir | dtCreatePrompt | dtRegisterExt)
  47. //REGDATA(debugger,   "tdw")
  48.   REGDATA(insertable, "")
  49. //x  REGDATA(control, "")
  50.   REGDATA(verb0,      "&Edit")
  51.   REGDATA(verb1,      "&Open")
  52.   REGFORMAT(0, DrawPadFormat,   ocrContent,  ocrHGlobal,              ocrGetSet)
  53.   REGFORMAT(1, ocrEmbedSource,  ocrContent,  ocrIStorage,             ocrGetSet)
  54.   REGFORMAT(2, ocrMetafilePict, ocrContent,  ocrMfPict|ocrStaticMed,  ocrGet)
  55.   REGFORMAT(3, ocrBitmap,       ocrContent,  ocrGDI|ocrStaticMed,     ocrGet)
  56.   REGFORMAT(4, ocrDib,          ocrContent,  ocrHGlobal|ocrStaticMed, ocrGet)
  57. END_REGISTRATION
  58. BEGIN_REGISTRATION(ListReg)
  59.   REGDATA(description,"Line List")
  60.   REGDATA(extension,  "p18")
  61.   REGDATA(docfilter,  "*.p18")
  62.   REGDOCFLAGS(dtAutoDelete | dtHidden)
  63. END_REGISTRATION
  64.  
  65. DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawView,       DrawTemplate);
  66. DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawListView,   DrawListTemplate);
  67. DrawTemplate drawTpl(DocReg);
  68. DrawListTemplate drawListTpl(ListReg);
  69. HRESULT OcDispSetProp (IDispatch *pID, DISPID id, VARIANTARG *propVal);
  70. HRESULT OcDispGetProp (IDispatch *pID, DISPID id, VARIANTARG *propVal);
  71. HRESULT OcDispGetPropString (IDispatch *pID, DISPID id,
  72.   char *propVal, int bufSize);
  73.  
  74. //===============================  TLine  =====================================
  75. //
  76. void
  77. TLine::SetPen(int penSize)
  78. {
  79.   if (penSize < 1)
  80.     PenSize = 1;
  81.   else
  82.     PenSize = penSize;
  83. }
  84.  
  85. void
  86. TLine::SetPen(const TColor& newColor, int penSize)
  87. {
  88.   // If penSize isn't the default (0), set PenSize to the new size.
  89.   if (penSize)
  90.     PenSize = penSize;
  91.  
  92.   Color = newColor;
  93. }
  94.  
  95. void
  96. TLine::Invalidate(TDrawView& view)
  97. {
  98.   TOleClientDC dc(view);
  99.  
  100.   TRect rUpdate(GetBound());
  101.   rUpdate.Inflate(1, 1);
  102.   dc.LPtoDP((TPoint *)&rUpdate, 2);
  103.   TUIHandle handle(rUpdate, TUIHandle::Framed);
  104.   rUpdate = handle.GetBoundingRect();
  105.  
  106.   view.GetDocument().NotifyViews(vnInvalidate, (long)&rUpdate, 0);
  107. }
  108.  
  109. void
  110. TLine::UpdateBound()
  111. {
  112.   // Iterates through the points in the line i.
  113.   TPointsIterator j(*this);
  114.   if (!j)
  115.     return;
  116.   TPoint p = j++;
  117.   Bound.Set(p.x, p.y, 0, 0);
  118.  
  119.   while (j) {
  120.     p = j++;
  121.    if ((p.x - PenSize) < Bound.left)
  122.      Bound.left = (p.x - PenSize);
  123.    if ((p.x + PenSize) > Bound.right)
  124.      Bound.right = (p.x + PenSize);
  125.    if ((p.y - PenSize) < Bound.top)
  126.      Bound.top = (p.y - PenSize);
  127.    if ((p.y + PenSize) > Bound.bottom)
  128.      Bound.bottom = (p.y + PenSize);
  129.   }
  130.   Bound.right  += 1;
  131.   Bound.bottom += 1;
  132. }
  133.  
  134. void
  135. TLine::UpdatePosition(TPoint& newPos)
  136. {
  137.   for (TPointsIterator i(*this); i; i++) {
  138.     TPoint* pt = (TPoint *)&i.Current();
  139.     pt->x += newPos.x;
  140.     pt->y += newPos.y;
  141.   }
  142.  
  143.   Bound.Offset(newPos.x, newPos.y);
  144. }
  145.  
  146. void
  147. TLine::UpdateSize(TSize& newSize)
  148. {
  149.   TSize delta = newSize - GetSize();
  150.   for (TPointsIterator i(*this); i; i++) {
  151.     TPoint* pt = (TPoint *)&i.Current();
  152.     pt->x += (((pt->x - Bound.left) * delta.cx + (GetSize().cx >> 1))/GetSize().cx);
  153.     pt->y += (((pt->y - Bound.top) * delta.cy + (GetSize().cy >> 1))/GetSize().cy);
  154.   }
  155.  
  156.   Bound.right = Bound.left + newSize.cx;
  157.   Bound.bottom = Bound.top  + newSize.cy;
  158. }
  159.  
  160. void
  161. TLine::DrawSelection(TDC &dc)
  162. {
  163.   TUIHandle(Bound, TUIHandle::DashFramed).Paint(dc);
  164. }
  165.  
  166. bool
  167. TLine::Draw(TDC& dc) const
  168. {
  169.   // Set pen for the dc to the values for this line
  170.   TPen pen(Color, PenSize, PS_INSIDEFRAME);
  171.   dc.SelectObject(pen);
  172.  
  173.   // Iterates through the points in the line i.
  174.   TPointsIterator j(*this);
  175.   bool first = true;
  176.  
  177.   while (j) {
  178.     TPoint p = j++;
  179.  
  180.     if (!first)
  181.       dc.LineTo(p);
  182.     else {
  183.       dc.MoveTo(p);
  184.       first = false;
  185.     }
  186.   }
  187.   dc.RestorePen();
  188.   return true;
  189. }
  190.  
  191. ostream&
  192. operator <<(ostream& os, const TLine& line)
  193. {
  194.   // Write the number of points in the line
  195.   os << line.GetItemsInContainer();
  196.  
  197.   // Get and write pen attributes.
  198.   os << ' ' << line.Color << ' ' << line.PenSize;
  199.  
  200.   // Get an iterator for the array of points
  201.   TPointsIterator j(line);
  202.  
  203.   // While the iterator is valid (i.e. we haven't run out of points)
  204.   while(j)
  205.     // Write the point from the iterator and increment the array.
  206.     os << j++;
  207.   os << '\n';
  208.  
  209.   // return the stream object
  210.   return os;
  211. }
  212.  
  213. istream&
  214. operator >>(istream& is, TLine& line)
  215. {
  216.   unsigned numPoints;
  217.   is >> numPoints;
  218.  
  219.   COLORREF color;
  220.   int penSize;
  221.   is >> color >> penSize;
  222.   line.SetPen(TColor(color), penSize);
  223.  
  224.   while (numPoints--) {
  225.     TPoint point;
  226.     is >> point;
  227.     line.Add(point);
  228.   }
  229.  
  230.   // return the stream object
  231.   return is;
  232. }
  233.  
  234. DEFINE_AUTOCLASS(TDrawDocument)
  235.   EXPOSE_PROPRW(PenSize,    TAutoShort, "PenSize",    "Current pen size", 0)
  236.   EXPOSE_PROPRW(PenColor,   TAutoLong,  "PenColor",   "Current pen color", 0)
  237.   EXPOSE_METHOD(AddPoint,   TAutoVoid,  "AddPoint",   "Add a point to the current line", 0)
  238.    REQUIRED_ARG(            TAutoShort, "X")
  239.    REQUIRED_ARG(            TAutoShort, "Y")
  240.   EXPOSE_METHOD(AddLine,    TAutoVoid,  "AddLine",    "Add current line into drawing", 0)
  241.   EXPOSE_METHOD(ClearLine,  TAutoVoid,  "ClearLine",  "Erases current line", 0)
  242.   EXPOSE_APPLICATION(       TDrawApp,   "Application","Application object", 0)
  243. END_AUTOCLASS(TDrawDocument, tfNormal,  "TDrawDoc",   "Draw document class", 0)
  244.  
  245. TDrawDocument::TDrawDocument(TDocument* parent)
  246.   : TOleDocument(parent), UndoLine(0), UndoState(UndoNone)
  247. {
  248.   Lines         = new TLines(100, 0, 5);
  249.   AutoPenSize   = 1;
  250.   AutoPenColor  = RGB(0, 0, 0);
  251.   AutoLine      = new TLine(AutoPenColor, AutoPenSize);
  252.  
  253.   TScreenDC dc;
  254.  
  255.   // 8.5"" x 11" draw document
  256.   DocSize.cx = dc.GetDeviceCaps(LOGPIXELSX)* 85 / 10;
  257.   DocSize.cy = dc.GetDeviceCaps(LOGPIXELSY)* 11;
  258. }
  259.  
  260. TDrawDocument::~TDrawDocument()
  261. {
  262.   delete AutoLine;
  263.   delete Lines;
  264.   delete UndoLine;
  265. }
  266.  
  267. TLine*
  268. TDrawDocument::GetLine(TString& moniker)
  269. {
  270.   int index = atoi(moniker);
  271.   return GetLine(index);
  272. }
  273.  
  274. bool
  275. TDrawDocument::CommitSelection(TOleWindow& oleWin, void* userData)
  276. {
  277.   TOleDocument::CommitSelection(oleWin, userData);
  278.  
  279.   TDrawView* drawView = TYPESAFE_DOWNCAST(&oleWin, TDrawView);
  280.   TOutStream* os = OutStream(ofWrite);
  281.   if (!os || !drawView)
  282.     return false;
  283.  
  284.   // Make the line usable in a container by adjusting its origin
  285.   //
  286.   TLine* line = (TLine*)userData;
  287.   int i = line? 1 : 0;
  288.   TPoint newPos(Margin, Margin);
  289.   if (line) {
  290.     newPos -= line->GetBound().TopLeft();
  291.     line->UpdatePosition(newPos);
  292.   }
  293.  
  294.   // Write the number of lines in the figure
  295.   *os << i;
  296.  
  297.   // Append a description using a resource string
  298.   *os << ' ' << FileInfo << '\n';
  299.  
  300.   // Copy the current line from the iterator and increment the array.
  301.   if (line)
  302.     *os << *line;
  303.  
  304.   delete os;
  305.  
  306.   // restore line
  307.   //
  308.   if (line)
  309.     line->UpdatePosition(-newPos);
  310.  
  311.   //
  312.   // Commit the storage if it was opened in transacted mode
  313. //  TOleDocument::CommitTransactedStorage();
  314.  
  315.   return true;
  316. }
  317.  
  318. bool
  319. TDrawDocument::Commit(bool force)
  320. {
  321.   TOleDocument::Commit(force);
  322.  
  323.   TOutStream* os = OutStream(ofWrite);
  324.   if (!os)
  325.     return false;
  326.  
  327.   // Write the number of lines in the figure
  328.   *os << Lines->GetItemsInContainer();
  329.  
  330.   // Append a description using a resource string
  331.   *os << ' ' << FileInfo << '\n';
  332.  
  333.   // Get an iterator for the array of lines
  334.   TLinesIterator i(*Lines);
  335.  
  336.   // While the iterator is valid (i.e. we haven't run out of lines)
  337.   while (i) {
  338.     // Copy the current line from the iterator and increment the array.
  339.     *os << i++;
  340.   }
  341.   delete os;
  342.  
  343.   //
  344.   // Commit the storage if it was opened in transacted mode
  345.   TOleDocument::CommitTransactedStorage();
  346.   SetDirty(false);
  347.  
  348.   return true;
  349. }
  350.  
  351. bool
  352. TDrawDocument::Open(int mode, const char far* path)
  353. {
  354.   char fileinfo[100];
  355.  
  356.   TOleDocument::Open(mode, path);   // normally path should be null
  357.   if (GetDocPath()) {
  358.     TInStream* is = (TInStream*)InStream(ofRead);
  359.     if (!is)
  360.       return false;
  361.  
  362.     unsigned numLines;
  363.     *is >> numLines;
  364.     is->getline(fileinfo, sizeof(fileinfo));
  365.     while (numLines--) {
  366.       TLine line;
  367.       *is >> line;
  368.       line.UpdateBound();
  369.       Lines->Add(line);
  370.     }
  371.  
  372.     delete is;
  373.  
  374.     FileInfo = fileinfo;
  375.   } else {
  376.     FileInfo = string(*::Module,IDS_FILEINFO);
  377.   }
  378.   SetDirty(false);
  379.   UndoState = UndoNone;
  380.   return true;
  381. }
  382.  
  383. //
  384. // Read in the lines from a storage and put them at the location specified
  385. // by where
  386. //
  387. bool
  388. TDrawDocument::OpenSelection(int mode, const char far* path, TPoint far* where)
  389. {
  390.   char fileinfo[100];
  391.  
  392.   TOleDocument::Open(mode, path);   // normally path should be null
  393.   //if (GetDocPath()) {
  394.     TInStream* is = (TInStream*)InStream(ofRead);
  395.     if (!is)
  396.       return false;
  397.  
  398.     unsigned numLines;
  399.     *is >> numLines;
  400.     is->getline(fileinfo, sizeof(fileinfo));
  401.     while (numLines--) {
  402.       TLine line;
  403.       *is >> line;
  404.       if (where) {
  405.         TPoint newPos(where->x, where->y);
  406.         newPos -= line.GetBound().TopLeft();
  407.         line.UpdatePosition(newPos);
  408.       }
  409.       line.UpdateBound();
  410.       Lines->Add(line);
  411.     }
  412.  
  413.     delete is;
  414.  
  415.   if (GetDocPath()) {
  416.     FileInfo = fileinfo;
  417.   } else {
  418.     FileInfo = string(*::Module,IDS_FILEINFO);
  419.   }
  420.   SetDirty(false);
  421.   UndoState = UndoNone;
  422.   return true;
  423. }
  424.  
  425. bool
  426. TDrawDocument::Close()
  427. {
  428.   Lines->Flush();
  429.   return TOleDocument::Close();
  430. }
  431.  
  432. TLine*
  433. TDrawDocument::GetLine(uint index)
  434. {
  435.   return index < Lines->GetItemsInContainer() ? &(*Lines)[index] : 0;
  436. }
  437.  
  438. int
  439. TDrawDocument::AddLine(TLine& line)
  440. {
  441.   int index = Lines->GetItemsInContainer();
  442.   Lines->Add(line);
  443.   SetDirty(true);
  444.   NotifyViews(vnDrawAppend, index);
  445.   UndoState = UndoAppend;
  446.   return index;
  447. }
  448.  
  449. void
  450. TDrawDocument::DeleteLine(uint index)
  451. {
  452.   const TLine* oldLine = GetLine(index);
  453.   if (!oldLine)
  454.     return;
  455.   delete UndoLine;
  456.   UndoLine = new TLine(*oldLine);
  457.   Lines->Detach(index);
  458.   SetDirty(true);
  459.   NotifyViews(vnDrawDelete, index);
  460.   UndoState = UndoDelete;
  461. }
  462.  
  463. void
  464. TDrawDocument::ModifyLine(TLine& line, uint index)
  465. {
  466.   delete UndoLine;
  467.   UndoLine = new TLine((*Lines)[index]);
  468.   SetDirty(true);
  469.   (*Lines)[index] = line;
  470.   NotifyViews(vnDrawModify, index);
  471.   UndoState = UndoModify;
  472.   UndoIndex = index;
  473. }
  474.  
  475. void
  476. TDrawDocument::Clear()
  477. {
  478.   Lines->Flush();
  479.   NotifyViews(vnRevert, true);
  480. }
  481.  
  482. void
  483. TDrawDocument::Undo()
  484. {
  485.   switch (UndoState) {
  486.     case UndoAppend:
  487.       DeleteLine(Lines->GetItemsInContainer()-1);
  488.       return;
  489.     case UndoDelete:
  490.       AddLine(*UndoLine);
  491.       delete UndoLine;
  492.       UndoLine = 0;
  493.       return;
  494.     case UndoModify:
  495.       TLine* temp = UndoLine;
  496.       UndoLine = 0;
  497.       ModifyLine(*temp, UndoIndex);
  498.       delete temp;
  499.   }
  500. }
  501.  
  502. bool
  503. GetPenSize(TWindow* parent, TLine& line)
  504. {
  505.   char inputText[6];
  506.  
  507.   wsprintf(inputText, "%d", line.QueryPenSize());
  508.   if (TInputDialog(parent, "Line Thickness",
  509.                    "Input a new thickness:",
  510.                    inputText,
  511.                    sizeof(inputText)).Execute() != IDOK)
  512.     return false;
  513.   line.SetPen(atoi(inputText));
  514.  
  515.   if (line.QueryPenSize() < 1)
  516.     line.SetPen(1);
  517.  
  518.   return true;
  519. }
  520.  
  521. bool
  522. GetPenColor(TWindow* parent, TLine& line)
  523. {
  524.   TChooseColorDialog::TData colors;
  525.   static TColor custColors[16] =
  526.   {
  527.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  528.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  529.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  530.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  531.   };
  532.  
  533.   colors.Flags = CC_RGBINIT;
  534.   colors.Color = TColor(line.QueryColor());
  535.   colors.CustColors = custColors;
  536.   if (TChooseColorDialog(parent, colors).Execute() != IDOK)
  537.     return false;
  538.   line.SetPen(colors.Color);
  539.   return true;
  540. }
  541.  
  542. DEFINE_RESPONSE_TABLE1(TDrawLinkView, TOleLinkView)
  543.   EV_VN_DRAWDELETE,
  544.   EV_VN_DRAWMODIFY,
  545. END_RESPONSE_TABLE;
  546.  
  547. TDrawLinkView::TDrawLinkView(TDocument& doc, TOcLinkView& view)
  548.   :TOleLinkView(doc, view)
  549. {
  550.   DrawDoc = TYPESAFE_DOWNCAST(&doc, TDrawDocument);
  551.   CHECK(DrawDoc);
  552. }
  553.  
  554. TDrawLinkView::~TDrawLinkView()
  555. {
  556. }
  557.  
  558. //
  559. // Line was modified
  560. //
  561. bool
  562. TDrawLinkView::VnModify(uint index)
  563. {
  564.   // Get the selection correspondign to the moniker
  565.   //
  566.   TLine * line = DrawDoc->GetLine(GetMoniker());
  567.   if (!line)
  568.     return false;
  569.  
  570.   // Notify the container
  571.   //
  572.   if (index == DrawDoc->GetLines()->Find(*line)) {
  573.     UpdateLinks();
  574.   }
  575.  
  576.   return true;
  577. }
  578.  
  579. //
  580. // Line was deleted
  581. //
  582. bool
  583. TDrawLinkView::VnDelete(uint index)
  584. {
  585.   // Get the selection correspondign to the moniker
  586.   //
  587.   TLine * line = DrawDoc->GetLine(GetMoniker());
  588.   if (!line)
  589.     return false;
  590.  
  591.   // Notify the container
  592.   //
  593.   if (index == DrawDoc->GetLines()->Find(*line)) {
  594.     UpdateLinks();
  595.   }
  596.   return true;
  597. }
  598.  
  599. DEFINE_RESPONSE_TABLE1(TDrawView, TOleView)
  600.   EV_WM_LBUTTONDOWN,
  601.   EV_WM_MOUSEMOVE,
  602.   EV_WM_LBUTTONUP,
  603.  
  604.   EV_COMMAND(CM_NEWCONTROL, CmNewControl),
  605.   EV_COMMAND(CM_CONTROLPROPS, CmControlProps),
  606.   EV_COMMAND_ENABLE(CM_CONTROLPROPS, CeControlProps),
  607.   EV_COMMAND(CM_CONTROLFONT, CmControlFont),
  608.   EV_COMMAND(CM_CONTROLCAPTION, CmControlCaption),
  609.   EV_COMMAND(CM_CONTAINERMODE, CmContainerMode),
  610.   EV_COMMAND_ENABLE(CM_CONTAINERMODE, CeContainerMode),
  611.   EV_COMMAND_ENABLE(CM_CONTROLCAPTION, CeControlProps),
  612.   EV_COMMAND_ENABLE(CM_CONTROLFONT, CeControlProps),
  613.   EV_COMMAND(CM_REGISTEROCX, CmRegisterControl),
  614.   EV_COMMAND(CM_UNREGISTEROCX, CmUnregisterControl),
  615.   EV_COMMAND(CM_PEN, CmPen),
  616.   EV_COMMAND_ENABLE(CM_PEN, CePen),
  617.   EV_COMMAND(CM_SELECT, CmSelect),
  618.   EV_COMMAND_ENABLE(CM_SELECT, CeSelect),
  619.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  620.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  621.   EV_COMMAND(CM_EDITCLEAR, CmClear),
  622.   EV_COMMAND(CM_EDITUNDO, CmUndo),
  623.   EV_COMMAND(CM_EDITCUT, CmEditCut),
  624.   EV_COMMAND(CM_EDITCOPY, CmEditCopy),
  625.   EV_COMMAND_ENABLE(CM_EDITCUT, CeEditCut),
  626.   EV_COMMAND_ENABLE(CM_EDITCOPY, CeEditCopy),
  627.   EV_COMMAND(CM_ORGSIZE, CmOrgSize),
  628.   EV_COMMAND(CM_DOUBLESIZE, CmDoubleSize),
  629.   EV_COMMAND(CM_HALFSIZE, CmHalfSize),
  630.   EV_COMMAND_ENABLE(CM_ORGSIZE, CeOrgSize),
  631.   EV_COMMAND_ENABLE(CM_DOUBLESIZE, CeDoubleSize),
  632.   EV_COMMAND_ENABLE(CM_HALFSIZE, CeHalfSize),
  633.   EV_VN_COMMIT,
  634.   EV_VN_REVERT,
  635.   EV_VN_DRAWAPPEND,
  636.   EV_VN_DRAWDELETE,
  637.   EV_VN_DRAWMODIFY,
  638.  
  639.   EV_WM_SETFOCUS,
  640.   EV_OC_VIEWPARTSIZE,
  641.   EV_OC_VIEWSHOWTOOLS,
  642.   EV_OC_VIEWGETITEMNAME,
  643.   EV_OC_VIEWSETLINK,
  644.   EV_OC_VIEWCLIPDATA,
  645.  
  646. END_RESPONSE_TABLE;
  647.  
  648. TDrawView::TDrawView(TDrawDocument& doc, TWindow* parent)
  649. :
  650.   TOleView(doc, parent), DrawDoc(&doc), pIFont (NULL)
  651. {
  652.   // this is temporary to let all control to paint
  653.   // we need CLIPCHILDREN, so we'll put it back
  654.   ModifyStyle(WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
  655.  
  656.   Selected  = 0;
  657.   Tool      = DrawPen;
  658.   ToolBar   = 0;
  659.  
  660.   Line = new TLine(TColor::Black, 1);
  661.   Attr.AccelTable = IDA_DRAWVIEW;
  662.   SetViewMenu(new TMenuDescr(IDM_DRAWVIEW));
  663.  
  664.   // Name our clipboard format
  665.   //
  666.   OcApp->AddUserFormatName("DrawPad Native Data", "Owl DrawPad native data", DrawPadFormat);
  667.  
  668.   IUnknown *pIU;
  669.   OcApp->BOleComponentCreate (&pIU, NULL, cidBOleFont);
  670.   pIU->QueryInterface (IID_IFontDisp, &(LPVOID)pIFont);
  671.   pIU->Release ();
  672.   backRGB = RGB (0xFF, 0x00, 0x00);
  673.   designMode = FALSE;
  674. }
  675.  
  676. TDrawView::~TDrawView()
  677. {
  678.   delete Line;
  679.   if (pIFont)
  680.     pIFont->Release ();
  681. }
  682.  
  683. void
  684. TDrawView::SetupWindow()
  685. {
  686.   TOleView::SetupWindow();
  687.  
  688.   // Scroll bars
  689.   Attr.Style |= WS_VSCROLL | WS_HSCROLL;
  690.  
  691.   Scroller = new TScroller(this, 1, 1, 0, 0);
  692.   AdjustScroller();
  693.  
  694.   // Set this option to force all embedded servers to open out of place
  695.   // GetOcView()->SetOption(voNoInPlace,true);
  696.  
  697.   // Set this option to force all embedded servers to open out of place
  698.   // when the container/server is inplace
  699.   // GetOcView()->SetOption(voNoNestedInPlace,true);
  700.  
  701. }
  702.  
  703. //
  704. // Adjust the Scroller range
  705. //
  706. void
  707. TDrawView::AdjustScroller()
  708. {
  709.   TDrawDocument *drawDoc = TYPESAFE_DOWNCAST(&GetDocument(), TDrawDocument);
  710.   CHECK(drawDoc);
  711.   TSize range = drawDoc->GetDocSize();
  712.  
  713.   // Use device unit for scroll range
  714.   //
  715.   TOleClientDC dc(*this);
  716.   dc.LPtoDP((TPoint*)&range);
  717.  
  718.   range -= GetClientRect().Size();
  719.   Scroller->SetRange(range.cx, range.cy);
  720. }
  721.  
  722. //
  723. // Reset scroller range.
  724. //
  725. void
  726. TDrawView::EvSize(UINT SizeType, TSize& Size)
  727. {
  728.   TOleView::EvSize(SizeType, Size);
  729.   if (SizeType != SIZEICONIC) {
  730.     AdjustScroller();
  731.   }
  732. }
  733.  
  734. static int
  735. Intersect(const TLine& line, void* param)
  736. {
  737.   TPoint*  pt = (TPoint*)param;
  738.   TLine &modify = const_cast<TLine&>(line);
  739.   if (modify.IsSelected()) {
  740.     modify.Where = TUIHandle(modify.GetBound(), TUIHandle::Framed).HitTest(*pt);
  741.   }
  742.   else {
  743.     if (modify.GetBound().Contains(*pt))
  744.       modify.Where = TUIHandle::MidCenter;
  745.     else
  746.       modify.Where = TUIHandle::Outside;
  747.   }
  748.  
  749.   return line.Where != TUIHandle::Outside;
  750. }
  751.  
  752. TLine*
  753. TDrawView::HitTest(TPoint& pt)
  754. {
  755.   return DrawDoc->GetLines()->LastThat(Intersect, &pt);
  756. }
  757.  
  758. bool
  759. TDrawView::ShowCursor(HWND /*wnd*/, uint hitTest, uint /*mouseMsg*/)
  760. {
  761.   TPoint pt;
  762.   GetCursorPos(pt);
  763.   ScreenToClient(pt);
  764.   if (Tool == DrawSelect) {
  765.     ::SetCursor(::LoadCursor(0, IDC_ARROW));
  766.     return true;
  767.   }
  768.  
  769.   if (Tool == DrawPen && (hitTest == HTCLIENT)) {
  770.     HCURSOR cur = ::LoadCursor(*GetModule(), MAKEINTRESOURCE(IDC_PENCIL));
  771.     ::SetCursor(cur);
  772.     return true;
  773.   }
  774.  
  775.   if (Tool == DrawPen && ((hitTest == HTHSCROLL) || (hitTest == HTVSCROLL))) {
  776.     ::SetCursor(::LoadCursor(0, IDC_ARROW));
  777.     return true;
  778.   }
  779.  
  780.   return false;
  781. }
  782.  
  783.  
  784. //
  785. // Let container know about the server view size in pixels
  786. //
  787. bool
  788. TDrawView::EvOcViewPartSize(TOcPartSize far& ps)
  789. {
  790.   TClientDC dc(*this);
  791.  
  792.   TRect rect(0, 0, 0, 0);
  793.   TLine* line = 0;
  794.   if (ps.Selection) {
  795.     if (ps.Moniker) {
  796.       if (strcmp(*ps.Moniker, OleStr(DocContent)) == 0)
  797.         line = 0; // whole document
  798.       else
  799.         line = DrawDoc->GetLine(*ps.Moniker);
  800.     }
  801.     else{
  802.       line = (TLine*) ps.UserData;
  803.     }
  804.   }
  805.  
  806.   if (line) {
  807.     *(TPoint*)&rect.left   = line->GetBound().TopLeft();
  808.     rect.right  = rect.left + line->GetBound().Width()  + 2 * Margin;
  809.     rect.bottom = rect.top  + line->GetBound().Height() + 2 * Margin;
  810.   }
  811.   else {
  812.     // a 2" x 2" extent for server
  813.     //
  814.     rect.right  = dc.GetDeviceCaps(LOGPIXELSX) * 2;
  815.     rect.bottom = dc.GetDeviceCaps(LOGPIXELSY) * 2;
  816.   }
  817.  
  818.   ps.PartRect = rect;
  819.   return true;
  820. }
  821.  
  822. bool
  823. TDrawView::EvOcViewShowTools(TOcToolBarInfo far& tbi)
  824. {
  825.   // Construct & create a control bar for show, destroy our bar for hide
  826.   //
  827.   if (tbi.Show) {
  828.     if (!ToolBar) {
  829.       ToolBar = new TControlBar(this);
  830.       ToolBar->Insert(*new TButtonGadget(CM_PENSIZE, CM_PENSIZE, TButtonGadget::Command));
  831.       ToolBar->Insert(*new TButtonGadget(CM_PENCOLOR, CM_PENCOLOR, TButtonGadget::Command));
  832.       ToolBar->Insert(*new TSeparatorGadget);
  833.       ToolBar->Insert(*new TButtonGadget(CM_PEN, CM_PEN, TButtonGadget::Exclusive));
  834.       ToolBar->Insert(*new TButtonGadget(CM_SELECT, CM_SELECT, TButtonGadget::Exclusive));
  835.       ToolBar->Insert(*new TButtonGadget(CM_ABOUT, CM_ABOUT, TButtonGadget::Command));
  836.       ToolBar->SetHintMode(TGadgetWindow::EnterHints);
  837.     }
  838.     ToolBar->Create();
  839.     tbi.HTopTB = (HWND)*ToolBar;
  840.   }
  841.   else {
  842.     if (ToolBar) {
  843.       ToolBar->Destroy();
  844.       delete ToolBar;
  845.       ToolBar = 0;
  846.     }
  847.   }
  848.   return true;
  849. }
  850.  
  851. //
  852. // Find the item name for whole doc or selection
  853. //
  854. bool
  855. TDrawView::EvOcViewGetItemName(TOcItemName& item)
  856. {
  857.   if (item.Selection) {
  858.     if (!Selected)
  859.       return false;
  860.     char name[32];
  861.     itoa(DrawDoc->GetLines()->Find(*Selected), name, 10);
  862.     item.Name = name;
  863.   }
  864.   else {
  865.     item.Name = "content"; // item name representing the whole document
  866.   }
  867.   return true;
  868. }
  869.  
  870.  
  871. //
  872. // Ask server to provide data according to the format in a handle
  873. //
  874. bool
  875. TDrawView::EvOcViewClipData(TOcFormatData far& formatData)
  876. {
  877.   if (strcmp(OleStr(formatData.Format.GetRegName()), OleStr(DrawPadFormat)) != 0)
  878.     return false; // not our clipboard format
  879.  
  880.   bool status = true;
  881.   if (formatData.Paste) { // Pasting native data
  882.     DrawDoc->SetHandle(ofReadWrite, formatData.Handle, false);
  883.     DrawDoc->OpenSelection(ofRead, 0, formatData.Where);
  884.     Invalidate();
  885.     // Restore the original storage
  886.     //
  887.     DrawDoc->RestoreStorage();
  888.  
  889.   }
  890.   else { // Copying native data
  891.     HANDLE data = GlobalAlloc(GHND|GMEM_SHARE, 0);
  892.     DrawDoc->SetHandle(ofReadWrite, data, true);
  893.  
  894.     // Copy the selection if the target format is "DrawPad"
  895.     //
  896.     if (formatData.UserData) {
  897.       status = DrawDoc->CommitSelection(*this, formatData.UserData);
  898.     }
  899.     else {
  900.       status = DrawDoc->Commit(true);
  901.     }
  902.  
  903.     formatData.Handle = data;
  904.     // Restore the original storage
  905.     //
  906.     DrawDoc->RestoreStorage();
  907.   }
  908.  
  909.   return status;
  910. }
  911.  
  912. bool
  913. TDrawView::EvOcAmbientGetBackColor(long *rgb)
  914. {
  915.   *rgb = backRGB;
  916.   return true;
  917. }
  918.  
  919. bool
  920. TDrawView::EvOcAmbientGetFont(IDispatch** font)
  921. {
  922.   *font = pIFont;
  923.   pIFont->AddRef ();
  924.   return true;
  925. }
  926.  
  927. bool
  928. TDrawView::EvOcAmbientGetUserMode(bool* mode)
  929. {
  930.   *mode = (designMode == FALSE);
  931.   return true;
  932. }
  933.  
  934. bool
  935. TDrawView::EvOcAmbientGetShowGrabHandles(bool* show)
  936. {
  937.   *show = designMode;
  938.   return true;
  939. }
  940.  
  941. bool
  942. TDrawView::EvOcAmbientGetShowHatching(bool* show)
  943. {
  944.   *show = designMode;
  945.   return true;
  946. }
  947.  
  948. bool
  949. TDrawView::EvOcAmbientGetDisplayAsDefault(bool* show)
  950. {
  951.   *show = (designMode == FALSE);
  952.   return true;
  953. }
  954.  
  955. bool
  956. TDrawView::EvOcAmbientGetTextAlign(short* align)
  957. {
  958.   *align = 3;  // right justify
  959.   return true;
  960. }
  961.  
  962. bool
  963. TDrawView::EvOcCtrlClick(TCtrlEvent*)
  964. {
  965.   MessageBeep (1);
  966.   SetStatusText ("Click Event");
  967.   return true;
  968. }
  969.  
  970. bool
  971. TDrawView::EvOcCtrlDblClick(TCtrlEvent*)
  972. {
  973.   MessageBeep (1);
  974.   SetStatusText ("Double Click Event");
  975.   return true;
  976. }
  977.  
  978. bool
  979. TDrawView::EvOcCtrlCustomEvent(TCtrlCustomEvent* pev)
  980. {
  981.   char       propString[256];
  982.   ITypeInfo *pITypeInfo;
  983.   LPTYPEATTR pTA;
  984.   UINT       i, j;
  985.   UINT       cEvents;
  986.  
  987.   propString[0] = '\0';
  988.   lstrcat (propString, "Custom Event:  ");
  989.   pITypeInfo = pev->Ctrl->GetEventTypeInfo ();
  990.   MessageBeep (1);
  991.   if (pITypeInfo)  {
  992.     pITypeInfo->GetTypeAttr (&pTA);
  993.     if (pTA) {
  994.       cEvents = pTA->cFuncs;
  995.       pITypeInfo->ReleaseTypeAttr (pTA);
  996.       for (i = 0; i < cEvents; i++) {
  997.         LPFUNCDESC    pFD;
  998.  
  999.         if (SUCCEEDED (pITypeInfo->GetFuncDesc (i, &pFD))) {
  1000.           if (pFD->memid == pev->Args->DispId) {
  1001.             UINT       cNames;
  1002.             BSTR       bstrName;       //Event name (function only)
  1003.             TAutoVal   Val;
  1004.  
  1005.             pITypeInfo->GetNames (pFD->memid, &bstrName, 1, &cNames);
  1006.             lstrcat (propString, OleStr (bstrName));
  1007.             SysFreeString (bstrName);
  1008.             pITypeInfo->ReleaseFuncDesc (pFD);
  1009.  
  1010.             lstrcat (propString, "    ");
  1011.             if ((pev->Args->ArgCount < 100) && (pev->Args->ArgCount > 0)) {  // rayk - bug check for how this is set
  1012.               for (j = 0; j < pev->Args->ArgCount; j++) {
  1013.                 Val = (*pev->Args)[j];
  1014.                 if ((Val.GetDataType() == VT_I4) ||
  1015.                     (Val.GetDataType() == VT_I2))
  1016.                   wsprintf (propString, "%s(int)Arg\[%d\]=0x%x; ",
  1017.                        propString, j, (int)(Val));
  1018.               }
  1019.             }
  1020.             SetStatusText (propString);
  1021.           }
  1022.         }
  1023.       }
  1024.     }
  1025.     pITypeInfo->Release();
  1026.   }
  1027.   return TRUE;
  1028. }
  1029.  
  1030. void
  1031. TDrawView::SetStatusText (char far* text)
  1032. {
  1033.   TOleFrame* mw =
  1034.         TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(), TOleFrame);
  1035.   TMessageBar* mb =
  1036.         TYPESAFE_DOWNCAST(mw->ChildWithId(IDW_STATUSBAR), TMessageBar);
  1037.   if (mb) {
  1038. #if defined(BI_DATA_NEAR)
  1039.     mb->SetText(string(text).c_str());
  1040. #else
  1041.     mb->SetText(text);
  1042. #endif
  1043.   }
  1044. }
  1045.  
  1046. //
  1047. // object selection
  1048. //
  1049. bool
  1050. TDrawView::Select(uint modKeys, TPoint& point)
  1051. {
  1052.   if (Tool != DrawSelect)
  1053.     return false;
  1054.  
  1055.   // Clicked in lines?
  1056.   TLine *line = HitTest(point);
  1057.   SetLineSelection(line);
  1058.  
  1059.   if (Selected) { // there is a selection
  1060.     TOleView::SetSelection(0);
  1061.     DragRect = line->GetBound();
  1062.     DragRect.right++;
  1063.     DragRect.bottom++;
  1064.     DragHit = line->Where;
  1065.     DragStart = DragPt = point;
  1066.     if (!DragDC)
  1067.       DragDC = new TOleClientDC(*this);
  1068.  
  1069.     DragDC->DrawFocusRect(DragRect);
  1070.     SetCapture();
  1071.     return true;
  1072.   }
  1073.   else
  1074.     // Select OLE object, if any
  1075.     return TOleView::Select(modKeys, point);
  1076.  
  1077. }
  1078.  
  1079. void
  1080. TDrawView::EvLButtonDown(uint modKeys, TPoint& point)
  1081. {
  1082.   TOleView::EvLButtonDown(modKeys, point);
  1083.   if (SelectEmbedded() || !DragDC)
  1084.     return;
  1085.  
  1086.   if (Tool == DrawSelect) { // selection
  1087. //    Select(modKeys, point);
  1088.   }
  1089.   else if (Tool == DrawPen) {
  1090.     SetCapture();
  1091.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  1092.     DragDC->SelectObject(*Pen);
  1093.     DragRect.SetNull();
  1094.     DragDC->MoveTo(point);
  1095.     Line->Add(point);
  1096.   }
  1097. }
  1098.  
  1099. void
  1100. TDrawView::EvMouseMove(uint modKeys, TPoint& point)
  1101. {
  1102.   TOleView::EvMouseMove(modKeys, point);
  1103.   if (SelectEmbedded() || !DragDC)
  1104.     return;
  1105.  
  1106.   if (Tool == DrawPen) {
  1107.     DragDC->LineTo(point);
  1108.     Line->Add(point);
  1109.   }
  1110.   else if (Selected && DragHit == TUIHandle::MidCenter &&
  1111.     !InClient(*DragDC, point)) { // selection
  1112.     DragDC->DrawFocusRect(DragRect);   // erase old rect
  1113.  
  1114.     // Start drag & drop
  1115.     //
  1116.     TOcDropAction outAction;
  1117.     TOcDataProvider* ocData = new TOcDataProvider(*OcView, &DocReg, 0,
  1118.                                                   (void*)Selected, CleanUp);
  1119.     OcApp->Drag(ocData, (TOcDropAction)(daDropCopy | daDropMove | daDropLink),
  1120.                 outAction);
  1121.  
  1122.     if (outAction == daDropMove) {
  1123.       DrawDoc->DeleteLine(DrawDoc->GetLines()->Find(*Selected));
  1124.       SetLineSelection(0);
  1125.     }
  1126.     ocData->Release();
  1127.     DragHit = TUIHandle::Outside;
  1128.   }
  1129. }
  1130.  
  1131. void
  1132. TDrawView::SetLineSelection(TLine *Line)
  1133. {
  1134.   if (Selected) {
  1135.     Selected->Invalidate(*this);
  1136.     Selected->Select(false);
  1137.   }
  1138.   Selected = Line;
  1139.   if (Selected) {
  1140.     Selected->Select(true);
  1141.     Selected->Invalidate(*this);
  1142.   }
  1143. }
  1144.  
  1145. void
  1146. TDrawView::SetLineSelection(int index)
  1147. {
  1148.   SetLineSelection(DrawDoc->GetLine(index));
  1149. }
  1150.  
  1151. void TDrawView::EvLButtonUp(uint modKeys, TPoint& point)
  1152. {
  1153.   TPoint oldPoint = point;
  1154.  
  1155.   if (!DragDC)
  1156.     return;
  1157.  
  1158.   if ((Tool == DrawSelect) && !SelectEmbedded()) {
  1159.     if (Selected && DragHit == TUIHandle::MidCenter) {
  1160.       Selected->Invalidate(*this);
  1161.       DragDC->DPtoLP(&point);
  1162.       TPoint newPos = point - DragStart;
  1163.       Selected->UpdatePosition(newPos);
  1164.       Selected->Invalidate(*this);
  1165.       InvalidatePart(invView);
  1166.       DragHit = TUIHandle::Outside;
  1167.       ReleaseCapture();
  1168.     }
  1169.   } else if ((Tool == DrawPen) && !SelectEmbedded()) {
  1170.     ReleaseCapture();
  1171.     if (Line->GetItemsInContainer() > 1) {
  1172.       Line->UpdateBound();
  1173.       DrawDoc->AddLine(*Line);
  1174.     }
  1175.  
  1176.     Line->Flush();
  1177.     delete Pen;
  1178.   }
  1179.  
  1180.   TOleView::EvLButtonUp(modKeys, oldPoint);
  1181. }
  1182.  
  1183. void
  1184. TDrawView::CePen(TCommandEnabler& ce)
  1185. {
  1186.   ce.SetCheck(Tool == DrawPen);
  1187. }
  1188.  
  1189. void
  1190. TDrawView::CeSelect(TCommandEnabler& ce)
  1191. {
  1192.   ce.SetCheck(Tool == DrawSelect);
  1193. }
  1194.  
  1195. void
  1196. TDrawView::CeContainerMode(TCommandEnabler& ce)
  1197. {
  1198.   if (designMode)
  1199.     ce.SetCheck (1);
  1200.   else
  1201.     ce.SetCheck (0);
  1202. }
  1203.  
  1204. void
  1205. TDrawView::CeControlProps(TCommandEnabler& ce)
  1206. {
  1207.   bool CtrlActive = FALSE;
  1208.   TOcPart* p = OcView->GetActivePart();
  1209.   if (p) {
  1210.     IBControl *CtrlI;
  1211.     if (SUCCEEDED(p->QueryInterface(IID_IBControl, &(LPVOID)CtrlI))) {
  1212.       CtrlActive = TRUE;
  1213.       CtrlI->Release();
  1214.     }
  1215.   }
  1216.   ce.Enable(CtrlActive);
  1217. }
  1218.  
  1219. void
  1220. TDrawView::CmControlProps()
  1221. {
  1222.   TOcPart* p = OcView->GetActivePart();
  1223.   if (p) {
  1224.  
  1225.     char          propString[4096];
  1226.     char       temp[128];
  1227.     IDispatch *pID = NULL;
  1228.     TOcControl*  pCtrl;
  1229.     IBControl* pIU;
  1230.  
  1231.     ITypeInfo     *pITypeInfo = NULL;
  1232.     LPTYPEATTR     pTA;
  1233.     UINT           i;
  1234.     UINT           cVars, cEvents;
  1235.  
  1236.     if (FAILED (p->QueryInterface(IID_IBControl, &(LPVOID)pIU)))
  1237.       goto err2a;
  1238.     pIU->Release ();
  1239.     pCtrl = (TOcControl *)p;
  1240.  
  1241.     if (FAILED (pIU->GetCtrlDispatch(&pID)))
  1242.       goto err2a;
  1243.  
  1244.     //if (FAILED (pCtrl->QueryInterface(IID_IDispatch, &(LPVOID)pID)))
  1245.     //  goto err2a;
  1246.  
  1247.     pID->GetTypeInfo (0, 0, &pITypeInfo);
  1248.     if (!pITypeInfo)
  1249.       goto err2;
  1250.  
  1251.     pITypeInfo->GetTypeAttr (&pTA);
  1252.     if (!pTA)
  1253.       goto err;
  1254.  
  1255.     cEvents = pTA->cFuncs;
  1256.     cVars = pTA->cVars;
  1257.     pITypeInfo->ReleaseTypeAttr (pTA);
  1258.  
  1259.     propString[0] = '\0';
  1260.         lstrcat (propString, "\nMETHODS:\n");
  1261.     for (i = 0; i < cEvents; i++) {
  1262.       LPFUNCDESC    pFD;
  1263.  
  1264.       /*
  1265.        * The only piece of information we want from for each
  1266.        * event is the function name using ITypeInfo::GetNames.
  1267.        */
  1268.  
  1269.       if (SUCCEEDED (pITypeInfo->GetFuncDesc (i, &pFD)))
  1270.       {
  1271.         UINT       cNames;
  1272.         BSTR       bstrName;       //Event name (function only)
  1273.  
  1274.         pITypeInfo->GetNames (pFD->memid, &bstrName, 1, &cNames);
  1275.         lstrcat (propString, OleStr(bstrName));
  1276.         wsprintf (temp, "\(0x%08lX\)", pFD->memid);
  1277.         lstrcat (propString, temp);
  1278.         lstrcat (propString, "\n");
  1279.         SysFreeString (bstrName);
  1280.         pITypeInfo->ReleaseFuncDesc (pFD);
  1281.       }
  1282.    }
  1283.  
  1284.    lstrcat (propString, _TEXT("\nPROPERTIES:\n"));
  1285.    for (i = 0; i < cVars; i++) {
  1286.      LPVARDESC    pVD;
  1287.      BSTR         bstrName;
  1288.  
  1289.      if (SUCCEEDED (pITypeInfo->GetVarDesc (i, &pVD)))
  1290.      {
  1291.        UINT      cNames;
  1292.  
  1293.        pITypeInfo->GetNames (pVD->memid, &bstrName, 1, &cNames);
  1294.        lstrcat (propString, OleStr(bstrName));
  1295.        wsprintf (temp, "\(0x%08lX\)", pVD->memid);
  1296.        lstrcat (propString, temp);
  1297.        lstrcat (propString, ": ");
  1298.        if (SUCCEEDED (OcDispGetPropString (pID, pVD->memid, temp, 255)))
  1299.          lstrcat (propString, temp);
  1300.  
  1301.        lstrcat (propString, "\n");
  1302.        SysFreeString (bstrName);
  1303.        pITypeInfo->ReleaseVarDesc (pVD);
  1304.      }
  1305.    }
  1306.  
  1307.    if (pITypeInfo)
  1308.      pITypeInfo->Release ();
  1309.  
  1310.    lstrcat (propString, "\nEVENTS:\n");
  1311.    pITypeInfo = pCtrl->GetEventTypeInfo ();
  1312.    if (pITypeInfo)  {
  1313.  
  1314.      if (SUCCEEDED (pITypeInfo->GetTypeAttr(&pTA))) {
  1315.  
  1316.        cEvents = pTA->cFuncs;
  1317.        pITypeInfo->ReleaseTypeAttr (pTA);
  1318.  
  1319.        for (i=0; i < cEvents; i++)
  1320.        {
  1321.          LPFUNCDESC     pFD;
  1322.  
  1323.          if (SUCCEEDED (pITypeInfo->GetFuncDesc(i, &pFD)))
  1324.          {
  1325.            UINT       cNames;
  1326.            BSTR       bstrName;       //Event name (function only)
  1327.  
  1328.            pITypeInfo->GetNames (pFD->memid, &bstrName, 1, &cNames);
  1329.            lstrcat (propString, OleStr (bstrName));
  1330.            wsprintf (temp, "\(0x%08lX\)", pFD->memid);
  1331.            lstrcat (propString, temp);
  1332.                  lstrcat (propString, "\n");
  1333.            SysFreeString (bstrName);
  1334.            pITypeInfo->ReleaseFuncDesc (pFD);
  1335.          }
  1336.        }
  1337.      }
  1338.    }
  1339.  
  1340.    MessageBox (propString, "OCX Properties", MB_APPLMODAL);
  1341.  
  1342. err:
  1343.    if (pITypeInfo)
  1344.      pITypeInfo->Release();
  1345. err2:
  1346.    if (pID)
  1347.      pID->Release ();
  1348. err2a:
  1349.   }
  1350. }
  1351.  
  1352.  
  1353. void
  1354. TDrawView::CmControlFont ()
  1355. {
  1356.   TOcPart* p = OcView->GetActivePart();
  1357.   if (p) {
  1358.     IDispatch *pID;
  1359.     IDispatch *pIF;
  1360.     VARIANTARG result;
  1361.     VARIANTARG result2;
  1362.  
  1363.     IBControl* pICtrl;
  1364.     if (FAILED(p->QueryInterface(IID_IBControl, &(LPVOID)pICtrl)))
  1365.       return;
  1366.     pICtrl->Release();
  1367.  
  1368.                 // get control's IDispatch
  1369.     if (FAILED(pICtrl->GetCtrlDispatch(&pID)))
  1370.       return;
  1371.  
  1372.                 // ask for control's font
  1373.     if (SUCCEEDED (OcDispGetProp (pID, DISPID_FONT, &result))) {
  1374.  
  1375.       pIF = result.pdispVal;
  1376.       if (SUCCEEDED (OcDispGetProp (pIF, DISPID_FONT_BOLD, &result2))) {
  1377.         VariantChangeType( &result2, &result2, 0, VT_BOOL);
  1378.         result2.boolVal = result2.boolVal ? false : true;
  1379.         OcDispSetProp (pIF, DISPID_FONT_BOLD, &result2);
  1380.       }
  1381.             if (SUCCEEDED (OcDispGetProp (pIF, DISPID_FONT_SIZE, &result2))) {
  1382.               VariantChangeType( &result2, &result2, 0, VT_CY);
  1383.         #ifdef WIN32
  1384.               result2.cyVal.s.Lo = result2.cyVal.s.Lo + 20000;
  1385.               if (result2.cyVal.s.Lo > 140000)
  1386.                 result2.cyVal.s.Lo = 60000;
  1387.         #else
  1388.               result2.cyVal.Lo = result2.cyVal.Lo + 20000;
  1389.         #endif
  1390.               OcDispSetProp (pIF, DISPID_FONT_SIZE, &result2);
  1391.             }
  1392.     }
  1393.  
  1394.     pID->Release();
  1395.   }
  1396. }
  1397.  
  1398.  
  1399. void
  1400. TDrawView::CmContainerMode ()
  1401. {
  1402.   designMode ^= TRUE;
  1403.   if (OcView) {
  1404.     ((TOcxView *) OcView)->SetUserMode (designMode == FALSE);
  1405.     ((TOcxView *) OcView)->SetDisplayAsDefault (designMode == FALSE);
  1406.     ((TOcxView *) OcView)->SetShowGrabHandles (designMode == TRUE);
  1407.     ((TOcxView *) OcView)->SetShowHatching (designMode == TRUE);
  1408.     ((TOcxView *) OcView)->SetUIDead (designMode == TRUE);
  1409.     TOleView::SetSelection(0);
  1410.   }
  1411. }
  1412.  
  1413.  
  1414. void
  1415. TDrawView::CmRegisterControl ()
  1416. {
  1417.   //
  1418.   // Create/Init TFileOpenDialog data structure
  1419.   //
  1420.   TOpenSaveDialog::TData *data;
  1421.   data = new TOpenSaveDialog::TData (OFN_FILEMUSTEXIST,
  1422.               "Ole Controls (*.ocx)\0*.ocx\0All Files (*.*)\0*.*\0",
  1423.               0, ".");
  1424.  
  1425.   //
  1426.   // Execute dialog and return status [copying new filename if necessary]
  1427.   //
  1428.   TFileOpenDialog fopenDlg(this, *data, 0, "Register Control");
  1429.   int ret = fopenDlg.Execute();
  1430.  
  1431.   if (ret == IDOK) {
  1432.     if (SUCCEEDED (OcRegisterControl (data->FileName)))
  1433.       MessageBox ("Control was successfully registered.", "OCX Registration", MB_APPLMODAL);
  1434.     else
  1435.       MessageBox ("Unable to register control.", "OCX Registration", MB_APPLMODAL);
  1436.   }
  1437.   delete data;
  1438. }
  1439.  
  1440.  
  1441. void
  1442. TDrawView::CmUnregisterControl ()
  1443. {
  1444.   TOcInitInfo initInfo (OcView);
  1445.   initInfo.Container = NULL; // use active document
  1446.   if (OcApp->BrowseControls (initInfo)) {
  1447.     if (SUCCEEDED (OcUnregisterControl (*(LPIID)initInfo.CId)))
  1448.       MessageBox ("Control was successfully unregistered.", "OCX Registration", MB_APPLMODAL);
  1449.     else
  1450.       MessageBox ("Unable to unregister control.", "OCX Registration", MB_APPLMODAL);
  1451.   }
  1452. }
  1453.  
  1454. void
  1455. TDrawView::CmControlCaption ()
  1456. {
  1457.   TOcPart* p = OcView->GetActivePart();
  1458.   if (p) {
  1459.     char       propString[256];
  1460.     IDispatch *pID;
  1461.     BSTR       bstrName;       //Event name (function only)
  1462.     VARIANTARG result;
  1463.     static int num = 0;
  1464.  
  1465.     IBControl* pIU;
  1466.     if (FAILED (p->QueryInterface(IID_IBControl, &(LPVOID)pIU)))
  1467.       return;
  1468.     pIU->Release ();
  1469.  
  1470.     if (FAILED (pIU->GetCtrlDispatch(&pID)))
  1471.       return;
  1472.  
  1473.     wsprintf (propString, "OCX #&%d", num++);
  1474.     bstrName = SysAllocString (propString);
  1475.     VariantInit (&result);
  1476.     result.vt = VT_BSTR;
  1477.     result.bstrVal = bstrName;
  1478.     OcDispSetProp (pID, DISPID_CAPTION, &result);
  1479.     SysFreeString (bstrName);
  1480.     pID->Release();
  1481.   }
  1482. }
  1483.  
  1484. void
  1485. TDrawView::CmNewControl()
  1486. {
  1487.   PRECONDITION(OcView);
  1488.   TOcInitInfo initInfo(OcView);
  1489.   static int count = 0;
  1490.  
  1491.   if (OcApp->BrowseControls(initInfo)) {
  1492.     TRect rect;
  1493.     GetInsertPosition(rect);
  1494.     rect.left += count * 40;
  1495.     rect.top  += count * 40;
  1496.     rect.right  = rect.left + 100;
  1497.     rect.bottom = rect.top + 100;
  1498.     TMyOcxEvent *pEv = new TMyOcxEvent ();
  1499.     TOcControl *ctrl = new TOcControl(*GetOcDoc(), 0, (TOcControlEvent *)pEv);
  1500.     ctrl->Init (&initInfo, rect);
  1501.     SetSelection (ctrl);
  1502.     CmControlCaption ();
  1503.     count++;
  1504.  
  1505.     OcView->Rename();
  1506.     InvalidatePart(invView);
  1507.   }
  1508. }
  1509.  
  1510. void
  1511. TDrawView::CmPen()
  1512. {
  1513.   Tool = DrawPen;
  1514. }
  1515.  
  1516. void
  1517. TDrawView::CmSelect()
  1518. {
  1519.   Tool = DrawSelect;
  1520. }
  1521.  
  1522. void
  1523. TDrawView::CmPenSize()
  1524. {
  1525.   if (Selected) {
  1526.     GetPenSize(this, *Selected);
  1527.     Selected->UpdateBound();
  1528.     DrawDoc->ModifyLine(*Selected, DrawDoc->GetLines()->Find(*Selected));
  1529.   }
  1530.   else
  1531.     GetPenSize(this, *Line);
  1532. }
  1533.  
  1534. void
  1535. TDrawView::CmPenColor()
  1536. {
  1537.   if (Selected) {
  1538.     GetPenColor(this, *Selected);
  1539.     DrawDoc->ModifyLine(*Selected, DrawDoc->GetLines()->Find(*Selected));
  1540.   }
  1541.   else
  1542.     GetPenColor(this, *Line);
  1543. }
  1544.  
  1545. void
  1546. TDrawView::CmOrgSize()
  1547. {
  1548.   SetScale(100);
  1549. }
  1550.  
  1551. void
  1552. TDrawView::CmDoubleSize()
  1553. {
  1554.   SetScale(200);
  1555. }
  1556.  
  1557. void
  1558. TDrawView::CmHalfSize()
  1559. {
  1560.   SetScale(50);
  1561. }
  1562.  
  1563. void
  1564. TDrawView::CeOrgSize(TCommandEnabler& ce)
  1565. {
  1566.   ce.SetCheck(!Scale.IsZoomed());
  1567. }
  1568.  
  1569. void
  1570. TDrawView::CeDoubleSize(TCommandEnabler& ce)
  1571. {
  1572.   ce.SetCheck(Scale.GetScale() == 200);
  1573. }
  1574.  
  1575. void
  1576. TDrawView::CeHalfSize(TCommandEnabler& ce)
  1577. {
  1578.   ce.SetCheck(Scale.GetScale() == 50);
  1579. }
  1580.  
  1581. void
  1582. TDrawView::CmClear()
  1583. {
  1584.   DrawDoc->Clear();
  1585. }
  1586.  
  1587. void
  1588. TDrawView::CmUndo()
  1589. {
  1590.   DrawDoc->Undo();
  1591. }
  1592.  
  1593. void
  1594. TDrawView::CeEditCut(TCommandEnabler& ce)
  1595. {
  1596.   ce.Enable(Selected != 0 || SelectEmbedded());
  1597. }
  1598.  
  1599. void
  1600. TDrawView::CeEditCopy(TCommandEnabler& ce)
  1601. {
  1602.   ce.Enable(Selected != 0 || SelectEmbedded());
  1603. }
  1604.  
  1605. //
  1606. // method to clean up the userdata passed to TOcDataProvider
  1607. //
  1608. void
  1609. TDrawView::CleanUp(void* /*userData*/)
  1610. {
  1611.   // No data clean up to do here
  1612. }
  1613.  
  1614. void
  1615. TDrawView::CmEditCut()
  1616. {
  1617.   if (Selected) {
  1618.     // Create a TOcDataProvider with current selection
  1619.     //
  1620.     TOcDataProvider* ocData = new TOcDataProvider(*OcView, &DocReg, 0,
  1621.                                                   (void*)Selected, CleanUp);
  1622.     OcApp->Copy(ocData);
  1623.  
  1624.     // Ask server to render its data before it's deleted
  1625.     //
  1626.     ocData->Disconnect();
  1627.     ocData->Release();
  1628.  
  1629.     // Delete the line
  1630.     //
  1631.     DrawDoc->DeleteLine(DrawDoc->GetLines()->Find(*Selected));
  1632.     SetLineSelection(0);
  1633.   }
  1634.   else
  1635.     TOleView::CmEditCut();
  1636. }
  1637.  
  1638. void
  1639. TDrawView::CmEditCopy()
  1640. {
  1641.   if (Selected) {
  1642.     // Create a TOcDataProvider with current selection
  1643.     //
  1644.     TOcDataProvider* ocData = new TOcDataProvider(*OcView, &DocReg, 0,
  1645.                                                   (void*)Selected, CleanUp);
  1646.     OcApp->Copy(ocData);
  1647.     ocData->Release();
  1648.   }
  1649.   else
  1650.     TOleView::CmEditCopy();
  1651. }
  1652.  
  1653. void
  1654. TDrawView::Paint(TDC& dc, bool /*erase*/, TRect& /*rect*/)
  1655. {
  1656.   bool metafile = (dc.GetDeviceCaps(TECHNOLOGY) == DT_METAFILE);
  1657.  
  1658.   // Iterates through the array of line objects.
  1659.   int j = 0;
  1660.   TLine* line;
  1661.   while ((line = const_cast<TLine *>(DrawDoc->GetLine(j++))) != 0) {
  1662.     line->Draw(dc);
  1663.     if (line->IsSelected() && !metafile)
  1664.       line->DrawSelection(dc);
  1665.   }
  1666. }
  1667.  
  1668. bool
  1669. TDrawView::PaintSelection(TDC& dc, bool /*erase*/, TRect& /*rect*/, void* userData)
  1670. {
  1671.   TLine* line = (TLine*) userData;
  1672.   if (!line)
  1673.     return false;
  1674.  
  1675.   TPoint newPos(Margin, Margin);
  1676.   newPos -= line->GetBound().TopLeft();
  1677.   line->UpdatePosition(newPos);
  1678.   line->Draw(dc);
  1679.   line->UpdatePosition(-newPos);
  1680.  
  1681.   return true;
  1682. }
  1683.  
  1684. // Establish link with whole doc or selection
  1685. //
  1686. bool
  1687. TDrawView::EvOcViewSetLink(TOcLinkView& view)
  1688. {
  1689.   // Attach a linked view to this document
  1690.   //
  1691.   new TDrawLinkView(GetDocument(), view);
  1692.   return true;
  1693. }
  1694.  
  1695. bool
  1696. TDrawView::PaintLink(TDC& dc, bool erase, TRect& rect, TString& moniker)
  1697. {
  1698.   //Draw the whole document if linking to the whole doc
  1699.   //
  1700.   if (strcmp(moniker, OleStr(DocContent)) == 0) {
  1701.     Paint(dc, erase, rect);
  1702.     return true;
  1703.   }
  1704.  
  1705.   // Find the selection with the corresponding moniker
  1706.   //
  1707.   TLine* line = DrawDoc->GetLine(moniker);
  1708.  
  1709.   if (!line)
  1710.     return false;
  1711.  
  1712.   TPoint newPos(Margin, Margin);
  1713.   newPos -= rect.TopLeft();
  1714.   line->UpdatePosition(newPos);
  1715.   line->Draw(dc);
  1716.   line->UpdatePosition(-newPos);
  1717.   return true;
  1718. }
  1719.  
  1720. bool
  1721. TDrawView::VnCommit(bool /*force*/)
  1722. {
  1723.   // nothing to do here, no data held in view
  1724.   return true;
  1725. }
  1726.  
  1727. bool
  1728. TDrawView::VnRevert(bool /*clear*/)
  1729. {
  1730.   Invalidate();  // force full repaint
  1731.   InvalidatePart(invView);
  1732.   return true;
  1733. }
  1734.  
  1735. bool
  1736. TDrawView::VnAppend(uint index)
  1737. {
  1738.   TLine* line = DrawDoc->GetLine(index);
  1739.   line->UpdateBound();
  1740.   line->Invalidate(*this);
  1741.   InvalidatePart(invView);
  1742.   return true;
  1743. }
  1744.  
  1745. bool
  1746. TDrawView::VnModify(uint /*index*/)
  1747. {
  1748.   Invalidate();  // force full repaint
  1749.   InvalidatePart(invView);
  1750.   return true;
  1751. }
  1752.  
  1753. bool
  1754. TDrawView::VnDelete(uint /*index*/)
  1755. {
  1756.   Invalidate();  // force full repaint
  1757.   InvalidatePart(invView);
  1758.   return true;
  1759. }
  1760.  
  1761. DEFINE_RESPONSE_TABLE1(TDrawListView, TListBox)
  1762.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  1763.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  1764.   EV_COMMAND(CM_EDITCLEAR, CmClear),
  1765.   EV_COMMAND(CM_EDITUNDO, CmUndo),
  1766.   EV_COMMAND(CM_EDITDELETE, CmDelete),
  1767.   EV_VN_ISWINDOW,
  1768.   EV_VN_COMMIT,
  1769.   EV_VN_REVERT,
  1770.   EV_VN_DRAWAPPEND,
  1771.   EV_VN_DRAWDELETE,
  1772.   EV_VN_DRAWMODIFY,
  1773. END_RESPONSE_TABLE;
  1774.  
  1775. TDrawListView::TDrawListView(TDrawDocument& doc,TWindow *parent)
  1776.        : TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0), DrawDoc(&doc)
  1777. {
  1778.   Attr.Style &= ~(WS_BORDER | LBS_SORT);
  1779.   Attr.Style |= LBS_NOINTEGRALHEIGHT;
  1780.   Attr.AccelTable = IDA_DRAWLISTVIEW;
  1781.   SetViewMenu(new TMenuDescr(IDM_DRAWLISTVIEW));
  1782. }
  1783.  
  1784. bool
  1785. TDrawListView::Create()
  1786. {
  1787.   TListBox::Create();
  1788.   LoadData();
  1789.   return true;
  1790. }
  1791.  
  1792. void
  1793. TDrawListView::LoadData()
  1794. {
  1795.   ClearList();
  1796.   int i = 0;
  1797.   const TLine* line;
  1798.   while ((line = DrawDoc->GetLine(i)) != 0)
  1799.     FormatData(line, i++);
  1800.  
  1801.   SetSelIndex(0);
  1802. }
  1803.  
  1804. void
  1805. TDrawListView::FormatData(const TLine* line, int unsigned index)
  1806. {
  1807.   char buf[80];
  1808.   TColor color(line->QueryColor());
  1809.   wsprintf(buf, "Color = R%d G%d B%d, Size = %d, Points = %d",
  1810.            color.Red(), color.Green(), color.Blue(),
  1811.            line->QueryPenSize(), line->GetItemsInContainer());
  1812.   DeleteString(index);
  1813.   InsertString(buf, index);
  1814.   SetSelIndex(index);
  1815. }
  1816.  
  1817. void
  1818. TDrawListView::CmPenSize()
  1819. {
  1820.   int index = GetSelIndex();
  1821.   const TLine* line = DrawDoc->GetLine(index);
  1822.   if (line) {
  1823.     TLine* newline = new TLine(*line);
  1824.     if (GetPenSize(this, *newline))
  1825.       DrawDoc->ModifyLine(*newline, index);
  1826.     delete newline;
  1827.   }
  1828. }
  1829.  
  1830. void
  1831. TDrawListView::CmPenColor()
  1832. {
  1833.   int index = GetSelIndex();
  1834.   const TLine* line = DrawDoc->GetLine(index);
  1835.   if (line) {
  1836.     TLine* newline = new TLine(*line);
  1837.     if (GetPenColor(this, *newline))
  1838.       DrawDoc->ModifyLine(*newline, index);
  1839.     delete newline;
  1840.   }
  1841. }
  1842.  
  1843. void
  1844. TDrawListView::CmClear()
  1845. {
  1846.   DrawDoc->Clear();
  1847. }
  1848.  
  1849. void
  1850. TDrawListView::CmUndo()
  1851. {
  1852.   DrawDoc->Undo();
  1853. }
  1854.  
  1855. void
  1856. TDrawListView::CmDelete()
  1857. {
  1858.   DrawDoc->DeleteLine(GetSelIndex());
  1859. }
  1860.  
  1861. bool
  1862. TDrawListView::VnCommit(bool /*force*/)
  1863. {
  1864.   return true;
  1865. }
  1866.  
  1867. bool
  1868. TDrawListView::VnRevert(bool /*clear*/)
  1869. {
  1870.   LoadData();
  1871.   return true;
  1872. }
  1873.  
  1874. bool
  1875. TDrawListView::VnAppend(uint index)
  1876. {
  1877.   const TLine* line = DrawDoc->GetLine(index);
  1878.   FormatData(line, index);
  1879.   SetSelIndex(index);
  1880.   return true;
  1881. }
  1882.  
  1883. bool
  1884. TDrawListView::VnDelete(uint index)
  1885. {
  1886.   DeleteString(index);
  1887.   HandleMessage(WM_KEYDOWN,VK_DOWN); // force selection
  1888.   return true;
  1889. }
  1890.  
  1891. bool
  1892. TDrawListView::VnModify(uint index)
  1893. {
  1894.   const TLine* line = DrawDoc->GetLine(index);
  1895.   FormatData(line, index);
  1896.   return true;
  1897. }
  1898.  
  1899. static char* PropNames[] = {
  1900.   "Line Count",      // LineCount
  1901.   "Description",       // Description
  1902. };
  1903.  
  1904. static int PropFlags[] = {
  1905.   pfGetBinary|pfGetText, // LineCount
  1906.   pfGetText,             // Description
  1907. };
  1908.  
  1909. const char*
  1910. TDrawDocument::PropertyName(int index)
  1911. {
  1912.   if (index <= PrevProperty)
  1913.     return TStorageDocument::PropertyName(index);  // OC server change
  1914.   else if (index < NextProperty)
  1915.     return PropNames[index-PrevProperty-1];
  1916.   else
  1917.     return 0;
  1918. }
  1919.  
  1920. int
  1921. TDrawDocument::PropertyFlags(int index)
  1922. {
  1923.   if (index <= PrevProperty)
  1924.     return TStorageDocument::PropertyFlags(index); // OC server change
  1925.   else if (index < NextProperty)
  1926.     return PropFlags[index-PrevProperty-1];
  1927.   else
  1928.     return 0;
  1929. }
  1930.  
  1931. int
  1932. TDrawDocument::FindProperty(const char far* name)
  1933. {
  1934.   for (int i=0; i < NextProperty-PrevProperty-1; i++)
  1935.     if (strcmp(PropNames[i], name) == 0)
  1936.       return i+PrevProperty+1;
  1937.   return 0;
  1938. }
  1939.  
  1940. int
  1941. TDrawDocument::GetProperty(int prop, void far* dest, int textlen)
  1942. {
  1943.   switch(prop) {
  1944.     case LineCount: {
  1945.       int count = Lines->GetItemsInContainer();
  1946.       if (!textlen) {
  1947.         *(int far*)dest = count;
  1948.         return sizeof(int);
  1949.       }
  1950.       return wsprintf((char far*)dest, "%d", count);
  1951.     }
  1952.     case Description:
  1953.       char* temp = new char[textlen]; // need local copy for medium model
  1954.       int len = FileInfo.copy(temp, textlen);
  1955.       strcpy((char far*)dest, temp);
  1956.       return len;
  1957.   }
  1958.   return TStorageDocument::GetProperty(prop, dest, textlen); // OC server change
  1959. }
  1960.  
  1961.  
  1962. ObjectPtr GetMyControl(ObjectPtr ctl);
  1963.  
  1964. DEFINE_AUTOCLASS (TMyOcxEvent)
  1965.   EXPOSE_METHOD (SpinPositive,  TAutoLong,  "SpinPositive",   "SpinPositive",     0)
  1966.   EXPOSE_INHERIT (TOcControlEvent, "TOcControlEvent")
  1967. END_AUTOCLASS (TMyOcxEvent, tfNormal, "TMyOcx",   "TMyOcx class", 0)
  1968.  
  1969. ObjectPtr GetMyControl(ObjectPtr ctl)
  1970. {
  1971.   return (ObjectPtr) ((TOcControlEvent *)ctl)->GetControl();
  1972. }
  1973.  
  1974. void
  1975. TMyOcxEvent::InitEventDispatch()
  1976. {
  1977.   if (!pIEvents)
  1978.     (TUnknown *)pIEvents = CreateAutoObject(this, ClassInfo);
  1979. }
  1980.  
  1981. long
  1982. TMyOcxEvent::SpinPositive ()
  1983. {
  1984.   // this event is only applicable for spindial from the MS CDK
  1985.   MessageBox (0, "My Spin Positive Special Event", "Special Event Handler", MB_APPLMODAL);
  1986.   return 0;
  1987. }
  1988.  
  1989.  
  1990. HRESULT OcDispGetPropString (IDispatch *pID, DISPID id,
  1991.   char *propVal, int /*bufSize*/)
  1992. {
  1993.   VARIANTARG result;
  1994.   HRESULT    hr;
  1995.   if (SUCCEEDED (hr = OcDispGetProp (pID, id, &result))) {
  1996.     // Coerce to a string
  1997.     if (SUCCEEDED (VariantChangeType (&result, &result, 0,
  1998.         VT_BSTR )))  {
  1999.                         if (*(result.bstrVal))
  2000.         lstrcpy (propVal, OleStr(result.bstrVal));
  2001.       else
  2002.         *propVal = '\0';
  2003.     }
  2004.   }
  2005.   VariantClear (&result);
  2006.   return hr;
  2007. }
  2008.  
  2009.  
  2010. HRESULT OcDispGetProp (IDispatch *pID, DISPID id, VARIANTARG *propVal)
  2011. {
  2012.   DISPPARAMS args;
  2013.  
  2014.   VariantInit (propVal);
  2015.   args.rgvarg = NULL;
  2016.   args.cArgs = 0;
  2017.   args.cNamedArgs = 0;
  2018.   args.rgdispidNamedArgs = NULL;
  2019.  
  2020.   return pID->Invoke (id, IID_NULL,
  2021.       LOCALE_SYSTEM_DEFAULT,
  2022.       DISPATCH_PROPERTYGET, &args, propVal, NULL, NULL);
  2023. }
  2024.  
  2025.  
  2026. HRESULT OcDispSetProp (IDispatch *pID, DISPID id, VARIANTARG *propVal)
  2027. {
  2028.   HRESULT    hr;
  2029.   DISPPARAMS args;
  2030.   VARIANTARG name[1];
  2031.   DISPID     namedArgs[1];
  2032.  
  2033.   VariantInit (&name[0]);
  2034.   VariantCopy (&name[0], propVal);
  2035.   namedArgs[0] = DISPID_PROPERTYPUT;
  2036.   args.rgvarg = NULL;
  2037.   args.cArgs = 1;
  2038.   args.cNamedArgs = 1;
  2039.   args.rgvarg = name;
  2040.   args.rgdispidNamedArgs = namedArgs;
  2041.   hr = pID->Invoke (id, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  2042.       DISPATCH_PROPERTYPUT, &args, NULL, NULL, NULL);
  2043.   VariantClear (&name[0]);
  2044.   return hr;
  2045. }
  2046.