편집

다음을 통해 공유


특성 프로그래밍 FAQ

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 파일이 있는 비대치 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() {}

특성 인터페이스를 선언하는 방법은 무엇입니까?

특성이 지정된 인터페이스의 전달 선언을 만들려는 경우 실제 인터페이스 선언에 적용하는 것과 동일한 특성을 전달 선언에 적용해야 합니다. 또한 내보내특성을 정방향 선언에 적용해야 합니다.

특성을 사용하는 클래스에서 파생된 클래스에 특성을 사용할 수 있나요?

아니요, 특성을 사용하는 클래스에서 파생된 클래스에 특성을 사용하는 것은 지원되지 않습니다.