⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 autofigs.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * AUTOFIGS.CPP
 * Cosmo Chapter 14
 *
 * "Figures" collection object for Cosmo's OLE Automation support,
 * derived from CAutoBase.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Right Reserved.
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  INTERNET>kraigb@microsoft.com
 */


#include "cosmo.h"


/*
 * CAutoFigures::CAutoFigures
 * CAutoFigures::~CAutoFigures
 *
 * Constructor Parameters:
 *  pCL             PCCosmoClient to the client object that we use
 *                  to implement much of this interface.
 */

CAutoFigures::CAutoFigures(PCCosmoClient pCL)
    : CAutoBase(pCL, pCL->m_hInst, IID_ICosmoFigures
    , DIID_DICosmoFigures, NULL)
    {
    return;
    }


CAutoFigures::~CAutoFigures(void)
    {
    return;
    }




/*
 * CAutoFigures::QueryInterface
 * CAutoFigures::AddRef
 * CAutoFigures::Release
 */

STDMETHODIMP CAutoFigures::QueryInterface(REFIID riid, PPVOID ppv)
    {
    *ppv=NULL;

    if (IID_IUnknown==riid || IID_ICosmoFigures==riid)
        *ppv=(IUnknown *)this;

    if (IID_IDispatch==riid || m_diid==riid)
        *ppv=m_pImpIDispatch;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }

STDMETHODIMP_(ULONG) CAutoFigures::AddRef(void)
    {
    return ++m_cRef;
    }

STDMETHODIMP_(ULONG) CAutoFigures::Release(void)
    {
    //CCosmoClient deletes this object during shutdown
    if (0==--m_cRef)
        {
        /*
         * Note:  This early release is to avoid a bug in
         * Beta Windows NT 3.51 at the time this code was
         * finalized.  Technically it should be fine to leave
         * the Release call in CImpIDispatch::~CImpIDispatch
         * (see autobase.cpp), but making the call here
         * avoids a crash on a null pointer.
         */
        ReleaseInterface(m_pImpIDispatch->m_pITypeInfo);
        }
    return m_cRef;
    }




/*
 * CAutoFigures::VTableInterface
 *
 * Purpose:
 *  Returns the right vtable pointer to use when calling
 *  ITypeInfo::Invoke (see CImpIDispatch::Invoke in AUTOBASE.CPP).
 */
void *CAutoFigures::VTableInterface(void)
    {
    return (ICosmoFigures *)this;
    }



//The ICosmoFigures implementation

/*
 * CAutoFigures::Application
 * CAutoFigures::Parent
 * Properties, read-only
 *
 * The application object (CAutoApp) in which we're contained,
 * which is stored in the frame object.  Basically we walk
 * up from the client to the frame to it's application object
 * to get the IDispatch we need.
 */

STDMETHODIMP_(IDispatch *) CAutoFigures::get_Application(void)
    {
    PCCosmoFrame    pFR;

    pFR=(PCCosmoFrame)m_pCL->Frame();
    return pFR->AutoApp()->get_Application();
    }

STDMETHODIMP_(IDispatch *) CAutoFigures::get_Parent(void)
    {
    return get_Application();
    }



/*
 * CAutoFigures::Count
 * Property, read-only
 *
 * The number of figures in this collection
 */

STDMETHODIMP_(long) CAutoFigures::get_Count(void)
    {
    //This is easy:  just the number of items in the listbox.
    return m_pCL->m_cDoc;
    }



/*
 * CAutoFigures::Item
 * Method
 *
 * This is essentially an array lookup operator for the collection.
 * Collection.Item by itself the same as the collection itself.
 * Otherwise you can refer to the item by index or by path, which
 * shows up in the VARIANT parameter.  We have to check the type
 * of the variant to see if it's VT_I4 (an index) or VT_BSTR (a
 * path) and do the right thing.
 */

