属性プログラミングの FAQ
このトピックでは次のよく寄せられる質問とその回答 :
HRESULT は何ですか。
My は属性のパラメーター名を指定する必要があります。
今日は属性ブロックでコメントを使用できますか。
属性はどの程度の継承と対話しているか。
引数に属性なし ATL プロジェクトで属性を使用できますか。
引数に属性付きプロジェクトの .idl ファイルを使用できますか。
今日は属性によって挿入されたコードを変更できますか。
引数に宣言する属性付きインターフェイスを転送したらいいのでしょうか。
My は属性を使用するクラスの派生クラス属性を使用できますか。
HRESULT は何ですか。
HRESULT は属性と ATL で戻り値として一般によく使用される単純型です。次の表に各種の値を示します。以上の値はwinerror.h ヘッダー ファイルに含まれています。
名前 |
Description |
値 |
---|---|---|
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 |
My は属性のパラメーター名を指定する必要があります。
ほとんどの場合属性に一つのパラメーターがの場合そのパラメーターの名前はです。この名前はコードの属性を挿入する必要があります。たとえばaggregatable の属性の使用 :
[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)
]
属性はどの程度の継承と対話しているか。
独自の場合も属性を使用する他のクラスから属性付き ATL オブジェクトと属性のないクラス継承できます。属性付きクラスから派生した結果は属性プロバイダーの後にそのクラスから派生するコードを追加することも同じです。属性はC++ の継承は派生クラスに転送されません。属性プロバイダーは属性の近くにのみコードを変換します。
引数に属性なし ATL プロジェクトで属性を使用できますか。
.idl ファイルを使用して属性付きオブジェクトを追加するときに開始し属性なし ATL プロジェクトが必要です。このコードを提供するためにクラスの追加ウィザードを使用します。
引数に属性付きプロジェクトの .idl ファイルを使用できますか。
ATL によって属性付きプロジェクトで使用する .idl ファイルがある場合があります。この場合.h ファイルに importidl の属性をコンパイルして .idl ファイル (プロジェクトの [プロパティ ページ] ダイアログ ボックスの [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() {}
引数に宣言する属性付きインターフェイスを転送したらいいのでしょうか。
属性付きインターフェイスの事前の宣言を作ろうな場合実際のインターフェイス宣言に適用する事前宣言に同じ属性を適用する必要があります。また事前宣言にエクスポート属性を適用する必要があります。
My は属性を使用するクラスの派生クラス属性を使用できますか。
また属性を使用するクラスの派生クラス属性を使用してではサポートされません。