Edit

Bagikan melalui


FAQ pemrograman atribut

Apa itu HRESULT?

HRESULT adalah jenis data sederhana yang sering digunakan sebagai nilai pengembalian berdasarkan atribut dan ATL secara umum. Tabel berikut ini menjelaskan berbagai nilai. Nilai lainnya terkandung dalam file header winerror.h.

Nama Deskripsi Nilai
S_OK Operasi berhasil 0x00000000
E_UNEXPECTED Kegagalan tak terduga 0x8000FFFF
E_NOTIMPL Tidak diimplementasikan 0x80004001
E_OUTOFMEMORY Gagal mengalokasikan memori yang diperlukan 0x8007000E
E_INVALIDARG Satu atau beberapa argumen tidak valid 0x80070057
E_NOINTERFACE Tidak ada antarmuka seperti itu yang didukung 0x80004002
E_POINTER Penunjuk tidak valid 0x80004003
E_HANDLE Handel tidak valid 0x80070006
E_ABORT Operasi dibatalkan 0x80004004
E_FAIL Kegagalan yang tidak ditentukan 0x80004005
E_ACCESSDENIED Kesalahan akses umum ditolak 0x80070005

Kapan saya harus menentukan nama parameter untuk atribut?

Dalam kebanyakan kasus, jika atribut memiliki parameter tunggal, parameter tersebut diberi nama. Nama ini tidak diperlukan saat menyisipkan atribut dalam kode Anda. Misalnya, penggunaan atribut agregat berikut:

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

sama persis dengan:

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

Namun, atribut berikut memiliki parameter tunggal yang tidak disebutkan namanya:

Dapatkah saya menggunakan komentar dalam blok atribut?

Anda dapat menggunakan komentar baris tunggal dan beberapa baris dalam blok atribut. Namun, Anda tidak dapat menggunakan salah satu gaya komentar dalam tanda kurung yang menyimpan parameter ke atribut .

Berikut ini diperbolehkan:

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

Berikut ini tidak diizinkan:

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

Bagaimana atribut berinteraksi dengan pewarisan?

Anda dapat mewarisi kelas yang diatribusikan dan tidak dikaitkan dari kelas lain, yang mungkin dikaitkan atau tidak. Hasil dari turunan dari kelas yang diatribusikan sama dengan turunan dari kelas tersebut setelah penyedia atribut mengubah kodenya. Atribut tidak ditransmisikan ke kelas turunan melalui warisan C++. Penyedia atribut hanya mengubah kode di sekitar atributnya.

Bagaimana cara menggunakan atribut dalam proyek ATL yang tidak diganggu?

Anda mungkin memiliki proyek ATL yang tidak terganggu, yang memiliki file .idl, dan Anda mungkin ingin mulai menambahkan objek yang diatribusikan. Dalam hal ini, gunakan Wizard Tambahkan Kelas untuk memberikan kode.

Bagaimana cara menggunakan file .idl dalam proyek yang diatribusikan?

Anda mungkin memiliki file .idl yang ingin Anda gunakan dalam proyek yang diatribusikan ATL Anda. Dalam hal ini, Anda akan menggunakan atribut importidl, mengkompilasi file .idl ke file .h (lihat Halaman Properti MIDL dalam kotak dialog Halaman Properti proyek), lalu menyertakan file .h dalam proyek Anda.

Dapatkah saya mengubah kode yang disuntikkan oleh atribut?

Beberapa atribut menyuntikkan kode ke dalam proyek Anda. Anda dapat melihat kode yang disuntikkan dengan menggunakan opsi pengkompilasi /Fx . Dimungkinkan juga untuk menyalin kode dari file yang disuntikkan dan menempelkannya ke dalam kode sumber Anda. Ini memungkinkan Anda untuk memodifikasi perilaku atribut. Namun, Anda mungkin juga harus memodifikasi bagian lain dari kode Anda.

Sampel berikut adalah hasil penyalinan kode yang disuntikkan ke dalam file kode sumber:

// 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() {}

Bagaimana cara meneruskan deklarasikan antarmuka yang diatribusikan?

Jika Anda akan membuat deklarasi ke depan antarmuka yang diatribusikan, Anda harus menerapkan atribut yang sama ke deklarasi penerusan yang Anda terapkan ke deklarasi antarmuka aktual. Anda juga harus menerapkan atribut ekspor ke deklarasi penerusan Anda.

Dapatkah saya menggunakan atribut pada kelas yang berasal dari kelas yang juga menggunakan atribut?

Tidak, menggunakan atribut pada kelas yang berasal dari kelas yang juga menggunakan atribut tidak didukung.