home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Sample Controls / Events / CEventClient.cpp next >
Encoding:
Text File  |  1996-12-16  |  9.5 KB  |  463 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //
  3. //    CEventSend.cpp                ©1996 Microsoft Corporation All rights reserved.
  4. //
  5. // =================================================================================
  6.  
  7. #include "ocheaders.h"
  8. #include "CEventClient.h"
  9.  
  10.  
  11. const Uint32    DefaultIdleRefCon    = 1;
  12. const Int32        DefaultIdleTime        = 60;
  13.  
  14. //=====================================================================
  15. //
  16. //    Static functions
  17.  
  18. static void GetObjectPName (IUnknown* inSource, Str255 outName);
  19.  
  20. //
  21. //    GetObjectPName
  22. //
  23. //    Retrieve the control's name and copy it into a pascal string
  24. //
  25.  
  26. static void GetObjectPName (IUnknown* inSource, Str255 outName)
  27. {
  28.     IControl*        sourceObject = nil;
  29.  
  30.     // Snag the IControl interface
  31.     if (inSource)
  32.         inSource->QueryInterface(IID_IControl, &sourceObject);
  33.  
  34.     // Copy the name and convert it to a pascal string
  35.     if (sourceObject) {
  36.         sourceObject->GetID(255, (char *)outName);
  37.         c2pstr((char *) outName);
  38.         PLstrcat(outName, "\p:");
  39.         sourceObject->Release();
  40.     }
  41.     else{
  42.         PLstrcpy(outName, "\p");
  43.     }
  44. }
  45.  
  46.  
  47. //
  48. //  CEventClient::CEventClient
  49. //
  50.  
  51. CEventClient::CEventClient(void) : CBaseControl()
  52. {
  53.     mCookie = 0;
  54.     mMessage = NULL;
  55.     mNumMsgs = 0;
  56.     mCurrentMsg = 0;
  57. }
  58.  
  59.  
  60. //
  61. //  CEventClient::~CEventClient
  62. //
  63.  
  64. CEventClient::~CEventClient()
  65. {
  66.     if (mMessage)
  67.     {
  68.         DisposeHandle((Handle) mMessage);
  69.         mMessage = NULL;
  70.     }
  71. }
  72.  
  73.  
  74. //
  75. //  CEventClient::IUnknown::QueryInterface
  76. //
  77. //  Returns a pointer to the specified interface on a component to which a
  78. //  client currently holds an interface pointer.
  79. //
  80.  
  81. STDMETHODIMP
  82. CEventClient::QueryInterface(REFIID inRefID, void** outObj)
  83. {
  84.     if ( inRefID == IID_IStandardEvents )
  85.     {
  86.         *outObj = (void*) (IStandardEvents*) this;
  87.         AddRef();
  88.         
  89.         return S_OK;
  90.     }
  91.     else
  92.         return CBaseControl::QueryInterface(inRefID, outObj);
  93. }
  94.  
  95.  
  96. //
  97. //  CEventClient::IObjectWithSite::SetSite
  98. //
  99. STDMETHODIMP
  100. CEventClient::SetSite(IUnknown* inUnkSite)
  101. {
  102.     ErrorCode    Result = CBaseControl::SetSite(inUnkSite);
  103.  
  104.     if (mContainerSiteP)
  105.         mContainerSiteP->SetIdleTime(DefaultIdleTime, DefaultIdleRefCon);
  106.  
  107.     return Result;
  108. }
  109.  
  110.  
  111. //
  112. //  CEventClient::IControl::Draw
  113. //
  114.  
  115. STDMETHODIMP
  116. CEventClient::Draw(DrawContext* inContext)
  117. {
  118.     FontInfo    fInfo;
  119.     Int16        curX;
  120.     Int16        curY;
  121.     Int16        i;
  122.     Int16        msgIndex;
  123.     Char8        theState;
  124.     RgnHandle    saveClipRgn;
  125.     Rect        controlRect, newClipRect;
  126.     Boolean8    overlap = false;
  127.     
  128.     if (inContext->DrawAspect != DVASPECT_CONTENT)
  129.         return DV_E_DVASPECT;
  130.  
  131.     // Set the font and size    
  132.     ::TextFont(applFont);
  133.     ::TextFace(0);
  134.     ::TextMode(srcCopy);
  135.     ::TextSize(9);
  136.     ::GetFontInfo(&fInfo);
  137.  
  138.     // Erase the area and outline the frame
  139.     ::EraseRect(&inContext->Location);
  140.     ::PenSize(1, 1);
  141.     ::FrameRect(&inContext->Location);
  142.  
  143.     // Save the current clip
  144.     saveClipRgn = ::NewRgn();
  145.     ::GetClip(saveClipRgn);
  146.  
  147.     controlRect = inContext->Location;
  148.     ::InsetRect(&controlRect, 3, 3);
  149.     overlap = SectRect(&controlRect, &((*saveClipRgn)->rgnBBox), &newClipRect);
  150.  
  151.     if (overlap)
  152.     {
  153.         // Reset the clip
  154.         ::ClipRect(&newClipRect);
  155.     }
  156.  
  157.     // Initialize the message storage, if not already done
  158.     if (!mMessage) {
  159.         InitMessages();
  160.     }
  161.     
  162.     curX = inContext->Location.left+3;
  163.     curY = inContext->Location.top+3;
  164.  
  165.     // Draw the messages, one on each line    
  166.     curY += fInfo.ascent;
  167.     
  168.     msgIndex = (mCurrentMsg + 1) % mNumMsgs;
  169.     theState = ::HGetState((Handle) mMessage);
  170.     ::HLock((Handle) mMessage);
  171.  
  172.     for (i = 1; i <= mNumMsgs; i++)
  173.     {
  174.         ::MoveTo(curX, curY);
  175.         ::DrawString(*(*mMessage + msgIndex));
  176.         curY += fInfo.ascent + fInfo.descent + fInfo.leading;
  177.         msgIndex = (msgIndex + 1) % mNumMsgs;
  178.     }
  179.  
  180.     ::HSetState((Handle) mMessage, theState);
  181.  
  182.     if (overlap)
  183.     {
  184.         // Restore the clip
  185.         ::SetClip(saveClipRgn);
  186.     }
  187.     ::DisposeRgn(saveClipRgn);
  188.  
  189.     return S_OK;
  190. }
  191.  
  192.  
  193. //
  194. //  CEventClient::IControl::DoIdle
  195. //
  196. STDMETHODIMP
  197. CEventClient::DoIdle(Uint32 inIdleRefCon)
  198. {
  199. #pragma unused (inIdleRefCon)
  200.     // if the client site has been set and the advisory cookie has not,
  201.     // enumerate the other controls in this container to find the one we want
  202.     // to connect to
  203.     if (mContainerSiteP  && mCookie == 0)
  204.     {
  205.         IUnknown*         testControl;
  206.         IEnumUnknown*    enumU;
  207.     
  208.         // if we don't have a container yet
  209.         // Get it now
  210.         if ( !mContainerP )
  211.         {
  212.             mContainerSiteP->GetContainer(&mContainerP);
  213.             mContainerP->AddRef();
  214.         }
  215.         
  216.         if ( mContainerP )
  217.         {
  218.             // Enumerate the objects
  219.             if ( SUCCEEDED(mContainerP->EnumControls(nil, OLECONTF_EMBEDDINGS, &enumU)) )
  220.             {
  221.                 IConnectionPointContainer* cpContainer = nil;
  222.                 
  223.                 while ( enumU->Next(1, &testControl, nil) == NOERROR )
  224.                 {
  225.                     // Try to get a connection point container from the control
  226.                     testControl->QueryInterface(IID_IConnectionPointContainer,  (void**) &cpContainer);
  227.                     
  228.                     // if it has one, this may be it
  229.                     if ( cpContainer )
  230.                     {
  231.                         IConnectionPoint* cp = nil;
  232.                         
  233.                         // See if this connection point container 
  234.                         // has a connection point with the outgoing interface we want
  235.                         cpContainer->FindConnectionPoint(IID_IStandardEvents, &cp);
  236.                     
  237.                         // if we got it, set an advise connection on the outgoing interface
  238.                         if ( cp )
  239.                         {
  240.                             cp->Advise((IControl*) this, &mCookie);
  241.                             mContainerSiteP->SetIdleTime(RemoveIdler, DefaultIdleRefCon);
  242.                             cp->Release();
  243.                         }
  244.  
  245.                         cpContainer->Release();
  246.                     }
  247.  
  248.                     testControl->Release();
  249.                 }
  250.                 
  251.                 // Don't forget to release
  252.                 enumU->Release();
  253.              }
  254.              else
  255.              {
  256.                  mCookie = -1;
  257.                 mContainerSiteP->SetIdleTime(RemoveIdler, DefaultIdleRefCon);
  258.              }
  259.         }
  260.     }
  261.  
  262.     return S_OK;
  263. }
  264.  
  265.  
  266. //
  267. //  CEventClient::IStandardEvents::OnDoubleClick
  268. //
  269. STDMETHODIMP
  270. CEventClient::OnDoubleClick(IUnknown* inSource, PlatformEvent* inEvent)
  271. {
  272. #pragma unused (inEvent)
  273.     Str255            theMessage;
  274.  
  275.     // Add <control_name>:OnDoubleClick message    
  276.     GetObjectPName(inSource, theMessage);
  277.     PLstrcat(theMessage, "\pOnDoubleClick");
  278.     AddMessage(theMessage);
  279.      FinishEvent();
  280.      return S_OK;
  281. }
  282.  
  283. //
  284. //  CEventClient::IStandardEvents::OnKeyDown
  285. //
  286. STDMETHODIMP
  287. CEventClient::OnKeyDown(IUnknown* inSource, PlatformEvent* inEvent)
  288. {
  289.     Str255    theMessage;
  290.     Char8    theKey;
  291.  
  292.     // Add <control_name>:OnKeyDown:<key> message    
  293.     theKey = inEvent->message & charCodeMask;
  294.     GetObjectPName(inSource, theMessage);
  295.     PLstrcat(theMessage, "\pOnKeyDown: ");
  296.     theMessage[0]++;
  297.     theMessage[theMessage[0]] = theKey;
  298.     AddMessage(theMessage);
  299.     FinishEvent();
  300.     return S_OK;
  301. }
  302.  
  303.  
  304. //
  305. //  CEventClient::IStandardEvents::OnAutoKey
  306. //
  307. STDMETHODIMP
  308. CEventClient::OnAutoKey(IUnknown* inSource, PlatformEvent* inEvent)
  309. {
  310.     Str255    theMessage;
  311.     Char8    theKey;
  312.  
  313.     // Add <control_name>:OnAutoKey:<key> message    
  314.     theKey = inEvent->message & charCodeMask;
  315.     GetObjectPName(inSource, theMessage);
  316.     PLstrcat(theMessage, "\pOnAutoKey: ");
  317.     theMessage[0]++;
  318.     theMessage[theMessage[0]] = theKey;
  319.     AddMessage(theMessage);
  320.     FinishEvent();
  321.     return S_OK;
  322. }
  323.  
  324.  
  325. //
  326. //  CEventClient::IStandardEvents::OnKeyUp
  327. //
  328. STDMETHODIMP
  329. CEventClient::OnKeyUp(IUnknown* inSource, PlatformEvent* inEvent)
  330. {
  331.     Str255    theMessage;
  332.     Char8    theKey;
  333.  
  334.     // Add <control_name>:OnKeyUp:<key> message    
  335.     theKey = inEvent->message & charCodeMask;
  336.     GetObjectPName(inSource, theMessage);
  337.     PLstrcat(theMessage, "\pOnKeyUp: ");
  338.     theMessage[0]++;
  339.     theMessage[theMessage[0]] = theKey;
  340.     AddMessage(theMessage);
  341.     FinishEvent();
  342.     return S_OK;
  343. }
  344.  
  345.  
  346.  
  347. //
  348. //  CEventClient::IStandardEvents::OnMouseDown
  349. //
  350. STDMETHODIMP
  351. CEventClient::OnMouseDown(IUnknown* inSource, PlatformEvent* inEvent)
  352. {
  353. #pragma unused (inEvent)
  354.     Str255            theMessage;
  355.     
  356.     // Add <control_name>:OnMouseDown message    
  357.     GetObjectPName(inSource, theMessage);
  358.     PLstrcat(theMessage, "\pOnMouseDown");
  359.     AddMessage(theMessage);
  360.     FinishEvent();
  361.     return S_OK;
  362. }
  363.  
  364.  
  365.  
  366. //
  367. //  CEventClient::IStandardEvents::OnMouseUp
  368. //
  369. STDMETHODIMP
  370. CEventClient::OnMouseUp(IUnknown* inSource, PlatformEvent* inEvent)
  371. {
  372. #pragma unused (inEvent)
  373.     Str255            theMessage;
  374.     
  375.     // Add <control_name>:OnMouseUp message    
  376.     GetObjectPName(inSource, theMessage);
  377.     PLstrcat(theMessage, "\pOnMouseUp");
  378.     AddMessage(theMessage);
  379.     FinishEvent();
  380.     return S_OK;
  381. }
  382.  
  383.  
  384.  
  385. //
  386. //  CEventClient::FinishEvent
  387. //
  388. void CEventClient::FinishEvent(void)
  389. {
  390.     InvalAllContexts();
  391. }
  392.  
  393. //
  394. //  CEventClient::AddMessage
  395. //
  396. void CEventClient::AddMessage(Str255 inMessage)
  397. {
  398.     char    theState;
  399.  
  400.     if (!mMessage)
  401.         InitMessages();
  402.  
  403.     // Lock the message storage    
  404.     theState = ::HGetState((Handle) mMessage);
  405.     ::HLock((Handle) mMessage);
  406.  
  407.     // Advance the message pointer    
  408.     mCurrentMsg++;
  409.     if (mCurrentMsg >= mNumMsgs)
  410.         mCurrentMsg = 0;
  411.  
  412.     // Copy the message into the message storage
  413.     ::PLstrcpy(*(*mMessage + mCurrentMsg), inMessage);
  414.     
  415.     // Unlock the message storage
  416.     ::HSetState((Handle) mMessage, theState);
  417. }
  418.  
  419. //
  420. //  CEventClient::InitMessages
  421. //
  422. void CEventClient::InitMessages(void)
  423. {
  424.     // Initialize the message storage, if not already done
  425.     if (!mMessage) 
  426.     {
  427.         DrawContext    Context = {BeginPortType};
  428.         Int16        height = 0;
  429.         FontInfo    fInfo;
  430.         Int32        index = 1;
  431.  
  432.         if (mContainerSiteP->AcquireContext(mActiveContext->GetContextID(), &Context) == S_OK)
  433.         {
  434.             // Set the font and size    
  435.             ::TextFont(applFont);
  436.             ::TextFace(0);
  437.             ::TextSize(9);
  438.             ::GetFontInfo(&fInfo);
  439.  
  440.             // Figure the number of lines that can be displayed in the control        
  441.             height = Context.Location.bottom - Context.Location.top - 6;
  442.             mNumMsgs = height/(fInfo.ascent + fInfo.descent + fInfo.leading);
  443.  
  444.             // Add one more line if the leading is the only part that won't fit
  445.             if (height - mNumMsgs * (fInfo.ascent + fInfo.descent + fInfo.leading) >= 
  446.                 (fInfo.ascent + fInfo.descent)) {
  447.                 mNumMsgs++;
  448.             }
  449.             
  450.             // Allocate the memory
  451.             if (mNumMsgs > 0)
  452.             {
  453.                 mMessage = (Str255**) ::NewHandleClear(sizeof(Str255) * mNumMsgs);
  454.                 mCurrentMsg = mNumMsgs ? mNumMsgs - 1: 0;
  455.             }
  456.             else
  457.                 mNumMsgs = 0;
  458.  
  459.             mContainerSiteP->ReleaseContext(&Context);
  460.         }
  461.     }
  462. }
  463.