¿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.