Example: Implementing a Property Page
В этом примере показано, как создать страницу свойств, отображающее свойства (и позволяет изменению) интерфейса Классы документов. Этот интерфейс является предоставление документами в Примеры модели объектов общей среды Visual Studio (хотя страница свойств, созданной не позаботит, где его обрабатывают объекты приденный из при условии, что они поддерживают необходимый интерфейс).
Пример основан на Образец ATLPages.
Чтобы завершить этот пример, необходимо:
Добавление класса страницы свойств библиотеки ATL, используя диалоговое окно добавление класса мастера и страницы свойств библиотеки ATL.
Ресурс диалогового окна правка путем добавления новых элементов управления для интересующих свойств интерфейса Документ.
Добавление обработчиков сообщений для хранения сайт страницы свойств сообщенный изменений, внесенных пользователем.
Добавьте некоторые выписки #import и typedef в разделе домоустройство.
переопределите IPropertyPageImpl::SetObjects для проверки объектов, переданного странице свойств.
Переопределение IPropertyPageImpl::Activate для инициализации интерфейс страницы свойств.
Переопределение IPropertyPageImpl::Apply для обновления объекта с самыми последними значениями свойств.
Откройте страницу свойств путем создания простого вспомогательный объект.
создайте макрос, которое проверяет страницу свойств.
Добавление класса страницы свойств библиотеки ATL
Сначала создайте новый проект библиотеки ATL для сервера библиотеки DLL ATLPages7. Теперь используйте Мастер страниц свойств библиотеки ATL чтобы создать страницу свойств. Присвойте странице свойств Короткое имяDocProperties а затем перейдите на страницу в Строки задать элементы свойство-страница- определенного как показано в таблице ниже.
Элемент |
Значение |
---|---|
Заголовок |
TextDocument |
Строка документации |
Свойства VCUE TextDocument |
Helpfile |
<blank> |
Значения, которые устанавливаются на этой странице мастера будут возвращены к контейнеру страницы свойств, когда она вызывает IPropertyPage::GetPageInfo. Что происходит на строки после зависящее от контейнере, но, как правило, они будут использоваться для определения странице пользователю. Обычно заголовок появится на вкладке по конкретной страницей и строка документа может отображаться в строке состояния или подсказке (хотя стандартный фрейм свойства не использует эту строку на всех).
Примечание
Строки, что набор здесь хранитесь как строковые ресурсы проекта мастером.Можно легко правка эти строки с помощью редактора ресурсов если необходимо изменить эти сведения, после того как был создан код для страницы.
Нажмите кнопку ОК иметь мастер создания странице свойств.
Ресурс диалогового окна редактирования
Теперь, когда страница свойств будет создана, необходимо добавить несколько элементов управления на ресурс диалогового окна, представляющий пользовательскую страницу. Добавьте элемент управления "поле ввода", статический текст и их идентификаторы и установите флажок, как показано ниже:
Эти элементы управления используются для отображения имени файла документа и его только для чтения.
Примечание
Ресурс диалогового окна не включает фрейм или кнопки, ни у него с вкладками, можно выбрать ожидается.Эти функции предоставляются кадром страницы свойств, созданный путем вызова OleCreatePropertyFrame.
Добавление обработчиков сообщений
С элементами управления в месте, можно добавить обработчики сообщений для обновления пакостное состояние страницы, когда значение из изменений элементов управления:
BEGIN_MSG_MAP(CDocProperties)
COMMAND_HANDLER(IDC_NAME, EN_CHANGE, OnUIChange)
COMMAND_HANDLER(IDC_READONLY, BN_CLICKED, OnUIChange)
CHAIN_MSG_MAP(IPropertyPageImpl<CDocProperties>)
END_MSG_MAP()
// Respond to changes in the UI to update the dirty status of the page
LRESULT OnUIChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
wNotifyCode; wID; hWndCtl; bHandled;
SetDirty(true);
return 0;
}
Этот код будет реагировать на изменения, сделанные в элемент управления "Поле ввода" или флажку путем вызова IPropertyPageImpl::SetDirty, который информирует сайт страниц, что страница изменена. Обычно страницы сайт отвечает, разрешить или запретить кнопку Применить во фрейме страницы свойств.
Примечание
В собственных страницах свойств, можно отслеживать точно, свойствам редактирования пользователем, что позволяет избежать обновления свойств, которые не были изменены.Инструменты этого примера, кодируют, отслеживать исходных значений свойств и сравнение их с текущими значениями из пользовательского интерфейса, если давно пора, чтобы применить изменения.
Домоустройство
Теперь добавьте несколько выписки #import к DocProperties.h, что компилятор знает об интерфейсе Документ:
// MSO.dll
#import <libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52> version("2.2") \
rename("RGB", "Rgb") \
rename("DocumentProperties", "documentproperties") \
rename("ReplaceText", "replaceText") \
rename("FindText", "findText") \
rename("GetObject", "getObject") \
raw_interfaces_only
// dte.olb
#import <libid:80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2> \
inject_statement("using namespace Office;") \
rename("ReplaceText", "replaceText") \
rename("FindText", "findText") \
rename("GetObject", "getObject") \
rename("SearchPath", "searchPath") \
raw_interfaces_only
Кроме того, необходимо обратиться к базовому классу IPropertyPageImpl; добавьте следующий typedef к классу CDocProperties:
typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;
Переопределение IPropertyPageImpl::SetObjects
Первый метод IPropertyPageImpl, который необходимо переопределить SetObjects. Здесь можно добавить код для проверки того, что был передан только один объект, и что он поддерживает интерфейс Документ, который ожидается:
STDMETHOD(SetObjects)(ULONG nObjects, IUnknown** ppUnk)
{
HRESULT hr = E_INVALIDARG;
if (nObjects == 1)
{
CComQIPtr<EnvDTE::Document> pDoc(ppUnk[0]);
if (pDoc)
hr = PPGBaseClass::SetObjects(nObjects, ppUnk);
}
return hr;
}
Примечание
Он имеет смысл поддерживать только один объект для данной страницы, поскольку вы разрешите пользователю задать имя файла объекта — только один файл может существовать в одном месте.
Переопределение IPropertyPageImpl::Activate
Следующим шагом будет инициализировать страница свойств со значениями свойства базового объекта при первоначальном создана страницы.
В этом случае необходимо добавить следующие элементы в класс, поскольку также потребуется использовать исходные значения свойств для сравнения, если пользователи страницы применить свои изменения:
CComBSTR m_bstrFullName; // The original name
VARIANT_BOOL m_bReadOnly; // The original read-only state
Реализация базового класса метода Активировать отвечает за создание диалогового окна и ее элементам управления, таким образом можно переопределить этот метод и добавить собственную инициализация после вызова метода базового класса:
STDMETHOD(Activate)(HWND hWndParent, LPCRECT prc, BOOL bModal)
{
// If we don't have any objects, this method should not be called
// Note that OleCreatePropertyFrame will call Activate even if
// a call to SetObjects fails, so this check is required
if (!m_ppUnk)
return E_UNEXPECTED;
// Use Activate to update the property page's UI with information
// obtained from the objects in the m_ppUnk array
// We update the page to display the Name and ReadOnly properties
// of the document
// Call the base class
HRESULT hr = PPGBaseClass::Activate(hWndParent, prc, bModal);
if (FAILED(hr))
return hr;
// Get the EnvDTE::Document pointer
CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
if (!pDoc)
return E_UNEXPECTED;
// Get the FullName property
hr = pDoc->get_FullName(&m_bstrFullName);
if (FAILED(hr))
return hr;
// Set the text box so that the user can see the document name
USES_CONVERSION;
SetDlgItemText(IDC_NAME, CW2CT(m_bstrFullName));
// Get the ReadOnly property
m_bReadOnly = VARIANT_FALSE;
hr = pDoc->get_ReadOnly(&m_bReadOnly);
if (FAILED(hr))
return hr;
// Set the check box so that the user can see the document's read-only status
CheckDlgButton(IDC_READONLY, m_bReadOnly ? BST_CHECKED : BST_UNCHECKED);
return hr;
}
Этот код использует методы интерфейса Документ модель COM для получения свойств, что нужно знать in. Затем он использует программы-оболочки API Win32, предоставляемых CDialogImpl и его базовых классов для отображения значений свойств для пользователя.
Переопределение IPropertyPageImpl::Apply
Когда пользователи хотят применить свои изменения в объекты, будут вызывать метод Применить сайта страницы свойств. Это размещение, чтобы сделать обратное кода в Активировать — тогда как в Активировать значения от объекта и отправляло их в элементы управления на странице свойств Применить принимает значения от элементов управления на странице свойств и помещает их в объект.
STDMETHOD(Apply)(void)
{
// If we don't have any objects, this method should not be called
if (!m_ppUnk)
return E_UNEXPECTED;
// Use Apply to validate the user's settings and update the objects'
// properties
// Check whether we need to update the object
// Quite important since standard property frame calls Apply
// when it doesn't need to
if (!m_bDirty)
return S_OK;
HRESULT hr = E_UNEXPECTED;
// Get a pointer to the document
CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
if (!pDoc)
return hr;
// Get the read-only setting
VARIANT_BOOL bReadOnly = IsDlgButtonChecked(IDC_READONLY) ? VARIANT_TRUE : VARIANT_FALSE;
// Get the file name
CComBSTR bstrName;
if (!GetDlgItemText(IDC_NAME, bstrName.m_str))
return E_FAIL;
// Set the read-only property
if (bReadOnly != m_bReadOnly)
{
hr = pDoc->put_ReadOnly(bReadOnly);
if (FAILED(hr))
return hr;
}
// Save the document
if (bstrName != m_bstrFullName)
{
EnvDTE::vsSaveStatus status;
hr = pDoc->Save(bstrName, &status);
if (FAILED(hr))
return hr;
}
// Clear the dirty status of the property page
SetDirty(false);
return S_OK;
}
Примечание
Проверка на соответствие m_bDirty в начале этой реализации начальный проверьте, предотвращаются ненужные обновления объектов, если Применить вызываются несколько раз.Также проверяет соответствие всех значений свойств, чтобы обеспечить, что только изменения приводят к вызову метода Документ.
Примечание
Предоставляет FullNameДокумент как свойство, доступное только для чтения.Чтобы обновить имя файла документа на основе изменениях, внесенных на странице свойств необходимо использовать метод Сохранить для сохранения файла под другим именем.Таким образом, код на странице свойств не должен ограничить на получение или устанавливать свойства.
Отображение страницы свойств
Для отображения этой страницы необходимо создать простой вспомогательный объект. Вспомогательный объект обеспечит метод, который упрощает API OleCreatePropertyFrame для отображения одной страницы подключенной к одному объекту. Это вспомогательный объект был разработан так, что его можно использовать в Visual Basic.
Используйте Диалоговое окно " добавление класса и Мастер объекта простой библиотеки ATL чтобы создать новый класс и использовать в качестве его Helper короткое имя. Как только создан добавьте метод, как показано в таблице ниже.
Элемент |
Значение |
---|---|
Имя метода |
ShowPage |
Параметры |
[in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk |
Параметр bstrCaption заголовок, отображаемый в виде заголовка диалогового окна. Параметр bstrID строка или CLSID или ProgID страницы свойств для отображения. Параметр pUnk будет указателем IUnknown объекта свойства которого будут настроитьы страницей свойств.
Реализуйте метод, как показано ниже:
STDMETHODIMP CHelper::ShowPage(BSTR bstrCaption, BSTR bstrID, IUnknown* pUnk)
{
if (!pUnk)
return E_INVALIDARG;
// First, assume bstrID is a string representing the CLSID
CLSID theCLSID = {0};
HRESULT hr = CLSIDFromString(bstrID, &theCLSID);
if (FAILED(hr))
{
// Now assume bstrID is a ProgID
hr = CLSIDFromProgID(bstrID, &theCLSID);
if (FAILED(hr))
return hr;
}
// Use the system-supplied property frame
return OleCreatePropertyFrame(
GetActiveWindow(), // Parent window of the property frame
0, // Horizontal position of the property frame
0, // Vertical position of the property frame
bstrCaption, // Property frame caption
1, // Number of objects
&pUnk, // Array of IUnknown pointers for objects
1, // Number of property pages
&theCLSID, // Array of CLSIDs for property pages
NULL, // Locale identifier
0, // Reserved - 0
NULL // Reserved - 0
);
}
Создать макрос
После построения проекта можно проверить страницы свойств и вспомогательный объект с помощью простой макрос, что можно создать и запустить в интегрированной среде разработки Visual Studio. Этот макрос создает объект помощника, а затем вызывает метод ShowPage, используя идентификатор ProgID страницы свойств DocProperties и указатель IUnknown активного документа в данный момент в редакторе Visual Studio. Код для этого макроса показано ниже:
Imports EnvDTE
Imports System.Diagnostics
Public Module AtlPages
Public Sub Test()
Dim Helper
Helper = CreateObject("ATLPages7.Helper.1")
On Error Resume Next
Helper.ShowPage( _
ActiveDocument.Name, _
"ATLPages7Lib.DocumentProperties.1", _
DTE.ActiveDocument _
)
End Sub
End Module
При выполнении этого макроса будет отображена страница свойств, указывающая имя файла и состояние только для чтения в настоящий момент активно текстового документа. Состояние только для чтения документа отражает только возможность записи в документ в интегрированной среде разработки; она не затрагивает только для чтения, атрибут файла на диске.