STDMETHODIMP_(IDispatch *) CAutoFigures::Item(VARIANT index)
    {
    IDispatch  *pIDispatch=NULL;
    PCCosmoDoc  pDoc;
    const int   cch=512;
    TCHAR       szPath[cch];
    UINT        i;
    HWND        hList=m_pCL->m_hListDocs;

    /*
     * Each case in this switch gets at a different pointer
     * and stores it in pIDispatch for return.
     */
    switch (index.vt)
        {
        case VT_ERROR:
            /*
             * No parameters, get the "Figures" collection
             * IDispatch, which we can easily retrieve with
             * our own QueryInterface.
             */
            QueryInterface(IID_IDispatch, (PPVOID)&pIDispatch);
            break;

        case VT_I4:
            if (LB_ERR!=SendMessage(hList, LB_GETTEXT
                , (int)index.lVal, (LONG)&pDoc))
                {
                //Sets pIDispatch to NULL on failure.
                pDoc->AutoFigure()->QueryInterface(IID_IDispatch
                    , (PPVOID)&pIDispatch);
                }

            break;

        case VT_BSTR:
            /*
             * First we'll iterate over the pages and check
             * for full path matches.  If that doesn't yield
             * anything, then we'll see if index.bstrVal is
             * just a filename inside one of the paths.
             */
            for (i=0; i < m_pCL->m_cDoc; i++)
                {
                if (LB_ERR!=SendMessage(hList, LB_GETTEXT
                    , i, (LONG)&pDoc))
                    {
                    pDoc->FilenameGet(szPath, cch);

                   #ifdef WIN32ANSI
                    char    szTemp[512];

                    WideCharToMultiByte(CP_ACP, 0, index.bstrVal, -1
                        , szTemp, 512, NULL, NULL);

                    if (0==lstrcmpi(szPath, szTemp))
                   #else
                    if (0==lstrcmpi(szPath, index.bstrVal))
                   #endif
                        {
                        //Found it...
                        pDoc->AutoFigure()->QueryInterface
                            (IID_IDispatch, (PPVOID)&pIDispatch);
                        }
                    }
                }

            //Stop now if we found anything.
            if (NULL!=pIDispatch)
                break;

            //Now look for portions of the path
            for (i=0; i < m_pCL->m_cDoc; i++)
                {
                if (LB_ERR!=SendMessage(hList, LB_GETTEXT
                    , i, (LONG)&pDoc))
                    {
                    LPTSTR  psz;

                    pDoc->FilenameGet(szPath, cch);

                   #ifdef WIN32ANSI
                    char    szTemp[512];

                    WideCharToMultiByte(CP_ACP, 0, index.bstrVal, -1
                        , szTemp, 512, NULL, NULL);
                    psz=_tcsstr(szPath, szTemp);
                   #else
                    psz=_tcsstr(szPath, index.bstrVal);
                   #endif

                    if (NULL!=psz)
                        {
                        //Found it...
                        pDoc->AutoFigure()->QueryInterface
                            (IID_IDispatch, (PPVOID)&pIDispatch);
                        }
                    }
                }


            break;

        default:
            return NULL;
        }

    return pIDispatch;
    }



/*
 * CAutoFigures::Add
 * CAutoFigures::Open
 * Methods
 *
 * Creates a new figure window with an empty figure (Add) or one
 * with the contents of a file (Open), and adds it to the collection.
 */

STDMETHODIMP_(IDispatch *) CAutoFigures::Add(void)
    {
    return NewFigure(NULL);
    }

STDMETHODIMP_(IDispatch *) CAutoFigures::Open(BSTR bstrPath)
    {
   #ifdef WIN32ANSI
    char        szTemp[512];

    WideCharToMultiByte(CP_ACP, 0, bstrPath, -1, szTemp
        , 512, NULL, NULL);
    return NewFigure(szTemp);
   #else
    return NewFigure(bstrPath);
   #endif
    }



/*
 * CAutoFigures:NewFigure
 *
 * Purpose:
 *  Internal helper function to centralize figure creation for
 *  Add and Open.
 *
 * Parameters:
 *  pszPath         LPTSTR to a file to open if this is an open.
 *                  Should be NULL for Add.
 *
 * Return Value:
 *  IDispatch *     Return value for Add and Open
 */

