Jaké třídy ATL umožňují používat kontejnery ovládacích prvků ActiveX?
Kód ATL pro hostování řízení nevyžaduje použití žádné třídy ATL; Můžete jednoduše vytvořit okno AtlAxWin80 a v případě potřeby použít rozhraní API pro hostování ovládacích prvků (další informace najdete v tématu Co je rozhraní API pro řízení a hostování ATL. Následující třídy však usnadňují používání funkcí zahrnutí.
Třída | Popis |
---|---|
CAxWindow | Zabalí okno "AtlAxWin80" a poskytuje metody pro vytvoření okna, vytvoření ovládacího prvku nebo připojení ovládacího prvku k okně a načtení ukazatelů rozhraní na objekt hostitele. |
CAxWindow2T | Zabalí okno "AtlAxWinLic80" , poskytuje metody pro vytvoření okna, vytvoření ovládacího prvku nebo připojení licencovaného ovládacího prvku k okně a načtení ukazatelů rozhraní na objekt hostitele. |
CComCompositeControl | Funguje jako základní třída pro třídy ovládacích prvků ActiveX na základě prostředku dialogového okna. Tyto ovládací prvky mohou obsahovat další ovládací prvky ActiveX. |
CAxDialogImpl | Funguje jako základní třída pro třídy dialogových oken založených na prostředku dialogového okna. Taková dialogová okna můžou obsahovat ovládací prvky ActiveX. |
CWindow | Poskytuje metodu GetDlgControl, která vrátí ukazatel rozhraní na ovládací prvek, vzhledem k ID jeho hostitelského okna. Kromě toho obálky rozhraní API systému Windows zpřístupněné CWindow obecně usnadňují správu oken. |
Co je API pro hostování ovládacích prvků ATL?
Rozhraní API pro hostování ovládacích prvků ATL je sada funkcí, které umožňují, aby jakékoli okno fungovalo jako kontejner ovládacího prvku ActiveX. Tyto funkce můžou být staticky nebo dynamicky propojené s vaším projektem, protože jsou dostupné jako zdrojový kód a zveřejněné ATL90.dll. Funkce pro hostování ovládacích prvků jsou uvedené v následující tabulce.
Function | Popis |
---|---|
AtlAxAttachControl | Vytvoří hostitelský objekt, připojí ho k zadanému okně a pak připojí existující ovládací prvek. |
AtlAxCreateControl | Vytvoří hostitelský objekt, připojí ho k zadanému okně a pak načte ovládací prvek. |
AtlAxCreateControlLic | Vytvoří licencovaný ovládací prvek ActiveX, inicializuje ho a hostuje ho v zadaném okně, podobně jako AtlAxCreateControl. |
AtlAxCreateControlEx | Vytvoří hostitelský objekt, připojí ho k zadanému okně a pak načte ovládací prvek (umožňuje také nastavit jímky událostí). |
AtlAxCreateControlLicEx | Vytvoří licencovaný ovládací prvek ActiveX, inicializuje ho a hostuje ho v zadaném okně, podobně jako AtlAxCreateControlLic. |
AtlAxCreateDialog | Vytvoří bezmodální dialogové okno z prostředku dialogového okna a vrátí popisovač okna. |
AtlAxDialogBox | Vytvoří modální dialogové okno z prostředku dialogového okna. |
AtlAxGetControl | Vrátí ukazatel rozhraní IUnknown ovládacího prvku hostovaného v okně. |
AtlAxGetHost | Vrátí ukazatel rozhraní IUnknown objektu hostitele připojeného k oknu. |
AtlAxWinInit | Inicializuje kód pro hostování ovládacích prvků. |
AtlAxWinTerm | Neinicializuje kód pro hostování ovládacích prvků. |
Parametry HWND
v prvních třech funkcích musí být existujícím oknem (téměř) jakéhokoli typu. Pokud explicitně zavoláte některou z těchto tří funkcí (obvykle nebudete muset), nepředávejte popisovač do okna, které už funguje jako hostitel (pokud to uděláte, stávající hostitelský objekt nebude uvolněn).
Prvních sedm funkcí volá AtlAxWinInit implicitně.
Poznámka:
Rozhraní API pro hostování ovládacích prvků tvoří základ podpory ovládacích prvků ACTIVEX pro zahrnutí ovládacího prvku ActiveX. Tyto funkce je však obvykle potřeba volat přímo, pokud využijete nebo plně využijete třídy obálky KNIHOVNY ATL. Další informace naleznete v tématu , které třídy ATL usnadňují zahrnutí ovládacích prvků ActiveX.
Co je AtlAxWin100?
AtlAxWin100
je název třídy okna, která pomáhá poskytovat funkce ATL pro hostování ovládacích prvků. Když vytvoříte instanci této třídy, procedura okna automaticky použije rozhraní API pro hostování ovládacích prvků k vytvoření hostitelského objektu přidruženého k tomuto okně a načte ho ovládacím prvku, který zadáte jako název okna.
Kdy potřebuji volat AtlAxWinInit?
AtlAxWinInit zaregistruje třídu okna AtlAxWin80 (plus několik vlastních zpráv oken), takže tato funkce musí být volána, než se pokusíte vytvořit okno hostitele. Tuto funkci ale nemusíte vždy volat explicitně, protože rozhraní API pro hostování (a třídy, které je používají), tuto funkci často volají za vás. Při volání této funkce více než jednou nedojde k žádné škodě.
Co je hostitelský objekt?
Hostitelský objekt je objekt COM, který představuje kontejner ovládacího prvku ActiveX zadaný atL pro konkrétní okno. Hostitelský objekt podtřídí okno kontejneru, aby bylo možné odrážet zprávy ovládacímu prvku, poskytuje potřebná rozhraní kontejneru, která má ovládací prvek používat, a zveřejňuje rozhraní IAxWinHostWindow a IAxWinAmbientDispatch , aby bylo možné nakonfigurovat prostředí ovládacího prvku.
Objekt hostitele můžete použít k nastavení okolních vlastností kontejneru.
Můžu v jednom okně hostovat několik ovládacích prvků?
V jednom okně hostitele ATL není možné hostovat více než jeden ovládací prvek. Každé okno hostitele je navržené tak, aby vždy drželo přesně jeden ovládací prvek (to umožňuje jednoduchý mechanismus pro zpracování reflexe zpráv a okolních vlastností ovládacího prvku). Pokud ale potřebujete, aby uživatel viděl více ovládacích prvků v jednom okně, je jednoduché vytvořit několik hostitelských oken jako podřízených položek tohoto okna.
Můžu opakovaně použít okno hostitele?
Nedoporučujeme opakovaně používat okna hostitele. Pokud chcete zajistit odolnost kódu, měli byste svázat životnost okna hostitele s životností jednoho ovládacího prvku.
Kdy potřebuji volat Call AtlAxWinTerm?
AtlAxWinTerm zruší registraci třídy okna AtlAxWin80 . Tuto funkci byste měli zavolat (pokud už nepotřebujete vytvářet okna hostitele) po zničení všech existujících hostitelských oken. Pokud tuto funkci nezavoláte, třída okna se po ukončení procesu automaticky zruší registrace.
Hostování ovládacích prvků ActiveX pomocí ATL AXHost
Ukázka v této části ukazuje, jak vytvořit AXHost a jak hostovat ovládací prvek ActiveX pomocí různých funkcí ATL. Ukazuje také, jak získat přístup k událostem ovládacího prvku a jímky (pomocí IDispEventImpl) z hostovaného ovládacího prvku. Ukázka hostuje ovládací prvek Kalendář v hlavním okně nebo v podřízeném okně.
Všimněte si definice symbolu USE_METHOD
. Hodnotu tohoto symbolu můžete změnit tak, aby se lišily od 1 do 8. Hodnota symbolu určuje způsob vytvoření ovládacího prvku:
U sudých hodnot
USE_METHOD
volání pro vytvoření podtřídy hostitele okno a převede ho na hostitele ovládacího prvku. Pro liché hodnoty vytvoří kód podřízené okno, které funguje jako hostitel.U hodnot
USE_METHOD
mezi 1 a 4 se přístup k řízení a jímce událostí provádí ve volání, které také vytvoří hostitele. Hodnoty v rozsahu 5 až 8 dotazují hostitele na rozhraní a zahodí jímku.
Tady je souhrn:
USE_METHOD | Hostitelský počítač | Řízení přístupu a jímky událostí | Demonstrována funkce |
---|---|---|---|
0 | Podřízené okno | Jeden krok | CreateControlLicEx |
2 | Hlavní okno | Jeden krok | AtlAxCreateControlLicEx |
3 | Podřízené okno | Jeden krok | CreateControlEx |
4 | Hlavní okno | Jeden krok | AtlAxCreateControlEx |
5 | Podřízené okno | Více kroků | CreateControlLic |
6 | Hlavní okno | Více kroků | AtlAxCreateControlLic |
7 | Podřízené okno | Více kroků | CreateControl |
8 | Hlavní okno | Více kroků | 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;
}
}