Здравствуйте, уважаемые
читатели!
Можно сказать, что я закончил
написание моей первой программы, в которой используется
только WTL и Win API. Программа называется CDOpen и
предназначена для быстрого открытия/закрытия лотка
CD-привода. Мне самому давно была нужна такая программа,
так как системный блок на моем рабочем месте установлен
не очень удобно и тянуться к кнопке открытия на приводе
не удобно (к тому же были случаи, когда вместо кнопки
открытия я нажимал кнопку питания, а это не смешно).
Несмотря на то, что программа получилась на вид довольно
простой, в ходе ее создания пришлось столкнуться с
решением некоторых проблем, которые не лежат на поверхности.
Почитать описание и возможности CDOpen, а также скачать
можете здесь.
Не сочтите за рекламу все
вышесказанное, так как программа некоммерческая и,
как я считаю, вполне совпадает с тематикой рассылки.
Если кому-либо будет интересно, как что-то сделано
в программе, то я с удовольствием расскажу, а Вы, надеюсь,
мне расскажете как сделать это луше.
Первые впечатления
Многое из того, что предлагает
WTL я в своей программе не использовал. ПОКА. Но все
равно кое-какие мысли на тему WTL у меня появились.
Попробую организовать их по пунктам:
- Не все то, что я знал про MFC нужно забыть.
Многие классы в WTL, такие как CMenu или СBrush,
практически один-а-один повторяют интерфейс классов
MFC. С одной стороны это не очень хорошо, так как
можно было переписать такие классы так, чтобы ими
удобнее пользоваться. С другой стороны это большой
плюс, так как тем, кто использовал MFC такие классы
будут привычны, а те, кто не использовал MFC смогут
посмотреть описание таких классов в MSDN. Сразу оговорюсь,
что я не проверял соответствие классов WTL классам
MFC, это сходство было замечено мной лишь на некоторых,
но я сделал предположение, что такое сходство в большей
или меньшей степени будет повторяться и для других
схожих классов. Впоследствии, может быть, я более
внимательно займусь этим вопросом.
- Исходники должны лежать по правую руку.
Практически во всех статьях по WTL пишут, что исходники
библиотеки должны стать верным спутником разработчика,
который ее использует. Со своей стороны могу согласиться
на 101% с этим утверждением. При любой неясности,
в исходных текстах WTL можно найти ответ практически
наверняка. Задачу навигации по WTL облегчает VC -
команда "Go definition of _____" контекстного
меню, она мнгновенно перебрасывает в один из исходных
файлов WTL на место определения интересующего макроса,
функции, класса и т.д.
- Организация классов целиком в h-файлах не самая
удачная мысль. Во-первых, интерфейс класса
захламляется реализацией и без Class Wizard-а уже
сразу не разберешься что и где лежит. Во-вторых, "традиционное" разделение
на интерфейс и реализацию, как мне кажется, наиболее
естественно. Но в таком случае методы класса перестают
быть inline-методами. Делайте со мной что хотите,
но я все равно не пойму, зачем в обычной программе
делать все методы inline?
Что же получается в итоге? Могу сказать, что WTL пока
меня не разочаровала. Могу сказать, что даже
наоборот - постепенно WTL мне стала нравиться больше.
WTL практически не навязывает мне как разработчику
никаких правил и не обременяет толстой прослойкой,
наподобии VCL. Минус WTL - это небольшая ее распространненость
и небольшое число разных расширений, например классов
для работы с сетью и т.д. в отличии от MFC, под которую
понаписано столько всего, что кажется количество всяких
сторонних библиотек и классов приближается к бесконечности.
Макросы WTL
Один из читателей предложил мне составить список макросов
WTL, я пробежался по заголовочным файлам и набросал
вот эту табличку:
Название макроса |
Файл,
где определен |
BEGIN_DDX_MAP(thisClass) |
atlddx.h |
BEGIN_MSG_MAP_EX(theClass) |
atlcrack.h |
BEGIN_UPDATE_UI_MAP(thisClass) |
atlframe.h |
CHAIN_CLIENT_COMMANDS() |
atlframe.h |
CHAIN_COMMANDS(theChainClass) |
atlframe.h |
CHAIN_COMMANDS_ALT(theChainClass,
msgMapID) |
atlframe.h |
CHAIN_COMMANDS_ALT_MEMBER(theChainMember,
msgMapID) |
atlframe.h |
CHAIN_COMMANDS_MEMBER(theChainMember) |
atlframe.h |
CHAIN_MDI_CHILD_COMMANDS() |
atlframe.h |
COMMAND_CODE_HANDLER_EX(code,
func) |
atlcrack.h |
COMMAND_HANDLER_EX(id,
code, func) |
atlcrack.h |
COMMAND_ID_HANDLER_EX(id,
func) |
atlcrack.h |
COMMAND_RANGE_CODE_HANDLER_EX(idFirst,
idLast, code, func) |
atlcrack.h |
COMMAND_RANGE_HANDLER_EX(idFirst,
idLast, func) |
atlcrack.h |
DDX_CHECK(nID,
var) |
atlddx.h |
DDX_CONTROL(nID,
obj) |
atlddx.h |
DDX_FLOAT(nID,
var) |
atlddx.h |
DDX_FLOAT_RANGE(nID,
var, min, max) |
atlddx.h |
DDX_INT(nID, var) |
atlddx.h |
DDX_INT_RANGE(nID,
var, min, max) |
atlddx.h |
DDX_RADIO(nID,
var) |
atlddx.h |
DDX_TEXT(nID, var) |
atlddx.h |
DDX_TEXT_LEN(nID,
var, len) |
atlddx.h |
DDX_UINT(nID, var) |
atlddx.h |
DDX_UINT_RANGE(nID,
var, min, max) |
atlddx.h |
DECLARE_FRAME_WND_CLASS(WndClassName,
uCommonResourceID) |
atlframe.h |
DECLARE_FRAME_WND_CLASS_EX(WndClassName,
uCommonResourceID, style, bkgnd) |
atlframe.h |
DECLARE_FRAME_WND_SUPERCLASS(WndClassName,
OrigWndClassName, uCommonResourceID) |
atlframe.h |
END_DDX_MAP() |
atlddx.h |
FORWARD_NOTIFICATIONS() |
atlapp.h |
HandleToLong( h
) |
atlapp.h |
HandleToUlong(
h ) |
atlapp.h |
IntToPtr( i ) |
atlapp.h |
LongToHandle( h) |
atlapp.h |
LongToPtr( l ) |
atlapp.h |
MESSAGE_HANDLER_EX(msg,
func) |
atlcrack.h |
MESSAGE_RANGE_HANDLER_EX(msgFirst,
msgLast, func) |
atlcrack.h |
NOTIFY_CODE_HANDLER_EX(cd,
func) |
atlcrack.h |
NOTIFY_HANDLER_EX(id,
cd, func) |
atlcrack.h |
NOTIFY_ID_HANDLER_EX(id,
func) |
atlcrack.h |
NOTIFY_RANGE_CODE_HANDLER_EX(idFirst,
idLast, cd, func) |
atlcrack.h |
NOTIFY_RANGE_HANDLER_EX(idFirst,
idLast, func) |
atlcrack.h |
PtrToInt( p ) |
atlapp.h |
PtrToLong( p ) |
atlapp.h |
PtrToShort( p ) |
atlapp.h |
PtrToUint( p ) |
atlapp.h |
PtrToUlong( p ) |
atlapp.h |
PtrToUshort( p
) |
atlapp.h |
REFLECTED_COMMAND_CODE_HANDLER |
atlapp.h |
REFLECTED_COMMAND_CODE_HANDLER_EX(code,
func) |
atlcrack.h |
REFLECTED_COMMAND_HANDLER |
atlapp.h |
REFLECTED_COMMAND_HANDLER_EX(id,
code, func) |
atlcrack.h |
REFLECTED_COMMAND_ID_HANDLER |
atlapp.h |
REFLECTED_COMMAND_ID_HANDLER_EX(id,
func) |
atlcrack.h |
REFLECTED_COMMAND_RANGE_CODE_HANDLER |
atlapp.h |
REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst,
idLast, code, func) |
atlcrack.h |
REFLECTED_COMMAND_RANGE_HANDLER |
atlapp.h |
REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst,
idLast, func) |
atlcrack.h |
REFLECTED_NOTIFY_CODE_HANDLER |
atlapp.h |
REFLECTED_NOTIFY_CODE_HANDLER_EX(cd,
func) |
atlcrack.h |
REFLECTED_NOTIFY_HANDLER |
atlapp.h |
REFLECTED_NOTIFY_HANDLER_EX(id,
cd, func) |
atlcrack.h |
REFLECTED_NOTIFY_ID_HANDLER |
atlapp.h |
REFLECTED_NOTIFY_ID_HANDLER_EX(id,
func) |
atlcrack.h |
REFLECTED_NOTIFY_RANGE_CODE_HANDLER |
atlapp.h |
REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst,
idLast, cd, func) |
atlcrack.h |
REFLECTED_NOTIFY_RANGE_HANDLER |
atlapp.h |
REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst,
idLast, func) |
atlcrack.h |
UIntToPtr( ui ) |
atlapp.h |
ULongToPtr( ul
) |
atlapp.h |
В файле atlcrack.h кроме
перечисленных макросов определено очень много макросов,
имеющих префиск MSG_WM и
несколько MSG_OCM.
Почитать про них можно на сайте RSDN,
в статье Использование
WTL. Часть 1.
На сегодня
вроде все.
Всего наилучшего. |