Добавление события (учебник ATL, часть 5)
На этом шаге вы добавите ClickIn
событие и ClickOut
событие в элемент управления ATL. Событие будет срабатывает ClickIn
, если пользователь щелкает в многоугольнике и срабатывает ClickOut
, если пользователь щелкает за пределами. Задачи для добавления события приведены следующим образом:
ClickIn
Добавление иClickOut
методыСоздание библиотеки типов
Реализация интерфейсов точки подключения
Добавление методов ClickIn и ClickOut
При создании элемента управления ATL на шаге 2 установлен флажок "Точки подключения". Он создал _IPolyCtlEvents
интерфейс в файле Polygon.idl. Обратите внимание, что имя интерфейса начинается с подчеркивания. Это соглашение, указывающее, что интерфейс является внутренним интерфейсом. Таким образом, программы, позволяющие просматривать COM-объекты, могут не отображать интерфейс пользователю. Кроме того, обратите внимание, что при выборе точек подключения в файле Polygon.idl добавлена следующая строка, указывающая, что _IPolyCtlEvents
это исходный интерфейс по умолчанию:
[default, source] dispinterface _IPolyCtlEvents;
Исходный атрибут указывает, что элемент управления является источником уведомлений, поэтому он вызовет этот интерфейс в контейнере.
Теперь добавьте ClickIn
методы и ClickOut
методы в _IPolyCtlEvents
интерфейс.
Добавление методов ClickIn и ClickOut
В Обозреватель решений откройте Polygon.idl и добавьте следующий код
methods:
вdispInterface_IPolyCtlEvents
объявлении библиотеки 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);
ClickOut
Методы ClickIn
принимают координаты x и y в качестве параметров.
Создание библиотеки типов
Создайте библиотеку типов на этом этапе, так как проект будет использовать его для получения сведений, необходимых для создания интерфейса точки подключения и интерфейса контейнера точки подключения для элемента управления.
Создание библиотеки типов
Перестройте свой проект.
–или–
Щелкните правой кнопкой мыши файл Polygon.idl в Обозреватель решений и щелкните "Скомпилировать" в контекстном меню.
При этом будет создан файл Polygon.tlb, который является вашей библиотекой типов. Файл Polygon.tlb не отображается из Обозреватель решений, так как он является двоичным файлом и не может просматриваться или изменяться напрямую.
Реализация интерфейсов точки подключения
Реализуйте интерфейс точки подключения и интерфейс контейнера точки подключения для элемента управления. В COM события реализуются через механизм точек подключения. Для получения событий из COM-объекта контейнер устанавливает консультативное подключение к точке подключения, реализуемой объектом COM. Так как com-объект может иметь несколько точек подключения, com-объект также реализует интерфейс контейнера точки подключения. С помощью этого интерфейса контейнер может определить, какие точки подключения поддерживаются.
Интерфейс, реализующий точку подключения, вызывается IConnectionPoint
, а интерфейс IConnectionPointContainer
, реализующий контейнер точки подключения.
Для реализации IConnectionPoint
используется мастер реализации точки подключения. Этот мастер создает IConnectionPoint
интерфейс, считывая библиотеку типов и реализуя функцию для каждого события, которое можно запустить.
Реализация точек подключения
В Обозреватель решений откройте _IPolyCtlEvents_CP.h и добавьте следующий код в инструкцию
public:
CProxy_IPolyCtlEvents
в классе: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; }
Вы увидите, что этот файл имеет класс, вызывающий CProxy_IPolyCtlEvents
производный от IConnectionPointImpl
. _IPolyCtlEvents_CP.h теперь определяет два метода Fire_ClickIn
и Fire_ClickOut
, которые принимают два параметра координаты. Эти методы вызываются, когда требуется запустить событие из элемента управления.
При создании элемента управления с выбранным параметром "Точки подключения" был создан файл _IPolyCtlEvents_CP.h. Он также добавил CProxy_PolyEvents
и IConnectionPointContainerImpl
в список наследования элемента управления несколько и предоставляется IConnectionPointContainer
для вас путем добавления соответствующих записей на карту COM.
Вы завершите реализацию кода для поддержки событий. Теперь добавьте код, чтобы запустить события в соответствующий момент. Помните, что вы собираетесь запустить ClickIn
или ClickOut
событие, когда пользователь нажимает левую кнопку мыши в элементе управления. Чтобы узнать, когда пользователь нажимает кнопку, добавьте обработчик сообщения WM_LBUTTONDOWN
.
Добавление обработчика для сообщения WM_LBUTTONDOWN
В представлении классов щелкните правой кнопкой мыши класс и выберите пункт "Свойства"
CPolyCtl
в контекстном меню.В окне "Свойства" щелкните значок "Сообщения", а затем в
WM_LBUTTONDOWN
списке слева.В появившемся раскрывающемся списке нажмите кнопку <"Добавить> OnLButtonDown".
OnLButtonDown
Объявление обработчика будет добавлено в PolyCtl.h, а реализация обработчика будет добавлена в PolyCtl.cpp.
Затем измените обработчик.
Изменение метода OnLButtonDown
Измените код, который состоит из
OnLButtonDown
метода в PolyCtl.cpp (удаление любого кода, размещенного мастером), чтобы он выглядел следующим образом: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; }
Этот код использует точки, вычисляемые в OnDraw
функции, чтобы создать регион, который обнаруживает щелчки мыши пользователя с вызовом PtInRegion
.
Параметр uMsg — это идентификатор обрабатываемого сообщения Windows. Это позволяет использовать одну функцию, которая обрабатывает диапазон сообщений. Параметры wParam и lParam — это стандартные значения для обрабатываемого сообщения. Параметр bHandled позволяет указать, обрабатывает ли функция сообщение или нет. По умолчанию значение имеет значение TRUE, чтобы указать, что функция обрабатывает сообщение, но ее можно задать значение FALSE. Это приведет к тому, что ATL продолжит поиск другой функции обработчика сообщений для отправки сообщения.
Сборка и тестирование элемента управления
Теперь попробуйте события. Создайте элемент управления и снова запустите контейнер тестов activeX. На этот раз просмотрите окно журнала событий. Чтобы перенаправить события в выходное окно, щелкните "Ведение журнала " в меню "Параметры " и выберите "Журнал" в окне вывода. Вставьте элемент управления и попробуйте щелкнуть в окне. Обратите внимание, что ClickIn
при щелчке внутри заполненного многоугольника и ClickOut
при щелчке за его пределами.
Затем вы добавите страницу свойств.
Вернуться к шагу 4 | Вкл. Шаг 6