Które klasy ATL umożliwiają zawieranie kontrolek ActiveX?
Kod hostingu kontrolek atl nie wymaga używania żadnych klas ATL; Możesz po prostu utworzyć okno "AtlAxWin80" i w razie potrzeby użyć interfejsu API hostingu kontrolek (aby uzyskać więcej informacji, zobacz Co to jest interfejs API hostingu kontrolek ATL. Jednak następujące klasy ułatwiają korzystanie z funkcji zawierania.
Klasa | opis |
---|---|
CAxWindow | Opakowuje okno "AtlAxWin80" , udostępniając metody tworzenia okna, tworzenia kontrolki i/lub dołączania kontrolki do okna oraz pobierania wskaźników interfejsu w obiekcie hosta. |
CAxWindow2T | Opakowuje okno "AtlAxWinLic80" , udostępniając metody tworzenia okna, tworzenia kontrolki i/lub dołączania licencjonowanej kontrolki do okna i pobierania wskaźników interfejsu w obiekcie hosta. |
CComCompositeControl | Działa jako klasa bazowa dla klas kontrolek ActiveX na podstawie zasobu okna dialogowego. Takie kontrolki mogą zawierać inne kontrolki ActiveX. |
CAxDialogImpl | Działa jako klasa bazowa dla klas okien dialogowych na podstawie zasobu okna dialogowego. Takie okna dialogowe mogą zawierać kontrolki ActiveX. |
CWindow | Udostępnia metodę GetDlgControl, która zwróci wskaźnik interfejsu w kontrolce, biorąc pod uwagę identyfikator okna hosta. Ponadto otoki interfejsu API systemu Windows udostępniane przez CWindow zwykle ułatwiają zarządzanie oknami. |
Co to jest interfejs API hostingu kontrolek ATL?
Interfejs API hostowania kontrolek ATL to zestaw funkcji, który umożliwia każdemu oknie działanie jako kontener kontrolek ActiveX. Te funkcje mogą być statycznie lub dynamicznie połączone z projektem, ponieważ są one dostępne jako kod źródłowy i udostępniane przez ATL90.dll. Funkcje hostingu kontrolek są wymienione w poniższej tabeli.
Function | opis |
---|---|
AtlAxAttachControl | Tworzy obiekt hosta, łączy go z podanym oknem, a następnie dołącza istniejącą kontrolkę. |
AtlAxCreateControl | Tworzy obiekt hosta, łączy go z podanym oknem, a następnie ładuje kontrolkę. |
AtlAxCreateControlLic | Tworzy licencjonowany formant ActiveX, inicjuje go i hostuje go w określonym oknie, podobnie jak AtlAxCreateControl. |
AtlAxCreateControlEx | Tworzy obiekt hosta, łączy go z podanym oknem, a następnie ładuje kontrolkę (umożliwia również skonfigurowanie ujścia zdarzeń). |
AtlAxCreateControlLicEx | Tworzy licencjonowany formant ActiveX, inicjuje go i hostuje go w określonym oknie, podobnie jak AtlAxCreateControlLic. |
AtlAxCreateDialog | Tworzy okno dialogowe bez moderowania z zasobu okna dialogowego i zwraca uchwyt okna. |
AtlAxDialogBox | Tworzy modalne okno dialogowe z zasobu okna dialogowego. |
AtlAxGetControl | Zwraca wskaźnik interfejsu IUnknown kontrolki hostowanej w oknie. |
AtlAxGetHost | Zwraca wskaźnik interfejsu IUnknown obiektu hosta połączonego z oknem. |
AtlAxWinInit | Inicjuje kod hostingu kontrolek. |
AtlAxWinTerm | Uninitializuje kod hostingu kontrolek. |
HWND
Parametry w pierwszych trzech funkcjach muszą być istniejącym oknem (prawie) dowolnego typu. Jeśli jawnie wywołasz dowolną z tych trzech funkcji (zazwyczaj nie musisz), nie przekaż uchwytu do okna, które działa już jako host (jeśli to zrobisz, istniejący obiekt hosta nie zostanie uwolniony).
Pierwsze siedem funkcji wywołuje niejawnie atlAxWinInit .
Uwaga
Interfejs API hostingu kontrolek stanowi podstawę obsługi formantów ActiveX przez atl. Jednak zwykle nie trzeba wywoływać tych funkcji bezpośrednio, jeśli korzystasz z klas otoki ATL lub korzystasz z nich w pełni. Aby uzyskać więcej informacji, zobacz Które klasy ATL ułatwiają zawieranie kontrolek ActiveX.
Co to jest klasa AtlAxWin100?
AtlAxWin100
to nazwa klasy okien, która pomaga zapewnić funkcje hostingu kontrolek ATL. Podczas tworzenia wystąpienia tej klasy procedura okna automatycznie użyje interfejsu API hostingu kontrolek do utworzenia obiektu hosta skojarzonego z oknem i załadowania go za pomocą kontrolki określonej jako tytuł okna.
Kiedy muszę tworzyć wywołanie klasy AtlAxWinInit?
AtlAxWinInit rejestruje klasę okien "AtlAxWin80" (plus kilka niestandardowych komunikatów okna), aby ta funkcja musiała zostać wywołana przed próbą utworzenia okna hosta. Jednak nie zawsze trzeba jawnie wywoływać tę funkcję, ponieważ interfejsy API hostingu (i klasy, które ich używają) często nazywają tę funkcję za Ciebie. Nie ma żadnych szkód w wywoływaniu tej funkcji więcej niż raz.
Co to jest obiekt hosta?
Obiekt hosta jest obiektem COM, który reprezentuje kontener sterowania ActiveX dostarczony przez ATL dla określonego okna. Podklasy obiektu hosta okno kontenera, dzięki czemu może odzwierciedlać komunikaty do kontrolki, udostępnia niezbędne interfejsy kontenera do użycia przez kontrolkę i uwidacznia interfejsy IAxWinHostWindow i IAxWinAmbientDispatch , aby umożliwić skonfigurowanie środowiska kontrolki.
Za pomocą obiektu hosta można ustawić właściwości otoczenia kontenera.
Czy mogę umieścić więcej niż jedną kontrolkę w jednym oknie?
Nie można hostować więcej niż jednej kontrolki w jednym oknie hosta ATL. Każde okno hosta jest przeznaczone do przechowywania dokładnie jednej kontrolki naraz (pozwala to na prosty mechanizm obsługi odbicia komunikatów i właściwości otoczenia dla poszczególnych kontrolek). Jeśli jednak chcesz, aby użytkownik widział wiele kontrolek w jednym oknie, wystarczy utworzyć wiele okien hosta jako elementów podrzędnych tego okna.
Czy mogę ponownie użyć okna hosta?
Nie zaleca się ponownego używania okien hostów. Aby zapewnić niezawodność kodu, należy powiązać okres istnienia okna hosta z okresem istnienia pojedynczej kontrolki.
Kiedy muszę tworzyć wywołanie klasy AtlAxWinTerm?
AtlAxWinTerm wyrejestrowuje klasę okna "AtlAxWin80". Należy wywołać tę funkcję (jeśli nie trzeba już tworzyć okien hosta) po zniszczeniu wszystkich istniejących okien hosta. Jeśli ta funkcja nie zostanie wywołana, klasa okna zostanie automatycznie wyrejestrowana po zakończeniu procesu.
Hostowanie kontrolek ActiveX przy użyciu biblioteki ATL AXHost
W przykładzie w tej sekcji pokazano, jak utworzyć axhost i jak hostować kontrolkę ActiveX przy użyciu różnych funkcji ATL. Pokazano również, jak uzyskać dostęp do zdarzeń kontroli i ujścia (przy użyciu protokołu IDispEventImpl) z hostowanej kontrolki. Przykład obsługuje kontrolkę Kalendarz w oknie głównym lub w oknie podrzędnym.
Zwróć uwagę na definicję symbolu USE_METHOD
. Możesz zmienić wartość tego symbolu tak, aby różniła się w zakresie od 1 do 8. Wartość symbolu określa sposób tworzenia kontrolki:
W przypadku parzystym numerem wartości
USE_METHOD
wywołania w celu utworzenia podklas hosta okno i konwertuje je na hosta sterującego. W przypadku wartości z nieparzystą liczbą kod tworzy okno podrzędne, które działa jako host.W przypadku wartości z
USE_METHOD
zakresu od 1 do 4 dostęp do kontroli i ujścia zdarzeń odbywa się w wywołaniu, które tworzy również hosta. Wartości z zakresu od 5 do 8 wysyłają zapytanie do hosta dla interfejsów i podłączają ujście.
Oto podsumowanie:
USE_METHOD | Gospodarz | Kontrolowanie dostępu i ujścia zdarzeń | Pokazano funkcję |
---|---|---|---|
1 | Okno podrzędne | Jeden krok | CreateControlLicEx |
2 | Okno główne | Jeden krok | AtlAxCreateControlLicEx |
3 | Okno podrzędne | Jeden krok | CreateControlEx |
100 | Okno główne | Jeden krok | AtlAxCreateControlEx |
5 | Okno podrzędne | Wiele kroków | CreateControlLic |
6 | Okno główne | Wiele kroków | AtlAxCreateControlLic |
7 | Okno podrzędne | Wiele kroków | CreateControl |
8 | Okno główne | Wiele kroków | 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;
}
}