Düzenle

Aracılığıyla paylaş


ATL Denetim Kapsamı SSS

Hangi ATL Sınıfları ActiveX Denetim Kapsamından Yararlanır?

ATL'nin denetim barındırma kodu herhangi bir ATL sınıfı kullanmanızı gerektirmez; Bir "AtlAxWin80" penceresi oluşturabilir ve gerekirse control-hosting API'sini kullanabilirsiniz (daha fazla bilgi için bkz. ATL Control-Hosting API'si nedir? Ancak, aşağıdaki sınıflar kapsama özelliklerinin kullanımını kolaylaştırır.

Sınıf Açıklama
CAxWindow Bir "AtlAxWin80" penceresini kaydırarak pencereyi oluşturma, denetim oluşturma ve/veya pencereye denetim ekleme ve konak nesnesinde arabirim işaretçilerini alma yöntemlerini sağlar.
CAxWindow2T "AtlAxWinLic80" penceresini sarmalar, pencereyi oluşturma, denetim oluşturma ve/veya pencereye lisanslı denetim ekleme ve konak nesnesinde arabirim işaretçilerini alma yöntemleri sağlar.
CComCompositeControl bir iletişim kutusu kaynağını temel alan ActiveX denetim sınıfları için temel sınıf görevi görür. Bu tür denetimler diğer ActiveX denetimlerini içerebilir.
CAxDialogImpl bir iletişim kutusu kaynağını temel alan iletişim kutusu sınıfları için temel sınıf görevi görür. Bu tür iletişim kutuları ActiveX denetimleri içerebilir.
CWindow Konak penceresinin kimliğine göre bir denetim üzerinde arabirim işaretçisi döndürecek GetDlgControl adlı bir yöntem sağlar. Buna ek olarak, genellikle tarafından kullanıma sunulan CWindow Windows API sarmalayıcıları pencere yönetimini kolaylaştırır.

ATL Denetim Barındırma API’si nedir?

ATL'nin denetim barındırma API'si, herhangi bir pencerenin ActiveX denetim kapsayıcısı olarak davranmasını sağlayan işlev kümesidir. Bu işlevler, kaynak kod olarak kullanılabilir ve ATL90.dll tarafından kullanıma sunulduğundan projenize statik veya dinamik olarak bağlanabilir. Denetim barındırma işlevleri aşağıdaki tabloda listelenmiştir.

İşlev Açıklama
AtlAxAttachControl Bir konak nesnesi oluşturur, bunu sağlanan pencereye bağlar ve ardından var olan bir denetimi ekler.
AtlAxCreateControl Bir konak nesnesi oluşturur, sağlanan pencereye bağlar ve ardından bir denetim yükler.
AtlAxCreateControlLic Lisanslı bir ActiveX denetimi oluşturur, bunu başlatır ve AtlAxCreateControl'e benzer şekilde belirtilen pencerede barındırıyor.
AtlAxCreateControlEx Bir konak nesnesi oluşturur, bunu sağlanan pencereye bağlar, ardından bir denetim yükler (ayrıca olay havuzlarının ayarlanmasına izin verir).
AtlAxCreateControlLicEx Lisanslı bir ActiveX denetimi oluşturur, bunu başlatır ve AtlAxCreateControlLic'e benzer şekilde belirtilen pencerede barındırıyor.
AtlAxCreateDialog İletişim kutusu kaynağından modsuz bir iletişim kutusu oluşturur ve pencere tutamacını döndürür.
AtlAxDialogBox İletişim kutusu kaynağından kalıcı bir iletişim kutusu oluşturur.
AtlAxGetControl Bir pencerede barındırılan denetimin IUnknown arabirim işaretçisini döndürür.
AtlAxGetHost Pencereye bağlı konak nesnesinin IUnknown arabirim işaretçisini döndürür.
AtlAxWinInit Denetim barındırma kodunu başlatır.
AtlAxWinTerm Control-hosting kodunu başlatılmaz.

HWND İlk üç işlevdeki parametreler herhangi bir türde (neredeyse) mevcut bir pencere olmalıdır. Bu üç işlevden herhangi birini açıkça çağırırsanız (genellikle bunu yapmanız gerekmez), zaten konak olarak davranan bir pencereye tanıtıcı geçirmeyin (bunu yaparsanız, mevcut konak nesnesi serbest kalmaz).

İlk yedi işlev, AtlAxWinInit'i örtük olarak çağırır.

Not

Denetim barındırma API'si, ATL'nin ActiveX denetim kapsama desteğinin temelini oluşturur. Ancak, ATL'nin sarmalayıcı sınıflarından yararlanıyorsanız veya tam olarak kullanıyorsanız bu işlevleri doğrudan çağırmanız genellikle çok az gerekir. Daha fazla bilgi için bkz . Hangi ATL Sınıfları ActiveX Denetim Kapsamasını Kolaylaştırır.

AtlAxWin100 nedir?

AtlAxWin100 , ATL'nin denetim barındırma işlevselliğini sağlamaya yardımcı olan bir pencere sınıfının adıdır. Bu sınıfın bir örneğini oluşturduğunuzda, pencere yordamı otomatik olarak control-hosting API'sini kullanarak pencereyle ilişkilendirilmiş bir konak nesnesi oluşturur ve bunu pencerenin başlığı olarak belirttiğiniz denetimle yükler.

Ne Zaman AtlAxWinInit Çağrısı Yapmam Gerekir?

AtlAxWinInit , "AtlAxWin80" pencere sınıfını (artı birkaç özel pencere iletisi) kaydeder, bu nedenle konak penceresi oluşturmaya çalışmadan önce bu işlevin çağrılması gerekir. Ancak, barındırma API'leri (ve bunları kullanan sınıflar) genellikle bu işlevi sizin için çağırdığından, bu işlevi her zaman açıkça çağırmanız gerekmez. Bu işlevi birden çok kez çağırmanın bir zararı yoktur.

Konak Nesnesi Nedir?

Konak nesnesi, belirli bir pencere için ATL tarafından sağlanan ActiveX denetim kapsayıcısını temsil eden bir COM nesnesidir. Konak nesnesi kapsayıcı penceresini alt sınıflandırarak iletileri denetime yansıtabilmesini sağlar, denetim tarafından kullanılacak gerekli kapsayıcı arabirimlerini sağlar ve denetimin ortamını yapılandırmanıza olanak sağlamak için IAxWinHostWindow ve IAxWinAmbientDispatch arabirimlerini kullanıma sunar.

Kapsayıcının ortam özelliklerini ayarlamak için konak nesnesini kullanabilirsiniz.

Tek Bir Pencerede Birden Fazla Denetim Barındırabilir miyim?

Tek bir ATL konak penceresinde birden fazla denetim barındırmak mümkün değildir. Her konak penceresi, aynı anda tam olarak bir denetimi tutacak şekilde tasarlanmıştır (bu, ileti yansımasını ve denetim başına ortam özelliklerini işlemek için basit bir mekanizma sağlar). Ancak, kullanıcının tek bir pencerede birden çok denetim görmesi gerekiyorsa, bu pencerenin alt öğeleri olarak birden çok konak penceresi oluşturmak basit bir işlemdir.

Bir Konak Penceresini Yeniden Kullanabilir miyim?

Konak pencerelerini yeniden kullanmanız önerilmez. Kodunuzun sağlamlığını sağlamak için konak pencerenizin ömrünü tek bir denetimin ömrüne bağlamanız gerekir.

Ne Zaman AtlAxWinTerm Çağrısı Yapmam Gerekir?

AtlAxWinTerm, "AtlAxWin80" pencere sınıfının kaydını kaldırıyor. Mevcut tüm konak pencereleri yok edildikten sonra bu işlevi çağırmalısınız (artık konak pencereleri oluşturmanız gerekmiyorsa). Bu işlevi çağırmazsanız, işlem sonlandırıldığında pencere sınıfının kaydı otomatik olarak silinir.

ATL AXHost Kullanarak ActiveX Denetimlerini Barındırma

Bu bölümdeki örnekte AXHost'un nasıl oluşturulacağı ve çeşitli ATL işlevleri kullanılarak bir ActiveX denetiminin nasıl barındıracağı gösterilmektedir. Ayrıca, barındırılan denetimden denetim ve havuz olaylarına (IDispEventImpl kullanarak) nasıl erişildiğini de gösterir. Örnek, Takvim denetimini bir ana pencerede veya bir alt pencerede barındırıyor.

Sembolün tanımına USE_METHOD dikkat edin. Bu simgenin değerini 1 ile 8 arasında değişiklik gösterecek şekilde değiştirebilirsiniz. Sembolün değeri, denetimin nasıl oluşturulacağını belirler:

  • çift numaralı değerleri USE_METHODiçin, konak alt sınıfını oluşturma çağrısı bir pencereyi sınıflandırıp bir denetim konağına dönüştürür. Tek numaralı değerler için kod, konak işlevi gören bir alt pencere oluşturur.

  • 1 ile 4 arasındaki değerler USE_METHOD için, denetimine erişim ve olayların havuza alınması, konağı da oluşturan çağrıda gerçekleştirilir. 5 ile 8 arasındaki değerler, arabirimler için konağı sorgular ve havuzu bağlar.

Özet aşağıdadır:

USE_METHOD Ana Bilgisayar Erişimi ve olay havuzlarını denetleme İşlev gösterildi
1 Alt pencere Bir adım CreateControlLicEx
2 Ana pencere Bir adım AtlAxCreateControlLicEx
3 Alt pencere Bir adım CreateControlEx
4 Ana pencere Bir adım AtlAxCreateControlEx
5 Alt pencere Birden çok adım CreateControlLic
6 Ana pencere Birden çok adım AtlAxCreateControlLic
7 Alt pencere Birden çok adım CreateControl
8 Ana pencere Birden çok adım 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;   
   }
}