Welche ATL-Klassen machen die Kapselung von ActiveX-Steuerelementen verfügbar?
Der ATL-Steuerelementhostingcode erfordert keine ATL-Klassen; Sie können einfach ein "AtlAxWin80" -Fenster erstellen und bei Bedarf die Steuerelementhosting-API verwenden (weitere Informationen finden Sie unter What Is the ATL Control-Hosting API. Die folgenden Klassen erleichtern jedoch die Verwendung der Eindämmungsfeatures.
Klasse | Beschreibung |
---|---|
CAxWindow | Umschließt ein "AtlAxWin80" -Fenster, das Methoden zum Erstellen des Fensters, das Erstellen eines Steuerelements und/oder das Anfügen eines Steuerelements an das Fenster sowie das Abrufen von Schnittstellenzeigern auf dem Hostobjekt bereitstellt. |
CAxWindow2T | Umschließt ein "AtlAxWinLic80" -Fenster, das Methoden zum Erstellen des Fensters, das Erstellen eines Steuerelements und/oder das Anfügen eines lizenzierten Steuerelements an das Fenster sowie das Abrufen von Schnittstellenzeigern auf dem Hostobjekt bereitstellt. |
CComCompositeControl | Dient als Basisklasse für ActiveX-Steuerelementklassen basierend auf einer Dialogressource. Solche Steuerelemente können andere ActiveX-Steuerelemente enthalten. |
CAxDialogImpl | Dient als Basisklasse für Dialogklassen basierend auf einer Dialogressource. Solche Dialogfelder können ActiveX-Steuerelemente enthalten. |
CWindow | Stellt eine Methode, GetDlgControl, bereit, die einen Schnittstellenzeiger für ein Steuerelement zurückgibt, vorausgesetzt, die ID des Hostfensters. Darüber hinaus erleichtern die Windows-API-Wrapper, die von CWindow der Allgemeinen Fensterverwaltung verfügbar gemacht werden. |
Was ist die API des ATL-Steuerelementhostings?
Die ATL-Steuerelementhosting-API ist der Satz von Funktionen, mit denen jedes Fenster als ActiveX-Steuerelementcontainer fungieren kann. Diese Funktionen können statisch oder dynamisch mit Ihrem Projekt verknüpft werden, da sie als Quellcode verfügbar sind und von ATL90.dll verfügbar gemacht werden. Die Steuerelementhostingfunktionen sind in der folgenden Tabelle aufgeführt.
Funktion | Beschreibung |
---|---|
AtlAxAttachControl | Erstellt ein Hostobjekt, verbindet es mit dem angegebenen Fenster und fügt dann ein vorhandenes Steuerelement an. |
AtlAxCreateControl | Erstellt ein Hostobjekt, verbindet es mit dem angegebenen Fenster und lädt dann ein Steuerelement. |
AtlAxCreateControlLic | Erstellt ein lizenziertes ActiveX-Steuerelement, initialisiert es und hostet es im angegebenen Fenster, ähnlich wie AtlAxCreateControl. |
AtlAxCreateControlEx | Erstellt ein Hostobjekt, verbindet es mit dem angegebenen Fenster und lädt dann ein Steuerelement (ermöglicht auch das Einrichten von Ereignissenken). |
AtlAxCreateControlLicEx | Erstellt ein lizenziertes ActiveX-Steuerelement, initialisiert es und hostet es im angegebenen Fenster, ähnlich wie AtlAxCreateControlLic. |
AtlAxCreateDialog | Erstellt ein Dialogfeld ohne Modus aus einer Dialogressource und gibt das Fensterhandle zurück. |
AtlAxDialogBox | Erstellt ein modales Dialogfeld aus einer Dialogressource. |
AtlAxGetControl | Gibt den IUnknown-Schnittstellenzeiger des steuerelements zurück, das in einem Fenster gehostet wird. |
AtlAxGetHost | Gibt den IUnknown-Schnittstellenzeiger des hostobjekts zurück, das mit einem Fenster verbunden ist. |
AtlAxWinInit | Initialisiert den Steuerelementhostingcode. |
AtlAxWinTerm | Hebt die Initialisierung des Steuerelementhostingcodes auf. |
Die HWND
Parameter in den ersten drei Funktionen müssen ein (fast) beliebiges Fenster sein. Wenn Sie eine dieser drei Funktionen explizit aufrufen (in der Regel nicht erforderlich), übergeben Sie kein Handle an ein Fenster, das bereits als Host fungiert (wenn Sie dies tun, wird das vorhandene Hostobjekt nicht freigegeben).
Die ersten sieben Funktionen rufen AtlAxWinInit implizit auf.
Hinweis
Die Steuerelementhosting-API bildet die Grundlage der Unterstützung von ATL für die Eindämmung von ActiveX-Steuerelementen. In der Regel ist es jedoch wenig erforderlich, diese Funktionen direkt aufzurufen, wenn Sie die Wrapperklassen von ATL nutzen oder vollständig nutzen. Weitere Informationen finden Sie unter Welche ATL-Klassen die Eindämmung von ActiveX-Steuerelementen erleichtern.
Was ist AtlAxWin100?
AtlAxWin100
ist der Name einer Fensterklasse, die die Funktionalität des ATL-Steuerelementhostings bereitstellt. Wenn Sie eine Instanz dieser Klasse erstellen, verwendet die Fensterprozedur automatisch die Steuerelementhosting-API, um ein dem Fenster zugeordnetes Hostobjekt zu erstellen und mit dem Steuerelement zu laden, das Sie als Titel des Fensters angeben.
Wann muss ich AtlAxWinInit aufrufen?
AtlAxWinInit registriert die "AtlAxWin80"- Fensterklasse (plus ein paar benutzerdefinierte Fenstermeldungen), sodass diese Funktion aufgerufen werden muss, bevor Sie versuchen, ein Hostfenster zu erstellen. Sie müssen diese Funktion jedoch nicht immer explizit aufrufen, da die Host-APIs (und die Klassen, die sie verwenden) diese Funktion häufig für Sie aufrufen. Es gibt keinen Schaden daran, diese Funktion mehrmals aufzurufen.
Was ist ein Hostobjekt?
Ein Hostobjekt ist ein COM-Objekt, das den activeX-Steuerelementcontainer darstellt, der von ATL für ein bestimmtes Fenster bereitgestellt wird. Das Hostobjekt unterklassig das Containerfenster, sodass es Nachrichten an das Steuerelement wiedergeben kann, es stellt die erforderlichen Containerschnittstellen bereit, die vom Steuerelement verwendet werden sollen, und macht die IAxWinHostWindow - und IAxWinAmbientDispatch-Schnittstellen verfügbar, damit Sie die Umgebung des Steuerelements konfigurieren können.
Sie können das Hostobjekt verwenden, um die Umgebungseigenschaften des Containers festzulegen.
Kann ich in einem Fenster mehrere Steuerelemente hosten?
Es ist nicht möglich, mehrere Steuerelemente in einem einzelnen ATL-Hostfenster zu hosten. Jedes Hostfenster ist so konzipiert, dass jeweils genau ein Steuerelement gehalten wird (dies ermöglicht einen einfachen Mechanismus für die Behandlung von Nachrichtenreflektionen und Umgebungseigenschaften pro Steuerung). Wenn Der Benutzer jedoch mehrere Steuerelemente in einem einzelnen Fenster sehen muss, ist es einfach, mehrere Hostfenster als untergeordnete Elemente dieses Fensters zu erstellen.
Kann ich ein Hostfenster wiederverwenden?
Es wird nicht empfohlen, Hostfenster wiederzuverwenden. Um die Stabilität des Codes sicherzustellen, sollten Sie die Lebensdauer des Hostfensters auf die Lebensdauer eines einzelnen Steuerelements binden.
Wann muss ich AtlAxWinInit aufrufen?
AtlAxWinTerm hebt die Registrierung der "AtlAxWin80"- Fensterklasse auf. Sie sollten diese Funktion aufrufen (wenn Sie keine Hostfenster mehr erstellen müssen), nachdem alle vorhandenen Hostfenster zerstört wurden. Wenn Sie diese Funktion nicht aufrufen, wird die Registrierung der Fensterklasse automatisch aufgehoben, wenn der Prozess beendet wird.
Hosten von ActiveX-Steuerelementen mit ATL AXHost
Das Beispiel in diesem Abschnitt zeigt, wie AXHost erstellt und ein ActiveX-Steuerelement mithilfe verschiedener ATL-Funktionen gehostet wird. Außerdem wird gezeigt, wie Sie über das gehostete Steuerelement auf die Steuerelement- und Sinkereignisse (mit IDispEventImpl) zugreifen. Im Beispiel wird das Kalendersteuerelement in einem Hauptfenster oder in einem untergeordneten Fenster gehostet.
Beachten Sie die Definition des USE_METHOD
Symbols. Sie können den Wert dieses Symbols ändern, um zwischen 1 und 8 zu variieren. Der Wert des Symbols bestimmt, wie das Steuerelement erstellt wird:
Für gerade nummerierte Werte des
USE_METHOD
Aufrufs zum Erstellen der Hostunterklassen eines Fensters und konvertiert ihn in einen Steuerelementhost. Bei ungeraden Werten erstellt der Code ein untergeordnetes Fenster, das als Host fungiert.Für Werte zwischen
USE_METHOD
1 und 4 erfolgt der Zugriff auf das Steuerelement und das Sinken von Ereignissen im Aufruf, der auch den Host erstellt. Werte zwischen 5 und 8 abfragen den Host nach Schnittstellen und verbinden die Spüle.
Dies ist eine Zusammenfassung:
USE_METHOD | Host | Steuern des Zugriffs und des Sinkens von Ereignissen | Veranschaulichte Funktion |
---|---|---|---|
1 | Untergeordnetes Fenster | Ein Schritt | CreateControlLicEx |
2 | Hauptfenster | Ein Schritt | AtlAxCreateControlLicEx |
3 | Untergeordnetes Fenster | Ein Schritt | CreateControlEx |
4 | Hauptfenster | Ein Schritt | AtlAxCreateControlEx |
5 | Untergeordnetes Fenster | Mehrere -Schritte | CreateControlLic |
6 | Hauptfenster | Mehrere -Schritte | AtlAxCreateControlLic |
7 | Untergeordnetes Fenster | Mehrere -Schritte | CreateControl |
8 | Hauptfenster | Mehrere -Schritte | 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;
}
}