Здравствуйте Whisperer, Вы писали:
W>Очень хорошо если бы ВЫ привели побольше описания или другие вписали бы свои — тогда и появится ДОКА к этому файлу
1) Распаковщики сообщений
( используються для упрощения написания оконных процедур
делая код более читабельным )
наша главная оконная процедура
INT_PTR CALLBACK DlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg)
{
HANDLE_MSG(hwndDlg,WM_INITDIALOG,Cls_OnInitDialog);
HANDLE_MSG(hwndDlg,WM_COMMAND,Cls_OnCommand);
}
return 0;
}
HANDLE_MSG определен в библиотеке как
#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam),(lParam),(fn))
Он являяет собой всего-навсего макрос,
параметры которого имеют следующие значения:
hwnd – дескриптор окна
message – собщения которое нужно обработать в оконной процедуре
fn – название функции которая отвечает за обработку сообщения
(указаного в параметре message)
Здесь ОСТОРОЖНО ! Вы должны не забывать що прототип вашей оконной функции не может бить определен например как
CALLBACK DlgProc(.., WPARAM w, LPARAM l)
Переменные типов WPARAM, LPARAM не должны отличаться от wParam, lParam:
CALLBACK DlgProc(.., WPARAM wParam, LPARAM lParam)
Причиной этого служит тот факт что мы используем макрос HANDLE_MSG который передает макросу HANDLE_##message ети параметры хотя сам
их реально не получает.
Макросы семейства HANDLE_WM_* — это и есть настоящие распаковщики сообщений – они производят необходимые преобразования типов WPARAM LPARAM и вызывают Вашу функцию передавая ей 3 параметра
(дескриптор, и LPARAM,WPARAM соответственных типов)
#define HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, fn) \
(LRESULT)(DWORD)(UINT)(BOOL)(fn)((hwnd), (HWND)(wParam), lParam)
Есть еще одна вещь о которой нужно вспомнить.
Например если нам нужно в теле функции обработки сообщения вызвать оконною процедуру, используемою по умолчанию – то нам на помощь приходит макросы семейства FORWARD_*:
#define FORWARD_WM_INITDIALOG(hwnd, hwndFocus, lParam, fn) \
(BOOL)(DWORD)(fn)((hwnd), WM_INITDIALOG, (WPARAM)(HWND)(hwndFocus), (lParam))
На практике мы используем подобные макросы следующим способом:
BOOL Cls_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
...
FORWARD_WM_INITDIALOG(hwnd, hwndFocus, lParam, DefWindowProc);
}
2) Макросы для дочерных элементов управления
(Static, button, edit, scroolbar, listbox, combobox)
Имена каждого из этих макросов именуются по схеме:
ТипЭлемента_Сообщение
Пример: ListBox_DeleteString
Эти макросы попросту инкапсулируют вызов SendMessage
например посмотрим как реализирован макрос ListBox_DeleteString:
#define ListBox_DeleteString(hwndCtl, index)((int)(DWORD)SNDMSG((hwndCtl), LB_DELETESTRING, (WPARAM)(int)(index), 0L))
где SNDMSG определен в начале файла как
#ifndef _MAC
#define SNDMSG SendMessage
#else
#define SNDMSG AfxSendMessage
#endif
Заметка: большинство этих макросов требуют одного параметра – дескриптора окна. Поэтому если вы хотите вызывать разные макросы
для одного и того самого дескиптора – то будет полезно сохранить его
перед вызовами и после этого передавать им сохраненный описатель окна:
HWND hwndCtrl = GetDlgItem(hDlg, IDC_BUTTON);
GetCheck(hwndCtrl);
GetState(hwndCtrl);
3) Дополнительные макросы (секции KERNER Macro APIs,
USER Macro APIs и
GDI Macro APIs)
Они упрощают выполнение разных распространенных оперций.
Например API DeleteObject параметром имеет обьект типа HGDIOBJ.
Но вместо HGDIOBJ может бить HPEN, HBRUSH, HRGN.
Cоответственно чтобы не преобразовать ети типи явно к типу HGDIOBJ можна примененять непосредственно функции DeletePen, DeleteBrush, DeleteRgn:
#define DeletePen(hpen) DeleteObject((HGDIOBJ)(HPEN)(hpen))
#define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
#define DeleteRgn(hrgn) DeleteObject((HGDIOBJ)(HRGN)(hrgn))