Dodawanie zdarzenia (ALT — Samouczek, część 5)
W tym kroku dodasz ClickIn
zdarzenie i ClickOut
do kontrolki ATL. Zdarzenie zostanie wyzwolony ClickIn
, jeśli użytkownik kliknie w obrębie wielokąta i zostanie wyzwolony ClickOut
, jeśli użytkownik kliknie poza. Zadania dodawania zdarzenia są następujące:
ClickIn
Dodawanie metod iClickOut
Generowanie biblioteki typów
Implementowanie interfejsów punktu połączenia
Dodawanie metod ClickIn i ClickOut
Po utworzeniu kontrolki ATL w kroku 2 zaznaczono pole wyboru Punkty połączenia. Spowodowało to utworzenie interfejsu _IPolyCtlEvents
w pliku Polygon.idl. Pamiętaj, że nazwa interfejsu zaczyna się od podkreślenia. Jest to konwencja wskazująca, że interfejs jest interfejsem wewnętrznym. W związku z tym programy, które umożliwiają przeglądanie obiektów COM, mogą nie wyświetlać interfejsu użytkownikowi. Należy również pamiętać, że wybranie pozycji Punkty połączenia dodało następujący wiersz w pliku Polygon.idl, aby wskazać, że _IPolyCtlEvents
jest to domyślny interfejs źródłowy:
[default, source] dispinterface _IPolyCtlEvents;
Atrybut źródłowy wskazuje, że kontrolka jest źródłem powiadomień, więc wywoła ten interfejs w kontenerze.
Teraz dodaj ClickIn
metody i ClickOut
do interfejsu _IPolyCtlEvents
.
Aby dodać metody ClickIn i ClickOut
W Eksplorator rozwiązań otwórz plik Polygon.idl i dodaj następujący kod w
methods:
obszarze wdispInterface_IPolyCtlEvents
deklaracji biblioteki PolygonLib:[id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y); [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
Metody ClickIn
i ClickOut
przyjmują współrzędne x i y klikniętego punktu jako parametry.
Generowanie biblioteki typów
W tym momencie wygeneruj bibliotekę typów, ponieważ projekt użyje jej do uzyskania informacji potrzebnych do utworzenia interfejsu punktu połączenia i interfejsu kontenera punktu połączenia dla kontrolki.
Aby wygenerować bibliotekę typów
Ponownie skompiluj projekt.
— lub —
Kliknij prawym przyciskiem myszy plik Polygon.idl w Eksplorator rozwiązań i kliknij polecenie Skompiluj w menu skrótów.
Spowoduje to utworzenie pliku Polygon.tlb, który jest biblioteką typów. Plik Polygon.tlb nie jest widoczny z Eksplorator rozwiązań, ponieważ jest to plik binarny i nie można go wyświetlić ani edytować bezpośrednio.
Implementowanie interfejsów punktu połączenia
Zaimplementuj interfejs punktu połączenia i interfejs kontenera punktu połączenia dla kontrolki. W modelu COM zdarzenia są implementowane za pośrednictwem mechanizmu punktów połączenia. Aby odbierać zdarzenia z obiektu COM, kontener ustanawia połączenie doradcze z punktem połączenia, który implementuje obiekt COM. Ponieważ obiekt COM może mieć wiele punktów połączenia, obiekt COM implementuje również interfejs kontenera punktu połączenia. Za pomocą tego interfejsu kontener może określić, które punkty połączenia są obsługiwane.
Interfejs implementujący punkt połączenia nosi nazwę IConnectionPoint
, a interfejs implementujący kontener punktu połączenia nosi nazwę IConnectionPointContainer
.
Aby ułatwić implementację IConnectionPoint
programu , należy użyć Kreatora implementowania punktu połączenia. Ten kreator generuje IConnectionPoint
interfejs, odczytując bibliotekę typów i wdrażając funkcję dla każdego zdarzenia, które można wyzwolić.
Aby zaimplementować punkty połączenia
W Eksplorator rozwiązań otwórz plik _IPolyCtlEvents_CP.h i dodaj następujący kod w ramach
public:
instrukcji wCProxy_IPolyCtlEvents
klasie :VOID Fire_ClickIn(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; } VOID Fire_ClickOut(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; }
Zobaczysz, że ten plik ma klasę o nazwie CProxy_IPolyCtlEvents
, która pochodzi z klasy IConnectionPointImpl
. _IPolyCtlEvents_CP.h definiuje teraz dwie metody Fire_ClickIn
i Fire_ClickOut
, które przyjmują dwa parametry współrzędnych. Te metody są wywoływane, gdy chcesz uruchomić zdarzenie z kontrolki.
Tworząc kontrolkę z wybraną opcją Punkty połączenia, plik _IPolyCtlEvents_CP.h został wygenerowany. Dodano ją również CProxy_PolyEvents
do IConnectionPointContainerImpl
wielu list dziedziczenia kontrolki i uwidoczniliśmy IConnectionPointContainer
, dodając odpowiednie wpisy do mapy MODELU COM.
Zakończono implementowanie kodu w celu obsługi zdarzeń. Teraz dodaj kod w celu wyzwolenia zdarzeń w odpowiednim momencie. Pamiętaj, że uruchamiasz ClickIn
zdarzenie lub ClickOut
, gdy użytkownik kliknie lewy przycisk myszy w kontrolce. Aby dowiedzieć się, kiedy użytkownik kliknie przycisk, dodaj procedurę obsługi komunikatu WM_LBUTTONDOWN
.
Aby dodać procedurę obsługi komunikatu WM_LBUTTONDOWN
W widoku klasy kliknij prawym przyciskiem myszy klasę
CPolyCtl
i kliknij polecenie Właściwości w menu skrótów.W oknie Właściwości kliknij ikonę Komunikaty, a następnie kliknij
WM_LBUTTONDOWN
pozycję z listy po lewej stronie.Z wyświetlonej listy rozwijanej kliknij pozycję <Dodaj> przycisk OnLButtonDown. Deklaracja
OnLButtonDown
programu obsługi zostanie dodana do biblioteki PolyCtl.h, a implementacja programu obsługi zostanie dodana do PolyCtl.cpp.
Następnie zmodyfikuj procedurę obsługi.
Aby zmodyfikować metodę OnLButtonDown
Zmień kod, który składa się z
OnLButtonDown
metody w PolyCtl.cpp (usunięcie dowolnego kodu umieszczonego przez kreatora), tak aby wyglądało to następująco:LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) { HRGN hRgn; WORD xPos = LOWORD(lParam); // horizontal position of cursor WORD yPos = HIWORD(lParam); // vertical position of cursor CalcPoints(m_rcPos); // Create a region from our list of points hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING); // If the clicked point is in our polygon then fire the ClickIn // event otherwise we fire the ClickOut event if (PtInRegion(hRgn, xPos, yPos)) Fire_ClickIn(xPos, yPos); else Fire_ClickOut(xPos, yPos); // Delete the region that we created DeleteObject(hRgn); return 0; }
Ten kod korzysta z punktów obliczanych w funkcji w OnDraw
celu utworzenia regionu, który wykrywa kliknięcia myszy użytkownika za pomocą wywołania metody PtInRegion
.
Parametr uMsg jest identyfikatorem obsługiwanego komunikatu systemu Windows. Dzięki temu można mieć jedną funkcję, która obsługuje szereg komunikatów. Parametry wParam i lParam to standardowe wartości obsługiwanego komunikatu. Parametr bHandled umożliwia określenie, czy funkcja obsłużyła komunikat. Domyślnie wartość jest ustawiona na WARTOŚĆ TRUE, aby wskazać, że funkcja obsłużyła komunikat, ale można ustawić ją na FALSE. Spowoduje to, że usługa ATL będzie nadal szukać innej funkcji obsługi komunikatów w celu wysłania komunikatu do.
Kompilowanie i testowanie kontrolki
Teraz wypróbuj swoje zdarzenia. Skompiluj kontrolkę i ponownie uruchom kontener testów kontrolek ActiveX. Tym razem wyświetl okno dziennika zdarzeń. Aby skierować zdarzenia do okna danych wyjściowych, kliknij pozycję Rejestrowanie w menu Opcje i wybierz pozycję Dziennik do okna danych wyjściowych. Wstaw kontrolkę i spróbuj kliknąć w oknie. Pamiętaj, że ClickIn
jest uruchamiany, jeśli klikniesz w wypełnionym wielokącie i ClickOut
zostanie wyzwolony po kliknięciu poza nim.
Następnie dodasz stronę właściwości.