Иллюстрированный самоучитель по Visual Studio .NET

Окна с геометрией данных

Характерный для MFC двухступенчатый способ создания окна cwndGeom объясняется тем, что с каждым окном связаны две сущности: Windows-окно, характеризуемое описателем окна, и объект класса cwndGeom, который мы еще должны разработать. В коде функции show для каждого полигона сначала динамически создается объект класса cwndGeom (конструктор класса), а затем – управляемое им Windows-окно (Create).

При создании объекта мы передаем ему указатель на класс родительского окна и индекс полигона в контейнере. Поэтому окно впоследствии сможет найти нужный полигон в документе и изобразить его в своем контексте. Мы запоминаем адреса всех объектов CwndGeom в массиве m_pWnds, для того чтобы потом можно было уничтожить все Windows-окна (вызвав DestroyWindow), так же, как и все объекты класса cwndGeom (вызвав деструктор класса CWndGeom). Эту процедуру надо выполнять каждый раз, когда пользователь выбирает новый узел в файловом дереве.

Вам уже знакома процедура ввода в проект новых классов. Сейчас настала пора применить ее для ввода в проект класса cwndGeom. При работе с мастером MFC Class Wizard выберите в качестве базового класс cwnd и измените предлагаемые по умолчанию имена файлов, в которых будут размещены стартовые коды нового класса. Вместо WndGeom.h и WndGeom.cpp задайте RightView.h и RightView.cpp. После того как мастер закончит работу, вставьте в начало файла RightView.h упреждающее объявление class CWndGeom; так как класс CRightview содержит массив указателей этого типа, а его объявление стоит до объявления cwndGeom.

Примечание
Надо отметить, что в бета-версии Studio .NET описываемый способ размещения нового класса работает неверно и для исправления ситуации мне пришлось убрать вновь добавленную директиву #pragma once из файла RightView.h и три новые, вставленные мастером, директивы #include из файла RightView.cpp. Надеюсь, что у вас ошибок такого рода не будет
.

Изготовленная мастером заготовка класса содержит несколько больше элементов, чем нам необходимо. В частности, не нужны макросы DECLARE_DYNAMIC и IMPLEMENT_DYNAMIC, так как мы не собираемся использовать унаследованную от CObject функцию isKindOf. Посмотрите справку по концепции наследования от CObject, чтобы понять, как связаны макросы с функцией IsKindOf, затем уберите макросы и внесите изменения в интерфейс класса так, чтобы он был:

class CWndGeom: public CWnd
{
public:
CTreeDoc *m_pDoc;
// Адрес документа (для удобства)
CRightview *m_pView;
// Адрес родительского окна
int m_ID;
// Индекс окна документа в массиве CRect m_Rect;
// Координаты в правом окне
//====== Удобный для нас конструктор
CWndGeom (CRightview *p, int id);
~CWndGeom();
protected: DECLARE_MESSAGE_MAP()
};

В файле реализации класса измените коды конструктора, как показано ниже. Затем с помощью Studio .NET введите в класс реакции на следующие сообщения: WM_PAINT, WM_LBUTTONDOWN и WM_MOUSEMOVE. Цель этих действий такова. При наведении курсора мыши на одно из окон, управляемых классом CWndGeom, оно должно проявить признаки готовности быть выбранным. Для этого рисуем в нем обрамляющий прямоугольник, который исчезает при выходе указателя мыши за пределы окна. Эта функциональность реализуется за счет пары функций SetCaptureReleaseCapture.

Метод CWnd::SetCapture захватывает текущее окно как адресат для последующих сообщений мыши независимо от позиции курсора. Поэтому при перемещении курсора мыши можно выйти из пределов клиентской области окна и все равно получить и обработать сообщение им_ MOUSEMOVE. На этом свойстве окна и построен алгоритм его подсветки. Функция ReleaseCapture "освобождает мышь", то есть вновь восстанавливает обычный порядок обработки мышиных сообщений.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.