October 6, 1996
This document is a step-by-step tutorial for creating the BGSound Web design-time ActiveX control using MFC.
c:\progra~1\dcsdk\Samples\Mfc\include
BSTR Source short Loop
// control properties short m_nLoop; CString m_strSource;
short CBGSoundCtrl::GetLoop() 
{
      return m_nLoop;
}
void CBGSoundCtrl::SetLoop(short nNewValue) 
{
      // verify loop property is valid
      if (nNewValue >= -1)
      {
             // set our internal loop value
             m_nLoop = nNewValue;
             // notify container that a property was modified
             SetModifiedFlag();
             // notify property browsers that this property changed
             BoundPropertyChanged(dispidLoop);
      }
      else
      {
             ThrowError(CTL_E_INVALIDPROPERTYVALUE, 
                            _T("Loop must be an integer greater than or equal to -1"));
      }
}
BSTR CBGSoundCtrl::GetSource() 
{
      return m_strSource.AllocSysString();
}
void CBGSoundCtrl::SetSource(LPCTSTR lpszNewValue) 
{
    // set our internal source string
    m_strSource = lpszNewValue;
    // notify container that a property was modified
    SetModifiedFlag();
    // notify property browsers that this property changed
    BoundPropertyChanged(dispidSource);
    // make sure we get repainted since 'Source' is our caption
    InvalidateControl();
}
// persist our properties
PX_String(pPX, _T("Source"), m_strSource, _T(""));
PX_Short(pPX, _T("Loop"), m_nLoop, -1);
void CBGSoundCtrl::OnDraw(
                    CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
    CFont fnt;
    CRect rcText;
    // get text rect;
    rcText = rcBounds;
    rcText.left += 2;
    rcText.right -= 2;
    rcText.top += 2;
    rcText.bottom -= 2;
    // create font
    fnt.CreatePointFont(160, _T("MS Sans Serif"), pdc);
    CFont* pOldFont = pdc->SelectObject(&fnt);
    pdc->SetBkMode(TRANSPARENT);
    // fill our rect with gray
    pdc->FillRect(rcBounds,                                                                               CBrush::FromHandle((HBRUSH)GetStockObject(LTGRAY_BRUSH)));
    // draw an edge
    pdc->DrawEdge(&(RECT)rcBounds, EDGE_RAISED, BF_RECT);
    // draw the Source text
    pdc->DrawText(_T("\"") + m_strSource + _T("\""), &(RECT)rcText, DT_WORDBREAK | DT_CENTER); 
    // return to old font
    pdc->SelectObject(pOldFont);
}
#include "designer.h" #include "webdc.h"
// Interface maps DECLARE_INTERFACE_MAP(); // IActiveDesigner Interface BEGIN_INTERFACE_PART(ActiveDesigner, IActiveDesigner) STDMETHOD(GetRuntimeClassID)(CLSID *pclsid); STDMETHOD(GetRuntimeMiscStatusFlags)(DWORD *dwMiscFlags); STDMETHOD(QueryPersistenceInterface)(REFIID riidPersist); STDMETHOD(SaveRuntimeState)(REFIID riidPersist, REFIID riidObjStgMed, void *pObjStgMed); STDMETHOD(GetExtensibilityObject)(IDispatch **ppvObjOut); END_INTERFACE_PART(ActiveDesigner) virtual HRESULT GetRuntimeText(CString& strText);
// Define and initialize required GUIDs #include <initguid.h> #include "designer.h" #include "webdc.h"
////////////////////////////////////////////////////////////////////////
// Interface Map
BEGIN_INTERFACE_MAP(CBGSoundCtrl, COleControl)
      INTERFACE_PART(CBGSoundCtrl, IID_IActiveDesigner, ActiveDesigner)
END_INTERFACE_MAP()
////////////////////////////////////////////////////////////////////////
// CBGSoundCtrl::XActiveDesigner - IActiveDesigner interface
//
// The following functions represent the implementation of the IActiveDesigner
// interface. For the most part, these functions can be left as is. The
// SaveRuntimeState() function will call the CBGSoundCtrl::GetRuntimeText()
// function when it needs to generate run-time text.
STDMETHODIMP_(ULONG) CBGSoundCtrl::XActiveDesigner::AddRef(void)
{
      METHOD_MANAGE_STATE(CBGSoundCtrl, ActiveDesigner)
      return (ULONG)pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CBGSoundCtrl::XActiveDesigner::Release(void)
{
      METHOD_MANAGE_STATE(CBGSoundCtrl, ActiveDesigner)
      return (ULONG)pThis->ExternalRelease();
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::QueryInterface(REFIID iid,
                                                                                          LPVOID far* ppvObj)
{
      METHOD_MANAGE_STATE(CBGSoundCtrl, ActiveDesigner)
      return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::GetRuntimeClassID(CLSID *pclsid)
{
    *pclsid = CLSID_NULL;
    return S_FALSE;
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::GetRuntimeMiscStatusFlags(DWORD *pdwMiscFlags)
{
      if (!pdwMiscFlags)
             return E_INVALIDARG;
      *pdwMiscFlags = NULL;
      return E_UNEXPECTED;
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::QueryPersistenceInterface(REFIID riid)
{
      if (riid == IID_IPersistTextStream)
             return S_OK;
      return S_FALSE;
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::SaveRuntimeState
(
      REFIID riidPersist,
      REFIID riidObjStgMed,
      void  *pObjStgMed
)
{
      HRESULT  hr;
      CString  cstrText;
      BSTR     bstrText;
      METHOD_MANAGE_STATE(CBGSoundCtrl, ActiveDesigner)
      if (riidPersist != IID_IPersistTextStream)
             return E_NOINTERFACE;
      if (riidObjStgMed != IID_IStream)
             return E_NOINTERFACE;
      hr = pThis->GetRuntimeText(cstrText);
      if (SUCCEEDED(hr))
      {
             bstrText = cstrText.AllocSysString();
             if (bstrText)
             {
                    hr = ((IStream *)pObjStgMed)->Write(bstrText,                                     SysStringByteLen(bstrText) + sizeof(OLECHAR), NULL);
                 SysFreeString(bstrText);
             }
             else
                 hr = E_OUTOFMEMORY;
      }
      return hr;
}
STDMETHODIMP CBGSoundCtrl::XActiveDesigner::GetExtensibilityObject(IDispatch **ppvObjOut)
{
      if (!ppvObjOut)
             return E_INVALIDARG;
      return this->QueryInterface(IID_IDispatch, (void **)ppvObjOut);
}
////////////////////////////////////////////////////////////////////////
// CBGSoundCtrl::GetRuntimeText - Generates run-time text for the control
//
// GetRuntimeText() is called whenever the container needs to update the
// run-time text after property changes or other state changes are made.
HRESULT CBGSoundCtrl::GetRuntimeText(CString& strText)
{
    // our run-time Text template
    CString strTemplate = _T("<BGSOUND SRC=\"%s\" LOOP=%d>");
    // format our string with our properties
      strText.Format(strTemplate, m_strSource, m_nLoop);
      return S_OK;
}
© 1997 Microsoft Corporation. All rights reserved. Legal Notices.