Страницы свойств реализуются как отдельные COM объекты, это позволяют страницам свойств быть общедоступными, если необходимо. Чтобы добавить страницу свойств к вашему элементу управления Вы можете использовать ATL Object Wizard.
Запустите ATL Object Wizard и выберите Controls с левой стороны из групп. Выберите страницу свойств (Property Page) и нажмите Next. Выберите страницу свойств (Property Page) и нажмите Next. Вы увидите диалоговое окно, которое позволяет Вам ввести имя нового объекта. Назовем объект PolyProp и введем его имя в окно редактирования Short Name.
Обратите внимание, что окно Interface недоступно. Это потому что страница свойств не нуждается в заказном интерфейсе.
Нажмите на вкладку Strings, чтобы установить заголовок страницы свойств. Заголовок страницы свойств - это строка, которая появляется на вкладке. Напечатайте $Polygon как заголовок. Doc String - это описание, которое рамка свойства помещает в строку состояния или совет в панели инструментов. Обратите внимание, что стандартная страница свойств в настоящее время не использует эту строку, но Вы можете устанавливать ее в любом случае. Вы не собираетесь генерировать Helpfile в настоящее время, сотрите этот текстовый блок. Нажмите OK и объект страницы свойств будет создан.
Появятся следующие три файла:
Сделаны следующие изменения кода:
Теперь добавьте поля, которые Вы хотите видеть на странице свойств. Обратите внимание, что в Polygon.rc диалог пуст (кроме метки, которая напоминает, что нужно вставить свои управляющие элементы). Удалите эту метку и добавьте метку, которая содержит текст "Sides:". Рядом с меткой добавьте окно редактирования с идентификатором IDC_SIDES.
Включите Polygon.h в начале файла PolyProp.h:
#include "Polygon.h" // определение IPolyCtl
Теперь дайте возможность классу CPolyProp установить число сторон в вашем объекте, когда нажимается кнопка Apply. Измените функцию Apply в PolyProp.h следующим образом.
STDMETHOD(Apply)(void) { USES_CONVERSION; ATLTRACE(_T("CPolyProp::Apply\n")); for (UINT i = 0; i < m_nObjects; i++) { CComQIPtr<IPolyCtl, &IID_IPolyCtl> pPoly(m_ppUnk[i]); short nSides = (short)GetDlgItemInt(IDC_SIDES); if FAILED(pPoly->put_Sides(nSides)) { CComPtr<IErrorInfo> pError; CComBSTR strError; GetErrorInfo(0, &pError); pError->GetDescription(&strError); MessageBox(OLE2T(strError), _T("Error"), MB_ICONEXCLAMATION); return E_FAIL; } } m_bDirty = FALSE; return S_OK; }
Страница свойств может иметь несколько клиентов одновременно, поэтому функция Apply вызывает put_Sides каждого клиента со значением полученным из окна редактирования. Вы используете CComQIPtr класс, который выполняет QueryInterface для каждого объекта, чтобы получить интерфейс IPolyCtl из IUnknown (сохраненный в массиве m_ppUnk).
Код теперь проверяет, что установка свойства была произведена. Если установка свойств происходила не верно, то код отображает подробности в виде ошибки, отображая окно сообщения из интерфейса IErrorInfo. Обычно, контейнер запрашивает объект интерфейса ISupportErrorInfo и вызывает InterfaceSupportsErrorInfo, чтобы определить, поддерживает ли объект данные об ошибках. Но так как это наш элемент управления, то можно пропустить эту проверку.
CComPtr помогает автоматически обрабатывать подсчет ссылки, в результате можно не вызвать Release. CComBSTR помогает с обработкой BSTR, в результате не надо выполнять обращение SysFreeString. Использование строковых преобразований добавляется макрокомандой USES_CONVERSION в начале функции.
Мы должны создать флажок для страницы свойств, чтобы указать, что к кнопке Apply нужно разрешить доступ. Доступ нужно разрешать когда пользователь изменяет значение в окне редактирования Side. Щелкните правой кнопкой мыши на странице свойств класса в ClassView, и затем выберите Add Windows Message Handler... из контекстного меню. Выберите IDC_SIDES из списка и затем добавьте сообщение EN_CHANGE.
Теперь добавьте следующий код в Polyprop.h к функции OnChangeSides. (удалите весь код, который там поместил мастер):
LRESULT OnChangeSides(WORD wNotify, WORD wID, HWND hWnd, BOOL& bHandled) { SetDirty(TRUE); return 0; }
Функция OnChangeSides будет вызываться когда сообщение WM_COMMAND послано с уведомлением EN_CHANGE для элемента управления IDC_SIDES. OnChangeSides затем вызывает SetDirty и передает TRUE, чтобы указать, что страница свойств теперь изменена и кнопку Apply можно разрешить. Давайте добавим страницу свойств к вашему элементу управления. ATL Object Wizard не делает это автоматически с тех пор как в вашем проекте появляется несколько элементов управления.
Откройте PolyCtl.h и добавьте эту строку в карту свойств:
PROP_ENTRY("Sides", 1, CLSID_PolyProp)
Карта свойств элемента управления теперь выглядит следующим образом:
BEGIN_PROP_MAP(CPolyCtl) PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4) PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4) PROP_ENTRY("FillColor", DISPID_FILLCOLOR, CLSID_StockColorPage) PROP_ENTRY("Sides", 1, CLSID_PolyProp) // Example entries // PROP_ENTRY("Property Description", dispid, clsid) // PROP_PAGE(CLSID_StockColorPage) END_PROP_MAP()
Вы могли бы добавить макрокоманду PROP_PAGE с CLSID вашей страницы свойств, но если Вы используете макрокоманду PROP_ENTRY, то значение свойства Sides будет сохранено когда элемент управления сохранится. Три параметра для макрокоманды - описание свойства, DISPID свойства, CLSID страницы свойств. Это полезно, если Вы загружаете элемент управления в VB и устанавливаете число Sides во время разработки. Так как число Sides было сохранено, то когда Вы перезагружаете проект число Sides автоматически восстанавливается.
Соберите элемент управления и вставьте его в ActiveX Control Test Container. Затем в меню Edit нажимаем PolyCtl Class Object. На странице свойств выберите вкладку Polygon.
Кнопка Apply первоначально заблокирована. Начните печатать значение в окне редактирования Side и кнопка Apply станет доступной. После того, как Вы закончили вводить значение нажмите кнопку Apply. Элемент управления будет изменен и кнопка Apply снова заблокируется. Пробуйте ввести недопустимое значение и Вы увидите окно сообщения содержащее описание ошибки из функции put_Sides.