什麼是 HRESULT?
HRESULT 是簡單的數據類型,通常由屬性和 ATL 作為傳回值。 下表描述各種值。 標頭檔案 winerror.h 中會包含更多值。
名稱 | 描述: | 值 |
---|---|---|
S_OK | 作業已順利完成 | 0x00000000 |
E_UNEXPECTED | 非預期的失敗 | 0x8000FFFF |
E_NOTIMPL | 未實作 | 0x80004001 |
E_OUTOFMEMORY | 無法配置必要的記憶體 | 0x8007000E |
E_INVALIDARG | 一或多個自變數無效 | 0x80070057 |
E_NOINTERFACE | 不支援這類介面 | 0x80004002 |
E_POINTER | 無效的指標 | 0x80004003 |
E_HANDLE | 控制代碼不正確 | 0x80070006 |
E_ABORT | 作業中止 | 0x80004004 |
E_FAIL | 未指定的失敗 | 0x80004005 |
E_ACCESSDENIED | 一般存取遭拒錯誤 | 0x80070005 |
何時必須指定屬性的參數名稱?
在大部分情況下,如果屬性具有單一參數,該參數就會命名。 在程式代碼中插入 屬性時,不需要此名稱。 例如,下列可匯總屬性的使用方式:
[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};
與:
[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};
不過,下列屬性具有單一且未命名的參數:
我可以在屬性區塊中使用批注嗎?
您可以在屬性區塊內同時使用單行和多行批注。 不過,您無法在括弧內使用任一樣式的批注,將參數套用至屬性。
允許下列專案:
[ coclass, progid("MyClass.CMyClass.1"), /* Multiple-line
comment */
threading("both") // Single-line comment
]
不允許下列專案:
[ coclass, progid("MyClass.CMyClass.1" /* Multiple-line comment */ ), threading("both" // Single-line comment)
]
屬性如何與繼承互動?
您可以從其他類別繼承屬性化和未歸納類別,這些類別本身可能為屬性化或非屬性化。 衍生自屬性類別的結果,與屬性提供者轉換其程式代碼之後,衍生自該類別的結果相同。 屬性不會透過C++繼承傳送至衍生類別。 屬性提供者只會在其屬性附近轉換程序代碼。
如何在非屬性化 ATL 專案中使用屬性?
您可能有具有 .idl 檔案的非attributed ATL 專案,而且您可能想要開始新增屬性化物件。 在此情況下,請使用 [ 新增類別精靈 ] 來提供程序代碼。
如何在屬性化專案中使用 .idl 檔案?
您可能有想要在 ATL 屬性專案中使用的 .idl 檔案。 在此情況下,您會使用 importidl 屬性、將 .idl 檔案編譯為 .h 檔案(請參閱專案 [屬性頁] 對話框中的 MIDL 屬性頁),然後將 .h 檔案包含在專案中。
我可以修改屬性插入的程序代碼嗎?
某些屬性會將程式代碼插入您的專案中。 您可以使用 /Fx 編譯程式選項來查看插入的程式代碼。 您也可以從插入的檔案複製程序代碼,並將它貼到您的原始程式碼中。 這可讓您修改 屬性的行為。 不過,您可能也必須修改程序代碼的其他部分。
下列範例是將插入的程式代碼複製到原始碼檔案的結果:
// 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() {}
如何轉送宣告屬性化介面?
如果您要對屬性化介面進行轉送宣告,您必須將相同的屬性套用至您套用至實際介面宣告的轉送宣告。 您也必須將 export 屬性套用至轉送宣告。
我可以在衍生自也使用屬性的類別上使用屬性嗎?
否,不支援在衍生自也使用屬性的類別上使用屬性。