Jenter Алекс
Шрифт:
A2 Из вопроса не ясно, использует ли автор стили WS_HSCROLL и WS_VSCROLL или элемент управления scroll bar. Однако и в том, и в другом случае можно использовать одни и те же функции (SetScrollInfo/GetScrollInfo), чтобы управлять полосой прокрутки. Сначала (с помощью SetScrollInfo) для неё задаются 32-разрядные значения основных параметров (положения ползунка, диапазона изменения его положения и размера страницы). Затем в обработчике сообщений WS_HSCROLL и WS_VSCROLL можно использовать GetScrollInfo, чтобы получить значения всех этих параметров (опять же 32-разрядные!).
Допустим, окно имеет стиль WS_VSCROLL. Тогда в указанные функции нужно передавать HWND этого окна и константу SB_VERT (в случае с горизонтальной полосой прокрутки используется SB_HORZ). Например:
В том случае, когда вместо стилей WS_xSCROLL используется элемент управления scroll bar, код выглядит совершенно аналогично, но функциям SetScrollInfo, GetScrollInfo и пр. передаётся HWND самой полосы прокрутки (а не владеющего ею окна), а в качестве второго параметра передаётся SB_CTL.
Александр Шаргин (rudankort@mail.ru)Q. Как сделать так, чтобы программа сама себя могла стереть, т.е. свой *.exe файл?
LowFeaRЭто все на сегодня. Пока!
Алекс Jenter jenter@mail.ru Красноярск, 2001.Программирование на Visual C++
Выпуск №32 от 11 февраля 2001 г.
Приветствую вас, уважаемые подписчики!
СТАТЬЯ
Автоматизация и моторизация приложения
Акт первый
Автор: Николай Куртов
Редактор журнала СофтТерра
Софт Терра: Технологии Microsoft для разработчиков
Неслучайно именно эта статья была выбрана мной для начала рубрики, посвященной технологиям Microsoft для разработчиков. Слова OLE и COM (Component Object Model) на устах программистов вот уже 5 лет, тем не менее, парадигма компонентного подхода остается базовым и неизменным моментом в создании приложений. Я помню, насколько широкие горизонты я для себя открыл, осознав идею объектного подхода – с тех пор строю свои программы из компонентов-кирпичиков, объединяя их в более абстрактные модели – сервисы. Программирование давно стало сплавом творчества и строительства, оставляя в прошлом сугубо научно-шаманскую окраску ремесла. И если такой переход уже сделан, то сейчас можно обозначить новый виток – ломание барьеров API и переход к более обобщенному подходу в проектировании, выход на новый уровень абстракции. Немало этому способствовал интернет и его грандиозное творение – XML. Сегодня ключ к успеху приложения сплавляется из способности его создателей обеспечить максимальную совместимость со стандартами и в то же время масштабируемость. Придумано такое количество различных технологий для связи приложений и повторного использования кода, что сегодня прикладные программы не могут жить без такой "поддержки". Под термином "автоматизация" я понимаю настоящее оживление приложений, придание им способности взаимодействовать с внешней средой, предоставление пользователю максимального эффекта в работе с приложениями. Не равняясь на такие гранды технической документации, как MSDN, я, тем не менее, этой статьей хочу указать на путь, по которому сегодня проектируются современные приложения.
Автоматизация (Automation) была изначально создана как способ для приложений (таких как Word или Excel) предоставлять свою функциональность другим приложениям, включая скрипт-языки. Основная идея заключалась в том, чтобы обеспечить наиболее удобный режим доступа к внутренним объектам, свойствам и методам приложения, не нуждаясь при этом в многочисленных "хедерах" и библиотеках.
Вообще, я бы выделил два вида автоматизации – внешняя и внутренняя. Внешняя автоматизация – это работа сторонних приложений с объектной моделью вашей программы, а внутреняя – это когда сама программа предоставляет пользователю возможность работы со своей объектной структурой через скрипты. Комбинирование первого и второго вида представляется наиболее масштабируемым решением и именно о нем сегодня пойдет речь.
Для начала обратим внимание на самое дно – интерфейсы COM. Если термин "интерфейс" в этом контексте вам ничего не говорит, то представьте себе абстрактный класс без реализации – это и есть интерфейс. Реальные объекты наследуются от интерфейсов. Компоненты, наследующиеся от интерфейса IUnknown, называются COM-объектами. Этот интерфейс содержит методы подсчета ссылок и получения других интерфейсов объекта.
Автоматизация базируется на интерфейсе IDispatch, наследующегося от IUnknown. IDispatch позволяет запускать методы и обращаться к свойствам вашего объекта через их символьные имена. Интерфейс имеет немного методов, которые являются тем не менее довольно сложными в реализации. К счастью, существует множество шаблонных классов, предлагающих функциональность интерфейса IDispatch, поэтому для создания объекта, готового к автоматизации, необходимо весего лишь несколько раз щелкнуть мышкой в ClassWizard Visual C++.
Что касается способа доступа и динамического создания ваших внутренних dispatch объектов, то тут тут тоже все довольно просто – данные об объекте хранятся в реестре под специальным кодовым именем, которое называется ProgId. Например, progid программы Excel – Excel.Application. Cоздать в любой процедуре на VBScript достаточно легко – надо только вызвать функцию CreateObject, в которую передать нужный ProgID. Функция вернет указатель на созданный объект.
В MFC существует специальный класс, под названием CCmdTarget. Наследуя свои классы от cCmdtarget, вы можете обеспечить для них необходимую функциональность в dispatch виде – как раз как ее понимают скрипты. При созднании нового класса в ClassWizard (View>ClassWizard>Add Class>New), наследуемого от cСmdtarget, просто щелкните на кнопке Automation или Creatable by ID, чтобы обеспечить возможность создания экземпляра объекта по его ProgID. Замечу, что для программ, реализующих внутреннюю автоматизацию, это не нужно. Для приложений, реализующих внешнуюю и смешанную автоматизацию, это необходимо для "корневых" объектов.
После создания такого объекта, ClassWizard создает интерфейс ITestAutomatedClass (это dispatch интерфейс, т.е. наследуется от IDispatch), который реализуется моим CTestAutomatedClass. Теперь к этому интерфейсу я могу добавить методы или свойства, которые автоматически будут реализованы в CTestAutomatedClass. Я добавил свойство Age.
COM-объекты, коим и является наш CTestAutomatedClass, можно создавать только динамически. Это связано с тем, что объект может использоваться несколькими приложениями одновременно, а значит, удаление объекта из памяти не может выполнить ни одно из них. Разумно предположить, что объект сам должен отвечать за свое удаление. Такой механизм реализован при помощи механизма ссылок (reference count). Когда приложение получает указатель на объект, он увеличивает свой внутренний счетчик ссылок, а когда приложение освобождает объект – счетчик ссылок уменьшается. При достижении счетчиком нуля, объект удаляет сам себя. Если наш объект был создан по ProgID другим приложением, то программа CTestApp (другими словами, Automation-Server) не завершится до тех пор, пока счетчик ссылок CTestAutomatedClass не станет равным нулю.