Чтение онлайн

на главную - закладки

Жанры

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

Что такое одноразовый таймер? Просто говоря, это таймер который используется один раз, а потом уничтожается. Основная реализация, в случае изменения размера окна, – запустить таймер при получении сообщения WM_SIZE. Если таймер уже существует (в случае последовательных сообщений WM_SIZE), уничтожить его и запустить еще один. Когда наконец сообщение WM_TIMER пробивается скозь очередь других сообщений, уничтожаем таймер. Помните, что вы не получите сообщения WM_TIMER, пока не прекратится изменение окна приложения. У сообщений WM_TIMER очень низкий приоритет. Следующие две функции, OnSize и OnTimer, иллюстрируют как я приспособил таймер для этого приложения. В дополнение к

созданию и уничтожению таймеров, эти функции устанавливают значение m_fDraw.

void CMetavw1View::OnSize(UINT nType, int cx, int cy) {

 CView::OnSize(nType, cx, cy);

 // Это нужно делать только если опция отображения содержимого

 // окна при перемещении и изменении размера включена

 if (m_fFullDragOn) {

if (!m_uiTimer) KillTimer(1);

m_uiTimer = SetTimer(1, 100, NULL);

m_fDraw = FALSE;

 }

}

Когда мы наконец получаем сообщение WM_TIMER, функция OnTimer устанавливает значение m_fDraw в TRUE, уничтожает таймер и перерисовывает клиентскую область окна представления.

void CMetavw1View::OnTimer(UINT nIDEvent) {

 m_fDraw = TRUE;

 m_uiTimer = 0;

 KillTimer(1);

 InvalidateRect(NULL);

}

Переменная m_fFullDragOn, встречавшаяся в OnSize, устанавливается вызовом функции FullDragOn в конструкторе класса представления. Эта функция смотрит в ключе HKEY_CURRENT_USER\Control Panel\Desktop реестра, включена ли опция показа содержимого окна. Если значение подключа DragFullWindows равно 1, функция возвращает TRUE, иначе она возвращает FALSE. [Расположение ключей в реестре сильно зависит от типа и версии системы. Используйте эту возможность с осторожностью. – прим. перев.]

BOOL CMetavw1View::FullDragOn {

 HKEY hkey = NULL;

 DWORD dwType;

 long lResult;

 LPSTR lpszDataBuf;

 DWORD cbData = 0;

 lResult = RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &hkey);

 if (hkey) {

// Получить размер ключа.

lResult = RegQueryValueEx(hkey, "DragFullWindows", NULL, &dwType, NULL, &cbData);

// Зарезервировать память под значение ключа.

lpszDataBuf = (LPSTR)malloc(cbData * sizeof(char));

// Получить значение ключа.

lResult = RegQueryValueEx(hkey, "DragFullWindows", NULL, &dwType, (LPBYTE)lpszDataBuf, &cbData);

return (*lpszDataBuf == '1');

 }

 return FALSE;

}

Общий результат таков: когда окно изменяет размер, ничего не перерисовывается до тех пор, пока изменение размера не прекратится.

Добавление второго
представления

Вы наверное помните, что в задаче Найджела было требование, что программа должна выводить документ на экран в различных представлениях: либо в виде изображения, либо в виде заголовка метафайла отображаемого как текст. Никаких проблем; наверняка для этого есть свой мастер наподобие AppWizard. К моему сильнейшему изумлению, никакого мастера не было! Так что я посмотрел статью Дейла Роджерсона (Dale Rogerson) "Multiple Views for a Single Document" ("Несколько представлений для одного документа") в MSDN. Она была очень полезной. Тем не менее, пока вы не проделаете это три или четыре раза, вы очень просто можете запутаться! Поверьте мне, я потерял несколько часов, когда брался то за добавление второго представления, то за написание класса CEMF. Я советую полностью сфокусироваться на втором представлении, пока оно не заработает как надо. Найджел добавил второе представление в одну из своих программ-примеров ("VIEWDIB: Views Multiple DIBs Simultaneously" Прим. редактора: к сожалению, это приложение больше не входит в состав библиотеки MSDN), основанную на статье Дейла. Он вывел следующий список, основанный на своем опыте. Имея статью Дейла и список Найджела, я смог добавить второе представление без особых хлопот. А если я могу это сделать, то вы тоже можете!

1. Воспользуйтесь ClassWizard чтобы создать новый класс представления; например, CAppSecondView.

2. Добавьте включение заголовочного класса нового представления в нужный cpp-файл (см. пункт 12).

3. Добавьте функцию GetDocument к коду класса представления и заголовку. (Скопируйте ее из другого класса представления.)

4. Напишите код функции OnDraw для нового представления, или по крайней мере поставьте простую заглушку, которая вам позволит его протестировать. Убедитесь, что код класса нового представления включен в проект, и откомпилируйте новый модуль.

5. Создайте новый ресурсный идентификатор, типа IDR_VIEW2TYPE. Этот идентификатор будет использоваться для всех ресурсов второго представления.

6. Создайте пиктограмму для нового представления, используйте ресурсный идентификатор из пункта 5.

7. Создайте меню для второго представления (можете скопировать старое), опять используйте ресурсный идентификатор из пункта 5.

8. Добавьте в каждое меню пункты для смены текущего представления.

9. В строковую таблицу добавьте новую строку шаблона для нового ресурсного идентификатора в виде:

\nТип\n\n\n\nТип файла\nТип файла

10. В класс приложения добавьте public-переменную типа CMultiDocTemplate* для каждого представления, например m_pBasicViewTemplate и m_pNewViewTemplate.

11. В файл заголовка класса приложения включите следующую строку после объявления класса:

extern C???App NEAR theApp;

(замените ??? на название вашего приложения.)

12. Добавьте код создания каждого шаблона документа в реализацию класса приложения, напр.:

m_pBasicViewTemplate = new CMultiDocTemplate(...);

AddDocTemplate(m_pBasicViewTemplate);

13. С помощью ClassWizard'a добавьте в класс главного окна обработчики команд меню нового представления. Все обработчики в виде:

CreateOrActivateFrame(theApp.m_p????ViewTemplate, RUNTIME_CLASS(C???View));

Также не забудьте включить заголочный файл нового представления в MAINFRM.CPP

14. Добавьте функцию CreateOrActivateFrame в MAINFRM.CPP и MAINFRM.H.

Поделиться:
Популярные книги

Тройняшки не по плану. Идеальный генофонд

Лесневская Вероника
Роковые подмены
Любовные романы:
современные любовные романы
6.80
рейтинг книги
Тройняшки не по плану. Идеальный генофонд

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Завод-3: назад в СССР

Гуров Валерий Александрович
3. Завод
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Завод-3: назад в СССР

Секретарь лорда Демона

Лунёва Мария
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Секретарь лорда Демона

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Я тебя не отпущу

Коваленко Марья Сергеевна
4. Оголенные чувства
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Я тебя не отпущу

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Идеальный мир для Лекаря 7

Сапфир Олег
7. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 7

Хозяйка дома на холме

Скор Элен
1. Хозяйка своей судьбы
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка дома на холме

Жена проклятого некроманта

Рахманова Диана
Фантастика:
фэнтези
6.60
рейтинг книги
Жена проклятого некроманта

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9