Co to jest HRESULT?
HRESULT to prosty typ danych, który jest często używany jako wartość zwracana przez atrybuty i ATL ogólnie. W poniższej tabeli opisano różne wartości. Więcej wartości znajduje się w pliku nagłówka winerror.h.
Nazwa/nazwisko | Opis | Wartość |
---|---|---|
S_OK | Operacja powiodła się | 0x00000000 |
E_UNEXPECTED | Nieoczekiwany błąd | 0x8000FFFF |
E_NOTIMPL | Nie zaimplementowano | 0x80004001 |
E_OUTOFMEMORY | Nie można przydzielić wymaganej pamięci | 0x8007000E |
E_INVALIDARG | Co najmniej jeden argument jest nieprawidłowy | 0x80070057 |
E_NOINTERFACE | Nie jest obsługiwany taki interfejs | 0x80004002 |
E_POINTER | Nieprawidłowy wskaźnik | 0x80004003 |
E_HANDLE | Nieprawidłowy uchwyt | 0x80070006 |
E_ABORT | Operacja przerwana | 0x80004004 |
E_FAIL | Nieokreślony błąd | 0x80004005 |
E_ACCESSDENIED | Błąd odmowy dostępu ogólnego | 0x80070005 |
Kiedy muszę określić nazwę parametru dla atrybutu?
W większości przypadków, jeśli atrybut ma jeden parametr, ten parametr ma nazwę. Ta nazwa nie jest wymagana podczas wstawiania atrybutu w kodzie. Na przykład następujące użycie atrybutu aggregatable :
[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};
jest dokładnie taki sam jak:
[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};
Jednak następujące atrybuty mają pojedyncze, nienazwane parametry:
Czy mogę używać komentarzy w bloku atrybutów?
W bloku atrybutów można używać komentarzy jednowierszowych i wielowierszowych. Nie można jednak użyć dowolnego stylu komentarza w nawiasach trzymających parametry do atrybutu.
Dozwolone są następujące elementy:
[ coclass, progid("MyClass.CMyClass.1"), /* Multiple-line
comment */
threading("both") // Single-line comment
]
Następujące warunki są niedozwolone:
[ coclass, progid("MyClass.CMyClass.1" /* Multiple-line comment */ ), threading("both" // Single-line comment)
]
Jak atrybuty współdziałają z dziedziczeniem?
Można dziedziczyć zarówno klasy przypisywane, jak i nieprzydatne z innych klas, które same mogą być przypisywane. Wynik wyprowadzania z klasy przypisanej jest taki sam jak wyprowadzanie z tej klasy po tym, jak dostawca atrybutów przekształcił swój kod. Atrybuty nie są przesyłane do klas pochodnych za pośrednictwem dziedziczenia języka C++. Dostawca atrybutów przekształca kod tylko w pobliżu jego atrybutów.
Jak mogę używać atrybutów w projekcie ATL bez atrybutów?
Być może masz nieprzydatowany projekt ATL, który zawiera plik idl, i może być konieczne rozpoczęcie dodawania obiektów przypisanych. W tym przypadku użyj Kreatora dodawania klas, aby podać kod.
Jak mogę użyć pliku idl w projekcie przypisanym?
Być może masz plik idl, którego chcesz użyć w projekcie przypisanym ATL. W takim przypadku należy użyć atrybutu importidl, skompilować plik idl do pliku h (zobacz strony właściwości MIDL w oknie dialogowym Strony właściwości projektu), a następnie dołączyć plik .h w projekcie.
Czy mogę zmodyfikować kod wstrzykiwany przez atrybut?
Niektóre atrybuty wprowadzają kod do projektu. Możesz zobaczyć wstrzyknięty kod przy użyciu opcji /Fx kompilatora. Istnieje również możliwość skopiowania kodu z wprowadzonego pliku i wklejania go do kodu źródłowego. Dzięki temu można modyfikować zachowanie atrybutu. Może być jednak konieczne zmodyfikowanie innych części kodu.
Poniższy przykład jest wynikiem kopiowania wprowadzonego kodu do pliku kodu źródłowego:
// 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() {}
Jak mogę przekazać dalej deklarowanie interfejsu przypisanego?
Jeśli zamierzasz przesłać deklarację do przodu interfejsu przypisanego, należy zastosować te same atrybuty do deklaracji przesyłania dalej, która ma zastosowanie do rzeczywistej deklaracji interfejsu. Należy również zastosować atrybut eksportu do deklaracji przesyłania dalej.
Czy mogę używać atrybutów w klasie pochodzącej z klasy, która również używa atrybutów?
Nie, używanie atrybutów w klasie pochodzącej z klasy, która również używa atrybutów, nie jest obsługiwane.