Preguntas más frecuentes sobre la programación de atributo
En este tema se responden las preguntas más frecuentes siguientes:
¿Qué es un HRESULT?
¿Cuándo hay que especificar el nombre de parámetro para un atributo?
¿Puedo usar comentarios en un bloque de atributos?
¿Cómo los atributos interactúan con herencia?
¿Cómo puedo utilizar atributos en un proyecto sin atributos ATL?
¿Cómo se puede utilizar un archivo .idl en un proyecto con atributos?
¿Se puede modificar el código que es insertado por un atributo?
¿Cómo puedo reenviar declaro una interfaz con atributos?
¿Puedo usar atributos en una clase derivada de una clase que también utilice atributos?
¿Qué es un HRESULT?
HRESULT es un tipo de datos simple que se utiliza a menudo como valor devuelto por atributos y ATL en general.La tabla siguiente se describen los valores diferentes.Más valores se encuentran en el archivo de encabezado winerror.h.
Name |
Descripción |
Valor |
---|---|---|
S_OK |
operación correctamente |
0x00000000 |
E_UNEXPECTED |
error inesperado |
0x8000FFFF |
E_NOTIMPL |
no implementado |
0x80004001 |
E_OUTOFMEMORY |
Error al asignar memoria necesaria |
0x8007000E |
E_INVALIDARG |
Uno o varios argumentos no son válidos |
0x80070057 |
E_NOINTERFACE |
Ninguna como interfaz compatible |
0x80004002 |
E_POINTER |
Puntero no válido |
0x80004003 |
E_HANDLE |
Identificador no válido |
0x80070006 |
E_ABORT |
Operación anula |
0x80004004 |
E_FAIL |
error sin especificar |
0x80004005 |
E_ACCESSDENIED |
error general de acceso denegado |
0x80070005 |
¿Cuándo hay que especificar el nombre de parámetro para un atributo?
En la mayoría de los casos, si el atributo tiene un único parámetro, se llama a dicho parámetro.Este nombre no se requieren para insertar el atributo en el código.Por ejemplo, el uso de atributo siguiente de aggregatable :
[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};
es exactamente igual que:
[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};
Sin embargo, los atributos siguientes tienen parámetros únicos, sin nombre:
¿Puedo usar comentarios en un bloque de atributos?
Puede usar los comentarios de una sola línea y de varias líneas dentro de un bloque de atributos.Sin embargo, no puede utilizar cualquier estilo de comentario dentro de los paréntesis que contiene los parámetros para un atributo.
Se permite lo siguiente:
[ coclass,
progid("MyClass.CMyClass.1"), /* Multiple-line
comment */
threading("both") // Single-line comment
]
Se deniega a continuación:
[ coclass,
progid("MyClass.CMyClass.1" /* Multiple-line comment */ ),
threading("both" // Single-line comment)
]
¿Cómo los atributos interactúan con herencia?
Puede heredan las clases con y sin de otras clases, que pueden propios atributos o no.El resultado de derivación de una clase con atributos es igual que derivando de esa clase después de que el proveedor de atributo ha transformado el código.Los atributos no se transmiten a las clases derivadas con herencia de C++.Un proveedor de atributo transforma sólo código cerca de sus atributos.
¿Cómo puedo utilizar atributos en un proyecto sin atributos ATL?
Puede tener un proyecto sin atributos ATL, que tiene un archivo .idl, y puede que desee iniciar objetos atribuidos suma.En este caso, use el asistente para la clase add para proporcionar código.
¿Cómo se puede utilizar un archivo .idl en un proyecto con atributos?
Puede tener un archivo .idl que desee utilizar en el proyecto con atributos ATL.En este caso, usa el atributo de importidl , compila el archivo .idl un archivo .h (vea Páginas de propiedades MIDL en el cuadro de diálogo páginas de propiedades del proyecto) y, a continuación incluye el archivo .h en el proyecto.
¿Se puede modificar el código que es insertado por 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 de archivo insertado y pegarlo en el código fuente.Esto permite modificar el comportamiento del atributo.Sin embargo, puede ser necesario modificar otras partes del código también.
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 reenviar declaro una interfaz con atributos?
Si va a hacer una declaración adelantada de una interfaz con atributos, debe aplicar los mismos atributos a la declaración adelantada que aplica a la declaración de la interfaz.También debe aplicar el atributo de exportar a la declaración adelantada.
¿Puedo usar atributos en una clase derivada de una clase que también utilice atributos?
No, utilizando atributos en una clase derivada de una clase que también utilice atributos no se admite.