bullseye.cpp

来自「《ATL深入解析》随书源码」· C++ 代码 · 共 718 行 · 第 1/2 页

CPP
718
字号
	ATLTRACE2(atlTraceControls,2,_T("CBullsEye::EnumFormatEtc\n"));

    if (DATADIR_SET == dwDirection) return E_NOTIMPL;

    typedef CComObject <CComEnum <IEnumFORMATETC, &IID_IEnumFORMATETC, FORMATETC, _Copy<FORMATETC> > > EnumFORMATETC;

    EnumFORMATETC* penum = new EnumFORMATETC ();

    HRESULT hr = penum->Init (&array [0], &array [1], NULL, AtlFlagNoCopy);
    if (FAILED (hr)) return hr;

    penum->AddRef ();
    hr = penum->QueryInterface (ppenumFormatEtc);
    penum->Release ();
    return hr;
}

/////////////////////////////////////////////////////////////////////////////
// IOleControl method overrides

/******************/
/* GetControlInfo */
/******************/

STDMETHODIMP CBullsEye::GetControlInfo(CONTROLINFO *pci)
{
    if(!pci) return E_POINTER;
    pci->hAccel   = NULL;
    pci->cAccel   = 0;
    pci->dwFlags  = 0;     
    return S_OK;
}

/***************************/
/* OnAmbientPropertyChange */
/***************************/

