Was ist HRESULT?
HRESULT ist ein einfacher Datentyp, der häufig als Rückgabewert von Attributen und ATL im Allgemeinen verwendet wird. In der folgenden Tabelle sind die verschiedenen Werte beschrieben. Weitere Werte sind in der Headerdatei „winerror.h“ enthalten.
Name | Beschreibung | Wert |
---|---|---|
S_OK | Vorgang erfolgreich | 0x00000000 |
E_UNEXPECTED | Unerwarteter Fehler | 0x8000FFFF |
E_NOTIMPL | Nicht implementiert | 0x80004001 |
E_OUTOFMEMORY | Fehler beim Zuordnen des erforderlichen Arbeitsspeichers | 0x8007000E |
E_INVALIDARG | Mindestens ein Argument ist ungültig. | 0x80070057 |
E_NOINTERFACE | Schnittstelle nicht unterstützt. | 0x80004002 |
E_POINTER | Ungültiger Zeiger | 0x80004003 |
E_HANDLE | Ungültiges Handle | 0x80070006 |
E_ABORT | Vorgang abgebrochen | 0x80004004 |
E_FAIL | Unbekannter Fehler | 0x80004005 |
E_ACCESSDENIED | Allgemeiner Zugriffsfehler | 0x80070005 |
Wann muss ich den Parameternamen für ein Attribut angeben?
Wenn das Attribut über einen einzelnen Parameter verfügt, ist dieser Parameter in den meisten Fällen benannt. Dieser Name ist beim Einfügen des Attributs in den Code nicht erforderlich. Die folgende Verwendung des Attributs aggregatable ist beispielsweise:
[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};
identisch mit:
[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};
Die folgenden Attribute weisen jedoch einzelne, unbenannte Parameter auf:
Kann ich Kommentare in einem Attributblock verwenden?
Sie können sowohl einzeilige als auch mehrzeilige Kommentare innerhalb eines Attributblocks verwenden. Sie können jedoch keine der Kommentararten innerhalb der Klammern verwenden, die die Parameter für ein Attribut enthalten.
Folgendes ist nicht lässig:
[ coclass, progid("MyClass.CMyClass.1"), /* Multiple-line
comment */
threading("both") // Single-line comment
]
Folgendes ist nicht lässig:
[ coclass, progid("MyClass.CMyClass.1" /* Multiple-line comment */ ), threading("both" // Single-line comment)
]
Wie interagieren Attribute mit der Vererbung?
Sie können Klassen mit und ohne Attribute von anderen Klassen erben, die selbst Attribute bzw. keine Attribute besitzen können. Das Ergebnis der Ableitung von einer Klasse mit Attributen ist identisch mit der Ableitung von dieser Klasse, nachdem der Attributanbieter seinen Code transformiert hat. Attribute werden nicht über die C++-Vererbung an abgeleitete Klassen übertragen. Ein Attributanbieter transformiert Code nur in der Nähe seiner Attribute.
Wie kann ich Attribute in einem ATL-Projekt ohne Attribute verwenden?
Möglicherweise verfügen Sie über ein ATL-Projekt ohne Attribute mit einer IDL-Datei, und Sie möchten mit dem Hinzufügen von Objekten mit Attributen beginnen. Verwenden Sie in diesem Fall den Assistenten zum Hinzufügen von Klassen, um den Code bereitzustellen.
Wie kann ich eine IDL-Datei in einem Projekt mit Attributen verwenden?
Möglicherweise verfügen Sie über eine IDL-Datei, die Sie in Ihrem ATL-Attributprojekt verwenden möchten. In diesem Fall verwenden Sie das Attribut importidl, kompilieren die IDL-Datei in eine H-Datei (siehe MIDL-Eigenschaftenseiten im Dialogfeld Eigenschaftenseiten des Projekts) und fügen dann die H-Datei in Ihr Projekt ein.
Kann ich Code ändern, der von einem Attribut eingefügt wird?
Einige Attribute fügen Code in Ihr Projekt ein. Sie können den eingefügten Code mithilfe der Compileroption /Fx anzeigen. Es ist auch möglich, Code aus der eingefügten Datei zu kopieren und in Ihren Quellcode einzufügen. Auf diese Weise können Sie das Verhalten des Attributs ändern. Möglicherweise müssen Sie jedoch auch andere Teile des Codes ändern.
Das folgende Beispiel ist das Ergebnis beim Kopieren von eingefügtem Code in eine Quellcodedatei:
// 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() {}
Wie kann ich eine Schnittstelle mit Attributen vorwärts deklarieren?
Wenn Sie eine Vorwärtsdeklaration einer Schnittstelle mit Attributen vornehmen möchten, müssen Sie dieselben Attribute auf die Vorwärtsdeklaration anwenden, die Sie auf die tatsächliche Schnittstellendeklaration anwenden. Sie müssen auch das Attribut export auf die Vorwärtsdeklaration anwenden.
Kann ich Attribute für eine von einer Klasse abgeleitete Klasse verwenden, die auch Attribute verwendet?
Nein, die Verwendung von Attributen für eine von einer Klasse abgeleitete Klasse, die auch Attribute verwendet, wird nicht unterstützt.