Upravit

Sdílet prostřednictvím


Nejčastější dotazy k programování s atributy

Co je HRESULT?

HRESULT je jednoduchý datový typ, který se často používá jako návratová hodnota podle atributů a KNIHOVNY ATL obecně. Následující tabulka popisuje různé hodnoty. Další hodnoty jsou obsaženy v souboru hlavičky winerror.h.

Název Popis Hodnota
S_OK Operace byla úspěšná. 0x00000000
E_UNEXPECTED Neočekávané selhání 0x8000FFFF
E_NOTIMPL Není implementováno 0x80004001
E_OUTOFMEMORY Přidělení potřebné paměti se nezdařilo. 0x8007000E
E_INVALIDARG Nejméně jeden argument je neplatný. 0x80070057
E_NOINTERFACE Žádné takové rozhraní není podporováno. 0x80004002
E_POINTER Neplatný ukazatel 0x80004003
E_HANDLE Neplatný popisovač 0x80070006
E_ABORT Operace byla přerušena. 0x80004004
E_FAIL Nespecifikované selhání 0x80004005
E_ACCESSDENIED Obecná chyba odepření přístupu 0x80070005

Kdy musím zadat název parametru pro atribut?

Ve většině případů, pokud má atribut jeden parametr, má tento parametr název. Tento název se při vkládání atributu do kódu nevyžaduje. Například následující použití agregatable atributu:

[coclass, aggregatable(value=allowed)]
class CMyClass
{
// The class declaration
};

je úplně stejný jako:

[coclass, aggregatable(allowed)]
class CMyClass
{
// The class declaration
};

Následující atributy však mají jednoduché nepojmenované parametry:

Můžu použít komentáře v bloku atributů?

V bloku atributu můžete použít jednořádkové i víceřádkové komentáře. V závorkách, které mají parametry atributu, ale nemůžete použít ani jeden styl komentáře.

Je povoleno následující:

[ coclass, progid("MyClass.CMyClass.1"), /* Multiple-line
                                       comment */
   threading("both") // Single-line comment
]

Následující příkazy jsou zakázány:

[ coclass, progid("MyClass.CMyClass.1" /* Multiple-line comment */ ), threading("both" // Single-line comment)
]

Jak atributy komunikují s dědičností?

Můžete dědit atributy i unattributed třídy z jiných tříd, které mohou být přiřazeny, nebo ne. Výsledek odvození z atributu třídy je stejný jako odvození z této třídy poté, co zprostředkovatel atributu transformoval svůj kód. Atributy nejsou přenášeny do odvozených tříd prostřednictvím dědičnosti jazyka C++. Zprostředkovatel atributů transformuje kód pouze v blízkosti jeho atributů.

Jak můžu používat atributy v projektu ATL bez použití?

Je možné, že máte projekt ATL, který má soubor .idl, a můžete začít přidávat atributy objekty. V tomto případě zadejte kód pomocí Průvodce přidáním třídy.

Jak můžu použít soubor .idl v atributovaném projektu?

Pravděpodobně máte soubor .idl, který chcete použít v projektu s atributem ATL. V tomto případě byste použili atribut importidl, zkompilujte soubor .idl do souboru .h (viz stránky vlastností MIDL v dialogovém okně Stránky vlastností projektu) a pak do projektu zahrňte soubor .h.

Můžu upravit kód vložený atributem?

Některé atributy vloží kód do projektu. Vložený kód můžete zobrazit pomocí možnosti kompilátoru /Fx . Je také možné zkopírovat kód z vloženého souboru a vložit ho do zdrojového kódu. To vám umožní upravit chování atributu. Možná ale budete muset upravit i jiné části kódu.

Následující ukázka je výsledkem kopírování vloženého kódu do souboru zdrojového kódu:

// 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 můžu předat deklaraci atributového rozhraní?

Pokud budete provádět předávací deklaraci atributu rozhraní, musíte použít stejné atributy na předávací deklaraci, kterou použijete na skutečnou deklaraci rozhraní. Musíte také použít atribut exportu pro vaši deklaraci předávání.

Je možné použít atributy třídy odvozené z třídy, která používá také atributy?

Ne, použití atributů ve třídě odvozené z třídy, která používá také atributy, není podporováno.