STDMETHODIMP CBullsEye::OnAmbientPropertyChange (DISPID dispid)
{
    ATLTRACE2(atlTraceControls,2,_T("CBullsEye::OnAmbientPropertyChange\n"));
    ATLTRACE2(atlTraceControls,2,_T(" -- DISPID = %d (%d)\n"), dispid);

    bool bViewChange = false;
    if (DISPID_AMBIENT_APPEARANCE == dispid || DISPID_UNKNOWN == dispid) {
        HRESULT hr = GetAmbientAppearance (m_nAppearance);
        bViewChange = true;
    }

    if (DISPID_AMBIENT_BACKCOLOR == dispid || DISPID_UNKNOWN == dispid) {
        HRESULT hr = GetAmbientBackColor (m_clrBackColor);
        if (SUCCEEDED (hr)) {
            ::DeleteObject (m_backBrush);
            m_backBrush = NULL;
            bViewChange = true;
        }
    }

    if (DISPID_AMBIENT_FORECOLOR == dispid || DISPID_UNKNOWN == dispid) {
        HRESULT hr = GetAmbientForeColor (m_clrForeColor);
        if (SUCCEEDED (hr)) {
            bViewChange = true;
        }
    }

    if (bViewChange) FireViewChange(); // Request redraw
    return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// IOleInPlaceActiveObject method overrides

/************************/
/* TranslateAccelerator */
/************************/

typedef enum tagKEYMODIFIERS {
    KEYMOD_SHIFT      = 0x00000001, 
    KEYMOD_CONTROL    = 0x00000002,
    KEYMOD_ALT        = 0x00000004 
} KEYMODIFIERS; 

STDMETHODIMP CBullsEye::TranslateAccelerator(MSG *pMsg)
{
    if (((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST)) &&
        ((VK_TAB == pMsg->wParam) || (VK_RETURN == pMsg->wParam))) {
        
        CComQIPtr<IOleControlSite, &IID_IOleControlSite> spCtrlSite(m_spClientSite);
        if (spCtrlSite) {
            DWORD km = 0;
            km |= GetKeyState (VK_SHIFT)   < 0 ? KEYMOD_SHIFT   : 0;
            km |= GetKeyState (VK_CONTROL) < 0 ? KEYMOD_CONTROL : 0;
            km |= GetKeyState (VK_MENU)    < 0 ? KEYMOD_ALT     : 0;

            return spCtrlSite->TranslateAccelerator (pMsg, km);
        }
    }
    return S_FALSE;  
}

/////////////////////////////////////////////////////////////////////////////
// IOleControl method overrides

STDMETHODIMP CBullsEye::GetMiscStatus (DWORD dwAspect, DWORD *pdwStatus)
{
    if (NULL == pdwStatus) return E_POINTER;

    *pdwStatus = 
           OLEMISC_SETCLIENTSITEFIRST |
           OLEMISC_ACTIVATEWHENVISIBLE |
           OLEMISC_INSIDEOUT |
           OLEMISC_CANTLINKINSIDE |
           OLEMISC_RECOMPOSEONRESIZE |
           OLEMISC_NOUIACTIVATE ;

    return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// CComControlBase method overrides

/********************************/
/* IQuickActivate_QuickActivate */
/********************************/

HRESULT CBullsEye::IQuickActivate_QuickActivate(QACONTAINER *pQACont, QACONTROL *pQACtrl)
{
    m_clrForeColor = pQACont->colorFore;
    m_clrBackColor = pQACont->colorBack;
    m_nAppearance  = (short) pQACont->dwAppearance;
    m_bAmbientsFetched = true;

    HRESULT hr = CComControlBase::IQuickActivate_QuickActivate(pQACont, pQACtrl);
    return hr;
}

/****************************/
/* IOleObject_SetClientSite */
/****************************/

HRESULT CBullsEye::IOleObject_SetClientSite(IOleClientSite *pClientSite)
{
    HRESULT hr = CComControlBase::IOleObject_SetClientSite(pClientSite);
    // If we QuickActivated, we already have the ambients desired
    // otherwise, this is the time to grab them
    if (!m_bAmbientsFetched) {
        HRESULT hr = GetAmbientBackColor (m_clrBackColor);
                hr = GetAmbientForeColor (m_clrForeColor);
                hr = GetAmbientAppearance (m_nAppearance);
    }
    return hr;
}

/***************************/
/* IPersistStreamInit_Save */
/***************************/

HRESULT CBullsEye::IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap)
{
	if (NULL == pStm) return E_POINTER;

    // Save the properties described in the PROP_MAP
	HRESULT hr = IPersistStreamInitImpl<CBullsEye>::IPersistStreamInit_Save(pStm,  fClearDirty, pMap);
    if (FAILED (hr)) return hr;

    // Save the indexed property - RingValues

    // Get the number of rings
    short sRingCount;
    get_RingCount (&sRingCount);

    // For each ring, write its value
    for (short nIndex = 1; nIndex <= sRingCount; nIndex++) {

        // Get the ring value
        long lRingValue ;
        get_RingValue (nIndex, &lRingValue);

        // Write it to the stream
        ULONG cbWritten;
        hr = pStm->Write(&lRingValue, sizeof(lRingValue), &cbWritten);
        ATLASSERT (SUCCEEDED (hr));
        ATLASSERT (sizeof(lRingValue) == cbWritten);
        if (FAILED (hr) || cbWritten != sizeof(lRingValue)) {
            hr = E_UNEXPECTED;
            break;
        }
	}
    return hr;
}

/***************************/
/* IPersistStreamInit_Load */
/***************************/

HRESULT CBullsEye::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap)
{
    if (NULL == pStm) return E_POINTER;

    // Load the properties described in the PROP_MAP
	HRESULT hr = IPersistStreamInitImpl<CBullsEye>::IPersistStreamInit_Load(pStm, pMap);
    if (FAILED (hr)) return hr;

    // Load the indexed property - RingValues

    // Get the number of rings
    short sRingCount;
    get_RingCount (&sRingCount);

    // For each ring, read its value
    for (short nIndex = 1; nIndex <= sRingCount; nIndex++) {

        // Read ring value from the stream
        long lRingValue ;
        ULONG cbRead;
        hr = pStm->Read(&lRingValue, sizeof(lRingValue), &cbRead);
        ATLASSERT (SUCCEEDED (hr));
        ATLASSERT (sizeof(lRingValue) == cbRead);
        if (FAILED (hr) || cbRead != sizeof(lRingValue)) {
            hr = E_UNEXPECTED;
            break;
        }

        // Set the ring value
        put_RingValue (nIndex, lRingValue);

	}

    if (SUCCEEDED(hr)) m_bRequiresSave = TRUE;
    return hr;
}

/****************************/
/* IPersistPropertyBag_Save */
/****************************/

