Окна с геометрией данных
Характерный для 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, оно должно проявить признаки готовности быть выбранным. Для этого рисуем в нем обрамляющий прямоугольник, который исчезает при выходе указателя мыши за пределы окна. Эта функциональность реализуется за счет пары функций SetCapture – ReleaseCapture.
Метод CWnd::SetCapture захватывает текущее окно как адресат для последующих сообщений мыши независимо от позиции курсора. Поэтому при перемещении курсора мыши можно выйти из пределов клиентской области окна и все равно получить и обработать сообщение им_ MOUSEMOVE. На этом свойстве окна и построен алгоритм его подсветки. Функция ReleaseCapture "освобождает мышь", то есть вновь восстанавливает обычный порядок обработки мышиных сообщений.