IDispatch * CAutoFigures::NewFigure(LPTSTR pszPath)
    {
    PCCosmoDoc  pDoc;
    IDispatch  *pIDispatch=NULL;
    HRESULT     hr;

    //Try creating a hidden document, which creates the object.
    pDoc=(PCCosmoDoc)m_pCL->NewDocument(FALSE);

    if (NULL==pDoc)
        return NULL;

    hr=ResultFromScode(E_FAIL);

    //Try to load the file and get the IDispatch for the document
    if (DOCERR_NONE==pDoc->Load(TRUE, pszPath))
        {
        hr=pDoc->AutoFigure()->QueryInterface(IID_IDispatch
            , (PPVOID)&pIDispatch);
        }

    if (FAILED(hr))
        m_pCL->CloseDocument(pDoc);
    else
        g_cObj++;

    return pIDispatch;
    }





/*
 * CAutoFigures::Close
 * Method
 *
 * Closes all figure windows in the collection
 */

STDMETHODIMP_(void) CAutoFigures::Close(void)
    {
    m_pCL->QueryCloseAllDocuments(TRUE, FALSE);
    return;
    }





/*
 * CAutoFigures::_NewEnum
 * Method
 *
 * Creates and returns an enumerator of the current list of
 * figures in this collection.
 */

STDMETHODIMP_(IUnknown *) CAutoFigures::_NewEnum(void)
    {
    PCEnumFigures   pNew=NULL;
    BOOL            fRet=TRUE;

    pNew=new CEnumFigures(m_pCL->Instance());

    if (NULL!=pNew)
        {
        if (!pNew->Init(m_pCL->m_hListDocs, FALSE))
            {
            delete pNew;
            pNew=NULL;
            }
        else
            pNew->AddRef();
        }

    return (IUnknown *)pNew;
    }




//CEnumFigures implementation of IEnumVARIANT


/*
 * CEnumFigures::CEnumFigures
 * CEnumFigures::~CEnumFigures
 *
 * Parameters (Constructor):
 *  hInst           HINSTANCE of the application.
 */

CEnumFigures::CEnumFigures(HINSTANCE hInst)
    {
    m_cRef=0;
    m_hList=NULL;
    m_hInst=hInst;
    m_iCur=0;
    m_cItems=0;
    return;
    }


CEnumFigures::~CEnumFigures(void)
    {
    if (NULL!=m_hList)
        DestroyWindow(m_hList);

    return;
    }



/*
 * CEnumFigures::Init
 *
 * Purpose:
 *  Initializes the enumeration with any operations that might fail.
 *
 * Parameters:
 *  hListPDoc       HWND of the listbox containing the current
 *                  set of document pointers.
 *  fClone          BOOL indicating if this is a clone creation
 *                  in which case hListPDoc already has what we want
 *                  and we can just copy it directly.
 *
 * Return Value:
 *  BOOL            TRUE if initialization succeeded,
 *                  FALSE otherwise.
 */
BOOL CEnumFigures::Init(HWND hListPDoc, BOOL fClone)
    {
    UINT        i;
    UINT        cDoc;
    PCDocument  pDoc;

    //Create our own list
    m_hList=CreateWindow(TEXT("listbox"), TEXT("EnumList")
        , WS_POPUP | LBS_OWNERDRAWFIXED, 0, 0, 100, 100
        , HWND_DESKTOP, NULL, m_hInst, NULL);

    if (NULL==m_hList)
        return FALSE;

    /*
     * An enumeration should not be attached to any sort of
     * dynamic list, so we have to initialize our own list here.
     * Furthermore, the hList we get here has document object
     * pointers which could possibly become invalid and we have
     * no way of knowing it.  So we take each pointer and copy
     * the window handle of that document into our own list.  If
     * the window is destroyed, then we have a way of checking
     * that condition and failing to return a valid pointer
     * in other partsof this enumerator.
     */

    cDoc=(UINT)SendMessage(hListPDoc, LB_GETCOUNT, 0, 0L);

    for (i=0; i < cDoc; i++)
        {
        if (LB_ERR!=SendMessage(hListPDoc, LB_GETTEXT, i
            , (LONG)&pDoc))
            {
            HWND    hWndDoc;

            //When cloning we have the window handle already.
            if (fClone)
                hWndDoc=(HWND)(UINT)(LONG)pDoc;
            else
                hWndDoc=pDoc->Window();

            if (LB_ERR!=SendMessage(m_hList, LB_ADDSTRING, 0
                , (LONG)(UINT)hWndDoc))
                m_cItems++;
            }
        }

    return TRUE;
    }



