Класс для просмотра изображений
Функция SetScrollSizes одновременно с размерами задает и режим преобразования координат. Самым неприятным и непонятным моментом в наследовании от класса CScrollView является то, что функция SetScrollSizes не позволяет задавать режимы MM_ISOTROPIC и MM_ANISOTROPIC, которые позволяют, как вы помните работать с формулами. Этот недостаток MFC широко дискутировался как в MSDN, так и на одном из самых популярных сайтов для программистов – www.CodeGuru.com. Там же вы можете обнаружить некоторые решения этой проблемы. Измените конструктор класса. В момент своего рождения объект класса CRightView должен подготовиться к работе с окнами, управляемыми классом CWndGeom. К тому моменту, когда ему понадобится создать серию таких окон, их тип (класс окон в смысле структуры типа WNDCLASS) уже должен быть известен системе.
Примечание
Прекрасное решение дал Brad Pirtle, и вы можете найти его в одном из разделов CodeGuru, включив поиск по имени. Он создал свой класс CZoomView (производный от CScrolLView), в котором заменил функцию SetScrollSizes на другую – SetZoomSizes, а также переопределил (overrode) виртуальную функцию OnPrepareDC, родительская версия которой обнаруживает и запрещает попытку использовать формульные режимы. В своей версии OnPrepareDC он обходит вызов родительской версии, то есть версии CSrollView, и вместо этого вызывает "дедушкину" версию CView::OnPrepareDC, которая терпимо относится к формульным режимам. Этот пример, на мой взгляд, очень убедительно демонстрирует гибкость объектно-ориентированного подхода при разработке достаточно сложных приложений.
CRightView::CRightView() { m_szltem = CSize (200.150); // Размеры картинки m_szMargin = CSize (20.20); // Размеры полей try { //====== Попытка зарегистрировать класс окон m_WndClass=AfxRegisterWndClass(CS_VREDRAWICS_HREDRAW, ::LoadCursor(GetModuleHandle(0),(char*)IDC_MYHAND), (HBRUSH) CreateSolidBrush(GetSysColor(COLOR_INFOBK))); } catch (CResourceException* pEx) { AfxMessageBox(_T("Класс уже зарегистрирован")); pEx › Delete (); } }
В конструкторе класса CRightView происходит попытка зарегистрировать новый класс окон. Обычно отказов здесь не бывает, но технология требует проверить наличие сбоя, поэтому включаем механизм обработки исключений (try-catch). Мы хотим добиться особого поведения окон с картинками, поэтому зададим для них свою форму курсора и свой цвет фона. Цвет фона выбирается из того набора, который предоставляет система (см. справку по функции GetSysColor), а курсор создали сами.
Дело в том, что системный курсор, идентифицируемый как iDC_HAND, работает не во всех версиях Windows. Если вы работаете в среде Windows 2000, то можете заменить в параметре функции LoadCursor вызов GetModuleHandle (0) на 0, а идентификатор IDC_MYHAND на IDC_HAND и работать с системным курсором. В этом случае ресурс курсора IDC_MYHAND окажется лишним и его можно удалить.
В данный момент мы предполагаем, что в классе документа уже создан динамический контейнер m_Shapes объектов класса CPolygon, каждый элемент которого соответствует данным, полученным в результате чтения документов, обнаруженных в текущем каталоге. Теперь приступим к разработке самой сложной функции в составе класса CRightView, которая должна:
- Пройти по всему перечню объектов m_shapes класса CPolygon.
- Вычислить исходя из текущего размера окна количество рядов и колонок мини-окон с изображениями полигонов.
- Создать для каждого из них окно, управляемое классом CWndGeom.
Дальше события развиваются автоматически. После создания окна cwndGeom система пошлет ему сообщение WM_PAINT, в обработке которого надо создать и настроить контекст устройства мини-окна, а затем вызвать функцию Draw для того полигона из контейнера m_Shapes, индекс которого соответствует индексу окна CWndGeom. Каждый полигон рисует себя сам в заданном ему в качестве параметра контексте устройства.