Editar

Compartir vía


Preguntas más frecuentes de programación con atributos

¿Qué es un HRESULT?

Un HRESULT es un tipo de datos simple que a menudo se usa como un valor devuelto por atributos y ATL en general. En la tabla siguiente se describen los diversos valores. Hay más valores en el archivo de encabezado winerror.h.

Nombre Descripción Valor
S_OK Operación correcta 0x00000000
E_UNEXPECTED Error inesperado 0x8000FFFF
E_NOTIMPL No implementado 0x80004001
E_OUTOFMEMORY No se pudo asignar la memoria necesaria 0x8007000E
E_INVALIDARG Uno o más argumentos no son válidos 0x80070057
E_NOINTERFACE No se admite dicha interfaz 0x80004002
E_POINTER Puntero no válido 0x80004003
E_HANDLE Identificador no válido 0x80070006
E_ABORT Operación anulada 0x80004004
E_FAIL Error no especificado 0x80004005
E_ACCESSDENIED Error de acceso general denegado 0x80070005

¿Cuándo tengo que especificar el nombre del parámetro para un atributo?

En la mayoría de los casos, si el atributo tiene un único parámetro, ese parámetro recibe un nombre. Este nombre no es necesario al insertar el atributo en el código. Por ejemplo, el siguiente uso del atributo aggregatable:

[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};

es exactamente el mismo que:

[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};

Sin embargo, los siguientes atributos tienen parámetros únicos sin nombre:

¿Puedo usar comentarios en un bloque de atributos?

Puede usar comentarios de una sola línea y de varias líneas dentro de un bloque de atributos. Sin embargo, no puede usar ningún estilo de comentario entre los paréntesis que contienen los parámetros de un atributo.

Se permite lo siguiente:

[ coclass, progid("MyClass.CMyClass.1"), /* Multiple-line
                                       comment */
   threading("both") // Single-line comment
]

No se permite lo siguiente:

[ coclass, progid("MyClass.CMyClass.1" /* Multiple-line comment */ ), threading("both" // Single-line comment)
]

¿Cómo interactúan los atributos con la herencia?

Puede heredar clases con atributos y clases sin atributos de otras clases, que pueden atribuirse o no. El resultado de derivar de una clase con atributos es el mismo que derivar de esa clase después de que el proveedor de atributos transformó su código. Los atributos no se transmiten a clases derivadas a través de la herencia de C++. Un proveedor de atributos solo transforma el código en las proximidades de sus atributos.

¿Cómo puedo usar atributos en un proyecto ATL sin atributos?

Es posible que tenga un proyecto de ATL sin atributos, que tiene un archivo .idl, y es posible que quiera empezar a agregar objetos con atributos. En este caso, use el Asistente para agregar clases para proporcionar el código.

¿Cómo puedo usar un archivo .idl en un proyecto con atributos?

Es posible que tenga un archivo .idl que quiera usar en el proyecto ATL con atributos. En este caso, usaría el atributo importidl, compilaría el archivo .idl en un archivo .h (consulte las Páginas de propiedades MIDL en el cuadro de diálogo Páginas de propiedades del proyecto) e incluya el archivo .h en el proyecto.

¿Puedo modificar el código que inserta un atributo?

Algunos atributos insertan código en el proyecto. Puede ver el código insertado mediante la opción del compilador /Fx. También es posible copiar código del archivo insertado y pegarlo en el código fuente. Esto le permite modificar el comportamiento del atributo. Sin embargo, es posible que también tenga que modificar otras partes del código.

El ejemplo siguiente es el resultado de copiar código insertado en un archivo de código fuente:

// attr_injected.cpp
// compile with: comsupp.lib
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>

[ module(name="MyLibrary") ];

// ITestTest
[
   object, uuid("DADECE00-0FD2-46F1-BFD3-6A0579CA1BC4"), dual, helpstring("ITestTest Interface"), pointer_default(unique)
]

__interface ITestTest : IDispatch {
   [id(1), helpstring("method DoTest")]
   HRESULT DoTest([in] BSTR str);
};

// _ITestTestEvents
[
   uuid("12753B9F-DEF4-49b0-9D52-A79C371F2909"), dispinterface, helpstring("_ITestTestEvents Interface")
]

__interface _ITestTestEvents {
   [id(1), helpstring("method BeforeChange")] HRESULT BeforeChange([in] BSTR str, [in,out] VARIANT_BOOL* bCancel);
};

// CTestTest
[
   coclass, threading(apartment), vi_progid("TestATL1.TestTest"), progid("TestATL1.TestTest.1"), version(1.0), uuid("D9632007-14FA-4679-9E1C-28C9A949E784"), // this line would be commented out from original file
   // event_source("com"), // this line would be added to support injected code
   source(_ITestTestEvents), helpstring("TestTest Class")
]

class ATL_NO_VTABLE CTestTest : public ITestTest,
// the following base classes support added injected code
public IConnectionPointContainerImpl<CTestTest>,
public IConnectionPointImpl<CTestTest, &__uuidof(::_ITestTestEvents), CComDynamicUnkArray>
{
public:
   CTestTest() {
   }
   // this line would be commented out from original file
   // __event __interface _ITestTestEvents;
   DECLARE_PROTECT_FINAL_CONSTRUCT()
   HRESULT FinalConstruct() {
      return S_OK;
   }

void FinalRelease() {}

public:
   CComBSTR m_value;
   STDMETHOD(DoTest)(BSTR str) {
      VARIANT_BOOL bCancel = FALSE;
      BeforeChange(str,&bCancel);
      if (bCancel) {
          return Error("Error : Someone don't want us to change the value");
      }

   m_value =str;
   return S_OK;
    }
// the following was copied in from the injected code.
HRESULT BeforeChange(::BSTR i1,::VARIANT_BOOL* i2) {
   HRESULT hr = S_OK;
   IConnectionPointImpl<CTestTest, &__uuidof(_ITestTestEvents), CComDynamicUnkArray>* p = this;
   VARIANT rgvars[2];
   Lock();
   IUnknown** pp = p->m_vec.begin();
   Unlock();
   while (pp < p->m_vec.end()) {
      if (*pp != NULL) {
         IDispatch* pDispatch = (IDispatch*) *pp;
         ::VariantInit(&rgvars[1]);
         rgvars[1].vt = VT_BSTR;
         V_BSTR(&rgvars[1])= (BSTR) i1;
         ::VariantInit(&rgvars[0]);
         rgvars[0].vt = (VT_BOOL | VT_BYREF);
         V_BOOLREF(&rgvars[0])= (VARIANT_BOOL*) i2;
         DISPPARAMS disp = { rgvars, NULL, 2, 0 };
         VARIANT ret_val;
         hr = __ComInvokeEventHandler(pDispatch, 1, 1, &disp, &ret_val);
         if (FAILED(hr))
            break;
      }
      pp++;
   }
   return hr;
}

BEGIN_CONNECTION_POINT_MAP(CTestTest)
CONNECTION_POINT_ENTRY(__uuidof(::_ITestTestEvents))
END_CONNECTION_POINT_MAP()
// end added code section

// _ITestCtrlEvents Methods
public:
};

int main() {}

¿Cómo puedo realizar una declaración directa de una interfaz con atributos?

Si realizará una declaración directa de una interfaz con atributos, debe aplicar los mismos atributos a la declaración directa que se aplican a la declaración de interfaz real. También debe aplicar el atributo export a la declaración directa.

¿Puedo usar atributos en una clase derivada de una clase que también usa atributos?

No, no se admite el uso de atributos en una clase derivada de una clase que también usa atributos.