/*
 * CEnumFigures::QueryInterface
 * CEnumFigures::AddRef
 * CEnumFigures::Release
 */

STDMETHODIMP CEnumFigures::QueryInterface(REFIID riid, PPVOID ppv)
    {
    *ppv=NULL;

    if (IID_IUnknown==riid || IID_IEnumVARIANT==riid)
        *ppv=this;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }


STDMETHODIMP_(ULONG) CEnumFigures::AddRef(void)
    {
    ++m_cRef;
    return m_cRef;
    }

STDMETHODIMP_(ULONG) CEnumFigures::Release(void)
    {
    ULONG       cRefT;

    cRefT=--m_cRef;

    if (0L==m_cRef)
        delete this;

    return cRefT;
    }


/*
 * CEnumFigures::Next
 * CEnumFigures::Skip
 * CEnumFigures::Reset
 * CEnumFigures::Clone
 *
 * Standard enumerator members for IEnumVARIANT
 */

STDMETHODIMP CEnumFigures::Next(ULONG cVar, VARIANT *pVar
    , ULONG *pulVar)
    {
    ULONG       cReturn=0L;
    PCCosmoDoc  pDoc;
    HRESULT     hr;
    void       *pv;
    LONG        l;

    if (NULL==pulVar)
        {
        if (1L!=cVar)
            return ResultFromScode(E_POINTER);
        }
    else
        *pulVar=0L;

    if (NULL==pVar || m_iCur >= m_cItems)
        return ResultFromScode(S_FALSE);

    while (m_iCur < m_cItems && cVar > 0)
        {
        if (LB_ERR==SendMessage(m_hList, LB_GETTEXT, (UINT)m_iCur++
            , (LONG)&l))
            continue;

        /*
         * Try getting the document pointer.  If this fails
         * then the window is invalid (document is destroyed)
         * so remove it from the list for future enumerations.
         */
        pDoc=(PCCosmoDoc)SendMessage((HWND)(UINT)l
            , DOCM_PDOCUMENT, 0, 0L);

        if (NULL==pDoc)
            {
            SendMessage(m_hList, LB_DELETESTRING, (UINT)--m_iCur, 0L);
            continue;
            }

        hr=pDoc->AutoFigure()->QueryInterface(IID_IDispatch, &pv);

        if (SUCCEEDED(hr))
            {
            *pVar->ppdispVal=(IDispatch *)pv;
            pVar++;
            cReturn++;
            cVar--;
            }
        }


    if (NULL!=pulVar)
        *pulVar=cReturn;

    return NOERROR;
    }


STDMETHODIMP CEnumFigures::Skip(ULONG cSkip)
    {
    if ((m_iCur+cSkip) >= m_cItems)
        return ResultFromScode(S_FALSE);

    m_iCur+=cSkip;
    return NOERROR;
    }


STDMETHODIMP CEnumFigures::Reset(void)
    {
    m_iCur=0;
    return NOERROR;
    }


STDMETHODIMP CEnumFigures::Clone(LPENUMVARIANT *ppEnum)
    {
    PCEnumFigures   pNew;

    *ppEnum=NULL;

    pNew=new CEnumFigures(m_hInst);

    if (NULL!=pNew)
        {
        if (!pNew->Init(m_hList, TRUE))
            {
            delete pNew;
            pNew=NULL;
            }
        else
            pNew->AddRef();
        }

    *ppEnum=(IEnumVARIANT *)pNew;
    return (NULL!=pNew) ? NOERROR : ResultFromScode(E_OUTOFMEMORY);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -