Perguntas freqüentes sobre programação de atributo
Este tópico responde a perguntas freqüentes a seguir:
O que é um HRESULT?
Quando é necessário especificar o nome de parâmetro para um atributo?
Pode usar comentários em um bloco de atributo?
Como os atributos interagem com herança?
Como usar atributos em um projeto do ATL nonattributed?
Como posso usar um arquivo. idl em um projeto atribuído?
Posso modificar o código que é injetado por um atributo?
Como eu declaro frente uma interface atribuída?
Pode usar atributos em uma classe derivada de uma classe que também usa atributos?
O que é um HRESULT?
Um HRESULT é um tipo de dados simples que é freqüentemente usado como um valor de retorno, atributos e ATL em geral.A tabela a seguir descreve os vários valores.Valores mais estão contidos no arquivo de cabeçalho Winerror. h.
Nome |
Descrição |
Valor |
---|---|---|
S_OK |
Operação bem-sucedida |
0x00000000 |
E_UNEXPECTED |
Falha inesperada |
0x8000FFFF |
E_NOTIMPL |
Não implementado |
0x80004001 |
E_OUTOFMEMORY |
Falha ao alocar memória necessária |
0x8007000E |
E_INVALIDARG |
Um ou mais argumentos são inválidos |
0x80070057 |
E_NOINTERFACE |
Nenhuma interface suportada |
0x80004002 |
E_POINTER |
Ponteiro inválido |
0x80004003 |
E_HANDLE |
Identificador inválido |
0x80070006 |
E_ABORT |
Operação anulada |
0x80004004 |
E_FAIL |
Falha não especificada |
0x80004005 |
E_ACCESSDENIED |
Acesso geral negado erro |
0x80070005 |
Quando é necessário especificar o nome de parâmetro para um atributo?
Na maioria dos casos, se o atributo tem um único parâmetro, esse parâmetro é chamado.Esse nome não é necessário ao inserir o atributo no seu código.Por exemplo, o seguinte uso da agregável atributo:
[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};
é exatamente igual:
[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};
No entanto, os seguintes atributos têm parâmetros único, sem nome:
Pode usar comentários em um bloco de atributo?
Você pode usar os comentários de linha única e de várias linhas dentro de um bloco de atributo.No entanto, você não pode usar dois estilos de comentário dentro dos parênteses, mantendo os parâmetros para um atributo.
É permitido o seguinte:
[ coclass,
progid("MyClass.CMyClass.1"), /* Multiple-line
comment */
threading("both") // Single-line comment
]
A seguir não é permitida:
[ coclass,
progid("MyClass.CMyClass.1" /* Multiple-line comment */ ),
threading("both" // Single-line comment)
]
Como os atributos interagem com herança?
Você pode herdar classes atribuídas e unattributed de outras classes, que pode ser eles próprios ser atribuídos ou não.O resultado da derivação de uma classe atribuído em grande parte é o mesmo que derivar dessa classe depois que o provedor de atributo transformou seu código.Atributos não são transmitidos para derivadas de classes através de herança do C++.Um provedor de atributo apenas transforma código perto de seus atributos.
Como usar atributos em um projeto do ATL nonattributed?
Você pode ter um projeto ATL nonattributed, que tem um arquivo. idl, e você talvez queira começar a adicionar objetos atribuídos.Nesse caso, use o Assistente para adicionar classe para fornecer o código.
Como posso usar um arquivo. idl em um projeto atribuído?
Você pode ter um arquivo. idl que você deseja usar em seu projeto ATL atribuído.Nesse caso, você usaria o importidl de atributo, compile o arquivo. idl para um arquivo. h (consulte a Páginas de propriedades de MIDL na caixa de diálogo de páginas de propriedades do projeto) e, em seguida, incluir o arquivo. h em seu projeto.
Posso modificar o código que é injetado por um atributo?
Alguns atributos injetar código no seu projeto.Você pode ver o código injetado usando o /Fx opção de compilador.Também é possível copiar o código do arquivo injetado e colá-lo em seu código-fonte.Isso permite que você modificar o comportamento do atributo.No entanto, talvez você precise modificar outras partes do seu código também.
O exemplo a seguir é o resultado de copiar o código injetado em um arquivo de código-fonte:
// 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() {}
Como eu declaro frente uma interface atribuída?
Se você for fazer uma declaração de reenvio de uma interface atribuído em grande parte, você deve aplicar os mesmos atributos para a declaração de reenvio aplicáveis para a declaração de interface real.Você também deve aplicar o exportação atributo à declaração de encaminhamento.
Pode usar atributos em uma classe derivada de uma classe que também usa atributos?
Não, não há suporte para o uso de atributos em uma classe derivada de uma classe que também usa atributos.