This section steps you through the process of implementing a procedural surface with Microsoft® Visual Studio®.
#include <ocidl.h> #include <dxtrans.h> #include <dxbounds.h> #include <dxhelper.h> #include <dxsurfb.h> #include <atlctl.h>
#include <dxtguid.c> #include <dtbase.cpp> #include <dxsurfb.cpp> #include <atlctl.cpp>
import "Dxtrans.idl";
public CComObjectRootEx<CComMultiThreadModel>, public CComCoClass<CMySurface, &CLSID_MySurface>, public IDispatchImpl<IMySurface, &IID_IMySurface, &LIBID_MYPROJECTLib>
with the following lines.
public CComCoClass<CMySurface, &CLSID_MySurface>, public IDispatchImpl<IMySurface, &IID_IMySurface, &LIBID_MYPROJECTLib>, public CComPropertySupport<CMySurface>, public IPersistStorageImpl<CMySurface>, public ISpecifyPropertyPagesImpl<CMySurface>, public IPersistPropertyBagImpl<CMySurface>, public CDXBaseSurface, public IDXTScaleOutput
COM_INTERFACE_ENTRY_IMPL(IPersistStorage) COM_INTERFACE_ENTRY_IMPL(ISpecifyPropertyPages) COM_INTERFACE_ENTRY_IMPL(IPersistPropertyBag) COM_INTERFACE_ENTRY(IDXTScaleOutput) COM_INTERFACE_ENTRY_CHAIN(CDXBaseSurface)
BEGIN_PROPERTY_MAP(CMySurface) END_PROPERTY_MAP()
DECLARE_REGISTRY_RESOURCEID(IDR_MYSURFACE)
to:
DECLARE_REGISTER_DX_SURFACE(IDR_MYSURFACE) DECLARE_POLY_AGGREGATABLE(CMySurface) DECLARE_PROTECT_FINAL_CONSTRUCT()
const GUID & SurfaceCLSID() { return GetObjectCLSID(); } HRESULT CreateARGBPointer(CDXBaseSurface * pSurface, CDXBaseARGBPtr ** ppPtr); void DeleteARGBPointer(CDXBaseARGBPtr *pPtr); STDMETHODIMP SetOutputSize(const SIZE OutputSize, BOOL bMaintainAspect);
class MySurfacePtr : public CDXBaseARGBPtr { public: MySurfacePtr(CDXBaseSurface * pSurface) : CDXBaseARGBPtr(pSurface) {} void FillSamples(const DXPtrFillInfo & FillInfo); public: };
HRESULT CMySurface::CreateARGBPointer(CDXBaseSurface * pSurface, CDXBaseARGBPtr ** ppPtr) { *ppPtr = new MySurfacePtr(this); if (*ppPtr) { return S_OK; } else { return E_OUTOFMEMORY; } } void CMySurface::DeleteARGBPointer(CDXBaseARGBPtr *pPtr) { delete (MySurfacePtr *)pPtr; }
You need to write three main section of code: the surface constructor, the CMySurface::SetOutputSize method, and the MySurfacePtr::FillSamples method.
In the body of the constructor for your object, you will need to initialize the data members to configure your surface. In addition to the data members that represent the custom properties of the surface, you also need to set the inherited m_Width and m_Height variables that define the size of your surface.
This is the method called by the base class to change the size of the surface. If you need to recalculate any internal data members because of a change to the surface size, you should do that before the method returns.
This method creates your surface a row of samples at a time. It can be called repeatedly by the base class to read the samples of the entire surface or just once to read a portion of an arbitrary row.
The samples you need to calculate for the row are defined by a DXPtrFillInfo structure that is passed as a parameter to the method. It contains the x-axis and y-axis position of the first sample, the number of samples in the row to fill, and a pointer to the output sample array. There is also an option for the surface user to request the sample output in either ARGB32 or PMARGB32 format. You need to write routines that check for this and produce samples in the requested output format.
In the MySurface.h file, enter the following code to the PROPERTY_MAP statement, just before the END_PROPERTY_MAP statement.
PROP_PAGE(CLSID_MySurfacePP)
For each private data member of your surface that represents a custom property, you need to implement put_ and get_ access functions. These are often declared in your MySurface.h header file in the following manner.
STDMETHOD( get_MyProperty )( float *pVal ); STDMETHOD( put_MyProperty )( float newVal );
Add dispatch interface support for the MySurface interface. Create an enumeration for the dispatcher identifiers, with each property as an element of the enumeration. Place it just before the entry for MyEffect in the project's .idl file.
typedef enum MyEffectDISPID { DISPID_MyEffect_MyProperty1 = DISPID_DXE_NEXT_ID, DISPID_MyEffect_MyProperty2, } MyEffectDISPID;
Add dispatcher methods to the MyEffect interface, as shown in the following code.
interface MyEffect : IDXEffect { [propget, id(DISPID_MyEffect_MyProperty1), helpstring("property MyProperty1")] HRESULT MyProperty1([out, retval] float *pVal); [propput, id(DISPID_MyEffect_MyProperty1), helpstring("property MyProperty1")] HRESULT MyProperty1([in] float newVal); [propget, id(DISPID_MyEffect_MyProperty2), helpstring("property MyProperty2")] HRESULT MyProperty2([out, retval] float *pVal); [propput, id(DISPID_MyEffect_MyProperty2), helpstring("property MyProperty2")] HRESULT MyProperty2([in] float newVal); };
Top of Page
© 2000 Microsoft and/or its suppliers. All rights reserved. Terms of Use.