HRESULT CBullsEye::IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap)
{
	if (NULL == pPropBag) return E_POINTER;

    // Save the properties described in the PROP_MAP
	HRESULT hr = IPersistPropertyBagImpl<CBullsEye>::IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap);
    if (FAILED (hr)) return hr;

    // Save the indexed property - RingValues

    // Get the number of rings
    short sRingCount;
    get_RingCount (&sRingCount);

    // For each ring, write its value
    for (short nIndex = 1; nIndex <= sRingCount; nIndex++) {

        // Create the property name
        CComBSTR bstrName = OLESTR("RingValue");
        CComVariant vRingNumber = nIndex;
        hr = vRingNumber.ChangeType (VT_BSTR);
        ATLASSERT (SUCCEEDED (hr));
        bstrName += vRingNumber.bstrVal;

        // Get the ring value
        long lRingValue ;
        get_RingValue (nIndex, &lRingValue);

        // Write it to the stream
        CComVariant vValue = lRingValue;
        hr = pPropBag->Write(bstrName, &vValue);
        ATLASSERT (SUCCEEDED (hr));
        if (FAILED (hr)) {
            hr = E_UNEXPECTED;
            break;
        }
	}
    return hr;
}

/****************************/
/* IPersistPropertyBag_Load */
/****************************/

HRESULT CBullsEye::IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap)
{
    if (NULL == pPropBag) return E_POINTER;

    // Load the properties described in the PROP_MAP
//	HRESULT hr = IPersistPropertyBagImpl<CBullsEye>::IPersistPropertyBag_Load(pPropBag, pErrorLog, pMap);

    // Work around ATL 3.0 bug in AtlIPersistPropertyBag_Load
    HRESULT hr = FixedAtlIPersistPropertyBag_Load(pPropBag, pErrorLog, pMap, this, GetUnknown());
	if (SUCCEEDED(hr))
		m_bRequiresSave = FALSE;

    if (FAILED (hr)) return hr;

    // Load the indexed property - RingValues

    // Get the number of rings
    short sRingCount;
    get_RingCount (&sRingCount);

    // For each ring, read its value
    for (short nIndex = 1; nIndex <= sRingCount; nIndex++) {

        // Create the base property name
        CComBSTR bstrName = OLESTR("RingValue");

        // Create ring number as a string
        CComVariant vRingNumber = nIndex;
        hr = vRingNumber.ChangeType (VT_BSTR);
        ATLASSERT (SUCCEEDED (hr));

        // Concatenate the two strings to form property name
        bstrName += vRingNumber.bstrVal;

        // Read ring value from the property bag
        CComVariant vValue = 0L;
        hr = pPropBag->Read(bstrName, &vValue, pErrorLog);
        ATLASSERT (SUCCEEDED (hr));
        ATLASSERT (VT_I4 == vValue.vt);

        if (FAILED (hr)) {
            hr = E_UNEXPECTED;
            break;
        }

        // Set the ring value
        put_RingValue (nIndex, vValue.lVal);
	}

    if (SUCCEEDED(hr)) m_bRequiresSave = TRUE;
    return hr;
}

/***************************************************/
/* IPersistPropertyBag/IPersistStreamInit::InitNew */
/***************************************************/

/*

  *** Special Initialization required to run with Access ***

Control Initialization

After insertion, switch immediately to browse view (View | Form View) to
make sure your control doesn抰 cause the error - "No object in this
control." Many lightweight custom controls forget to mark themselves as
dirty after insertion in the container. Access optimizes its code-path
for saving cached merged type information for the extender object and
the controls inserted to just those controls that have been dirtied in
the current design session. When the user views the form in browse view,
the form gets destroyed, and recreated. If the control has not marked
itself as dirty, then just the extender object is on the form with no
control inside of it. This is a common mistake when control developers
use the BaseCtl framework, but the fix is simple. MFC and VB control
writers don抰 have to worry about this since the frameworks handle this
for you. Here are some additional comments from an email thread on a
similar case:

Some BaseCtl framework OCXs are getting the "There is no object in this
control" error message when an Access 

⌨️ 快捷键说明

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