屬性的程式設計的常見問題集

本主題回答下列常見的問題:

  • 什麼是 HRESULT?

  • 何時有指定屬性的參數名稱?

  • 可以在屬性區塊中使用註解?

  • 屬性互動繼承的方式?

  • 我要如何在非屬性化的 ATL 專案中使用屬性呢?

  • 我要如何使用屬性化專案中的一個.idl 檔案?

  • 可以修改由屬性插入的程式碼嗎?

  • 我如何向前宣告屬性的介面?

  • 可以使用屬性類別衍生自也要使用屬性的類別上嗎?

什麼是 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
};

不過,下列屬性的單一、 未命名的參數:

call_as

case

cpp_quote

default

預設值]

defaultvtable

emitidl

項目

first_is

helpcontext

說明檔案

helpstring

helpstringcontext

helpstringdll

id

iid_is

import

importlib

包含

includelib

last_is

length_is

max_is

no_injected_text

pointer_default

pragma

restricted

size_is

source

switch_is

switch_type

transmit_as

wire_marshal

可以在屬性區塊中使用註解?

您可以使用屬性區塊內的單行和多行註解。不過,您無法使用保留給屬性的參數在括號內的註解的兩種樣式。

下列被允許的:

[ 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++ 繼承的類別。屬性提供者只會轉換其屬性的 vicinity 中的程式碼。

我要如何在非屬性化的 ATL 專案中使用屬性呢?

您可能必須非屬性化的 ATL 專案,都有一個.idl 檔案,請和您可能想要開始加入屬性化的物件。如此一來,您也可使用 [加入類別精靈提供的程式碼。

我要如何使用屬性化專案中的一個.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() {}

我如何向前宣告屬性的介面?

如果您要做為屬性化的介面的向前宣告,您必須在向前宣告,則套用到實際的介面宣告中套用相同的屬性。您也必須套用匯出屬性設定為您的向前宣告。

可以使用屬性類別衍生自也要使用屬性的類別上嗎?

否,不支援使用屬性,也會使用屬性的類別衍生的類別。

請參閱

其他資源

屬性化程式設計概念