home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / tstcon / tcitem.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  88.2 KB  |  3,702 lines

  1. // CTestContainer98Item.cpp : implementation of the CTestContainer98Item class
  2. //
  3.  
  4. #include "StdAfx.H"
  5. #include "TestCon.H"
  6.  
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12.  
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CTestContainer98Item implementation
  15.  
  16. IMPLEMENT_SERIAL( CTestContainer98Item, COleClientItem, 0 )
  17.  
  18. CTestContainer98Item::CTestContainer98Item( CTestContainer98Doc* pContainer ) :
  19.    COleClientItem( pContainer ),
  20.    m_rect( 10, 10, 210, 210 ),
  21.    m_dwEventCookie( 0 ),
  22.    m_dwPropertyCookie( 0 ),
  23.    m_tInsideOut( FALSE ),
  24.    m_pDC( NULL ),
  25.    m_tWindowless( FALSE ),
  26.    m_tExtendedControl( FALSE ),
  27.    m_tDisplayAsDefault( FALSE ),
  28.    m_dwAspectPass2( DVASPECT_CONTENT )
  29. {
  30.    m_dpLastParams.cArgs = 0;
  31.    m_dpLastParams.cNamedArgs = 0;
  32.    m_dpLastParams.rgvarg = NULL;
  33.    m_dpLastParams.rgdispidNamedArgs = NULL;
  34.  
  35.    m_tracker.m_nHandleSize = MARGIN_PIXELS+1;
  36.    m_tracker.m_sizeMin.cx = 8;  // +MARGIN_PIXELS
  37.    m_tracker.m_sizeMin.cy = 8;  // +MARGIN_PIXELS
  38.    m_tracker.m_nStyle = CRectTracker::solidLine;
  39. }
  40.  
  41. CTestContainer98Item::~CTestContainer98Item()
  42. {
  43.    ASSERT( m_pDC == NULL );
  44.  
  45.    CleanupParams();
  46. }
  47.  
  48. IUnknown* CTestContainer98Item::GetInterfaceHook( const void* pv )
  49. {
  50.    const IID* piid;
  51.  
  52. #ifdef _DEBUG
  53.    // The standard MFC implementation of QueryInterface doesn't switch module
  54.    // states, since most objects just use static data to implement QI.  Since
  55.    // we're calling GetDocument(), though, we wind up calling ASSERT_VALID on
  56.    // a bunch of MFC objects, and that requires the correct module state.
  57.    // Because ASSERT_VALID doesn't do anything in release builds, we only need
  58.    // to switch module states in debug builds.
  59.    AFX_MANAGE_STATE( m_pModuleState );
  60. #endif  // _DEBUG
  61.  
  62.    piid = (const IID*)pv;
  63.  
  64.    if( *piid == m_infoEvents.GetIID() )
  65.    {
  66.       TCControlTrace( TRACELEVEL_NORMAL, this, "QI for event handler.\n" );
  67.       return( &m_xEventHandler );
  68.    }
  69.    else if( *piid == IID_IOleInPlaceSiteEx )
  70.    {
  71.       if( GetDocument()->SupportsInterface( IID_IOleInPlaceSiteEx ) )
  72.       {
  73.          TCControlTrace( TRACELEVEL_NORMAL, this,
  74.             "QI for IOleInPlaceSiteEx.\n" );
  75.          return( &m_xOleInPlaceSiteWindowless );
  76.       }
  77.    }
  78.    else if( *piid == IID_IOleInPlaceSiteWindowless )
  79.    {
  80.       if( GetDocument()->SupportsInterface( IID_IOleInPlaceSiteWindowless ) )
  81.       {
  82.          TCControlTrace( TRACELEVEL_NORMAL, this,
  83.             "QI for IOleInPlaceSiteWindowless.\n" );
  84.          return( &m_xOleInPlaceSiteWindowless );
  85.       }
  86.    }
  87.    else if( *piid == IID_IAdviseSinkEx )
  88.    {
  89.       if( GetDocument()->SupportsInterface( IID_IAdviseSinkEx ) )
  90.       {
  91.          TCControlTrace( TRACELEVEL_NORMAL, this, "QI for IAdviseSinkEx.\n" );
  92.          return( &m_xAdviseSinkEx );
  93.       }
  94.    }
  95.  
  96.    return( NULL );
  97. }
  98.  
  99. BOOL CTestContainer98Item::CreateFromClipboard( CArchive& ar,
  100.    IStorage* pStorage )
  101. {
  102.    HRESULT hResult;
  103.    CString strName;
  104.    CLSID clsid;
  105.  
  106.    ASSERT( !ar.IsStoring() );
  107.    ASSERT( pStorage != NULL );
  108.  
  109.    ar>>strName;
  110.    ar>>m_rect;
  111.  
  112.    hResult = ReadClassStg( pStorage, &clsid );
  113.    if( FAILED( hResult ) )
  114.    {
  115.       return( FALSE );
  116.    }
  117.  
  118.    return( CreateOrLoad( clsid, strName, IID_IStorage, pStorage ) );
  119. }
  120.  
  121. BOOL CTestContainer98Item::CreateOrLoad( REFCLSID clsid, LPCTSTR pszName,
  122.    REFIID iidPersistanceMedium, IUnknown* pPersistanceMedium )
  123. {
  124.    HRESULT hResult;
  125.    BOOL tSuccess;
  126.    BOOL tQuickActivated;
  127.    IPersistStreamInitPtr pPersistStreamInit;
  128.    IPersistStreamPtr pPersistStream;
  129.    IPersistStoragePtr pPersistStorage;
  130.    IStreamPtr pStream;
  131.    IStoragePtr pStorage;
  132.  
  133.    ASSERT( m_lpObject == NULL );
  134.    ASSERT( m_pDocument != NULL );
  135.  
  136.    m_dwItemNumber = GetNewItemNumber();
  137.    GetItemStorage();
  138.    ASSERT( m_lpStorage != NULL );
  139.  
  140.    m_tExtendedControl = TRUE;
  141.    hResult = CExtendedControl::CreateInstance( clsid, this, NULL,
  142.       IID_IOleObject, (void**)&m_lpObject );
  143.    if( FAILED( hResult ) )
  144.    {
  145.       m_tExtendedControl = FALSE;
  146.       // The control may not like being aggregated on, so just try to create it
  147.       // directly and punt the extended control stuff.
  148.       hResult = CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER|
  149.         CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER, IID_IOleObject,
  150.          (void**)&m_lpObject );
  151.       if( SUCCEEDED( hResult ) )
  152.       {
  153.          TCControlTrace( TRACELEVEL_NORMAL, this,
  154.             "Could not aggregate on the control, so it won't support extended properties.\n" );
  155.       }
  156.    }
  157.    if( SUCCEEDED( hResult ) )
  158.    {
  159.       CString strUserType;
  160.  
  161.       if( pszName == NULL )
  162.       {
  163.          GetUserType( USERCLASSTYPE_SHORT, strUserType );
  164.          GetDocument()->CreateUniqueItemName( this, strUserType,
  165.             m_strDisplayName );
  166.       }
  167.       else
  168.       {
  169.          GetDocument()->CreateUniqueItemName( this, pszName,
  170.             m_strDisplayName );
  171.       }
  172.    }
  173.  
  174.    if( m_tExtendedControl )
  175.    {
  176.       CString strName;
  177.  
  178.       strName = GetDisplayName();
  179.       m_pExtendedControl = m_lpObject;
  180.       ASSERT( m_pExtendedControl != NULL );
  181.       m_pExtendedControl->Name = _bstr_t( strName );
  182.    }
  183.  
  184.    if( SUCCEEDED( hResult ) )
  185.    {
  186.       hResult = InitControlInfo();
  187.    }
  188.  
  189.    tQuickActivated = FALSE;
  190.    if( SUCCEEDED( hResult ) )
  191.    {
  192.       tQuickActivated = QuickActivate();
  193.  
  194.       if( !tQuickActivated )
  195.       {
  196.          m_lpObject->GetMiscStatus( DVASPECT_CONTENT, &m_dwMiscStatus );
  197.          if( m_dwMiscStatus&OLEMISC_SETCLIENTSITEFIRST )
  198.          {
  199.             hResult = m_lpObject->SetClientSite( GetClientSite() );
  200.             if( FAILED( hResult ) )
  201.             {
  202.                TCControlTrace( TRACELEVEL_NORMAL, this,
  203.                   "SetClientSite failed.\n" );
  204.             }
  205.          }
  206.       }
  207.    }
  208.  
  209.    // Initialize or load the object's state.
  210.    if( SUCCEEDED( hResult ) )
  211.    {
  212.       if( iidPersistanceMedium == IID_NULL )
  213.       {
  214.          pPersistStreamInit = m_lpObject;
  215.          if( pPersistStreamInit != NULL )
  216.          {
  217.             hResult = pPersistStreamInit->InitNew();
  218.             if( hResult == E_NOTIMPL )
  219.             {
  220.                // Not implementing InitNew is OK.
  221.                hResult = S_OK;
  222.             }
  223.          }
  224.          else
  225.          {
  226.             pPersistStorage = m_lpObject;
  227.             if( pPersistStorage != NULL )
  228.             {
  229.                hResult = pPersistStorage->InitNew( m_lpStorage );
  230.             }
  231.             else
  232.             {
  233.             // Assume the control doesn't care about persistance.
  234.                hResult = S_OK;
  235.             }
  236.          }
  237.       }
  238.       else if( iidPersistanceMedium == IID_IStream )
  239.       {
  240.          pStream = pPersistanceMedium;
  241.          ASSERT( pStream != NULL );
  242.  
  243.          pPersistStreamInit = m_lpObject;
  244.          if( pPersistStreamInit != NULL )
  245.          {
  246.             hResult = pPersistStreamInit->Load( pStream );
  247.          }
  248.          else
  249.          {
  250.             pPersistStream = m_lpObject;
  251.             if( pPersistStream != NULL )
  252.             {
  253.                hResult = pPersistStream->Load( pStream );
  254.             }
  255.             else
  256.             {
  257.                hResult = E_NOINTERFACE;
  258.             }
  259.          }
  260.       }
  261.       else if( iidPersistanceMedium == IID_IStorage )
  262.       {
  263.          pStorage = pPersistanceMedium;
  264.          ASSERT( pStorage != NULL );
  265.  
  266.          pPersistStorage = m_lpObject;
  267.          if( pPersistStorage != NULL )
  268.          {
  269.             hResult = pStorage->CopyTo( 0, NULL, NULL, m_lpStorage );
  270.             if( SUCCEEDED( hResult ) )
  271.             {
  272.                hResult = pPersistStorage->Load( m_lpStorage );
  273.             }
  274.          }
  275.          else
  276.          {
  277.             hResult = E_NOINTERFACE;
  278.          }
  279.       }
  280.    }
  281.  
  282.    if( SUCCEEDED( hResult ) )
  283.    {
  284.       if( !tQuickActivated )
  285.       {
  286.          if( !(m_dwMiscStatus&OLEMISC_SETCLIENTSITEFIRST) )
  287.          {
  288.             hResult = m_lpObject->SetClientSite( GetClientSite() );
  289.             if( FAILED( hResult ) )
  290.             {
  291.                TCControlTrace( TRACELEVEL_NORMAL, this,
  292.                   "SetClientSite failed.\n" );
  293.             }
  294.          }
  295.       }
  296.    }
  297.  
  298.    tSuccess = FinishCreate( hResult );
  299.  
  300.    return( tSuccess );
  301. }
  302.  
  303. BOOL CTestContainer98Item::Create( REFCLSID clsid, LPCTSTR pszName )
  304. {
  305.    return( CreateOrLoad( clsid, pszName, IID_NULL, NULL ) );
  306. }
  307.  
  308. void CTestContainer98Item::CleanupParams()
  309. {
  310.    UINT iArg;
  311.    DISPPARAMS* pdpParams;
  312.  
  313.    ASSERT_VALID( this );
  314.  
  315.    pdpParams = &m_dpLastParams;
  316.    if( pdpParams->rgvarg != NULL )
  317.    {
  318.       for( iArg = 0; iArg < pdpParams->cArgs; iArg++ )
  319.       {
  320.          VariantClear( &pdpParams->rgvarg[iArg] );
  321.       }
  322.  
  323.       delete[] (COleVariant*)pdpParams->rgvarg;
  324.       pdpParams->rgvarg = NULL;
  325.    }
  326.  
  327.    if( pdpParams->rgdispidNamedArgs != NULL )
  328.    {
  329.       delete[] pdpParams->rgdispidNamedArgs;
  330.       pdpParams->rgdispidNamedArgs = NULL;
  331.    }
  332. }
  333.  
  334. void CTestContainer98Item::CopyParams( DISPPARAMS* pdpParams )
  335. {
  336.    UINT iArg;
  337.  
  338.    if( pdpParams == NULL )
  339.    {
  340.       return;  // Can't copy bogus params.
  341.    }
  342.  
  343.    if( m_dpLastParams.cArgs > 0 )
  344.    {
  345.       CleanupParams();
  346.    }
  347.  
  348.    // Change state information about incoming.
  349.    m_dpLastParams.cArgs = pdpParams->cArgs;
  350.    if( pdpParams->cArgs == 0 )
  351.    {
  352.       m_dpLastParams.rgvarg = NULL;
  353.    }
  354.    else
  355.    {
  356.       m_dpLastParams.rgvarg = new COleVariant[pdpParams->cArgs];
  357.    }
  358.  
  359.    m_dpLastParams.cNamedArgs = pdpParams->cNamedArgs;
  360.    if( pdpParams->cNamedArgs == 0 )
  361.    {
  362.       m_dpLastParams.rgdispidNamedArgs = NULL;
  363.    }
  364.    else
  365.    {
  366.       m_dpLastParams.rgdispidNamedArgs = new DISPID[pdpParams->cNamedArgs];
  367.       for( iArg = 0; iArg < m_dpLastParams.cNamedArgs; iArg++ )
  368.       {
  369.          m_dpLastParams.rgdispidNamedArgs[iArg] =
  370.             pdpParams->rgdispidNamedArgs[iArg];
  371.       }
  372.    }
  373.  
  374.    for( iArg = 0; iArg < m_dpLastParams.cArgs; iArg++ )
  375.    {
  376.       VariantCopy( &m_dpLastParams.rgvarg[iArg], &pdpParams->rgvarg[iArg] );
  377.    }
  378. }
  379.  
  380. class QAAMBIENTENTRY
  381. {
  382. public:
  383.    DISPID dispid;
  384.    DWORD dwQAFlag;
  385. };
  386.  
  387. static const QAAMBIENTENTRY g_aQAAmbients[] =
  388. {
  389.    { DISPID_AMBIENT_SHOWHATCHING, QACONTAINER_SHOWHATCHING },
  390.    { DISPID_AMBIENT_SHOWGRABHANDLES, QACONTAINER_SHOWGRABHANDLES },
  391.    { DISPID_AMBIENT_USERMODE, QACONTAINER_USERMODE },
  392.    { DISPID_AMBIENT_DISPLAYASDEFAULT, QACONTAINER_DISPLAYASDEFAULT },
  393.    { DISPID_AMBIENT_UIDEAD, QACONTAINER_UIDEAD },
  394.    { DISPID_AMBIENT_AUTOCLIP, QACONTAINER_AUTOCLIP },
  395.    { DISPID_AMBIENT_MESSAGEREFLECT, QACONTAINER_MESSAGEREFLECT },
  396.    { DISPID_AMBIENT_SUPPORTSMNEMONICS, QACONTAINER_SUPPORTSMNEMONICS }
  397. };
  398.  
  399. const int NUM_QAAMBIENTS = sizeof( g_aQAAmbients )/sizeof( g_aQAAmbients[0] );
  400.  
  401. BOOL CTestContainer98Item::QuickActivate()
  402. {
  403.    HRESULT hResult;
  404.    IQuickActivatePtr pQuickActivate;
  405.    IDispatch* pFontDispatch;
  406.    QACONTAINER qaContainer;
  407.    QACONTROL qaControl;
  408.    CTestContainer98Doc* pDoc;
  409.    CAmbientProperty* pProperty;
  410.    int iQAAmbient;
  411.  
  412.    pDoc = GetDocument();
  413.    if( !pDoc->UseQuickActivation() )
  414.    {
  415.       // The container doesn't want to use quick activation.
  416.       return( FALSE );
  417.    }
  418.  
  419.    hResult = m_lpObject->QueryInterface( IID_IQuickActivate,
  420.       (void**)&pQuickActivate );
  421.    if( FAILED( hResult ) )
  422.    {
  423.       // The control doesn't support quick activation.
  424.       return( FALSE );
  425.    }
  426.  
  427.    qaContainer.cbSize = sizeof( qaContainer );
  428.    qaContainer.pClientSite = GetClientSite();
  429.    qaContainer.pAdviseSink = NULL;
  430.    qaContainer.pPropertyNotifySink = &m_xPropertyNotifySink;
  431.    qaContainer.pUnkEventSink = &m_xEventHandler;
  432.    qaContainer.dwAmbientFlags = 0;
  433.  
  434.    for( iQAAmbient = 0; iQAAmbient < NUM_QAAMBIENTS; iQAAmbient++ )
  435.    {
  436.       pProperty = pDoc->FindAmbientProperty(
  437.          g_aQAAmbients[iQAAmbient].dispid );
  438.       if( pProperty != NULL )
  439.       {
  440.          ASSERT( pProperty->GetValue().vt == VT_BOOL );
  441.          if( pProperty->GetValue().bVal )
  442.          {
  443.             qaContainer.dwAmbientFlags |= g_aQAAmbients[iQAAmbient].dwQAFlag;
  444.          }
  445.       }
  446.    }
  447.  
  448.    qaContainer.colorFore = 0;
  449.    pProperty = pDoc->FindAmbientProperty( DISPID_AMBIENT_FORECOLOR );
  450.    if( pProperty != NULL )
  451.    {
  452.       ASSERT( pProperty->GetValue().vt == VT_COLOR );
  453.       qaContainer.colorFore = pProperty->GetValue().lVal;
  454.    }
  455.  
  456.    qaContainer.colorBack = 0;
  457.    pProperty = pDoc->FindAmbientProperty( DISPID_AMBIENT_BACKCOLOR );
  458.    if( pProperty != NULL )
  459.    {
  460.       ASSERT( pProperty->GetValue().vt == VT_COLOR );
  461.       qaContainer.colorBack = pProperty->GetValue().lVal;
  462.    }
  463.  
  464.    qaContainer.pFont = NULL;
  465.    pProperty = pDoc->FindAmbientProperty( DISPID_AMBIENT_FONT );
  466.    if( pProperty != NULL )
  467.    {
  468.       ASSERT( pProperty->GetValue().vt == VT_DISPATCH );
  469.       pFontDispatch = pProperty->GetValue().pdispVal;
  470.       hResult = pFontDispatch->QueryInterface( IID_IFont,
  471.          (void**)&qaContainer.pFont );
  472.       ASSERT( SUCCEEDED( hResult ) );
  473.    }
  474.  
  475.    qaContainer.pUndoMgr = NULL;
  476.  
  477.    qaContainer.dwAppearance = 0;
  478.    pProperty = pDoc->FindAmbientProperty( DISPID_AMBIENT_APPEARANCE );
  479.    if( pProperty != NULL )
  480.    {
  481.       ASSERT( pProperty->GetValue().vt == VT_I4 );
  482.       qaContainer.dwAppearance = pProperty->GetValue().lVal;
  483.    }
  484.  
  485.    qaContainer.lcid = 0;
  486.    pProperty = pDoc->FindAmbientProperty( DISPID_AMBIENT_LOCALEID );
  487.    if( pProperty != NULL )
  488.    {
  489.       ASSERT( pProperty->GetValue().vt == VT_I4 );
  490.       qaContainer.lcid = pProperty->GetValue().lVal;
  491.    }
  492.  
  493.    qaContainer.hpal = NULL;
  494.    qaContainer.pBindHost = GetBindHost();
  495.  
  496.    memset( &qaControl, 0, sizeof( qaControl ) );
  497.    qaControl.cbSize = sizeof( qaControl );
  498.  
  499.    hResult = pQuickActivate->QuickActivate( &qaContainer, &qaControl );
  500.    if( FAILED( hResult ) )
  501.    {
  502.       return( FALSE );
  503.    }
  504.  
  505.    m_dwMiscStatus = qaControl.dwMiscStatus;
  506.    m_dwViewStatus = qaControl.dwViewStatus;
  507.    m_dwEventCookie = qaControl.dwEventCookie;
  508.    m_dwPropertyCookie = qaControl.dwPropNotifyCookie;
  509.  
  510.    TCControlTrace( TRACELEVEL_NORMAL, this, "Quick activation successful.\n" );
  511.  
  512.    return( TRUE );
  513. }
  514.  
  515. BOOL CTestContainer98Item::FinishCreate( HRESULT hr )
  516. {
  517.    BOOL tSuccess;
  518.    IConnectionPointContainerPtr pCPContainer;
  519.    HRESULT hResult;
  520.  
  521.    tSuccess = COleClientItem::FinishCreate( hr );
  522.    if( !tSuccess )
  523.    {
  524.       return( tSuccess );
  525.    }
  526.  
  527.    hResult = m_lpObject->QueryInterface( IID_IOleControl,
  528.       (void**)&m_pOleControl );
  529.    if( FAILED( hResult ) )
  530.    {
  531.       // That's OK, it might not be a control
  532.       TCControlTrace( TRACELEVEL_NORMAL, this,
  533.          "Could not get object's IOleControl interface\n" );
  534.    }
  535.  
  536.    hResult = m_lpObject->QueryInterface( IID_IConnectionPointContainer,
  537.       (void**)&pCPContainer );
  538.    if( SUCCEEDED( hResult ) )
  539.    {
  540.       if( m_dwEventCookie == 0 )
  541.       {
  542.          hResult = pCPContainer->FindConnectionPoint( m_infoEvents.GetIID(),
  543.             &m_pEventCP );
  544.          if( SUCCEEDED( hResult ) )
  545.          {
  546.             m_pEventCP->Advise( &m_xEventHandler, &m_dwEventCookie );
  547.          }
  548.       }
  549.  
  550.       if( m_dwPropertyCookie == 0 )
  551.       {
  552.          hResult = pCPContainer->FindConnectionPoint( IID_IPropertyNotifySink,
  553.             &m_pPropertyCP );
  554.          if( SUCCEEDED( hResult ) )
  555.          {
  556.             m_pPropertyCP->Advise( &m_xPropertyNotifySink,
  557.                &m_dwPropertyCookie );
  558.          }
  559.       }
  560.    }
  561.  
  562.    m_lpObject->GetMiscStatus( DVASPECT_CONTENT, &m_dwMiscStatus );
  563.    if( m_dwMiscStatus&OLEMISC_INSIDEOUT )
  564.    {
  565.       TCControlTrace( TRACELEVEL_VERBOSE, this, "Control is inside-out\n" );
  566.       m_tInsideOut = TRUE;
  567.    }
  568.  
  569.    hResult = m_lpObject->QueryInterface( IID_IPointerInactive,
  570.       (void**)&m_pPointerInactive );
  571.    if( SUCCEEDED( hResult ) )
  572.    {
  573.       TCControlTrace( TRACELEVEL_NORMAL, this,
  574.          "Control supports IPointerInactive.\n" );
  575.    }
  576.  
  577.    hResult = m_lpObject->QueryInterface( IID_IViewObjectEx,
  578.       (void**)&m_pViewObjectEx );
  579.    if( SUCCEEDED( hResult ) )
  580.    {
  581.       TCControlTrace( TRACELEVEL_NORMAL, this,
  582.          "Control supports IViewObjectEx.\n" );
  583.       m_pViewObjectEx->GetViewStatus( &m_dwViewStatus );
  584.    }
  585.    else
  586.    {
  587.       m_dwViewStatus = 0;
  588.    }
  589.  
  590.    UpdateFromServerExtent();
  591.  
  592.    // Activate the item if it wants to be active all the time.
  593.    if( ShouldActivateWhenVisible() )
  594.    {
  595.       if( GetDocument()->GetUserMode() && IsInvisibleAtRuntime() )
  596.       {
  597.          DoVerb( OLEIVERB_HIDE, GetDocument()->GetView() );
  598.       }
  599.       else
  600.       {
  601.          DoVerb( OLEIVERB_SHOW, GetDocument()->GetView() );
  602.       }
  603.    }
  604.  
  605.    return( TRUE );
  606. }
  607.  
  608. CString CTestContainer98Item::GetDisplayName()
  609. {
  610.    CString strName;
  611.  
  612.    if( m_pExtendedControl != NULL )
  613.    {
  614.       strName = BSTR( m_pExtendedControl->Name );
  615.    }
  616.    else
  617.    {
  618.       strName = m_strDisplayName;
  619.    }
  620.  
  621.    return( strName );
  622. }
  623.  
  624. HRESULT CTestContainer98Item::GetControlInfo()
  625. {
  626.    HRESULT hResult;
  627.  
  628.    m_infoControl.cb = sizeof( m_infoControl );
  629.    m_infoControl.hAccel = NULL;
  630.    m_infoControl.cAccel = 0;
  631.    m_infoControl.dwFlags = 0;
  632.    hResult = m_pOleControl->GetControlInfo( &m_infoControl );
  633.    if( FAILED( hResult ) )
  634.    {
  635.       if( hResult == E_NOTIMPL )
  636.       {
  637.          TCControlTrace( TRACELEVEL_NORMAL, this,
  638.             "IOleControl::GetControlInfo() not implemented\n" );
  639.       }
  640.       else
  641.       {
  642.          return( hResult );
  643.       }
  644.    }
  645.  
  646.    return( S_OK );
  647. }
  648.  
  649. COleDataSource* CTestContainer98Item::OnGetClipboardData( BOOL tIncludeLink,
  650.    LPPOINT pptOffset, LPSIZE pSize )
  651. {
  652.    COleDataSource* pSource;
  653.    IStreamPtr pStream;
  654.    HRESULT hResult;
  655.    IPersistStreamInitPtr pPSI;
  656.    ULONG nStringLength;
  657.    CString strDisplayName;
  658.    CLSID clsid;
  659.  
  660.    ASSERT_VALID( this );
  661.  
  662.    pSource = new COleDataSource;
  663.    try
  664.    {
  665.       hResult = CreateStreamOnHGlobal( NULL, TRUE, &pStream );
  666.       if( FAILED( hResult ) )
  667.       {
  668.          AfxThrowOleException( hResult );
  669.       }
  670.       pPSI = m_lpObject;
  671.       if( pPSI == NULL )
  672.       {
  673.          AfxThrowOleException( E_NOINTERFACE );
  674.       }
  675.       strDisplayName = GetDisplayName();
  676.       nStringLength = strDisplayName.GetLength();
  677.       hResult = pStream->Write( &nStringLength, sizeof( ULONG ), NULL );
  678.       if( FAILED( hResult ) )
  679.       {
  680.          AfxThrowOleException( hResult );
  681.       }
  682.       hResult = pStream->Write( LPCTSTR( strDisplayName ), nStringLength*
  683.          sizeof( TCHAR ), NULL );
  684.       if( FAILED( hResult ) )
  685.       {
  686.          AfxThrowOleException( hResult );
  687.       }
  688.  
  689.       pPSI->GetClassID( &clsid );
  690.       hResult = WriteClassStm( pStream, clsid );
  691.       if( FAILED( hResult ) )
  692.       {
  693.          AfxThrowOleException( hResult );
  694.       }
  695.       hResult = pPSI->Save( pStream, FALSE );
  696.       if( FAILED( hResult ) )
  697.       {
  698.          AfxThrowOleException( hResult );
  699.       }
  700.  
  701.       LARGE_INTEGER nMove;
  702.  
  703.       nMove.QuadPart = 0;
  704.       pStream->Seek( nMove, STREAM_SEEK_SET, NULL );
  705.  
  706.       CLIPFORMAT cf = CLIPFORMAT( ::RegisterClipboardFormat( _T(
  707.          "TC98 Control" ) ) );
  708.       STGMEDIUM stgmedium;
  709.  
  710.       stgmedium.tymed = TYMED_ISTREAM;
  711.       stgmedium.pstm = pStream;
  712.       stgmedium.pstm->AddRef();
  713.       stgmedium.pUnkForRelease = NULL;
  714.  
  715.       pSource->CacheData( cf, &stgmedium );
  716.  
  717.       GetClipboardData( pSource, tIncludeLink, pptOffset, pSize );
  718.    }
  719.    catch( ... )
  720.    {
  721.       delete pSource;
  722.       throw;
  723.    }
  724.  
  725.    ASSERT_VALID( pSource );
  726.  
  727.    return( pSource );
  728. }
  729.  
  730. BOOL CTestContainer98Item::GetPropertyPageCLSIDs( CArray< CLSID,
  731.    CLSID& >& aclsidPages )
  732. {
  733.    ISpecifyPropertyPagesPtr pSpecify;
  734.    CAUUID pages;
  735.    HRESULT hResult;
  736.    ULONG iPage;
  737.    CLSID clsid;
  738.  
  739.    pSpecify = m_lpObject;
  740.    if( pSpecify != NULL )
  741.    {
  742.       pages.cElems = 0;
  743.       pages.pElems = NULL;
  744.       hResult = pSpecify->GetPages( &pages );
  745.       if( FAILED( hResult ) )
  746.       {
  747.          TCControlTrace( TRACELEVEL_NORMAL, this,
  748.             "ISpecifyPropertyPages::GetPages() failed\n" );
  749.          return( FALSE );
  750.       }
  751.  
  752.       for( iPage = 0; iPage < pages.cElems; iPage++ )
  753.       {
  754.          aclsidPages.Add( pages.pElems[iPage] );
  755.       }
  756.  
  757.       CoTaskMemFree( pages.pElems );
  758.    }
  759.  
  760.    if( m_pExtendedControl != NULL )
  761.    {
  762.       clsid = __uuidof( TCExtPage );
  763.       aclsidPages.Add( clsid );
  764.    }
  765.  
  766.    return( TRUE );
  767. }
  768.  
  769.  
  770. HRESULT CTestContainer98Item::InitControlInfo()
  771. {
  772.    IProvideClassInfoPtr pPCI;
  773.    ITypeInfoPtr pClassInfo;
  774.    ITypeInfoPtr pTypeInfo;
  775.    HRESULT hResult;
  776.    UINT iType;
  777.    int iFlags;
  778.    HREFTYPE hRefType;
  779.    BOOL tFoundDefaultSource;
  780.    BOOL tFoundDefaultInterface;
  781.  
  782.    hResult = m_lpObject->QueryInterface( IID_IProvideClassInfo,
  783.       (void**)&pPCI );
  784.    if( FAILED( hResult ) )
  785.    {
  786.      TCControlTrace( TRACELEVEL_NORMAL, this,
  787.         "Control doesn't support IProvideClassInfo" );
  788.       return( S_OK );
  789.    }
  790.  
  791.    hResult = pPCI->GetClassInfo( &pClassInfo );
  792.    if( FAILED( hResult ) )
  793.    {
  794.       return( hResult );
  795.    }
  796.  
  797.    CSmartTypeAttr pTypeAttr( pClassInfo );
  798.  
  799.    hResult = pClassInfo->GetTypeAttr( &pTypeAttr );
  800.    if( FAILED( hResult ) )
  801.    {
  802.       return( hResult );
  803.    }
  804.    ASSERT( pTypeAttr->typekind == TKIND_COCLASS );
  805.  
  806.    tFoundDefaultSource = FALSE;
  807.    tFoundDefaultInterface = FALSE;
  808.    for( iType = 0; (iType < pTypeAttr->cImplTypes) && !(tFoundDefaultSource &&
  809.       tFoundDefaultInterface); iType++ )
  810.    {
  811.       hResult = pClassInfo->GetImplTypeFlags( iType, &iFlags );
  812.       if( SUCCEEDED( hResult ) )
  813.       {
  814.          if( (iFlags&IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE )
  815.          {
  816.             ASSERT( !tFoundDefaultSource );
  817.             tFoundDefaultSource = TRUE;
  818.             hResult = pClassInfo->GetRefTypeOfImplType( iType, &hRefType );
  819.             if( FAILED( hResult ) )
  820.             {
  821.                return( hResult );
  822.             }
  823.             hResult = pClassInfo->GetRefTypeInfo( hRefType, &pTypeInfo );
  824.             if( FAILED( hResult ) )
  825.             {
  826.                return( hResult );
  827.             }
  828.             TRACE( "Events:\n" );
  829.             hResult = m_infoEvents.Init( pTypeInfo );
  830.             if( FAILED( hResult ) )
  831.             {
  832.                return( hResult );
  833.             }
  834.             pTypeInfo.Release();
  835.          }
  836.          else if( (iFlags&IMPLTYPE_MASK) == IMPLTYPE_DEFAULTINTERFACE )
  837.          {
  838.             ASSERT( !tFoundDefaultInterface );
  839.             tFoundDefaultInterface = TRUE;
  840.             hResult = pClassInfo->GetRefTypeOfImplType( iType, &hRefType );
  841.             if( FAILED( hResult ) )
  842.             {
  843.                return( hResult );
  844.             }
  845.             hResult = pClassInfo->GetRefTypeInfo( hRefType, &pTypeInfo );
  846.             if( FAILED( hResult ) )
  847.             {
  848.                return( hResult );
  849.             }
  850.             TRACE( "Methods\n" );
  851.             hResult = m_infoMethods.Init( pTypeInfo );
  852.             if( FAILED( hResult ) )
  853.             {
  854.                return( hResult );
  855.             }
  856.             pTypeInfo.Release();
  857.          }
  858.       }
  859.    }
  860.    if( !tFoundDefaultSource )
  861.    {
  862.       TCControlTrace( TRACELEVEL_NORMAL, this,
  863.          "Could not find control's default source\n" );
  864.    }
  865.    if( !tFoundDefaultInterface )
  866.    {
  867.       TCControlTrace( TRACELEVEL_NORMAL, this,
  868.          "Could not find control's default interface\n" );
  869.       return( E_FAIL );
  870.    }
  871.  
  872.    return( S_OK );
  873. }
  874.  
  875. BOOL CTestContainer98Item::IsInvisibleAtRuntime() const
  876. {
  877.    return( m_dwMiscStatus&OLEMISC_INVISIBLEATRUNTIME );
  878. }
  879.  
  880. BOOL CTestContainer98Item::IsWindowless() const
  881. {
  882.    return( m_tWindowless );
  883. }
  884.  
  885. BOOL CTestContainer98Item::SupportsIPointerInactive() const
  886. {
  887.    return( m_pPointerInactive != NULL );
  888. }
  889.  
  890. BOOL CTestContainer98Item::OnWindowlessDragEnter( COleDataObject* pDataObject,
  891.    DWORD dwKeyState, CPoint point, DWORD* pdwDropEffect )
  892. {
  893.    HRESULT hResult;
  894.    POINTL pointl;
  895.  
  896.    TRACE( "OnWindowlessDragEnter()\n" );
  897.  
  898.    ASSERT( pdwDropEffect != NULL );
  899.    *pdwDropEffect = DROPEFFECT_NONE;
  900.  
  901.    if( m_pDropTarget == NULL )
  902.    {
  903.       // We haven't tried to drop on this control yet, or the control doesn't
  904.       // support IDropTarget.
  905.       hResult = m_pOleInPlaceObjectWindowless->GetDropTarget( &m_pDropTarget );
  906.       if( FAILED( hResult ) )
  907.       {
  908.          // The control doesn't support IDropTarget.
  909.          return( FALSE );
  910.       }
  911.    }
  912.  
  913.    pointl.x = point.x;
  914.    pointl.y = point.y;
  915.    hResult = m_pDropTarget->DragEnter( pDataObject->m_lpDataObject, dwKeyState,
  916.       pointl, pdwDropEffect );
  917.    ASSERT( SUCCEEDED( hResult ) );
  918.    if( hResult == S_FALSE )
  919.    {
  920.       // The control doesn't support any of the object's data formats.
  921.       return( FALSE );
  922.    }
  923.  
  924.    return( TRUE );
  925. }
  926.  
  927. void CTestContainer98Item::OnWindowlessDragLeave()
  928. {
  929.    HRESULT hResult;
  930.  
  931.    TRACE( "OnWindowlessDragLeave()\n" );
  932.  
  933.    ASSERT( m_pDropTarget != NULL );
  934.  
  935.    hResult = m_pDropTarget->DragLeave();
  936.    ASSERT( SUCCEEDED( hResult ) );
  937. }
  938.  
  939. void CTestContainer98Item::OnWindowlessDragOver( DWORD dwKeyState,
  940.    CPoint point, DWORD* pdwDropEffect )
  941. {
  942.    HRESULT hResult;
  943.    POINTL pointl;
  944.  
  945.    ASSERT( pdwDropEffect != NULL );
  946.    *pdwDropEffect = DROPEFFECT_NONE;
  947.  
  948.    ASSERT( m_pDropTarget != NULL );
  949.  
  950.    pointl.x = point.x;
  951.    pointl.y = point.y;
  952.    hResult = m_pDropTarget->DragOver( dwKeyState, pointl, pdwDropEffect );
  953.    ASSERT( SUCCEEDED( hResult ) );
  954. }
  955.  
  956. void CTestContainer98Item::OnWindowlessDrop( COleDataObject* pDataObject,
  957.    DWORD dwKeyState, CPoint point, DWORD* pdwDropEffect )
  958. {
  959.    HRESULT hResult;
  960.    POINTL pointl;
  961.  
  962.    TRACE( "OnWindowlessDrop()\n" );
  963.  
  964.    ASSERT( m_pDropTarget != NULL );
  965.  
  966.    pointl.x = point.x;
  967.    pointl.y = point.y;
  968.    hResult = m_pDropTarget->Drop( pDataObject->m_lpDataObject, dwKeyState,
  969.       pointl, pdwDropEffect );
  970.    ASSERT( SUCCEEDED( hResult ) );
  971. }
  972.  
  973. BOOL CTestContainer98Item::ActsLikeButton() const
  974. {
  975.    return( m_dwMiscStatus&OLEMISC_ACTSLIKEBUTTON );
  976. }
  977.  
  978. DWORD CTestContainer98Item::GetActivationPolicy() const
  979. {
  980.    DWORD dwPolicy;
  981.    HRESULT hResult;
  982.  
  983.    ASSERT( m_pPointerInactive != NULL );
  984.    ASSERT( !IsInPlaceActive() );
  985.  
  986.    hResult = m_pPointerInactive->GetActivationPolicy( &dwPolicy );
  987.    if( FAILED( hResult ) )
  988.    {
  989.       return( 0 );
  990.    }
  991.  
  992.    return( dwPolicy );
  993. }
  994.  
  995. DWORD CTestContainer98Item::OnPointerInactiveMove( CPoint point,
  996.    DWORD dwKeyState )
  997. {
  998.    DWORD dwPolicy;
  999.  
  1000.    ASSERT( m_pPointerInactive != NULL );
  1001.    ASSERT( !IsInPlaceActive() );
  1002.  
  1003.    dwPolicy = GetActivationPolicy();
  1004.  
  1005.    if( dwPolicy&POINTERINACTIVE_ACTIVATEONENTRY )
  1006.    {
  1007.       return( dwPolicy );
  1008.    }
  1009.  
  1010.    m_pPointerInactive->OnInactiveMouseMove( &m_rect, point.x, point.y,
  1011.       dwKeyState );
  1012.  
  1013.    return( 0 );
  1014. }
  1015.  
  1016. DWORD CTestContainer98Item::OnPointerInactiveSetCursor( CPoint point,
  1017.    DWORD dwMouseMessage, BOOL* ptHandled )
  1018. {
  1019.    HRESULT hResult;
  1020.    DWORD dwPolicy;
  1021.  
  1022.    ASSERT( ptHandled != NULL );
  1023.    *ptHandled = FALSE;
  1024.  
  1025.    ASSERT( m_pPointerInactive != NULL );
  1026.    ASSERT( !IsInPlaceActive() );
  1027.  
  1028.    dwPolicy = GetActivationPolicy();
  1029.  
  1030.    if( dwPolicy&POINTERINACTIVE_ACTIVATEONENTRY )
  1031.    {
  1032.       return( dwPolicy );
  1033.    }
  1034.  
  1035.    hResult = m_pPointerInactive->OnInactiveSetCursor( &m_rect, point.x,
  1036.       point.y, dwMouseMessage, FALSE );
  1037.    if( hResult == S_OK )
  1038.    {
  1039.       *ptHandled = TRUE;
  1040.    }
  1041.  
  1042.    return( 0 );
  1043. }
  1044.  
  1045. void CTestContainer98Item::OnChange( OLE_NOTIFICATION nCode, DWORD dwParam )
  1046. {
  1047.     ASSERT_VALID( this );
  1048.  
  1049.     COleClientItem::OnChange( nCode, dwParam );
  1050.  
  1051.     // When an item is being edited (either in-place or fully open), it sends
  1052.    // OnChange notifications for changes in the state of the item or visual
  1053.    // appearance of its content.
  1054.  
  1055.    switch( nCode )
  1056.    {
  1057.    case OLE_CHANGED:
  1058.       InvalidateItem();
  1059.       UpdateFromServerExtent();
  1060.       break;
  1061.  
  1062.    case OLE_CHANGED_STATE:
  1063.    case OLE_CHANGED_ASPECT:
  1064.       InvalidateItem();
  1065.       break;
  1066.    }
  1067. }
  1068.  
  1069. BOOL CTestContainer98Item::OnChangeItemPosition( const CRect& rectPos )
  1070. {
  1071.     ASSERT_VALID( this );
  1072.  
  1073.     // During in-place activation CTestContainer98Item::OnChangeItemPosition
  1074.     //  is called by the server to change the position of the in-place
  1075.     //  window.  Usually, this is a result of the data in the server
  1076.     //  document changing such that the extent has changed or as a result
  1077.     //  of in-place resizing.
  1078.     //
  1079.     // The default here is to call the base class, which will call
  1080.     //  COleClientItem::SetItemRects to move the item
  1081.     //  to the new position.
  1082.  
  1083.     if( !COleClientItem::OnChangeItemPosition( rectPos ) )
  1084.    {
  1085.         return( FALSE );
  1086.    }
  1087.  
  1088.    InvalidateItem();
  1089.    m_rect = rectPos;
  1090.    InvalidateItem();
  1091.  
  1092.    // Mark document as dirty.
  1093.    GetDocument()->SetModifiedFlag();
  1094.  
  1095.     return( TRUE );
  1096. }
  1097.  
  1098. void CTestContainer98Item::OnGetClipRect( CRect& rectClip )
  1099. {
  1100.    ASSERT_VALID( this );
  1101.  
  1102.    rectClip = m_rect;
  1103. }
  1104.  
  1105. void CTestContainer98Item::OnGetItemPosition( CRect& rectPosition )
  1106. {
  1107.     ASSERT_VALID( this );
  1108.  
  1109.     // During in-place activation, CTestContainer98Item::OnGetItemPosition
  1110.     //  will be called to determine the location of this item.  The default
  1111.     //  implementation created from AppWizard simply returns a hard-coded
  1112.     //  rectangle.  Usually, this rectangle would reflect the current
  1113.     //  position of the item relative to the view used for activation.
  1114.     //  You can obtain the view by calling CTestContainer98Item::GetActiveView.
  1115.  
  1116.    rectPosition = m_rect;
  1117. }
  1118.  
  1119. void CTestContainer98Item::OnActivate()
  1120. {
  1121.    TCControlTrace( TRACELEVEL_NORMAL, this, "Activating control\n" );
  1122.  
  1123.    COleClientItem::OnActivate();
  1124.  
  1125.    UpdateStatusBar();
  1126. }
  1127.  
  1128. void CTestContainer98Item::OnActivateUI()
  1129. {
  1130.    CTestContainer98Item* pItem;
  1131.    CTestContainer98Doc* pDoc;
  1132.    POSITION posItem;
  1133.  
  1134.    TCControlTrace( TRACELEVEL_NORMAL, this, "UIActivating control\n" );
  1135.  
  1136.    // Allow only one UIActive item per frame.
  1137.    pDoc = GetDocument();
  1138.    posItem = pDoc->GetStartPosition();
  1139.    while( posItem != NULL )
  1140.    {
  1141.       pItem = (CTestContainer98Item*)pDoc->GetNextItem( posItem );
  1142.       if( pItem->IsUIActive() )
  1143.       {
  1144.          ASSERT( pItem != this );
  1145.          pItem->DeactivateUI();
  1146.       }
  1147.    }
  1148.  
  1149. //   GetActiveView()->SetSelection( this );
  1150.  
  1151.    COleClientItem::OnActivateUI();
  1152.  
  1153.    UpdateStatusBar();
  1154. }
  1155.  
  1156. void CTestContainer98Item::OnDeactivateUI( BOOL bUndoable )
  1157. {
  1158.    COleClientItem::OnDeactivateUI( bUndoable );
  1159.  
  1160.    TCControlTrace( TRACELEVEL_NORMAL, this, "UIDeactivating control\n" );
  1161.  
  1162.    // Also InPlaceDeactivate the object if it doesn't have the
  1163.    // ACTIVATEWHENVISIBLE flag set.
  1164.    if( !ShouldActivateWhenVisible() )
  1165.    {
  1166.       Close();
  1167.    }
  1168.  
  1169.    UpdateStatusBar();
  1170. }
  1171.  
  1172. BOOL CTestContainer98Item::ShouldActivateWhenVisible()
  1173. {
  1174.    DWORD dwMiscStatus;
  1175.  
  1176.    dwMiscStatus = 0;
  1177.    m_lpObject->GetMiscStatus( GetDrawAspect(), &dwMiscStatus );
  1178.  
  1179.    if( !(dwMiscStatus&OLEMISC_ACTIVATEWHENVISIBLE) )
  1180.    {
  1181.       return( FALSE );
  1182.    }
  1183.  
  1184.    if( (dwMiscStatus&OLEMISC_IGNOREACTIVATEWHENVISIBLE) &&
  1185.       (GetDocument()->HonorIgnoreActivateWhenVisible()) )
  1186.    {
  1187.       return( FALSE );
  1188.    }
  1189.  
  1190.    return( TRUE );
  1191. }
  1192.  
  1193. void CTestContainer98Item::Release( OLECLOSE dwCloseOption )
  1194. {
  1195.    UINT eState;
  1196.    IConnectionPointContainerPtr pConnectionPointContainer;
  1197.    HRESULT hResult;
  1198.  
  1199.    eState = GetItemState();
  1200.    if( (eState == activeUIState) || (eState == activeState) || (eState ==
  1201.       openState) )
  1202.    {
  1203.       Close( OLECLOSE_NOSAVE );
  1204.    }
  1205.  
  1206.    if( m_pDropTarget != NULL )
  1207.    {
  1208.       m_pDropTarget.Release();
  1209.    }
  1210.  
  1211.    if( m_pPointerInactive != NULL )
  1212.    {
  1213.       m_pPointerInactive.Release();
  1214.    }
  1215.  
  1216.    if( m_pOleInPlaceObjectWindowless != NULL )
  1217.    {
  1218.       m_pOleInPlaceObjectWindowless.Release();
  1219.    }
  1220.  
  1221.    if( m_pViewObjectEx != NULL )
  1222.    {
  1223.       m_pViewObjectEx.Release();
  1224.    }
  1225.  
  1226.    if( m_pOleControl != NULL )
  1227.    {
  1228.       m_pOleControl.Release();
  1229.    }
  1230.  
  1231.    if( m_pCtlDispatch != NULL )
  1232.    {
  1233.       m_pCtlDispatch.Release();
  1234.    }
  1235.  
  1236.    if( m_pExtendedControl != NULL )
  1237.    {
  1238.       // Salvage the display name from the extended control before it goes
  1239.       // away.
  1240.       m_strDisplayName = BSTR( m_pExtendedControl->Name );
  1241.       m_pExtendedControl.Release();
  1242.    }
  1243.  
  1244.    if( (m_lpObject != NULL) && ((m_dwEventCookie != 0) ||
  1245.       (m_dwPropertyCookie != 0)) )
  1246.    {
  1247.       m_lpObject->QueryInterface( IID_IConnectionPointContainer,
  1248.          (void**)&pConnectionPointContainer );
  1249.    }
  1250.  
  1251.    if( m_dwEventCookie != 0 )
  1252.    {
  1253.       if( m_pEventCP == NULL )
  1254.       {
  1255.          // We must have quick activated
  1256.          hResult = pConnectionPointContainer->FindConnectionPoint(
  1257.             m_infoEvents.GetIID(), &m_pEventCP );
  1258.          if( FAILED( hResult ) )
  1259.          {
  1260.             TCControlTrace( TRACELEVEL_NORMAL, this,
  1261.                "QuickActivated control connected to event sink, but doesn't support that connection point.\n" );
  1262.          }
  1263.       }
  1264.       if( m_pEventCP != NULL )
  1265.       {
  1266.          m_pEventCP->Unadvise( m_dwEventCookie );
  1267.          m_dwEventCookie = 0;
  1268.          m_pEventCP.Release();
  1269.       }
  1270.    }
  1271.  
  1272.    if( m_dwPropertyCookie != 0 )
  1273.    {
  1274.       if( m_pPropertyCP == NULL )
  1275.       {
  1276.          // We must have quick activated
  1277.          hResult = pConnectionPointContainer->FindConnectionPoint(
  1278.             IID_IPropertyNotifySink, &m_pPropertyCP );
  1279.          if( FAILED( hResult ) )
  1280.          {
  1281.             TCControlTrace( TRACELEVEL_NORMAL, this,
  1282.                "QuickActivated control connected to property notify sink, but doesn't support that connection point.\n" );
  1283.          }
  1284.       }
  1285.       if( m_pPropertyCP != NULL )
  1286.       {
  1287.          m_pPropertyCP->Unadvise( m_dwPropertyCookie );
  1288.          m_dwPropertyCookie = 0;
  1289.          m_pPropertyCP.Release();
  1290.       }
  1291.    }
  1292.  
  1293.    if( pConnectionPointContainer != NULL )
  1294.    {
  1295.       pConnectionPointContainer.Release();
  1296.    }
  1297.  
  1298.    COleClientItem::Release( dwCloseOption );
  1299.  
  1300.    CoFreeUnusedLibraries();
  1301. }
  1302.  
  1303. void CTestContainer98Item::CommitItem( BOOL bSuccess )
  1304. {
  1305.    IPersistStoragePtr pPersistStorage;
  1306.  
  1307.    if( !m_bNeedCommit )
  1308.    {
  1309.       return;
  1310.    }
  1311.  
  1312.    if( (m_lpNewStorage != NULL) && !bSuccess )
  1313.    {
  1314.       m_lpNewStorage->Release();
  1315.       m_lpNewStorage = NULL;
  1316.    }
  1317.  
  1318.    pPersistStorage = m_lpObject;
  1319.    // If the object doesn't support IPersistStorage, then we used
  1320.    // IPersistStreamInit in a stream inside the storage.
  1321.    if( pPersistStorage != NULL )
  1322.    {
  1323.       VERIFY( pPersistStorage->SaveCompleted( m_lpNewStorage ) == S_OK );
  1324.    }
  1325.  
  1326.    if( m_lpNewStorage != NULL )
  1327.    {
  1328.         m_lpStorage->Release();
  1329.         m_lpStorage = m_lpNewStorage;
  1330.         m_lpNewStorage = NULL;
  1331.    }
  1332.  
  1333.    m_bNeedCommit = FALSE;
  1334. }
  1335.  
  1336. void CTestContainer98Item::WriteItem( CArchive& ar )
  1337. {
  1338.    USES_CONVERSION;
  1339.    IStoragePtr pStorage;
  1340.    IStreamPtr pStream;
  1341.    IPersistStreamInitPtr pPSI;
  1342.    TCHAR szItemName[64];
  1343.    HRESULT hResult;
  1344.    IPersistStoragePtr pPersistStorage;
  1345.    CTestContainer98Doc* pDoc;
  1346.    CLSID clsid;
  1347.  
  1348.    (void)ar;
  1349.  
  1350.    pDoc = GetDocument();
  1351.    ASSERT_VALID( pDoc );
  1352.    ASSERT( pDoc->m_lpRootStg != NULL );
  1353.    ASSERT( pDoc->m_bCompoundFile );
  1354.    ASSERT( m_lpStorage != NULL );
  1355.    ASSERT( !ar.m_bForceFlat );
  1356.  
  1357.    GetItemName( szItemName );
  1358.  
  1359.    if( !pDoc->m_bSameAsLoad )
  1360.    {
  1361.       hResult = pDoc->m_lpRootStg->CreateStorage( T2COLE( szItemName ),
  1362.          STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE, 0, 0,
  1363.          &pStorage );
  1364.       if( FAILED( hResult ) )
  1365.       {
  1366.          AfxThrowOleException( hResult );
  1367.       }
  1368.       m_lpNewStorage = pStorage;
  1369.       m_lpNewStorage->AddRef();
  1370.       m_bNeedCommit = TRUE;
  1371.    }
  1372.    else
  1373.    {
  1374.       pStorage = m_lpStorage;
  1375.    }
  1376.  
  1377.    pPersistStorage = m_lpObject;
  1378.    if( pPersistStorage != NULL )
  1379.    {
  1380.       pPersistStorage->GetClassID( &clsid );
  1381.       hResult = WriteClassStg( pStorage, clsid );
  1382.       if( FAILED( hResult ) )
  1383.       {
  1384.          AfxThrowOleException( hResult );
  1385.       }
  1386.  
  1387.       hResult = pPersistStorage->Save( pStorage, pDoc->m_bSameAsLoad );
  1388.       if( FAILED( hResult ) )
  1389.       {
  1390.          AfxThrowOleException( hResult );
  1391.       }
  1392.    }
  1393.    else
  1394.    {
  1395.       pPSI = m_lpObject;
  1396.       if( pPSI == NULL )
  1397.       {
  1398.          AfxThrowOleException( E_NOINTERFACE );
  1399.       }
  1400.  
  1401.       // Set the storage's CLSID to CLSID_NULL, so we know that we actually
  1402.       // used a stream
  1403.       hResult = WriteClassStg( pStorage, CLSID_NULL );
  1404.       if( FAILED( hResult ) )
  1405.       {
  1406.          AfxThrowOleException( hResult );
  1407.       }
  1408.  
  1409.       hResult = pStorage->CreateStream( L"Contents", STGM_CREATE|
  1410.          STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &pStream );
  1411.       if( FAILED( hResult ) )
  1412.       {
  1413.          AfxThrowOleException( hResult );
  1414.       }
  1415.  
  1416.       pPSI->GetClassID( &clsid );
  1417.       hResult = WriteClassStm( pStream, clsid );
  1418.       if( FAILED( hResult ) )
  1419.       {
  1420.          AfxThrowOleException( hResult );
  1421.       }
  1422.  
  1423.       hResult = pPSI->Save( pStream, TRUE );
  1424.       if( FAILED( hResult ) )
  1425.       {
  1426.          AfxThrowOleException( hResult );
  1427.       }
  1428.  
  1429.       pStream.Release();
  1430.    }
  1431.  
  1432.    m_bNeedCommit = TRUE;
  1433.    pStorage->Commit( STGC_ONLYIFCURRENT );
  1434. }
  1435.  
  1436. void CTestContainer98Item::ReadItem( CArchive& ar )
  1437. {
  1438.     USES_CONVERSION;
  1439.    BOOL tUsedStream;
  1440.    IStoragePtr pStorage;
  1441.    IPersistStreamInitPtr pPSI;
  1442.    IStreamPtr pStream;
  1443.     TCHAR szItemName[64];
  1444.    HRESULT hResult;
  1445.    BOOL tQuickActivated;
  1446.    IPersistStoragePtr pPersistStorage;
  1447.    CLSID clsid;
  1448.  
  1449.    (void)ar;
  1450.  
  1451.     CTestContainer98Doc* pDoc = GetDocument();
  1452.     ASSERT_VALID(pDoc);
  1453.     ASSERT(pDoc->m_lpRootStg != NULL);
  1454.     ASSERT(pDoc->m_bCompoundFile);
  1455.     ASSERT(m_lpStorage == NULL);
  1456.     ASSERT(m_lpLockBytes == NULL);
  1457.    ASSERT( !ar.m_bForceFlat );
  1458.  
  1459.     // get item name
  1460.     GetItemName( szItemName );
  1461.  
  1462.     // open storage for this item
  1463.     hResult = pDoc->m_lpRootStg->OpenStorage( T2COLE( szItemName ), NULL,
  1464.         STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE, 0, 0, &pStorage );
  1465.     if( hResult != S_OK )
  1466.     {
  1467.         TRACE1( "Warning: unable to open child storage %s.\n", szItemName );
  1468.         // upon failure throw file exception (item will be cleaned up)
  1469.         AfxThrowOleException( hResult );
  1470.     }
  1471.     ASSERT(pStorage != NULL);
  1472.  
  1473.     // remember the storage
  1474.     m_lpStorage = pStorage;
  1475.     ASSERT(m_lpStorage != NULL);
  1476.    m_lpStorage->AddRef();
  1477.  
  1478.     // attempt to load the object from the storage
  1479.  
  1480.    hResult = ReadClassStg( m_lpStorage, &clsid );
  1481.    if( FAILED( hResult ) )
  1482.    {
  1483.       AfxThrowOleException( hResult );
  1484.    }
  1485.  
  1486.    tUsedStream = FALSE;
  1487.    if( clsid == CLSID_NULL )
  1488.    {
  1489.       hResult = m_lpStorage->OpenStream( L"Contents", NULL, STGM_READ|
  1490.          STGM_SHARE_EXCLUSIVE, 0, &pStream );
  1491.       if( FAILED( hResult ) )
  1492.       {
  1493.          AfxThrowOleException( hResult );
  1494.       }
  1495.  
  1496.       hResult = ReadClassStm( pStream, &clsid );
  1497.       if( FAILED( hResult ) )
  1498.       {
  1499.          AfxThrowOleException( hResult );
  1500.       }
  1501.  
  1502.       tUsedStream = TRUE;
  1503.    }
  1504.  
  1505.    m_tExtendedControl = TRUE;
  1506.    hResult = CExtendedControl::CreateInstance( clsid, this, NULL,
  1507.       IID_IOleObject, (void**)&m_lpObject );
  1508.    if( FAILED( hResult ) )
  1509.    {
  1510.       m_tExtendedControl = FALSE;
  1511.       // The control may not like being aggregated on, so just try to create it
  1512.       // directly and punt the extended control stuff.
  1513.       hResult = CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER|
  1514.         CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER, IID_IOleObject,
  1515.         (void**)&m_lpObject );
  1516.       if( SUCCEEDED( hResult ) )
  1517.       {
  1518.          TCControlTrace( TRACELEVEL_NORMAL, this,
  1519.             "Could not aggregate on the control, so it won't support extended properties.\n" );
  1520.       }
  1521.    }
  1522.    if( SUCCEEDED( hResult ) )
  1523.    {
  1524.       CString strUserType;
  1525.  
  1526.       GetUserType( USERCLASSTYPE_SHORT, strUserType );
  1527.       GetDocument()->CreateUniqueItemName( this, strUserType,
  1528.          m_strDisplayName );
  1529.    }
  1530.  
  1531.    if( m_tExtendedControl )
  1532.    {
  1533.       m_pExtendedControl = m_lpObject;
  1534.       ASSERT( m_pExtendedControl != NULL );
  1535.       m_pExtendedControl->Name = _bstr_t( m_strDisplayName );
  1536.    }
  1537.  
  1538.    if( SUCCEEDED( hResult ) )
  1539.    {
  1540.       hResult = InitControlInfo();
  1541.    }
  1542.  
  1543.    tQuickActivated = FALSE;
  1544.    if( SUCCEEDED( hResult ) )
  1545.    {
  1546.       tQuickActivated = QuickActivate();
  1547.  
  1548.       if( !tQuickActivated )
  1549.       {
  1550.          m_lpObject->GetMiscStatus( DVASPECT_CONTENT, &m_dwMiscStatus );
  1551.          if( m_dwMiscStatus&OLEMISC_SETCLIENTSITEFIRST )
  1552.          {
  1553.             hResult = m_lpObject->SetClientSite( GetClientSite() );
  1554.             if( FAILED( hResult ) )
  1555.             {
  1556.                TCControlTrace( TRACELEVEL_NORMAL, this,
  1557.                   "SetClientSite failed.\n" );
  1558.             }
  1559.          }
  1560.       }
  1561.    }
  1562.  
  1563.    if( SUCCEEDED( hResult ) )
  1564.    {
  1565.       pPersistStorage = m_lpObject;
  1566.       if( pPersistStorage != NULL )
  1567.       {
  1568.          hResult = pPersistStorage->Load( m_lpStorage );
  1569.       }
  1570.      else
  1571.      {
  1572.         if( !tUsedStream )
  1573.         {
  1574.            hResult = E_NOINTERFACE;
  1575.         }
  1576.         else
  1577.         {
  1578.            pPSI = m_lpObject;
  1579.            if( pPSI == NULL )
  1580.            {
  1581.               hResult = E_NOINTERFACE;
  1582.            }
  1583.            else
  1584.            {
  1585.               hResult = pPSI->Load( pStream );
  1586.            }
  1587.         }
  1588.      }
  1589.    }
  1590.  
  1591.    if( SUCCEEDED( hResult ) )
  1592.    {
  1593.       if( !tQuickActivated )
  1594.       {
  1595.          if( !(m_dwMiscStatus&OLEMISC_SETCLIENTSITEFIRST) )
  1596.          {
  1597.             hResult = m_lpObject->SetClientSite( GetClientSite() );
  1598.             if( FAILED( hResult ) )
  1599.             {
  1600.                TCControlTrace( TRACELEVEL_NORMAL, this,
  1601.                   "SetClientSite failed.\n" );
  1602.             }
  1603.          }
  1604.       }
  1605.    }
  1606.  
  1607.     CheckGeneral(hResult);
  1608. }
  1609.  
  1610. void CTestContainer98Item::CopyToClipboard( CArchive& ar, IStorage* pStorage )
  1611. {
  1612.    IPersistStoragePtr pPersistStorage;
  1613.    CLSID clsid;
  1614.    HRESULT hResult;
  1615.  
  1616.    ASSERT_VALID( this );
  1617.    ASSERT( ar.IsStoring() );
  1618.  
  1619.    ar<<GetDisplayName();
  1620.    ar<<m_rect;
  1621.  
  1622.    pPersistStorage = m_lpObject;
  1623.    if( pPersistStorage == NULL )
  1624.    {
  1625.       AfxThrowOleException( E_NOINTERFACE );
  1626.    }
  1627.  
  1628.    pPersistStorage->GetClassID( &clsid );
  1629.    hResult = WriteClassStg( pStorage, clsid );
  1630.    if( FAILED( hResult ) )
  1631.    {
  1632.       AfxThrowOleException( hResult );
  1633.    }
  1634.  
  1635.    hResult = pPersistStorage->Save( pStorage, FALSE );
  1636.    if( FAILED( hResult ) )
  1637.    {
  1638.       AfxThrowOleException( hResult );
  1639.    }
  1640.  
  1641.    hResult = pPersistStorage->SaveCompleted( NULL );
  1642.    if( FAILED( hResult ) )
  1643.    {
  1644.       AfxThrowOleException( hResult );
  1645.    }
  1646. }
  1647.  
  1648. void CTestContainer98Item::Serialize(CArchive& ar)
  1649. {
  1650.    CString strDisplayName;
  1651.  
  1652.     ASSERT_VALID( this );
  1653.  
  1654.    if( ar.IsStoring() )
  1655.    {
  1656.       ar<<m_rect;
  1657.       ar<<GetDisplayName();
  1658.    }
  1659.     else
  1660.     {
  1661.       ar>>m_rect;
  1662.       ar>>strDisplayName;
  1663.    }
  1664.  
  1665.     COleClientItem::Serialize( ar );
  1666.  
  1667.     if( !ar.IsStoring() )
  1668.     {
  1669.       if( m_pExtendedControl != NULL )
  1670.       {
  1671.          m_pExtendedControl->Name = _bstr_t( strDisplayName );
  1672.       }
  1673.     }
  1674. }
  1675.  
  1676. /////////////////////////////////////////////////////////////////////////////
  1677. // CTestContainer98Item diagnostics
  1678.  
  1679. #ifdef _DEBUG
  1680. void CTestContainer98Item::AssertValid() const
  1681. {
  1682.     COleClientItem::AssertValid();
  1683. }
  1684.  
  1685. void CTestContainer98Item::Dump(CDumpContext& dc) const
  1686. {
  1687.     COleClientItem::Dump(dc);
  1688. }
  1689. #endif
  1690.  
  1691. /////////////////////////////////////////////////////////////////////////////
  1692.  
  1693. IBindHost* CTestContainer98Item::GetBindHost()
  1694. {
  1695.    HRESULT hResult;
  1696.  
  1697.    if( m_pBindHost == NULL )
  1698.    {
  1699.       hResult = CTCBindHost::CreateInstance( IID_IBindHost,
  1700.          (void**)&m_pBindHost );
  1701.       if( FAILED( hResult ) )
  1702.       {
  1703.          return( NULL );
  1704.       }
  1705.    }
  1706.    ASSERT( m_pBindHost != NULL );
  1707.  
  1708.    return( m_pBindHost );
  1709. }
  1710.  
  1711. CInterfaceInfo* CTestContainer98Item::GetEventInfo()
  1712. {
  1713.    return( &m_infoEvents );
  1714. }
  1715.  
  1716. CInterfaceInfo* CTestContainer98Item::GetMethodInfo()
  1717. {
  1718.    return( &m_infoMethods );
  1719. }
  1720.  
  1721. void CTestContainer98Item::OnEvent( DISPID dispid, DISPPARAMS* pdpParams )
  1722. {
  1723.    CMethodInfo* pEventInfo;
  1724.    CLog* pLog;
  1725.  
  1726.    m_dispidEvent = dispid;
  1727.    CopyParams( pdpParams );
  1728.  
  1729.    pLog = GetDocument()->GetLog();
  1730.    if( pLog != NULL )
  1731.    {
  1732.       // Find the event.
  1733.       pEventInfo = m_infoEvents.FindMethod( m_dispidEvent );
  1734.       if( pEventInfo == NULL )
  1735.       {
  1736.          (*pLog)<<GetDisplayName()<<_T( ": Unknown event (DISPID=" )<<dispid<<
  1737.             _T( ")\n" );
  1738.       }
  1739.       else
  1740.       {
  1741.          if( pEventInfo->IsLogged() )
  1742.          {
  1743.             (*pLog)<<GetDisplayName()<<_T( ": " );
  1744.             pEventInfo->LogEvent( *pLog, pdpParams );
  1745.          }
  1746.       }
  1747.    }
  1748. }
  1749.  
  1750. void CTestContainer98Item::UpdateFromServerExtent()
  1751. {
  1752.    CSize size;
  1753.  
  1754.    if( GetCachedExtent( &size ) )
  1755.    {
  1756.       // OLE returns the extent in HIMETRIC units -- we need pixels.
  1757.       CClientDC dc( NULL );
  1758.       dc.HIMETRICtoDP( &size );
  1759.  
  1760.       // Only invalidate if it has actually changed and also only if it is not
  1761.       // in-place active.
  1762.       if( (size != m_rect.Size()) && !IsInPlaceActive() )
  1763.       {
  1764.          // Invalidate old, update, invalidate new.
  1765.          InvalidateItem();
  1766.          m_rect.bottom = m_rect.top+size.cy;
  1767.          m_rect.right = m_rect.left+size.cx;
  1768.          InvalidateItem();
  1769.  
  1770.          // mark document as modified.
  1771.          GetDocument()->SetModifiedFlag();
  1772.       }
  1773.    }
  1774. }
  1775.  
  1776. void CTestContainer98Item::InvalidateItem()
  1777. {
  1778.    GetDocument()->UpdateAllViews( NULL, HINT_UPDATE_ITEM, this );
  1779. }
  1780.  
  1781. void CTestContainer98Item::SetLoggingOptions()
  1782. {
  1783.    CMethodInfo* pMethod;
  1784.    int iMethod;
  1785.    int iRequestEditProperty;
  1786.    int iBindableProperty;
  1787.    int nResult;
  1788.    CEventLoggingPage pageEventLogging;
  1789.    CPropertyChangesPage pagePropertyChanges;
  1790.    CPropertyEditRequestsPage pageEditRequests;
  1791.    CPropertySheet sheet( IDS_CONTROLLOGGINGOPTIONS );
  1792.  
  1793.    for( iMethod = 0; iMethod < m_infoEvents.GetNumMethods(); iMethod++ )
  1794.    {
  1795.       pMethod = m_infoEvents.GetMethod( iMethod );
  1796.       pageEventLogging.m_astrEventNames.Add( pMethod->GetName() );
  1797.       pageEventLogging.m_atLogFlags.Add( pMethod->IsLogged() );
  1798.    }
  1799.  
  1800.    for( iMethod = 0; iMethod < m_infoMethods.GetNumMethods(); iMethod++ )
  1801.    {
  1802.       pMethod = m_infoMethods.GetMethod( iMethod );
  1803.       if( pMethod->GetInvokeKind() == INVOKE_PROPERTYGET )
  1804.       {
  1805.          if( pMethod->IsBindable() )
  1806.          {
  1807.             pagePropertyChanges.m_astrPropertyNames.Add( pMethod->GetName() );
  1808.             pagePropertyChanges.m_atLogFlags.Add( pMethod->IsLogged() );
  1809.          }
  1810.          if( pMethod->RequestsEdit() )
  1811.          {
  1812.             CPropertyEditRequestsPage::CPropertyInfo info( pMethod->GetName(),
  1813.                pMethod->LogEditRequests(), pMethod->GetRequestEditResponse() );
  1814.  
  1815.             pageEditRequests.m_aProperties.Add( info );
  1816.          }
  1817.       }
  1818.    }
  1819.  
  1820.    sheet.AddPage( &pageEventLogging );
  1821.    sheet.AddPage( &pagePropertyChanges );
  1822.    sheet.AddPage( &pageEditRequests );
  1823.  
  1824.    sheet.m_psh.dwFlags &= ~PSH_HASHELP;
  1825.    sheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;
  1826.    nResult = sheet.DoModal();
  1827.    if( nResult != IDOK )
  1828.    {
  1829.       return;
  1830.    }
  1831.  
  1832.    for( iMethod = 0; iMethod < m_infoEvents.GetNumMethods(); iMethod++ )
  1833.    {
  1834.       pMethod = m_infoEvents.GetMethod( iMethod );
  1835.       pMethod->EnableLogging( pageEventLogging.m_atLogFlags[iMethod] );
  1836.    }
  1837.  
  1838.    iBindableProperty = 0;
  1839.    iRequestEditProperty = 0;
  1840.    for( iMethod = 0; iMethod < m_infoMethods.GetNumMethods(); iMethod++ )
  1841.    {
  1842.       pMethod = m_infoMethods.GetMethod( iMethod );
  1843.       if( pMethod->GetInvokeKind() == INVOKE_PROPERTYGET )
  1844.       {
  1845.          if( pMethod->IsBindable() )
  1846.          {
  1847.             pMethod->EnableLogging(
  1848.                pagePropertyChanges.m_atLogFlags[iBindableProperty] );
  1849.             iBindableProperty++;
  1850.          }
  1851.          if( pMethod->RequestsEdit() )
  1852.          {
  1853.             pMethod->EnableEditRequestLogging( pageEditRequests.m_aProperties[
  1854.                iRequestEditProperty].m_tLogged );
  1855.             pMethod->SetRequestEditResponse( pageEditRequests.m_aProperties[
  1856.                iRequestEditProperty].m_iResponse );
  1857.             iRequestEditProperty++;
  1858.          }
  1859.       }
  1860.    }
  1861. }
  1862.  
  1863. void CTestContainer98Item::InvokeMethods()
  1864. {
  1865.    HRESULT hResult;
  1866.    IDispatchPtr pDispatch;
  1867.  
  1868.    if( GetMethodInfo()->GetNumMethods() == 0 )
  1869.    {
  1870.       AfxMessageBox( IDS_CONTROLHASNOMETHODS );
  1871.       return;
  1872.    }
  1873.  
  1874.    hResult = m_lpObject->QueryInterface( IID_IDispatch, (void**)&pDispatch );
  1875.    if( FAILED( hResult ) )
  1876.    {
  1877.       TCControlTrace( TRACELEVEL_NORMAL, this,
  1878.          "Failed to get object's primary IDispatch interface.\n" );
  1879.       return;
  1880.    }
  1881.  
  1882.    CMethodDlg dlg( NULL, pDispatch, &m_infoMethods );
  1883.  
  1884.    dlg.DoModal();
  1885. }
  1886.  
  1887. void CTestContainer98Item::OnFocus( BOOL tGotFocus )
  1888. {
  1889.    if( tGotFocus )
  1890.    {
  1891.       TCControlTrace( TRACELEVEL_NORMAL, this, "Control got focus\n" );
  1892.    }
  1893.    else
  1894.    {
  1895.       TCControlTrace( TRACELEVEL_NORMAL, this, "Control lost focus\n" );
  1896.    }
  1897.  
  1898.    GetActiveView()->OnFocus( this, tGotFocus );
  1899. }
  1900.  
  1901. BEGIN_INTERFACE_MAP( CTestContainer98Item, COleClientItem )
  1902.    INTERFACE_PART( CTestContainer98Item, IID_IServiceProvider,
  1903.       ServiceProvider )
  1904.    INTERFACE_PART( CTestContainer98Item, IID_IPropertyNotifySink,
  1905.       PropertyNotifySink )
  1906.    INTERFACE_PART( CTestContainer98Item, IID_IDispatch, AmbientProperties )
  1907.    INTERFACE_PART( CTestContainer98Item, IID_IOleControlSite, OleControlSite )
  1908. //   INTERFACE_PART( CTestContainer98Item, IID_IOleInPlaceSiteEx,
  1909. //      OleInPlaceSiteWindowless )
  1910. //   INTERFACE_PART( CTestContainer98Item, IID_IOleInPlaceSiteWindowless,
  1911. //      OleInPlaceSiteWindowless )
  1912. END_INTERFACE_MAP()
  1913.  
  1914.  
  1915. ///////////////////////////////////////////////////////////////////////////////
  1916. // CTestContainer98Item::XOleControlSite
  1917. ///////////////////////////////////////////////////////////////////////////////
  1918.  
  1919. STDMETHODIMP_( ULONG ) CTestContainer98Item::XOleControlSite::AddRef()
  1920. {
  1921.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1922.  
  1923.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XOleControlSite::AddRef().\n" );
  1924.  
  1925.    return( pThis->ExternalAddRef() );
  1926. }
  1927.  
  1928. STDMETHODIMP_( ULONG ) CTestContainer98Item::XOleControlSite::Release()
  1929. {
  1930.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1931.  
  1932.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XOleControlSite::Release().\n" );
  1933.  
  1934.    return( pThis->ExternalRelease() );
  1935. }
  1936.  
  1937. STDMETHODIMP CTestContainer98Item::XOleControlSite::QueryInterface( REFIID iid,
  1938.    LPVOID* ppvObj)
  1939. {
  1940.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1941.  
  1942.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  1943. }
  1944.  
  1945. STDMETHODIMP CTestContainer98Item::XOleControlSite::GetExtendedControl(
  1946.    IDispatch** ppExtendedControl )
  1947. {
  1948.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1949.  
  1950.    if( ppExtendedControl == NULL )
  1951.    {
  1952.       return( E_POINTER );
  1953.    }
  1954.  
  1955.    *ppExtendedControl = pThis->m_pExtendedControl;
  1956.    if( *ppExtendedControl == NULL )
  1957.    {
  1958.       return( E_NOTIMPL );
  1959.    }
  1960.    else
  1961.    {
  1962.       (*ppExtendedControl)->AddRef();
  1963.    }
  1964.  
  1965.    return( S_OK );
  1966. }
  1967.  
  1968. STDMETHODIMP CTestContainer98Item::XOleControlSite::LockInPlaceActive(
  1969.    BOOL tLock )
  1970. {
  1971.    (void)tLock;
  1972.  
  1973.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1974.  
  1975.    return( E_NOTIMPL );
  1976. }
  1977.  
  1978. STDMETHODIMP CTestContainer98Item::XOleControlSite::OnControlInfoChanged()
  1979. {
  1980.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1981.  
  1982.    return( E_NOTIMPL );
  1983. }
  1984.  
  1985. STDMETHODIMP CTestContainer98Item::XOleControlSite::OnFocus( BOOL tGotFocus )
  1986. {
  1987.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  1988.  
  1989.    pThis->OnFocus( tGotFocus );
  1990.  
  1991.    return( S_OK );
  1992. }
  1993.  
  1994. STDMETHODIMP CTestContainer98Item::XOleControlSite::ShowPropertyFrame()
  1995. {
  1996.    USES_CONVERSION;
  1997.    HRESULT hResult;
  1998.    ISpecifyPropertyPagesPtr pSpecify;
  1999.    CAUUID pages;
  2000.    CLSID* pclsidPages;
  2001.    ULONG nPages;
  2002.    ULONG iPage;
  2003.    IUnknown* pControl;
  2004.    CString strDisplayName;
  2005.  
  2006.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  2007.  
  2008.    pControl = pThis->m_lpObject;
  2009.    pSpecify = pControl;
  2010.    if( pSpecify == NULL )
  2011.    {
  2012.       return( E_NOINTERFACE );
  2013.    }
  2014.  
  2015.    pages.cElems = 0;
  2016.    pages.pElems = NULL;
  2017.    hResult = pSpecify->GetPages( &pages );
  2018.    if( FAILED( hResult ) )
  2019.    {
  2020.       return( hResult );
  2021.    }
  2022.  
  2023.    nPages = pages.cElems;
  2024.    if( pThis->m_pExtendedControl != NULL )
  2025.    {
  2026.       nPages++;
  2027.    }
  2028.  
  2029.    pclsidPages = (CLSID*)_alloca( nPages*sizeof( CLSID ) );
  2030.    for( iPage = 0; iPage < pages.cElems; iPage++ )
  2031.    {
  2032.       pclsidPages[iPage] = pages.pElems[iPage];
  2033.    }
  2034.    if( pThis->m_pExtendedControl != NULL )
  2035.    {
  2036.       pclsidPages[nPages-1] = __uuidof( TCExtPage );
  2037.    }
  2038.    CoTaskMemFree( pages.pElems );
  2039.  
  2040.    strDisplayName = pThis->GetDisplayName();
  2041.    hResult = OleCreatePropertyFrame( AfxGetMainWnd()->m_hWnd, 0, 0,
  2042.       T2COLE( strDisplayName ), 1, &pControl, nPages, pclsidPages,
  2043.       GetUserDefaultLCID(), 0, NULL );
  2044.    if( FAILED( hResult ) )
  2045.    {
  2046.       return( hResult );
  2047.    }
  2048.  
  2049.    //WINBUG: OleCreatePropertyFrame doesn't return focus to its parent when it
  2050.    // closes
  2051.    pThis->GetDocument()->GetView()->SetFocus();
  2052.  
  2053.    return( S_OK );
  2054. }
  2055.  
  2056. STDMETHODIMP CTestContainer98Item::XOleControlSite::TransformCoords(
  2057.    POINTL* pptHiMetric, POINTF* pptContainer, DWORD dwFlags )
  2058. {
  2059.    (void)pptHiMetric;
  2060.    (void)pptContainer;
  2061.    (void)dwFlags;
  2062.  
  2063.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  2064.  
  2065.    return( E_NOTIMPL );
  2066. }
  2067.  
  2068. STDMETHODIMP CTestContainer98Item::XOleControlSite::TranslateAccelerator(
  2069.    LPMSG pMessage, DWORD dwModifiers )
  2070. {
  2071.    (void)pMessage;
  2072.    (void)dwModifiers;
  2073.  
  2074.    METHOD_PROLOGUE( CTestContainer98Item, OleControlSite )
  2075.  
  2076.    return( E_NOTIMPL );
  2077. }
  2078.  
  2079.  
  2080. ///////////////////////////////////////////////////////////////////////////////
  2081. // CTestContainer98Item::XServiceProvider
  2082. ///////////////////////////////////////////////////////////////////////////////
  2083.  
  2084. STDMETHODIMP_( ULONG ) CTestContainer98Item::XServiceProvider::AddRef()
  2085. {
  2086.    METHOD_PROLOGUE( CTestContainer98Item, ServiceProvider )
  2087.  
  2088.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XServiceProvider::AddRef()\n" );
  2089.  
  2090.    return( pThis->ExternalAddRef() );
  2091. }
  2092.  
  2093. STDMETHODIMP_( ULONG ) CTestContainer98Item::XServiceProvider::Release()
  2094. {
  2095.    METHOD_PROLOGUE( CTestContainer98Item, ServiceProvider )
  2096.  
  2097.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XServiceProvider::Release()\n" );
  2098.  
  2099.    return( pThis->ExternalRelease() );
  2100. }
  2101.  
  2102. STDMETHODIMP CTestContainer98Item::XServiceProvider::QueryInterface(
  2103.    REFIID iid, LPVOID* ppvObj)
  2104. {
  2105.    METHOD_PROLOGUE( CTestContainer98Item, ServiceProvider )
  2106.  
  2107.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  2108. }
  2109.  
  2110. STDMETHODIMP CTestContainer98Item::XServiceProvider::QueryService(
  2111.    REFGUID guidService, REFIID iid, void** ppService )
  2112. {
  2113.    IBindHost* pBindHost;
  2114.  
  2115.    METHOD_PROLOGUE( CTestContainer98Item, ServiceProvider );
  2116.  
  2117.    if( ppService == NULL )
  2118.    {
  2119.       return( E_POINTER );
  2120.    }
  2121.    *ppService = NULL;
  2122.  
  2123.    if( IsEqualGUID( guidService, SID_SBindHost ) )
  2124.    {
  2125.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2126.          "QueryService for SID_SBindHost\n" );
  2127.       if( !pThis->GetDocument()->SupportsService( guidService ) )
  2128.       {
  2129.          return( E_NOINTERFACE );
  2130.       }
  2131.       pBindHost = pThis->GetBindHost();
  2132.       if( pBindHost == NULL )
  2133.       {
  2134.          return( E_NOINTERFACE );
  2135.       }
  2136.       else
  2137.       {
  2138.          return( pBindHost->QueryInterface( iid, ppService ) );
  2139.       }
  2140.    }
  2141.    else
  2142.    {
  2143.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2144.          "QueryService for unknown service\n" );
  2145.       return( E_NOINTERFACE );
  2146.    }
  2147. }
  2148.  
  2149. ///////////////////////////////////////////////////////////////////////////////
  2150. // CTestContainer98Item::XEventHandler
  2151. ///////////////////////////////////////////////////////////////////////////////
  2152.  
  2153. STDMETHODIMP_( ULONG ) CTestContainer98Item::XEventHandler::AddRef()
  2154. {
  2155.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2156.  
  2157.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XEventHandler::AddRef()\n" );
  2158.  
  2159.    return( pThis->ExternalAddRef() );
  2160. }
  2161.  
  2162. STDMETHODIMP_( ULONG ) CTestContainer98Item::XEventHandler::Release()
  2163. {
  2164.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2165.  
  2166.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XEventHandler::Release()\n" );
  2167.  
  2168.    return( pThis->ExternalRelease() );
  2169. }
  2170.  
  2171. STDMETHODIMP CTestContainer98Item::XEventHandler::QueryInterface( REFIID iid,
  2172.    LPVOID* ppvObj)
  2173. {
  2174.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2175.  
  2176.    if( IsEqualIID( iid, IID_IDispatch ) )
  2177.    {
  2178.       // QI'ing for IID_IDispatch will get you the default dispinterface on an
  2179.       // object.  In the case of the control site, that would be the ambient
  2180.       // properties dispinterface.  Since the control's event sink connection
  2181.       // point is exposed not as IID_IDispatch, but rather as the IID of the
  2182.       // control's event dispinterface,
  2183.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2184.          "Warning: QI for IID_IDispatch on event handler interface.\n"
  2185.          "\tDid you really mean to QI for your specific event interface?\n" );
  2186.    }
  2187.  
  2188.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  2189. }
  2190.  
  2191. STDMETHODIMP CTestContainer98Item::XEventHandler::GetIDsOfNames( REFIID iid,
  2192.    LPOLESTR* ppszNames, UINT nNames, LCID lcid, DISPID* pDispIDs )
  2193. {
  2194.    (void)iid;
  2195.    (void)ppszNames;
  2196.    (void)nNames;
  2197.    (void)lcid;
  2198.    (void)pDispIDs;
  2199.  
  2200.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2201.    ASSERT_VALID( pThis );
  2202.  
  2203.    return( E_NOTIMPL );
  2204. }
  2205.  
  2206. STDMETHODIMP CTestContainer98Item::XEventHandler::GetTypeInfo( UINT iTypeInfo,
  2207.    LCID lcid, ITypeInfo** ppTypeInfo )
  2208. {
  2209.    (void)iTypeInfo;
  2210.    (void)lcid;
  2211.    (void)ppTypeInfo;
  2212.  
  2213.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2214.    ASSERT_VALID( pThis );
  2215.  
  2216.    return( E_NOTIMPL );
  2217. }
  2218.  
  2219. STDMETHODIMP CTestContainer98Item::XEventHandler::GetTypeInfoCount(
  2220.    UINT* pnInfoCount )
  2221. {
  2222.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2223.    ASSERT_VALID( pThis );
  2224.  
  2225.    *pnInfoCount = 0;
  2226.  
  2227.    return( S_OK );
  2228. }
  2229.  
  2230. STDMETHODIMP CTestContainer98Item::XEventHandler::Invoke( DISPID dispidMember,
  2231.    REFIID iid, LCID lcid, USHORT wFlags, DISPPARAMS* pdpParams,
  2232.    VARIANT* pvarResult, EXCEPINFO* pExceptionInfo, UINT* piArgErr )
  2233. {
  2234.    (void)iid;
  2235.    (void)lcid;
  2236.    (void)wFlags;
  2237.    (void)pvarResult;
  2238.    (void)pExceptionInfo;
  2239.    (void)piArgErr;
  2240.  
  2241.    METHOD_PROLOGUE( CTestContainer98Item, EventHandler )
  2242.    ASSERT_VALID( pThis );
  2243.  
  2244.    pThis->OnEvent( dispidMember, pdpParams );  // Call the event handler, who
  2245.       // also cleans up.
  2246.  
  2247.    return( S_OK );
  2248. }
  2249.  
  2250.  
  2251. ///////////////////////////////////////////////////////////////////////////////
  2252. // CTestContainer98Item::XAmbientProperties
  2253. ///////////////////////////////////////////////////////////////////////////////
  2254.  
  2255. STDMETHODIMP_( ULONG ) CTestContainer98Item::XAmbientProperties::AddRef()
  2256. {
  2257.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2258.  
  2259.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2260.       "XAmbientProperties::AddRef().\n" );
  2261.  
  2262.    return( pThis->ExternalAddRef() );
  2263. }
  2264.  
  2265. STDMETHODIMP_( ULONG ) CTestContainer98Item::XAmbientProperties::Release()
  2266. {
  2267.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2268.  
  2269.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2270.       "XAmbientProperties::Release().\n" );
  2271.  
  2272.    return( pThis->ExternalRelease() );
  2273. }
  2274.  
  2275. STDMETHODIMP CTestContainer98Item::XAmbientProperties::QueryInterface(
  2276.    REFIID iid, LPVOID* ppvObj)
  2277. {
  2278.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2279.  
  2280.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  2281. }
  2282.  
  2283. STDMETHODIMP CTestContainer98Item::XAmbientProperties::GetIDsOfNames(
  2284.    REFIID iid, LPOLESTR* ppszNames, UINT nNames, LCID lcid, DISPID* pDispIDs )
  2285. {
  2286.    CTestContainer98Doc* pDoc;
  2287.    CAmbientProperty* pProp;
  2288.    UINT iName;
  2289.    HRESULT hResult;
  2290.  
  2291.    (void)lcid;
  2292.  
  2293.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2294.    ASSERT_VALID( pThis );
  2295.  
  2296.    if( !IsEqualIID( iid, IID_NULL ) )
  2297.    {
  2298.       return( E_INVALIDARG );
  2299.    }
  2300.    if( ppszNames == NULL )
  2301.    {
  2302.       return( E_INVALIDARG );
  2303.    }
  2304.    if( nNames < 1 )
  2305.    {
  2306.       return( E_INVALIDARG );
  2307.    }
  2308.    if( pDispIDs == NULL )
  2309.    {
  2310.       return( E_POINTER );
  2311.    }
  2312.  
  2313.    hResult = S_OK;
  2314.    pDoc = pThis->GetDocument();
  2315.    pProp = pDoc->FindAmbientProperty( ppszNames[0] );
  2316.    if( pProp == NULL )
  2317.    {
  2318.       pDispIDs[0] = DISPID_UNKNOWN;
  2319.       hResult = DISP_E_UNKNOWNNAME;
  2320.    }
  2321.  
  2322.    pDispIDs[0] = pProp->GetID();
  2323.  
  2324.    if( nNames > 1 )
  2325.    {
  2326.       for( iName = 1; iName < nNames; iName++ )
  2327.       {
  2328.          pDispIDs[iName] = DISPID_UNKNOWN;
  2329.       }
  2330.       hResult = DISP_E_UNKNOWNNAME;
  2331.    }
  2332.  
  2333.    return( hResult );
  2334. }
  2335.  
  2336. STDMETHODIMP CTestContainer98Item::XAmbientProperties::GetTypeInfo(
  2337.    UINT iTypeInfo, LCID lcid, ITypeInfo** ppTypeInfo )
  2338. {
  2339.    (void)iTypeInfo;
  2340.    (void)lcid;
  2341.    (void)ppTypeInfo;
  2342.  
  2343.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2344.    ASSERT_VALID( pThis );
  2345.  
  2346.    return( E_NOTIMPL );
  2347. }
  2348.  
  2349. STDMETHODIMP CTestContainer98Item::XAmbientProperties::GetTypeInfoCount(
  2350.    UINT* pnInfoCount )
  2351. {
  2352.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2353.    ASSERT_VALID( pThis );
  2354.  
  2355.    *pnInfoCount = 0;
  2356.  
  2357.    return( S_OK );
  2358. }
  2359.  
  2360. STDMETHODIMP CTestContainer98Item::XAmbientProperties::Invoke(
  2361.    DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags,
  2362.    DISPPARAMS* pdpParams, VARIANT* pvarResult, EXCEPINFO* pExceptionInfo,
  2363.    UINT* piArgErr )
  2364. {
  2365.    CTestContainer98Doc* pDoc;
  2366.    CAmbientProperty* pProp;
  2367.    HRESULT hResult;
  2368.    COleVariant varValue;
  2369.  
  2370.    (void)iid;
  2371.    (void)lcid;
  2372.    (void)wFlags;
  2373.    (void)pdpParams;
  2374.    (void)pExceptionInfo;
  2375.    (void)piArgErr;
  2376.  
  2377.    METHOD_PROLOGUE( CTestContainer98Item, AmbientProperties )
  2378.    ASSERT_VALID( pThis );
  2379.  
  2380.    if( dispidMember == DISPID_AMBIENT_DISPLAYASDEFAULT )
  2381.    {
  2382.       VariantClear( pvarResult );
  2383.       pvarResult->vt = VT_BOOL;
  2384.       if( pThis->m_tDisplayAsDefault )
  2385.       {
  2386.          pvarResult->boolVal = VAR_TRUE;
  2387.       }
  2388.       else
  2389.       {
  2390.          pvarResult->boolVal = VAR_FALSE;
  2391.       }
  2392.  
  2393.       return( S_OK );
  2394.    }
  2395.  
  2396.    pDoc = pThis->GetDocument();
  2397.  
  2398.    pProp = pDoc->FindAmbientProperty( dispidMember );
  2399.    if( pProp == NULL )
  2400.    {
  2401.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2402.          "Control asked for unknown ambient property.  DISPID=%d\n",
  2403.          dispidMember );
  2404.       return( DISP_E_MEMBERNOTFOUND );
  2405.    }
  2406.  
  2407.    if( !pProp->IsEnabled() )
  2408.    {
  2409.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2410.          "Control asked for ambient property %s, but the property was disabled.\n",
  2411.          LPCTSTR( pProp->GetName() ) );
  2412.       return( DISP_E_MEMBERNOTFOUND );
  2413.    }
  2414.  
  2415.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2416.       "Control got ambient property %s.\n", LPCTSTR( pProp->GetName() ) );
  2417.  
  2418.    varValue = pProp->GetValue();
  2419.    hResult = VariantCopy( pvarResult, &varValue );
  2420.    if( FAILED( hResult ) )
  2421.    {
  2422.       return( hResult );
  2423.    }
  2424.  
  2425.    return( S_OK );
  2426. }
  2427.  
  2428.  
  2429. ///////////////////////////////////////////////////////////////////////////////
  2430. // CTestContainer98Item::XPropertyNotifySink
  2431. ///////////////////////////////////////////////////////////////////////////////
  2432.  
  2433. STDMETHODIMP_( ULONG ) CTestContainer98Item::XPropertyNotifySink::AddRef()
  2434. {
  2435.    METHOD_PROLOGUE( CTestContainer98Item, PropertyNotifySink )
  2436.  
  2437.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2438.       "XPropertyNotifySink::AddRef().\n" );
  2439.  
  2440.    return( pThis->ExternalAddRef() );
  2441. }
  2442.  
  2443. STDMETHODIMP_( ULONG ) CTestContainer98Item::XPropertyNotifySink::Release()
  2444. {
  2445.    METHOD_PROLOGUE( CTestContainer98Item, PropertyNotifySink )
  2446.  
  2447.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  2448.       "XPropertyNotifySink::Release().\n" );
  2449.  
  2450.    return( pThis->ExternalRelease() );
  2451. }
  2452.  
  2453. STDMETHODIMP CTestContainer98Item::XPropertyNotifySink::QueryInterface(
  2454.    REFIID iid, LPVOID* ppvObj )
  2455. {
  2456.    METHOD_PROLOGUE( CTestContainer98Item, PropertyNotifySink )
  2457.  
  2458.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  2459. }
  2460.  
  2461. STDMETHODIMP CTestContainer98Item::XPropertyNotifySink::OnChanged(
  2462.    DISPID dispid )
  2463. {
  2464.    CMethodInfo* pPropertyInfo;
  2465.    CLog* pLog;
  2466.  
  2467.    METHOD_PROLOGUE( CTestContainer98Item, PropertyNotifySink )
  2468.  
  2469.    pLog = pThis->GetDocument()->GetLog();
  2470.    if( pLog != NULL )
  2471.    {
  2472.       pPropertyInfo = pThis->m_infoMethods.FindPropertyGet( dispid );
  2473.       if( pPropertyInfo == NULL )
  2474.       {
  2475.          (*pLog)<<pThis->GetDisplayName()<<_T(
  2476.             ": Property Change: Unknown property (DISPID=" )<<dispid<<_T(
  2477.             ")\n" );
  2478.       }
  2479.       else
  2480.       {
  2481.          if( pPropertyInfo->IsLogged() )
  2482.          {
  2483.             (*pLog)<<pThis->GetDisplayName()<<_T( ": Property Change: " )<<
  2484.                pPropertyInfo->GetName()<<_T( "\n" );
  2485.          }
  2486.       }
  2487.     }
  2488.  
  2489.    return( S_OK );
  2490. }
  2491.  
  2492. STDMETHODIMP CTestContainer98Item::XPropertyNotifySink::OnRequestEdit(
  2493.    DISPID dispid )
  2494. {
  2495.    CMethodInfo* pPropertyInfo;
  2496.    CLog* pLog;
  2497.    CString strFormat;
  2498.    CString strPrompt;
  2499.    CString strUserType;
  2500.    int nResult;
  2501.    HRESULT hrResponse = S_FALSE;
  2502.  
  2503.    METHOD_PROLOGUE( CTestContainer98Item, PropertyNotifySink )
  2504.  
  2505.    pPropertyInfo = pThis->m_infoMethods.FindMethod( dispid );
  2506.    if( pPropertyInfo == NULL )
  2507.    {
  2508.       hrResponse = S_OK;
  2509.    }
  2510.    else
  2511.    {
  2512.       switch( pPropertyInfo->GetRequestEditResponse() )
  2513.       {
  2514.       case REQUESTEDIT_ALWAYS:
  2515.          hrResponse = S_OK;
  2516.          break;
  2517.  
  2518.       case REQUESTEDIT_NEVER:
  2519.          hrResponse = S_FALSE;
  2520.          break;
  2521.  
  2522.       case REQUESTEDIT_PROMPT:
  2523.          AfxFormatString2( strPrompt, IDS_PROPERTYEDITREQUESTFORMAT,
  2524.             pPropertyInfo->GetName(), pThis->GetDisplayName() );
  2525.          nResult = AfxMessageBox( strPrompt, MB_YESNO );
  2526.          if( nResult == IDYES )
  2527.          {
  2528.             hrResponse = S_OK;
  2529.          }
  2530.          else
  2531.          {
  2532.             hrResponse = S_FALSE;
  2533.          }
  2534.          break;
  2535.  
  2536.       default:
  2537.          ASSERT( FALSE );
  2538.          break;
  2539.       }
  2540.    }
  2541.  
  2542.    pLog = pThis->GetDocument()->GetLog();
  2543.    if( pLog != NULL )
  2544.    {
  2545.       if( pPropertyInfo == NULL )
  2546.       {
  2547.          (*pLog)<<pThis->GetDisplayName()<<_T(
  2548.             "Property Edit Request: Unknown property (DISPID=" )<<dispid<<_T(
  2549.             ")\n" );
  2550.       }
  2551.       else
  2552.       {
  2553.          if( pPropertyInfo->LogEditRequests() )
  2554.          {
  2555.             (*pLog)<<pThis->GetDisplayName()<<_T(
  2556.                ": Property Edit Request: " )<<pPropertyInfo->GetName()<<_T(
  2557.                " (" );
  2558.             if( hrResponse == S_OK )
  2559.             {
  2560.                (*pLog)<<_T( "Allowed)\n" );
  2561.             }
  2562.             else
  2563.             {
  2564.                (*pLog)<<_T( "Denied)\n" );
  2565.             }
  2566.          }
  2567.       }
  2568.    }
  2569.  
  2570.    return( hrResponse );
  2571. }
  2572.  
  2573. void CTestContainer98Item::DisplayAsDefault( BOOL tDefault )
  2574. {
  2575.    BOOL tOldDisplayAsDefault;
  2576.  
  2577.    ASSERT( ActsLikeButton() );
  2578.  
  2579.    tOldDisplayAsDefault = m_tDisplayAsDefault;
  2580.    m_tDisplayAsDefault = tDefault;
  2581.  
  2582.    if( (tOldDisplayAsDefault && !m_tDisplayAsDefault) ||
  2583.       (!tOldDisplayAsDefault && m_tDisplayAsDefault) )
  2584.    {
  2585.       // The default setting changed.
  2586.       m_pOleControl->OnAmbientPropertyChange(
  2587.          DISPID_AMBIENT_DISPLAYASDEFAULT );
  2588.    }
  2589. }
  2590.  
  2591. void CTestContainer98Item::FreezeEvents( BOOL tFreeze )
  2592. {
  2593.    if( m_pOleControl != NULL )
  2594.    {
  2595.       m_pOleControl->FreezeEvents( tFreeze );
  2596.    }
  2597. }
  2598.  
  2599. BOOL CTestContainer98Item::IsInPlaceActive() const
  2600. {
  2601.    UINT eState;
  2602.  
  2603.    eState = GetItemState();
  2604.  
  2605.    return( (eState == activeState) || (eState == activeUIState) );
  2606. }
  2607.  
  2608. BOOL CTestContainer98Item::IsUIActive() const
  2609. {
  2610.    return( GetItemState() == activeUIState );
  2611. }
  2612.  
  2613. void CTestContainer98Item::OnAmbientPropertyChange( DISPID dispid )
  2614. {
  2615.    m_pOleControl->OnAmbientPropertyChange( dispid );
  2616. }
  2617.  
  2618. void CTestContainer98Item::OnDeselect()
  2619. {
  2620.    CWnd* pStatusBarWnd;
  2621.    CWnd* pFrameWnd;
  2622.    CMainFrame* pFrame;
  2623.    CStatusBar* pStatusBar;
  2624.  
  2625.    pFrameWnd = AfxGetMainWnd();
  2626.    pFrame = STATIC_DOWNCAST( CMainFrame, pFrameWnd );
  2627.  
  2628.    pStatusBarWnd = pFrame->GetMessageBar();
  2629.    pStatusBar = STATIC_DOWNCAST( CStatusBar, pStatusBarWnd );
  2630.  
  2631.    pStatusBar->SetPaneText( 1, _T( "" ) );
  2632.    pStatusBar->SetPaneText( 2, _T( "" ) );
  2633. }
  2634.  
  2635. void CTestContainer98Item::UpdateStatusBar()
  2636. {
  2637.    CWnd* pStatusBarWnd;
  2638.    CWnd* pFrameWnd;
  2639.    CMainFrame* pFrame;
  2640.    CStatusBar* pStatusBar;
  2641.  
  2642.    pFrameWnd = AfxGetMainWnd();
  2643.    pFrame = STATIC_DOWNCAST( CMainFrame, pFrameWnd );
  2644.  
  2645.    pStatusBarWnd = pFrame->GetMessageBar();
  2646.    pStatusBar = STATIC_DOWNCAST( CStatusBar, pStatusBarWnd );
  2647.  
  2648.    switch( GetItemState() )
  2649.    {
  2650.    case activeState:
  2651.       pStatusBar->SetPaneText( 1, _T( "Active" ) );
  2652.       if( m_tWindowless )
  2653.       {
  2654.          pStatusBar->SetPaneText( 2, _T( "Windowless" ) );
  2655.       }
  2656.       else
  2657.       {
  2658.          pStatusBar->SetPaneText( 2, _T( "Windowed" ) );
  2659.       }
  2660.       break;
  2661.  
  2662.    case activeUIState:
  2663.       pStatusBar->SetPaneText( 1, _T( "UIActive" ) );
  2664.       if( m_tWindowless )
  2665.       {
  2666.          pStatusBar->SetPaneText( 2, _T( "Windowless" ) );
  2667.       }
  2668.       else
  2669.       {
  2670.          pStatusBar->SetPaneText( 2, _T( "Windowed" ) );
  2671.       }
  2672.       break;
  2673.  
  2674.    case openState:
  2675.       pStatusBar->SetPaneText( 1, _T( "Open" ) );
  2676.       pStatusBar->SetPaneText( 2, _T( "" ) );
  2677.       break;
  2678.  
  2679.    case loadedState:
  2680.       pStatusBar->SetPaneText( 1, _T( "Loaded" ) );
  2681.       pStatusBar->SetPaneText( 2, _T( "" ) );
  2682.       break;
  2683.  
  2684.    case emptyState:
  2685.       pStatusBar->SetPaneText( 1, _T( "Empty" ) );
  2686.       pStatusBar->SetPaneText( 2, _T( "" ) );
  2687.       break;
  2688.  
  2689.    default:
  2690.       ASSERT( FALSE );
  2691.       break;
  2692.    }
  2693.  
  2694. }
  2695.  
  2696. void CTestContainer98Item::OnSelect()
  2697. {
  2698.    UpdateStatusBar();
  2699. }
  2700.  
  2701. BOOL CTestContainer98Item::HasUIActiveState() const
  2702. {
  2703.    DWORD dwMiscStatus;
  2704.  
  2705.    dwMiscStatus = 0;
  2706.    m_lpObject->GetMiscStatus( DVASPECT_CONTENT, &dwMiscStatus );
  2707.  
  2708.    return( !(dwMiscStatus&OLEMISC_NOUIACTIVATE) );
  2709. }
  2710.  
  2711. BOOL CTestContainer98Item::IsInsideOut() const
  2712. {
  2713.    return( m_tInsideOut );
  2714. }
  2715.  
  2716. void CTestContainer98Item::Move( const CRect& rect )
  2717. {
  2718.    BOOL tSizeChanged;
  2719.    CRect rectOld;
  2720.    CSize size;
  2721.    BOOL tSuccess;
  2722.  
  2723.    tSizeChanged = (rect.Size() != m_rect.Size());
  2724.  
  2725.    InvalidateItem();
  2726.    rectOld = m_rect;
  2727.    m_rect = rect;
  2728.  
  2729.    if( IsInPlaceActive() )
  2730.    {
  2731.       SetItemRects();
  2732.    }
  2733.  
  2734.    if( tSizeChanged )
  2735.    {
  2736.       CClientDC dc( NULL );
  2737.  
  2738.       tSuccess = TRUE;
  2739.       size = m_rect.Size();
  2740.       dc.DPtoHIMETRIC( &size );
  2741.       TRY
  2742.       {
  2743.          SetExtent( size );
  2744.       }
  2745.       CATCH( CException, e )
  2746.       {
  2747.          tSuccess = FALSE;
  2748.       }
  2749.       END_CATCH
  2750.  
  2751.       if( !tSuccess )
  2752.       {
  2753.          m_rect = rectOld;
  2754.          if( IsInPlaceActive() )
  2755.          {
  2756.             SetItemRects();
  2757.          }
  2758.       }
  2759.    }
  2760.  
  2761.    InvalidateItem();
  2762. }
  2763.  
  2764. void CTestContainer98Item::Prepare()
  2765. {
  2766.    m_tracker.m_rect = m_rect;
  2767.    m_tracker.m_rect.InflateRect( MARGIN_PIXELS, MARGIN_PIXELS );
  2768.  
  2769.    if( m_pView->IsSelected( this ) )
  2770.    {
  2771.       m_tracker.m_nStyle |= CRectTracker::resizeInside;
  2772.    }
  2773.    else
  2774.    {
  2775.       m_tracker.m_nStyle &= ~CRectTracker::resizeInside;
  2776.    }
  2777.  
  2778.    if( (GetItemState() == openState) || (GetItemState() == activeUIState) )
  2779.    {
  2780.       m_tracker.m_nStyle |= CRectTracker::hatchInside;
  2781.    }
  2782.    else
  2783.    {
  2784.       m_tracker.m_nStyle &= ~CRectTracker::hatchInside;
  2785.    }
  2786. }
  2787.  
  2788. HRESULT CTestContainer98Item::SaveToPropertyBag( IPropertyBag* pPropertyBag )
  2789. {
  2790.    HRESULT hResult;
  2791.    IPersistPropertyBagPtr pPersistPropertyBag;
  2792.  
  2793.    ASSERT( pPropertyBag != NULL );
  2794.    ASSERT( m_lpObject != NULL );
  2795.  
  2796.    hResult = m_lpObject->QueryInterface( IID_IPersistPropertyBag,
  2797.       (void**)&pPersistPropertyBag );
  2798.    if( FAILED( hResult ) )
  2799.    {
  2800.       TCControlTrace( TRACELEVEL_NORMAL, this,
  2801.          "Control does not support IPersistPropertyBag.\n" );
  2802.       return( hResult );
  2803.    }
  2804.  
  2805.    hResult = pPersistPropertyBag->Save( pPropertyBag, TRUE, TRUE );
  2806.    if( FAILED( hResult ) )
  2807.    {
  2808.       return( hResult );
  2809.    }
  2810.  
  2811.    return( S_OK );
  2812. }
  2813.  
  2814. HRESULT CTestContainer98Item::SaveToStorage( IStorage* pStorage )
  2815. {
  2816.    HRESULT hResult;
  2817.    IPersistStoragePtr pPersistStorage;
  2818.    CLSID clsid;
  2819.  
  2820.    ASSERT( pStorage != NULL );
  2821.    ASSERT( m_lpObject != NULL );
  2822.  
  2823.    pPersistStorage = m_lpObject;
  2824.    if( pPersistStorage == NULL )
  2825.    {
  2826.       return( E_NOINTERFACE );
  2827.    }
  2828.  
  2829.    pPersistStorage->GetClassID( &clsid );
  2830.    hResult = WriteClassStg( pStorage, clsid );
  2831.    if( FAILED( hResult ) )
  2832.    {
  2833.       return( hResult );
  2834.    }
  2835.  
  2836.    hResult = pPersistStorage->Save( pStorage, FALSE );
  2837.    if( FAILED( hResult ) )
  2838.    {
  2839.       return( hResult );
  2840.    }
  2841.  
  2842.    pPersistStorage->SaveCompleted( NULL );
  2843.  
  2844.    return( S_OK );
  2845. }
  2846.  
  2847. HRESULT CTestContainer98Item::SaveToStream( IStream* pStream )
  2848. {
  2849.    HRESULT hResult;
  2850.    IPersistStreamPtr pPersistStream;
  2851.    IPersistStreamInitPtr pPersistStreamInit;
  2852.    IPersistPtr pPersist;
  2853.    CLSID clsid;
  2854.  
  2855.    ASSERT( pStream != NULL );
  2856.    ASSERT( m_lpObject != NULL );
  2857.  
  2858.    hResult = m_lpObject->QueryInterface( IID_IPersist, (void**)&pPersist );
  2859.    if( FAILED( hResult ) )
  2860.    {
  2861.       // Some control implementers forget that the IPersist* interfaces are all
  2862.       // derived from IPersist.  If they forget to allow a QI for IPersist, let
  2863.       // them know the error of their ways, and just go for IPersistStorage to
  2864.       // get the IPersist interface.
  2865.       TCControlTrace( TRACELEVEL_NORMAL, this,
  2866.          "Object doesn't support IPersist.  What a wanker.\n" );
  2867.       hResult = m_lpObject->QueryInterface( IID_IPersistStorage,
  2868.          (void**)&pPersist );
  2869.       if( FAILED( hResult ) )
  2870.       {
  2871.          return( hResult );
  2872.       }
  2873.    }
  2874.  
  2875.    pPersist->GetClassID( &clsid );
  2876.    hResult = WriteClassStm( pStream, clsid );
  2877.    if( FAILED( hResult ) )
  2878.    {
  2879.       return( hResult );
  2880.    }
  2881.  
  2882.    hResult = m_lpObject->QueryInterface( IID_IPersistStream,
  2883.       (void**)&pPersistStream );
  2884.    if( SUCCEEDED( hResult ) )
  2885.    {
  2886.       hResult = pPersistStream->Save( pStream, TRUE );
  2887.    }
  2888.    else
  2889.    {
  2890.       hResult = m_lpObject->QueryInterface( IID_IPersistStreamInit,
  2891.          (void**)&pPersistStreamInit );
  2892.       if( FAILED( hResult ) )
  2893.       {
  2894.          return( hResult );
  2895.       }
  2896.       hResult = pPersistStreamInit->Save( pStream, TRUE );
  2897.    }
  2898.    if( FAILED( hResult ) )
  2899.    {
  2900.       return( hResult );
  2901.    }
  2902.  
  2903.    return( S_OK );
  2904. }
  2905.  
  2906. DWORD CTestContainer98Item::HitTest( CPoint point )
  2907. {
  2908.    HRESULT hResult;
  2909.    IViewObjectExPtr pViewObjectEx;
  2910.    DWORD dwHitResult;
  2911.  
  2912.    if( !m_rect.PtInRect( point ) )
  2913.    {
  2914.       // Trivially reject the point.
  2915.       return( HITRESULT_OUTSIDE );
  2916.    }
  2917.  
  2918.    hResult = m_lpObject->QueryInterface( IID_IViewObjectEx,
  2919.       (void**)&pViewObjectEx );
  2920.    if( SUCCEEDED( hResult ) )
  2921.    {
  2922.       hResult = pViewObjectEx->QueryHitPoint( DVASPECT_CONTENT, &m_rect, point,
  2923.          0, &dwHitResult );
  2924.       if( SUCCEEDED( hResult ) )
  2925.       {
  2926.          return( dwHitResult );
  2927.       }
  2928.    }
  2929.  
  2930.    // If we got here, either the object doesn't support hit testing, or the hit
  2931.    // test call failed.  Since we would have rejected the point if it didn't
  2932.    // lie within the object's bounding rect, we know that the point lies within
  2933.    // the object.
  2934.  
  2935.    return( HITRESULT_HIT );
  2936. }
  2937.  
  2938. BOOL CTestContainer98Item::DrawFrontToBack( CDC* pDC, LPCRECT prectBounds )
  2939. {
  2940.    HRESULT hResult;
  2941.    RECTL rclBounds;
  2942.    RECTL* prclBounds;
  2943.    DWORD dwViewStatus;
  2944.    RECTL rclClip;
  2945.    CRect rectClip;
  2946.    CSize size;
  2947.  
  2948.    if( (m_lpObject == NULL) || (m_lpViewObject == NULL) )
  2949.    {
  2950.       return( FALSE );
  2951.    }
  2952.  
  2953.    if( IsInPlaceActive() && !m_tWindowless )
  2954.    {
  2955.       return( FALSE );
  2956.    }
  2957.  
  2958.    if( m_pViewObjectEx == NULL )
  2959.    {
  2960.       // The control doesn't understand two-pass drawing, so just draw it on
  2961.       // pass 2.
  2962.       return( FALSE );
  2963.    }
  2964.  
  2965.    if( GetDocument()->GetUserMode() && IsInvisibleAtRuntime() )
  2966.    {
  2967.       // We are invisible.
  2968.       return( FALSE );
  2969.    }
  2970.  
  2971.    // convert RECT lpBounds to RECTL rclBounds
  2972.    rclBounds.left = prectBounds->left;
  2973.    rclBounds.top = prectBounds->top;
  2974.    rclBounds.right = prectBounds->right;
  2975.    rclBounds.bottom = prectBounds->bottom;
  2976.  
  2977.    if( m_tWindowless )
  2978.    {
  2979.       prclBounds = NULL;
  2980.    }
  2981.    else
  2982.    {
  2983.       prclBounds = &rclBounds;
  2984.    }
  2985.  
  2986.    // Assume that we won't be able to draw the first pass.
  2987.    m_dwAspectPass2 = DVASPECT_CONTENT;
  2988.  
  2989.    m_pViewObjectEx->GetViewStatus( &dwViewStatus );
  2990.    ASSERT( m_dwViewStatus == dwViewStatus );
  2991.    if( !(m_dwViewStatus&VIEWSTATUS_DVASPECTOPAQUE) )
  2992.    {
  2993.       return( FALSE );
  2994.    }
  2995.  
  2996.    hResult = m_pViewObjectEx->GetRect( DVASPECT_OPAQUE, &rclClip );
  2997.    if( FAILED( hResult ) )
  2998.    {
  2999.       return( FALSE );
  3000.    }
  3001.  
  3002.    hResult = m_lpViewObject->Draw( DVASPECT_OPAQUE, -1, NULL, NULL, NULL,
  3003.       pDC->m_hDC, prclBounds, NULL, NULL, 0 );
  3004.    if( SUCCEEDED( hResult ) )
  3005.    {
  3006.       // Just draw the transparent part in pass 2.
  3007.       m_dwAspectPass2 = DVASPECT_TRANSPARENT;
  3008.    }
  3009.  
  3010.    size = CSize( rclClip.left, rclClip.top );
  3011.    pDC->HIMETRICtoDP( &size );
  3012.    rectClip.left = m_rect.left+size.cx;
  3013.    rectClip.top = m_rect.top+size.cy;
  3014.    size = CSize( rclClip.right, rclClip.bottom );
  3015.    pDC->HIMETRICtoDP( &size );
  3016.    rectClip.right = m_rect.left+size.cx;
  3017.    rectClip.bottom = m_rect.top+size.cy;
  3018.    pDC->ExcludeClipRect( &rectClip );
  3019.  
  3020.    return( TRUE );
  3021. }
  3022.  
  3023. BOOL CTestContainer98Item::DrawBackToFront( CDC* pDC, LPCRECT prectBounds )
  3024. {
  3025.    RECTL rclBounds;
  3026.    RECTL* prclBounds;
  3027.    DWORD dwViewStatus;
  3028.  
  3029.    if( (m_lpObject == NULL) || (m_lpViewObject == NULL) )
  3030.    {
  3031.       return( FALSE );
  3032.    }
  3033.  
  3034.    if( GetDocument()->GetUserMode() && IsInvisibleAtRuntime() )
  3035.    {
  3036.       // We are invisible.
  3037.       return( FALSE );
  3038.    }
  3039.  
  3040.    if( IsInPlaceActive() && !m_tWindowless )
  3041.    {
  3042.       return( FALSE );
  3043.    }
  3044.  
  3045.    // convert RECT lpBounds to RECTL rclBounds
  3046.    rclBounds.left = prectBounds->left;
  3047.    rclBounds.top = prectBounds->top;
  3048.    rclBounds.right = prectBounds->right;
  3049.    rclBounds.bottom = prectBounds->bottom;
  3050.  
  3051.    if( m_tWindowless )
  3052.    {
  3053.       prclBounds = NULL;
  3054.    }
  3055.    else
  3056.    {
  3057.       prclBounds = &rclBounds;
  3058.    }
  3059.  
  3060.    if( m_pViewObjectEx != NULL )
  3061.    {
  3062.       m_pViewObjectEx->GetViewStatus( &dwViewStatus );
  3063.       ASSERT( dwViewStatus == m_dwViewStatus );
  3064.    }
  3065.    else
  3066.    {
  3067.       ASSERT( m_dwViewStatus == 0 );
  3068.    }
  3069.  
  3070.    if( (m_dwAspectPass2 == DVASPECT_TRANSPARENT)&&(m_dwViewStatus&
  3071.       VIEWSTATUS_DVASPECTTRANSPARENT) )
  3072.    {
  3073.       m_lpViewObject->Draw( DVASPECT_TRANSPARENT, -1, NULL, NULL, NULL,
  3074.          pDC->m_hDC, prclBounds, NULL, NULL, 0 );
  3075.    }
  3076.    else if( m_dwAspectPass2 == DVASPECT_CONTENT )
  3077.    {
  3078.       m_lpViewObject->Draw( DVASPECT_CONTENT, -1, NULL, NULL, NULL, pDC->m_hDC,
  3079.          prclBounds, NULL, NULL, 0 );
  3080.    }
  3081.  
  3082.    return( TRUE );
  3083. }
  3084.  
  3085. BOOL CTestContainer98Item::Draw( CDC* pDC, LPCRECT prectBounds,
  3086.    DVASPECT nDrawAspect )
  3087. {
  3088.    RECTL rclBounds;
  3089.    RECTL* prclBounds;
  3090.    CRect rectClip;
  3091.    CSize size;
  3092.  
  3093.    if( (m_lpObject == NULL) || (m_lpViewObject == NULL) )
  3094.    {
  3095.       return( FALSE );
  3096.    }
  3097.  
  3098.    if( GetDocument()->GetUserMode() && IsInvisibleAtRuntime() )
  3099.    {
  3100.       // We are invisible.
  3101.       return( FALSE );
  3102.    }
  3103.  
  3104.    // use current draw aspect if aspect is -1 (default)
  3105.    if( nDrawAspect == -1 )
  3106.    {
  3107.       nDrawAspect = m_nDrawAspect;
  3108.    }
  3109.  
  3110.    // convert RECT lpBounds to RECTL rclBounds
  3111.    rclBounds.left = prectBounds->left;
  3112.    rclBounds.top = prectBounds->top;
  3113.    rclBounds.right = prectBounds->right;
  3114.    rclBounds.bottom = prectBounds->bottom;
  3115.  
  3116.    if( m_tWindowless )
  3117.    {
  3118.       prclBounds = NULL;
  3119.    }
  3120.    else
  3121.    {
  3122.       prclBounds = &rclBounds;
  3123.    }
  3124.  
  3125.    m_lpViewObject->Draw( DVASPECT_CONTENT, -1, NULL, NULL, NULL, pDC->m_hDC,
  3126.       prclBounds, NULL, NULL, 0 );
  3127.  
  3128.    return( TRUE );
  3129. }
  3130.  
  3131. void CTestContainer98Item::OnDeactivate( BOOL tNoRedraw )
  3132. {
  3133.    TCControlTrace( TRACELEVEL_NORMAL, this, "Deactivating control\n" );
  3134.  
  3135.    if( m_tWindowless )
  3136.    {
  3137.       if( GetActiveView()->GetItemWithFocus() == this )
  3138.       {
  3139.          GetActiveView()->OnWindowlessReleaseFocus();
  3140.       }
  3141.       m_tWindowless = FALSE;
  3142.       m_pOleInPlaceObjectWindowless.Release();
  3143.    }
  3144.  
  3145.    if( !tNoRedraw )
  3146.    {
  3147.       InvalidateItem();
  3148.    }
  3149.  
  3150.    COleClientItem::OnDeactivate();
  3151.  
  3152.    UpdateStatusBar();
  3153. }
  3154.  
  3155. void CTestContainer98Item::OnDeactivate()
  3156. {
  3157.    OnDeactivate( FALSE );
  3158. }
  3159.  
  3160. STDMETHODIMP_( ULONG ) CTestContainer98Item::XOleInPlaceSiteWindowless::
  3161.    AddRef()
  3162. {
  3163.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless )
  3164.  
  3165.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3166.       "XOleInPlaceSiteWindowless::AddRef().\n" );
  3167.  
  3168.    return( pThis->ExternalAddRef() );
  3169. }
  3170.  
  3171. STDMETHODIMP_( ULONG ) CTestContainer98Item::XOleInPlaceSiteWindowless::
  3172.    Release()
  3173. {
  3174.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless )
  3175.  
  3176.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3177.       "XOleInPlaceSiteWindowless::Release().\n" );
  3178.  
  3179.    return( pThis->ExternalRelease() );
  3180. }
  3181.  
  3182. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::QueryInterface(
  3183.    REFIID iid, LPVOID* ppvObj )
  3184. {
  3185.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless )
  3186.  
  3187.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  3188. }
  3189.  
  3190. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3191.    ContextSensitiveHelp( BOOL tEnterMode )
  3192. {
  3193.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3194.  
  3195.    return( pThis->m_xOleIPSite.ContextSensitiveHelp( tEnterMode ) );
  3196. }
  3197.  
  3198. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::GetWindow(
  3199.    HWND* phWnd )
  3200. {
  3201.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3202.  
  3203.    return( pThis->m_xOleIPSite.GetWindow( phWnd ) );
  3204. }
  3205.  
  3206. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3207.    CanInPlaceActivate()
  3208. {
  3209.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3210.  
  3211.    return( pThis->m_xOleIPSite.CanInPlaceActivate() );
  3212. }
  3213.  
  3214. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3215.    DeactivateAndUndo()
  3216. {
  3217.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3218.  
  3219.    return( pThis->m_xOleIPSite.DeactivateAndUndo() );
  3220. }
  3221.  
  3222. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3223.    DiscardUndoState()
  3224. {
  3225.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3226.  
  3227.    return( pThis->m_xOleIPSite.DiscardUndoState() );
  3228. }
  3229.  
  3230. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::GetWindowContext(
  3231.    IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT prectPos,
  3232.    LPRECT prectClip, LPOLEINPLACEFRAMEINFO pFrameInfo )
  3233. {
  3234.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3235.  
  3236.    return( pThis->m_xOleIPSite.GetWindowContext( ppFrame, ppDoc, prectPos,
  3237.       prectClip, pFrameInfo ) );
  3238. }
  3239.  
  3240. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3241.    OnInPlaceActivate()
  3242. {
  3243.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3244.  
  3245.    return( pThis->m_xOleIPSite.OnInPlaceActivate() );
  3246. }
  3247.  
  3248. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3249.    OnInPlaceDeactivate()
  3250. {
  3251.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3252.  
  3253.    return( pThis->m_xOleIPSite.OnInPlaceDeactivate() );
  3254. }
  3255.  
  3256. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::OnPosRectChange(
  3257.    LPCRECT prectPos )
  3258. {
  3259.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3260.  
  3261.    return( pThis->m_xOleIPSite.OnPosRectChange( prectPos ) );
  3262. }
  3263.  
  3264. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless:: OnUIActivate()
  3265. {
  3266.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3267.  
  3268.    return( pThis->m_xOleIPSite.OnUIActivate() );
  3269. }
  3270.  
  3271. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::OnUIDeactivate(
  3272.    BOOL tUndoable )
  3273. {
  3274.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3275.  
  3276.    return( pThis->m_xOleIPSite.OnUIDeactivate( tUndoable ) );
  3277. }
  3278.  
  3279. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::Scroll(
  3280.    SIZE sizeExtent )
  3281. {
  3282.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3283.  
  3284.    return( pThis->m_xOleIPSite.Scroll( sizeExtent ) );
  3285. }
  3286.  
  3287. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3288.    OnInPlaceActivateEx( BOOL* ptNoRedraw, DWORD dwFlags )
  3289. {
  3290.    HRESULT hResult;
  3291.  
  3292.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3293.  
  3294.    ASSERT( ptNoRedraw != NULL );
  3295.  
  3296.    ASSERT( pThis->m_tWindowless == FALSE );
  3297.  
  3298.    if( dwFlags&ACTIVATE_WINDOWLESS )
  3299.    {
  3300.       pThis->m_tWindowless = TRUE;
  3301.       hResult = pThis->m_lpObject->QueryInterface(
  3302.          IID_IOleInPlaceObjectWindowless,
  3303.          (void**)&pThis->m_pOleInPlaceObjectWindowless );
  3304.       ASSERT( SUCCEEDED( hResult ) );
  3305.    }
  3306.  
  3307.    if( ptNoRedraw != NULL )
  3308.    {
  3309.       if( pThis->GetActiveView()->GetUpdateRect( NULL ) )
  3310.       {
  3311.          *ptNoRedraw = FALSE;
  3312.       }
  3313.       else
  3314.       {
  3315.          *ptNoRedraw = TRUE;
  3316.       }
  3317.    }
  3318.  
  3319.    return( pThis->m_xOleIPSite.OnInPlaceActivate() );
  3320. }
  3321.  
  3322. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3323.    OnInPlaceDeactivateEx( BOOL tNoRedraw )
  3324. {
  3325.    (void)tNoRedraw;
  3326.  
  3327.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3328.  
  3329.    pThis->OnDeactivate( tNoRedraw );
  3330.  
  3331.    return( S_OK );
  3332. }
  3333.  
  3334. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3335.    RequestUIActivate()
  3336. {
  3337.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3338.  
  3339.    return( S_OK );
  3340. }
  3341.  
  3342. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::AdjustRect(
  3343.    LPRECT prect )
  3344. {
  3345.    (void)prect;
  3346.  
  3347.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3348.  
  3349.    return( E_NOTIMPL );
  3350. }
  3351.  
  3352. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3353.    CanWindowlessActivate()
  3354. {
  3355.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3356.  
  3357.    TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3358.       "Control wants to be windowless.\n" );
  3359.    if( pThis->GetDocument()->CanWindowlessActivate() )
  3360.    {
  3361.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3362.          "Windowless activation is allowed.\n" );
  3363.       return( S_OK );
  3364.    }
  3365.    else
  3366.    {
  3367.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3368.          "You'll create a window and like it.\n" );
  3369.       return( S_FALSE );
  3370.    }
  3371. }
  3372.  
  3373. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::GetCapture()
  3374. {
  3375.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3376.  
  3377.    if( pThis->GetActiveView()->GetItemWithCapture() == pThis )
  3378.    {
  3379.       return( S_OK );
  3380.    }
  3381.    else
  3382.    {
  3383.       return( S_FALSE );
  3384.    }
  3385. }
  3386.  
  3387. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::GetDC(
  3388.    LPCRECT prect, DWORD dwFlags, HDC* phDC )
  3389. {
  3390.    CView* pView;
  3391.    CRgn rgn;
  3392.    CRect rect;
  3393.  
  3394.    (void)dwFlags;
  3395.  
  3396.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3397.  
  3398.    ASSERT( phDC != NULL );
  3399.    *phDC = NULL;
  3400.  
  3401.    if( pThis->m_pDC != NULL )
  3402.    {
  3403.       return( E_FAIL );
  3404.    }
  3405.  
  3406.    pView = pThis->GetActiveView();
  3407.    ASSERT( pView != NULL );
  3408.  
  3409.    pThis->m_pDC = pView->GetDC();
  3410.    if( pThis->m_pDC == NULL )
  3411.    {
  3412.       return( E_FAIL );
  3413.    }
  3414.  
  3415.    if( prect == NULL )
  3416.    {
  3417.       // The clipping rectangle is the object's extent rectangle.
  3418.       rect = pThis->m_rect;
  3419.    }
  3420.    else
  3421.    {
  3422.       // The clipping rectangle is the object's extent rectangle intersected
  3423.       // with the rectangle requested by the object.
  3424.       rect.IntersectRect( &pThis->m_rect, prect );
  3425.    }
  3426.  
  3427.    rgn.CreateRectRgnIndirect( &rect );
  3428.    pThis->m_pDC->SelectClipRgn( &rgn, RGN_AND );
  3429.  
  3430.    *phDC = pThis->m_pDC->GetSafeHdc();
  3431.  
  3432.    return( S_OK );
  3433. }
  3434.  
  3435. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::GetFocus()
  3436. {
  3437.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3438.  
  3439.    if( pThis->GetActiveView()->GetItemWithFocus() == pThis )
  3440.    {
  3441.       return( S_OK );
  3442.    }
  3443.    else
  3444.    {
  3445.       return( S_FALSE );
  3446.    }
  3447. }
  3448.  
  3449. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::InvalidateRect(
  3450.    LPCRECT prect, BOOL tErase )
  3451. {
  3452.    CRect rect;
  3453.  
  3454.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3455.  
  3456.    if( prect == NULL )
  3457.    {
  3458.       rect = pThis->m_rect;
  3459.    }
  3460.    else
  3461.    {
  3462.       // Intersect the given rectangle with the bounds of the object.
  3463.       rect.IntersectRect( prect, &pThis->m_rect );
  3464.  
  3465.       if( rect != *prect )
  3466.       {
  3467.          TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3468.             "Object tried to invalidate pixels outside its bounds.  What a goober.\n" );
  3469.       }
  3470.    }
  3471.  
  3472.    if( !rect.IsRectEmpty() )
  3473.    {
  3474.       pThis->GetActiveView()->InvalidateRect( &rect, tErase );
  3475.       pThis->GetActiveView()->UpdateWindow();
  3476.    }
  3477.  
  3478.    return( S_OK );
  3479. }
  3480.  
  3481. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::InvalidateRgn(
  3482.    HRGN hRgn, BOOL tErase )
  3483. {
  3484.    CRgn rgn;
  3485.    CRgn* pRgn;
  3486.    CRect rectRgn;
  3487.    CRect rect;
  3488.  
  3489.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3490.  
  3491.    if( hRgn == NULL )
  3492.    {
  3493.       // The object wants its full extent invalidated.  It's much easier to do
  3494.       // this with a rect than a region.
  3495.       return( InvalidateRect( NULL, tErase ) );
  3496.    }
  3497.  
  3498.    pRgn = CRgn::FromHandle( hRgn );
  3499.    pRgn->GetRgnBox( &rectRgn );
  3500.    rect.IntersectRect( &rectRgn, &pThis->m_rect );
  3501.    if( rect != rectRgn )
  3502.    {
  3503.       TCControlTrace( TRACELEVEL_NORMAL, pThis,
  3504.          "Object tried to invalidate pixels outside its bounds.  What a goober.\n" );
  3505.       return( InvalidateRect( NULL, tErase ) );
  3506.    }
  3507.  
  3508.    pThis->GetActiveView()->InvalidateRgn( pRgn, tErase );
  3509.  
  3510.    return( S_OK );
  3511. }
  3512.  
  3513. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::
  3514.    OnDefWindowMessage( UINT nMessage, WPARAM wParam, LPARAM lParam,
  3515.    LRESULT* plResult )
  3516. {
  3517.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3518.  
  3519.    return( pThis->GetActiveView()->OnWindowlessDefWindowMessage( nMessage,
  3520.       wParam, lParam, plResult ) );
  3521. }
  3522.  
  3523. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::ReleaseDC(
  3524.    HDC hDC )
  3525. {
  3526.    CView* pView;
  3527.  
  3528.    UNUSED( hDC );
  3529.  
  3530.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3531.  
  3532.    pView = pThis->GetActiveView();
  3533.    ASSERT( pView != NULL );
  3534.  
  3535.    ASSERT( hDC == pThis->m_pDC->GetSafeHdc() );
  3536.  
  3537.    pView->ReleaseDC( pThis->m_pDC );
  3538.  
  3539.    pThis->m_pDC = NULL;
  3540.  
  3541.    return( S_OK );
  3542. }
  3543.  
  3544. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::ScrollRect(
  3545.    int dx, int dy, LPCRECT prectScroll, LPCRECT prectClip )
  3546. {
  3547.    (void)dx;
  3548.    (void)dy;
  3549.    (void)prectScroll;
  3550.    (void)prectClip;
  3551.  
  3552.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3553.  
  3554.    return( E_NOTIMPL );
  3555. }
  3556.  
  3557. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::SetCapture(
  3558.    BOOL tCapture )
  3559. {
  3560.    HRESULT hResult;
  3561.  
  3562.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3563.  
  3564.    if( tCapture )
  3565.    {
  3566.       hResult = pThis->GetActiveView()->OnWindowlessSetCapture( pThis );
  3567.       if( FAILED( hResult ) )
  3568.       {
  3569.          return( hResult );
  3570.       }
  3571.    }
  3572.    else
  3573.    {
  3574.       hResult = pThis->GetActiveView()->OnWindowlessReleaseCapture( pThis );
  3575.       if( FAILED( hResult ) )
  3576.       {
  3577.          return( hResult );
  3578.       }
  3579.    }
  3580.  
  3581.    return( hResult );
  3582. }
  3583.  
  3584. STDMETHODIMP CTestContainer98Item::XOleInPlaceSiteWindowless::SetFocus(
  3585.    BOOL tFocus )
  3586. {
  3587.    HRESULT hResult;
  3588.  
  3589.    METHOD_PROLOGUE( CTestContainer98Item, OleInPlaceSiteWindowless );
  3590.  
  3591.    if( tFocus )
  3592.    {
  3593.       hResult = pThis->GetActiveView()->OnWindowlessSetFocus( pThis );
  3594.       if( FAILED( hResult ) )
  3595.       {
  3596.          return( hResult );
  3597.       }
  3598.    }
  3599.    else
  3600.    {
  3601.       hResult = pThis->GetActiveView()->OnWindowlessReleaseFocus();
  3602.       if( FAILED( hResult ) )
  3603.       {
  3604.          return( hResult );
  3605.       }
  3606.    }
  3607.  
  3608.    return( hResult );
  3609. }
  3610.  
  3611. STDMETHODIMP_( ULONG ) CTestContainer98Item::XAdviseSinkEx::AddRef()
  3612. {
  3613.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx )
  3614.  
  3615.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XAdviseSinkEx::AddRef().\n" );
  3616.  
  3617.    return( pThis->ExternalAddRef() );
  3618. }
  3619.  
  3620. STDMETHODIMP_( ULONG ) CTestContainer98Item::XAdviseSinkEx::Release()
  3621. {
  3622.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx )
  3623.  
  3624.    TCControlTrace( TRACELEVEL_NORMAL, pThis, "XAdviseSinkEx::Release().\n" );
  3625.  
  3626.    return( pThis->ExternalRelease() );
  3627. }
  3628.  
  3629. STDMETHODIMP CTestContainer98Item::XAdviseSinkEx::QueryInterface( REFIID iid,
  3630.    LPVOID* ppvObj )
  3631. {
  3632.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx )
  3633.  
  3634.    return( pThis->ExternalQueryInterface( &iid, ppvObj ) );
  3635. }
  3636.  
  3637. void CTestContainer98Item::XAdviseSinkEx::OnClose()
  3638. {
  3639.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3640.  
  3641.    pThis->m_xAdviseSink.OnClose();
  3642. }
  3643.  
  3644. void CTestContainer98Item::XAdviseSinkEx::OnDataChange( FORMATETC* pFormatEtc,
  3645.    STGMEDIUM* pStgMedium )
  3646. {
  3647.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3648.  
  3649.    pThis->m_xAdviseSink.OnDataChange( pFormatEtc, pStgMedium );
  3650. }
  3651.  
  3652. void CTestContainer98Item::XAdviseSinkEx::OnRename( IMoniker* pMoniker )
  3653. {
  3654.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3655.  
  3656.    pThis->m_xAdviseSink.OnRename( pMoniker );
  3657. }
  3658.  
  3659. void CTestContainer98Item::XAdviseSinkEx::OnSave()
  3660. {
  3661.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3662.  
  3663.    pThis->m_xAdviseSink.OnSave();
  3664. }
  3665.  
  3666. void CTestContainer98Item::XAdviseSinkEx::OnViewChange( DWORD dwAspect,
  3667.    LONG lindex )
  3668. {
  3669.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3670.  
  3671.    pThis->m_xAdviseSink.OnViewChange( dwAspect, lindex );
  3672. }
  3673.  
  3674. void CTestContainer98Item::XAdviseSinkEx::OnViewStatusChange(
  3675.    DWORD dwViewStatus )
  3676. {
  3677.    METHOD_PROLOGUE( CTestContainer98Item, AdviseSinkEx );
  3678.  
  3679.    TRACE( "IAdviseSinkEx::OnViewStatusChange()\n" );
  3680.  
  3681.    ASSERT( pThis->m_pViewObjectEx != NULL );
  3682.  
  3683.    pThis->m_dwViewStatus = dwViewStatus;
  3684. }
  3685.  
  3686. BOOL CTestContainer98Item::OnWindowMessage( const MSG* pMessage )
  3687. {
  3688.    LRESULT lResult;
  3689.    HRESULT hResult;
  3690.  
  3691.    hResult = m_pOleInPlaceObjectWindowless->OnWindowMessage( pMessage->message,
  3692.       pMessage->wParam, pMessage->lParam, &lResult );
  3693.    if( hResult == S_OK )
  3694.    {
  3695.       return( TRUE );
  3696.    }
  3697.    else
  3698.    {
  3699.       return( FALSE );
  3700.    }
  3701. }
  3702.