Приветствую вас, уважаемые читатели!
Вот наконец и свершилось - вышел в
свет первый номер этой рассылки. Для начала попробую
разобраться зачем я за это все взялся и кому это может
быть нужно, кроме меня ?
Итак, зачем?
Как язык программирования мне более всего нравится
С++, а как среда разработки - MS Visual C++ 6.0 (далее
просто "VC"). VC - очень мощный и гибкий инструмент.
В нем можно разрабатывать программы любого уровня сложности
- от самых простеньких, до серьезных, больших приложений.
Все это понятно. Что же предлагает для разработки программ
VC? Конечно есть "голый" Windows API, еще есть MFC,
есть еще библиотека ATL, которая в общем-то предназначена
для написания Active-X контролов. Чем же пользоваться
мне? Раньше, как мне кажется фактически было два варианта:
- MFC. Все описано, документировано, есть масса сторонних
библиотек, расширяющих функциональность. В Сети навалом
и даже больше информации по ней. И все-таки. Если
мне, например требуется написать небольшую программу,
то зачем стрелять пушкой по воробьям, тянуть за собой
рантайм и тому подобное? К тому же, про нестыковки
и ошибки MFC слагаются легенды. Так что - это не
мой путь :)
- Windows API. Тоже все документировано, все описано,
информации в Сети полным полно. Плюсы, как мне кажетсся
такие: никаких сторонних прослоек, то есть если есть
ошибка, то она либо в моем коде (что скорее), либо
в функции WinAPI (про котороую скорее всего давно
знают и описали), а не где-то в недрах какой-то там
библиотеки. Потом, размер программ, написанных с
помощью WinAPI, кардинально меньше, чем такой же
программы, написанной на MFC. Для меня лишь оставалось
небольшим неудобством то, что все построено на одних
С-функциях, обработка и маршрутизация сообщений выглядели
не так, как хотелось бы.
Но появилась библиотека WTL, которая в сущности является
расширением ATL и служит для работы с GUI. WTL появилась
достаточно давно и я не обращал на нее ососбого внимания.
А зря! Ведь это то, что мне было нужно: библотека в
виде тонкой прослойки, в которой есть масса необходимых
вещей и почти ничего лишнего. К тому же WTL, как мне
кажется, довольно красиво разработана и в ней учтены
многие недоработки проектирования MFC. Программы, написанные
на WTL, компактны, быстры и не тянут за собой никаких
рантаймов. На настоящий момент доступна версия 7.0,
взять ее можно здесь (434
Кб).
Теперь я приблизился к вопросу, который прозвучал
в начале. WTL официально не документирована и поставляется
в исходных текстах. Для освоения этой библиотеки приходиться
искать информацию в Сети и разбираться с ее внутренним
устройством. Так как я не могу причислить себя к гуру
в программировании, то и решил создать эту рассылку,
в которой публиковал бы разичные сведения на тему ATL/WTL
и Windows API, которые посчитал бы интересными. А читатели,
то есть вы, могли бы подсказать мне где я не прав или
предложить интересную тему для обсуждения.
Что планируется здесь публиковать
- Занимательные факты по поводу ATL, WTL, WinAPI,
MS VC.
- Решение каких-то проблем
- Код, который делает что-то полезное
- Интересные вопросы и ответы на них
- Может еще что-то в том же духе
Содержательная часть
Классы WTL
Хорошо, хватит общих слов, постараюсь сообщить что-нибудь
полезное. Для начала, для тех кто не знает, есть прекрасный
проект , который называется RSDN .
На этом сайте можно найти массу полезной информации
по Visual C++, Delphi, Windows API, различным алгоритмам
и еще много чему. Среди прочих, на сайте есть несколько
статей про библиотеку WTL. Эти статьи , на мой взгляд,
несут массу полезной информации и практически незаменимы
для тех, кто решил разобраться с основами программирования
с использованием WTL. Да и для тех, кто уже использует
эту библиотеку, но не так давно, думаю что почитать
тоже будет интересно. Вот ссылки на три статьи:
Прочитав эти статьи в свое время, я решил сделать
для себя полный список классов WTL с указанием файлов,
в которых определен каждый класс. Вот эта несложная
табличка (имена классов упорядочены по алфавиту):
Название класса В каком файле определен
Название класса |
В каком файле определен |
_U_MENUorID |
atlapp.h |
_U_RECT |
atlapp.h |
_U_STRINGorID |
atlapp.h |
CAnimateCtrl |
atlctrls.h |
CAppModule |
atlapp.h |
CAxPropertyPage |
atldlgs.h |
CAxPropertyPageImpl |
atldlgs.h |
CBitmap |
atlgdi.h |
CBitmapButton |
atlctrlx.h |
CBitmapButtonImpl |
atlctrlx.h |
CBitmapHandle |
atlgdi.h |
CBrush |
atlgdi.h |
CBrushHandle |
atlgdi.h |
CButton |
atlctrls.h |
CCheckListViewCtrl |
atlctrlx.h |
CCheckListViewCtrlImpl |
atlctrlx.h |
CCheckListViewCtrlImplTraits |
atlctrlx.h |
CClientDC |
atlgdi.h |
CColorDialog |
atldlgs.h |
CColorDialogImpl |
atldlgs.h |
CComboBox |
atlctrls.h |
CComboBoxEx |
atlctrls.h |
CCommandBarCtrl |
atlctrlw.h |
CCommandBarCtrlBase |
atlctrlw.h |
CCommandBarCtrlImpl |
atlctrlw.h |
CCommonDialogImplBase |
atldlgs.h |
CCustomDraw |
atlctrls.h |
CDateTimePickerCtrl |
atlctrls.h |
CDC |
atlgdi.h |
CDCHandle |
atlgdi.h |
CDevMode |
atlprint.h |
CDevModeHandle |
atlprint.h |
CDialogResize |
atlframe.h |
CDragListBox |
atlctrls.h |
CDragListNotifyImpl |
atlctrls.h |
CEdit |
atlctrls.h |
CEditCommands |
atlctrls.h |
CEnhMetaFile |
atlgdi.h |
CEnhMetaFileDC |
atlgdi.h |
CEnhMetaFileHandle |
atlgdi.h |
CEnhMetaFileInfo |
atlgdi.h |
CFileDialog |
atldlgs.h |
CFileDialogImpl |
atldlgs.h |
CFindFile |
atlmisc.h |
CFindReplaceDialog |
atldlgs.h |
CFindReplaceDialogImpl |
atldlgs.h |
CFlatScrollBar |
atlctrls.h |
CFlatScrollBarImpl |
atlctrls.h |
CFolderDialog |
atldlgs.h |
CFolderDialogImpl |
atldlgs.h |
CFont |
atlgdi.h |
CFontDialog |
atldlgs.h |
CFontDialogImpl |
atldlgs.h |
CFontHandle |
atlgdi.h |
CFrameWindowImpl |
atlframe.h |
CFrameWindowImplBase |
atlframe.h |
CFrameWndClassInfo |
atlframe.h |
CFSBWindowT |
atlscrl.h |
CHeaderCtrl |
atlctrls.h |
CHotKeyCtrl |
atlctrls.h |
CHyperLink |
atlctrlx.h |
CHyperLinkImpl |
atlctrlx.h |
CIdleHandler |
atlapp.h |
CImageList |
atlctrls.h |
CIPAddressCtrl |
atlctrls.h |
CLinkCtrl |
atlctrls.h |
CListBox |
atlctrls.h |
CListViewCtrl |
atlctrls.h |
CMapScrollImpl |
atlscrl.h |
CMapScrollWindowImpl |
atlscrl.h |
CMDIChildWindowImpl |
atlframe.h |
CMDICommandBarCtrl |
atlctrlw.h |
CMDICommandBarCtrlImpl |
atlctrlw.h |
CMDIFrameWindowImpl |
atlframe.h |
CMDIWindow |
atlframe.h |
CMenu |
atluser.h |
CMenuHandle |
atluser.h |
CMenuItemInfo |
atluser.h |
CMessageFilter |
atlapp.h |
CMessageLoop |
atlapp.h |
CMonthCalendarCtrl |
atlctrls.h |
CMultiPaneStatusBarCtrl |
atlctrlx.h |
CMultiPaneStatusBarCtrlImpl |
atlctrlx.h |
COwnerDraw |
atlframe.h |
CPagerCtrl |
atlctrls.h |
CPageSetupDialog |
atldlgs.h |
CPageSetupDialogImpl |
atldlgs.h |
CPaintDC |
atlgdi.h |
CPalette |
atlgdi.h |
CPaletteHandle |
atlgdi.h |
CPaneContainer |
atlctrlx.h |
CPaneContainerImpl |
atlctrlx.h |
CPen |
atlgdi.h |
CPenHandle |
atlgdi.h |
CPoint |
atlmisc.h |
CPrintDialog |
atldlgs.h |
CPrintDialogEx |
atldlgs.h |
CPrintDialogExImpl |
atldlgs.h |
CPrintDialogImpl |
atldlgs.h |
CPrinter |
atlprint.h |
CPrinterDC |
atlprint.h |
CPrinterHandle |
atlprint.h |
CPrinterInfo |
atlprint.h |
CPrintPreview |
atlprint.h |
CPrintPreviewWindow |
atlprint.h |
CPrintPreviewWindowImpl |
atlprint.h |
CProgressBarCtrl |
atlctrls.h |
CPropertyPage |
atldlgs.h |
CPropertyPageImpl |
atldlgs.h |
CPropertyPageWindow |
atldlgs.h |
CPropertySheet |
atldlgs.h |
CPropertySheetImpl |
atldlgs.h |
CPropertySheetWindow |
atldlgs.h |
CReBarCtrl |
atlctrls.h |
CRecentDocumentList |
atlmisc.h |
CRecentDocumentListBase |
atlmisc.h |
CRect |
atlmisc.h |
CRgn |
atlgdi.h |
CRgnHandle |
atlgdi.h |
CRichEditCommands |
atlctrls.h |
CRichEditCtrl |
atlctrls.h |
CRichEditFontDialog |
atldlgs.h |
CRichEditFontDialogImpl |
atldlgs.h |
CScrollBar |
atlctrls.h |
CScrollImpl |
atlscrl.h |
CScrollWindowImpl |
atlscrl.h |
CServerAppModule |
atlapp.h |
CSimpleArray |
atlbase.h |
CSimpleStack |
atlctrlw.h |
CSimpleValArray |
atlbase.h |
CSize |
atlmisc.h |
CSplitterImpl |
atlsplit.h |
CSplitterWindowImpl |
atlsplit.h |
CSplitterWindowT |
atlsplit.h |
CStatic |
atlctrls.h |
CStatusBarCtrl |
atlctrls.h |
CString |
atlmisc.h |
CStringData |
atlmisc.h |
CTabCtrl |
atlctrls.h |
CTheme |
atltheme.h |
CThemeImpl |
atltheme.h |
CToolBarCtrl |
atlctrls.h |
CToolInfo |
atlctrls.h |
CToolTipCtrl |
atlctrls.h |
CTrackBarCtrl |
atlctrls.h |
CTreeItem |
atlctrls.h |
CTreeViewCtrl |
atlctrls.h |
CTreeViewCtrlEx |
atlctrls.h |
CUpdateUI |
atlframe.h |
CUpdateUIBase |
atlframe.h |
CUpDownCtrl |
atlctrls.h |
CWaitCursor |
atlctrlx.h |
CWinDataExchange |
atlddx.h |
CWindowDC |
atlgdi.h |
В этом списке больше сотни классов. Не все классы
можно использовать напрямую. Некоторые из классов могут
быть только базовыми. В дальнейшем я планирую постепенно
составить описание если не всех, то хотя бы наиболее
интересных классов.
Далее я решил набросать иерархию классов в WTL. Ее
можно взять отсюда
(.rtf файл, запакованный в ZIP, 20 Кб) . Как видно
из этой схемы, многие классы в WTL не имеют общего
предка или вообще существуют "сами по себе".
Два простых класса контейнера
В библиотеке ATL, в файле atlbase.h определены, кроме
всего прочего, два интересных класса:
- CSimpleArray . Этот класс предсталяет
из себя динамический массив, который использует только
С++ и функции CRT для управления памятью.
- CSimpleMap . Тоже незатейливый
класс, позволяющий создавать списки вида "ключ,значение" (карта)
. Как написано в комментарии к этому классу:"предназначен
для небольшого количества простых типов или указателей".
Оба класса реализованы как шаблоны, оба очень простые
и не зависят от других классов. Как мне кажется, эти
классы можно использовать и для своих целей, особенно
когда нет желания писать похожие свои собственные и
нельзя воспльзоваться подобными классами из стандартной
библиотеки STL. В каждом классе есть функции, которые
могут найти требуемый элемент простым перебором, используя
как критерий результат операции "==" между искомым
элементом и элементами в контейнере. Это значит, что
если если используется пользовательский тип, то он
должен перегружать оператор "==", для того чтобы его
можно было найти. Если функции поиска элемента не вызываются,
то можно использовать простую структуру,например. Рассмотрю
более подробно эти два класса.
CSimpleArray
Объявить экземпляр класса можно, например, так:
CSimpleArray<TSimple> simle_array;
Вместо TSimple можно использовать свой тип или встроенный,
например int или double .
Теперь опишу методы класса CSimpleArray :
Синтаксис
метода |
Описание |
CSimpleArray() |
Конструктор по умолчанию. Тело конструктора
вообще ничего не делает, только через список инициализации
конструктора задаются начальные значения переменным
класса. |
~CSimpleArray() |
Деструктор. Вызвается при уничтожении
массива. Вызывает функцию RemoveAll() (см.ниже). |
int GetSize() const |
Возвращает число элементов в массиве |
BOOL Add(T& t) |
Добавляет один элемент в массив.
Добавляемый элемент должен быть уже создан. В принципе,
в этой и в других подобных функциях, было бы естественнее
передавать ссылку на константу, как мне кажется. |
BOOL Remove(T& t) |
Сначала находит позицию элемента
в массиве, а потом удаляет его из этой позиции. |
BOOL RemoveAt(int nIndex) |
Удаляет элемент массива из указанной
позиции. Метод также вызывает деструктор удаляемого
элемента. |
void RemoveAll() |
Удаляет все элементы и освобождает
занимаемую память. При удалении вызываются деструкторы
удаляемых элементов. |
T& operator[]
(int nIndex) const |
Возвращает ссылку на элемент, заднный
номером. Проверка границ диапазона происходит только
в отладочной версии. |
T* GetData() const |
Возвращает указатель на область памяти,
отведенной под массив. |
Служебные методы |
void SetAtIndex(int
nIndex, T& t) |
Записывает в указанную позицию передаваемый
элемент. Проверка границ диапазона происходит только
в отладочной версии. |
int Find(T& t)
const |
Возвращает позицию элемента в массиве
или -1, если такого элемента не найдено. |
CSimpleMap
Пример объявления экземпляра класса:
CSimpleMap<int, TSimple> simple_map;
Вместо int и TSimple можно использовать свои собственные
типы или встроенные.
Методы класса CSimpleMap :
Синтаксис
метода |
Описание |
CSimpleMap() |
Конструктор по умолчанию. Тело конструктора
вообще ничего не делает, только через список инициализации
конструктора задаются начальные значения переменным
класса. |
~CSimpleMap() |
Деструктор. Вызвается при уничтожении
карты. Вызывает функцию RemoveAll() (см.ниже). |
int GetSize() const |
Возвращает количество элементов в
карте. |
BOOL Add(TKey key, TVal val) |
Добавляет новую пару "ключ,значение". |
BOOL Remove(TKey key) |
Находит соответствующий ключ (если
есть) и удаляет пару "ключ, значение" из карты.
Для удаляемых элементов вызываются деструкторы. |
void RemoveAll() |
Удаляет все элементы и освобождает
память. Для всех удаляемых элементов вызываются
деструкторы. |
BOOL SetAt(TKey key, TVal
val) |
Записывает значение, соответствующее
ключу, при условии что такой ключ есть. |
TVal Lookup(TKey key) const |
Выполняет поиск значения по ключу. |
TKey ReverseLookup(TVal val)
const |
Выполняет поиск ключа по значению. |
TKey& GetKeyAt(int
nIndex) const |
Возвращает ссылку на ключ по его
позиции. Границы диапазона проверяются только в
отладочной версии. |
TVal& GetValueAt(int
nIndex) const |
Возвращает ссылку на значение по
его позиции. Границы диапазона проверяются только
в отладочной версии. |
Служебные методы |
void SetAtIndex(int
nIndex, TKey& key, TVal& val) |
Записывает в указанную позицию ключ
и значение. |
int FindKey(TKey& key)
const |
Выполняет поиск ключа и возвращает
его позицию или -1, если не найдено |
int FindVal(TVal& val)
const |
Выполняет поиск значения и возвращает
его позицию или -1, если не найдено. |
В обоих классах, как я уже говорил, поиск выполняется
простым перебором. К тому же при удалении элемента "лишняя" память
не освобождается. Вся отведенная память освобождается
только при удалении массива. Несмотря на все это, я
считаю что эти два класса вполне можно использовать
для небольших наборов данных.
Вот, пока все. Все вопросы, пожелания, критику
можете направлять мне по адресу: softonic@narod.ru |
|