Kelas ATL mana yang memfasilitasi ActiveX Control Containment?
Kode hosting kontrol ATL tidak mengharuskan Anda untuk menggunakan kelas ATL apa pun; Anda cukup membuat jendela "AtlAxWin80" dan menggunakan API hosting kontrol jika perlu (untuk informasi selengkapnya, lihat Apa ITU ATL Control-Hosting API. Namun, kelas berikut membuat fitur penahanan lebih mudah digunakan.
Kelas | Deskripsi |
---|---|
CAxWindow | Membungkus jendela "AtlAxWin80" , menyediakan metode untuk membuat jendela, membuat kontrol dan/atau melampirkan kontrol ke jendela, dan mengambil penunjuk antarmuka pada objek host. |
CAxWindow2T | Membungkus jendela "AtlAxWinLic80" , menyediakan metode untuk membuat jendela, membuat kontrol dan/atau melampirkan kontrol berlisensi ke jendela, dan mengambil penunjuk antarmuka pada objek host. |
CComCompositeControl | Bertindak sebagai kelas dasar untuk kelas kontrol ActiveX berdasarkan sumber daya dialog. Kontrol tersebut dapat berisi kontrol ActiveX lainnya. |
CAxDialogImpl | Bertindak sebagai kelas dasar untuk kelas dialog berdasarkan sumber daya dialog. Dialog tersebut dapat berisi kontrol ActiveX. |
CWindow | Menyediakan metode, GetDlgControl, yang akan mengembalikan penunjuk antarmuka pada kontrol, mengingat ID jendela host-nya. Selain itu, pembungkus Windows API yang diekspos oleh CWindow umumnya membuat manajemen jendela lebih mudah. |
Apa ITU ATL Control-Hosting API?
API hosting kontrol ATL adalah sekumpulan fungsi yang memungkinkan jendela apa pun bertindak sebagai kontainer kontrol ActiveX. Fungsi-fungsi ini dapat ditautkan secara statis atau dinamis ke dalam proyek Anda karena tersedia sebagai kode sumber dan diekspos oleh ATL90.dll. Fungsi hosting kontrol tercantum dalam tabel di bawah ini.
Fungsi | Deskripsi |
---|---|
AtlAxAttachControl | Membuat objek host, menghubungkannya ke jendela yang disediakan, lalu melampirkan kontrol yang ada. |
AtlAxCreateControl | Membuat objek host, menghubungkannya ke jendela yang disediakan, lalu memuat kontrol. |
AtlAxCreateControlLic | Membuat kontrol ActiveX berlisensi, menginisialisasinya, dan menghostingnya di jendela yang ditentukan, mirip dengan AtlAxCreateControl. |
AtlAxCreateControlEx | Membuat objek host, menghubungkannya ke jendela yang disediakan, lalu memuat kontrol (juga memungkinkan sink peristiwa disiapkan). |
AtlAxCreateControlLicEx | Membuat kontrol ActiveX berlisensi, menginisialisasinya, dan menghostingnya di jendela yang ditentukan, mirip dengan AtlAxCreateControlLic. |
AtlAxCreateDialog | Membuat kotak dialog tanpa mode dari sumber daya dialog dan mengembalikan gagang jendela. |
AtlAxDialogBox | Membuat kotak dialog modal dari sumber daya dialog. |
AtlAxGetControl | Mengembalikan penunjuk antarmuka IUnknown dari kontrol yang dihosting di jendela. |
AtlAxGetHost | Mengembalikan penunjuk antarmuka IUnknown objek host yang tersambung ke jendela. |
AtlAxWinInit | Menginisialisasi kode hosting kontrol. |
AtlAxWinTerm | Batalkan menginisialisasi kode hosting kontrol. |
Parameter HWND
dalam tiga fungsi pertama harus merupakan jendela (hampir) jenis apa pun yang ada. Jika Anda memanggil salah satu dari tiga fungsi ini secara eksplisit (biasanya, Anda tidak perlu), jangan meneruskan handel ke jendela yang sudah bertindak sebagai host (jika Anda melakukannya, objek host yang ada tidak akan dibebaskan).
Tujuh fungsi pertama memanggil AtlAxWinInit secara implisit.
Catatan
API hosting kontrol membentuk fondasi dukungan ATL untuk penahanan kontrol ActiveX. Namun, biasanya ada sedikit kebutuhan untuk memanggil fungsi-fungsi ini secara langsung jika Anda memanfaatkan atau memanfaatkan sepenuhnya kelas pembungkus ATL. Untuk informasi selengkapnya, lihat Kelas ATL Mana yang Memfasilitasi Kontainer Kontrol ActiveX.
Apa itu AtlAxWin100?
AtlAxWin100
adalah nama kelas jendela yang membantu menyediakan fungsionalitas hosting kontrol ATL. Saat Anda membuat instans kelas ini, prosedur jendela akan secara otomatis menggunakan API hosting kontrol untuk membuat objek host yang terkait dengan jendela dan memuatnya dengan kontrol yang Anda tentukan sebagai judul jendela.
Kapan Saya Perlu Memanggil AtlAxWinInit?
AtlAxWinInit mendaftarkan kelas jendela "AtlAxWin80" (ditambah beberapa pesan jendela kustom) sehingga fungsi ini harus dipanggil sebelum Anda mencoba membuat jendela host. Namun, Anda tidak selalu perlu memanggil fungsi ini secara eksplisit, karena API hosting (dan kelas yang menggunakannya) sering memanggil fungsi ini untuk Anda. Tidak ada salahnya memanggil fungsi ini lebih dari sekali.
Apa itu Objek Host?
Objek host adalah objek COM yang mewakili kontainer kontrol ActiveX yang disediakan oleh ATL untuk jendela tertentu. Objek host mensubkelas jendela kontainer sehingga dapat mencerminkan pesan ke kontrol, ini menyediakan antarmuka kontainer yang diperlukan untuk digunakan oleh kontrol, dan mengekspos antarmuka IAxWinHostWindow dan IAxWinAmbientDispatch untuk memungkinkan Anda mengonfigurasi lingkungan kontrol.
Anda dapat menggunakan objek host untuk mengatur properti sekitar kontainer.
Dapatkah saya Menghosting Lebih dari Satu Kontrol dalam Satu Jendela?
Tidak dimungkinkan untuk menghosting lebih dari satu kontrol dalam satu jendela host ATL. Setiap jendela host dirancang untuk memegang tepat satu kontrol pada satu waktu (ini memungkinkan mekanisme sederhana untuk menangani pantulan pesan dan properti sekitar per kontrol). Namun, jika Anda memerlukan pengguna untuk melihat beberapa kontrol dalam satu jendela, itu adalah masalah sederhana untuk membuat beberapa jendela host sebagai anak-anak jendela itu.
Dapatkah saya Menggunakan Kembali Jendela Host?
Tidak disarankan agar Anda menggunakan kembali jendela host. Untuk memastikan ketahanan kode Anda, Anda harus mengikat masa pakai jendela host Anda ke masa pakai satu kontrol.
Kapan Saya Perlu Memanggil AtlAxWinTerm?
AtlAxWinTerm membatalkan pendaftaran kelas jendela "AtlAxWin80 ". Anda harus memanggil fungsi ini (jika Anda tidak perlu lagi membuat jendela host) setelah semua jendela host yang ada telah dihancurkan. Jika Anda tidak memanggil fungsi ini, kelas jendela akan dibatalkan pendaftarannya secara otomatis saat proses berakhir.
Hosting Kontrol ActiveX Menggunakan ATL AXHost
Sampel di bagian ini menunjukkan cara membuat AXHost dan cara menghosting kontrol ActiveX menggunakan berbagai fungsi ATL. Ini juga menunjukkan cara mengakses peristiwa kontrol dan sink (menggunakan IDispEventImpl) dari kontrol yang dihosting. Sampel menghosting kontrol Kalender di jendela utama atau di jendela anak.
Perhatikan definisi USE_METHOD
simbol. Anda dapat mengubah nilai simbol ini menjadi bervariasi antara 1 dan 8. Nilai simbol menentukan bagaimana kontrol akan dibuat:
Untuk nilai
USE_METHOD
bernomor genap , panggilan untuk membuat subkelas host jendela dan mengonversinya menjadi host kontrol. Untuk nilai bernomor ganjil, kode membuat jendela anak yang bertindak sebagai host.Untuk nilai
USE_METHOD
antara 1 dan 4, akses ke kontrol dan tenggelamnya peristiwa dilakukan dalam panggilan yang juga membuat host. Nilai antara 5 dan 8 mengkueri host untuk antarmuka dan menghubungkan sink.
Berikut ringkasannya:
USE_METHOD | Host | Mengontrol akses dan peristiwa yang tenggelam | Fungsi yang ditunjukkan |
---|---|---|---|
1 | Jendela anak | Satu langkah | CreateControlLicEx |
2 | Jendela utama | Satu langkah | AtlAxCreateControlLicEx |
3 | Jendela anak | Satu langkah | CreateControlEx |
4 | Jendela utama | Satu langkah | AtlAxCreateControlEx |
5 | Jendela anak | Beberapa langkah | CreateControlLic |
6 | Jendela utama | Beberapa langkah | AtlAxCreateControlLic |
7 | Jendela anak | Beberapa langkah | CreateControl |
8 | Jendela utama | Beberapa langkah | AtlAxCreateControl |
// Your project must be apartment threaded or the (AtlAx)CreateControl(Lic)(Ex)
// calls will fail.
#define _ATL_APARTMENT_THREADED
#include <atlbase.h>
#include <atlwin.h>
#include <atlhost.h>
// Value of g_UseMethod determines the function used to create the control.
int g_UseMethod = 0; // 1 to 8 are valid values
bool ValidateUseMethod() { return (1 <= g_UseMethod) && (g_UseMethod <= 8); }
#import "PROGID:MSCAL.Calendar.7" no_namespace, raw_interfaces_only
// Child window class that will be subclassed for hosting Active X control
class CChildWindow : public CWindowImpl<CChildWindow>
{
public:
BEGIN_MSG_MAP(CChildWindow)
END_MSG_MAP()
};
class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>,
public IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>
{
public :
CChildWindow m_wndChild;
CAxWindow2 m_axwnd;
CWindow m_wndEdit;
static ATL::CWndClassInfo& GetWndClassInfo()
{
static ATL::CWndClassInfo wc =
{
{
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
StartWindowProc,
0, 0, NULL, NULL, NULL,
(HBRUSH)(COLOR_WINDOW + 1),
0,
_T("MainWindow"),
NULL
},
NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
};
return wc;
}
BEGIN_MSG_MAP(CMainWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
END_MSG_MAP()
BEGIN_SINK_MAP(CMainWindow)
SINK_ENTRY_EX(1, __uuidof(DCalendarEvents), DISPID_CLICK, OnClick)
END_SINK_MAP()
// Helper to display events
void DisplayNotification(TCHAR* pszMessage)
{
CWindow wnd;
wnd.Attach(GetDlgItem(2));
wnd.SendMessage(EM_SETSEL, (WPARAM)-1, -1);
wnd.SendMessage(EM_REPLACESEL, 0, (LPARAM)pszMessage);
}
// Event Handler for Click
STDMETHOD(OnClick)()
{
DisplayNotification(_T("OnClick\r\n"));
return S_OK;
}
LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&)
{
HRESULT hr = E_INVALIDARG;
_pAtlModule->Lock();
RECT rect;
GetClientRect(&rect);
RECT rect2;
rect2 = rect;
rect2.bottom -=200;
// if g_UseMethod is odd then create AxHost directly as the child of the main window
if (g_UseMethod & 0x1)
{
m_axwnd.Create(m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 1);
}
// if g_UseMethod is even then the AtlAx version is invoked.
else
{
// Create a child window.
// AtlAx functions will subclass this window.
m_wndChild.Create(m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 1);
// Attach the child window to the CAxWindow so we can access the
// host that subclasses the child window.
m_axwnd.Attach(m_wndChild);
}
if (m_axwnd.m_hWnd != NULL)
{
CComPtr<IUnknown> spControl;
// The calls to (AtlAx)CreateControl(Lic)(Ex) do the following:
// Create Calendar control. (Passing in NULL for license key.
// Pass in valid license key to the Lic functions if the
// control requires one.)
// Get the IUnknown pointer for the control.
// Sink events from the control.
// The AtlAx versions subclass the hWnd that is passed in to them
// to implement the host functionality.
// The first 4 calls accomplish it in one call.
// The last 4 calls accomplish it using multiple steps.
switch (g_UseMethod)
{
case 1:
{
hr = m_axwnd.CreateControlLicEx(
OLESTR("MSCAL.Calendar.7"),
NULL,
NULL,
&spControl,
__uuidof(DCalendarEvents),
(IUnknown*)(IDispEventImpl<1, CMainWindow,
&__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
);
break;
}
case 2:
{
hr = AtlAxCreateControlLicEx(
OLESTR("MSCAL.Calendar.7"),
m_wndChild.m_hWnd,
NULL,
NULL,
&spControl,
__uuidof(DCalendarEvents),
(IUnknown*)(IDispEventImpl<1, CMainWindow,
&__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this,
NULL
);
break;
}
case 3:
{
hr = m_axwnd.CreateControlEx(
OLESTR("MSCAL.Calendar.7"),
NULL,
NULL,
&spControl,
__uuidof(DCalendarEvents),
(IUnknown*)(IDispEventImpl<1, CMainWindow,
&__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
);
break;
}
case 4:
{
hr = AtlAxCreateControlEx(
OLESTR("MSCAL.Calendar.7"),
m_wndChild.m_hWnd,
NULL,
NULL,
&spControl,
__uuidof(DCalendarEvents),
(IUnknown*)(IDispEventImpl<1, CMainWindow,
&__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
);
break;
}
// The following calls create the control, obtain an interface to
// the control, and set up the sink in multiple steps.
case 5:
{
hr = m_axwnd.CreateControlLic(
OLESTR("MSCAL.Calendar.7")
);
break;
}
case 6:
{
hr = AtlAxCreateControlLic(
OLESTR("MSCAL.Calendar.7"),
m_wndChild.m_hWnd,
NULL,
NULL
);
break;
}
case 7:
{
hr = m_axwnd.CreateControl(
OLESTR("MSCAL.Calendar.7")
);
break;
}
case 8:
{
hr = AtlAxCreateControl(
OLESTR("MSCAL.Calendar.7"),
m_wndChild.m_hWnd ,
NULL,
NULL
);
break;
}
}
// have to obtain an interface to the control and set up the sink
if (g_UseMethod > 4)
{
if (SUCCEEDED(hr))
{
hr = m_axwnd.QueryControl(&spControl);
if (SUCCEEDED(hr))
{
// Sink events form the control
DispEventAdvise(spControl, &__uuidof(DCalendarEvents));
}
}
}
if (SUCCEEDED(hr))
{
// Use the returned IUnknown pointer.
CComPtr<ICalendar> spCalendar;
hr = spControl.QueryInterface(&spCalendar);
if (SUCCEEDED(hr))
{
spCalendar->put_ShowDateSelectors(VARIANT_FALSE);
}
}
}
rect2 = rect;
rect2.top = rect.bottom - 200 + 1;
m_wndEdit.Create(_T("Edit"), m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE |
WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0, 2);
return 0;
}
LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&)
{
_pAtlModule->Unlock();
return 0;
}
};
class CHostActiveXModule : public CAtlExeModuleT<CHostActiveXModule>
{
public :
CMainWindow m_wndMain;
// Create the Main window
HRESULT PreMessageLoop(int nCmdShow)
{
HRESULT hr = CAtlExeModuleT<CHostActiveXModule>::PreMessageLoop(nCmdShow);
if (SUCCEEDED(hr))
{
AtlAxWinInit();
hr = S_OK;
RECT rc;
rc.top = rc.left = 100;
rc.bottom = rc.right = 500;
m_wndMain.Create(NULL, rc, _T("Host Calendar") );
m_wndMain.ShowWindow(nCmdShow);
}
return hr;
}
// Clean up. App is exiting.
HRESULT PostMessageLoop()
{
AtlAxWinTerm();
return CAtlExeModuleT<CHostActiveXModule>::PostMessageLoop();
}
};
CHostActiveXModule _AtlModule;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
g_UseMethod = _ttoi(lpCmdLine);
if (ValidateUseMethod())
{
return _AtlModule.WinMain(nCmdShow);
}
else
{
return E_INVALIDARG;
}
}