Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Рихтер Дж., Назар К. - Windows via C C++. Программирование на языке Visual C++ - 2009

.pdf
Скачиваний:
6262
Добавлен:
13.08.2013
Размер:
31.38 Mб
Скачать

876 Часть VI. Приложения

/* void Cls_OnCommand(HWND hWnd, int Id, HWND hWndCtl, UINT codeNotify); */

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \ ((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)dParam), \ (UINT)HIWORD(wParam)), OL)

#deflne FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \ (void)(fn)((hwnd), WM_COMMAND, \ MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), \ (LPARAM)(HWND)(hwndCtl))

Первая строка—комментарий, показывающий прототип функции, которую вы должны написать. Следующая строка — уже рассмотренный нами макрос HANDLE_WM_, а последняя содержит предописатель сообщения (message forwarder). Допустим, при обработке сообщения WMCOMMAND вы хотите вызвать оконную процедуру, используемую по умолчанию. Это выглядело бы так.

void Cls_OnCommand (HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) {

//выполняем обычную обработку

//обработка по умолчанию

FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify, DefWindowProc);

}

Макросы FORWARD_WM_ принимают распакованные параметры сообщения и воссоздают их эквиваленты wParam и lParam, после чего вызывают указанную вами функцию. В приведенном примере это DefWindowProc, но так же легко можно использовать SendMessage или PostMessage. Фактически, чтобы отправить (синхронно или асинхронно) сообщение какому-то окну в системе, можно применить макрос FORWARD_WM_ — это поможет скомбинировать отдельные параметры сообщения.

Макросы для дочерних элементов управления

Эти макросы упрощают посылку сообщений дочерним элементам управления. Они очень похожи на макросы FORWARD_WM_. Имя каждого из них начинается с типа управляющего элемента, которому передается сообщение, затем идут знак подчеркивания и имя сообщения. Например, чтобы послать сообщение LB_ GETCOUNT окну списка, задействуйте такой макрос из файла WindowsX.h:

#define ListBox_GetCount(hwndCtl) \ ((int)(DWORD)SNDMSG((hwndCtl), LB_GETCOUNT, 0, 0L))

Позвольте сделать несколько замечаний по этому макросу. Во-первых, у него только один параметр (hwndCtl) — описатель окна списка. Так как сообщение LB_GETCOUNT игнорирует параметры wParam и lParam, вам вообще нет нужды беспокоиться о них. Макрос, как вы уже видели, автоматичес-

Приложение Б. Распаковщики сообщений, макросы для дочерних элементов управления и

API-макросы.docx 877

ки передаст нули. Во-вторых, тип значения, возвращаемого SendMessage, преобразуется в int, в связи с чем не нужно самому преобразовывать тип.

Что мне не нравится в этих макросах, так это необходимость передавать им описатель окна элемента управления. Чаще всего элементы управления, которым вы посылаете сообщения, являются дочерними окнами диалогового окна. Из-за этого придется все время вызывать GetDlgItem примерно так:

int n = ListBox_GetCount(GetDlgItem(hDlg, ID_LISTBOX));

Этот код выполняется ничуть не медленнее, чем код с использованием SendDlgItemMessage, но объем программы увеличивается из-за дополнительных вызовов GetDlgItem. Если надо послать несколько сообщений одному и тому же элементу управления, вы, возможно, захотите обратиться к GetDlgItem лишь раз, сохранить описатель дочернего окна, а затем вызвать все необходимые макросы:

HWND hWndCtl = GetDlgItem(hDlg, ID_LISTBOX); int n = ListBox_GetCount(hWndCtl);

ListBox_AddString(hWndCtl, TEXT("Another string"));

Если вы пишете код именно так, приложение заработает быстрее, поскольку не будет повторных вызовов GetDlgItem. Эта функция вообще-то выполняется довольно медленно, если в диалоговом окне много элементов управления, а искомый элемент находится где-то в конце Z-цепочки.

API-макросы

Они упрощают выполнение некоторых распространенных операций — например, создание нового шрифта, выбор его в контекст устройства и сохранение описателя исходного шрифта. Необходимый для этого код выглядит как-то вроде:

HFONT hFontOrig = (HFONT) SelectObject(hDC, (HGDIOBJ) hFontNew);

Этот оператор требует два преобразования типов, чтобы избежать предупреждений при компиляции. Как раз для этого и предназначен один из макросов, определенных в файле WindowsX.h:

#define SelectFont(hdc, hfont) \

((HFONT) SelectObject( (hdc), (HGDIOBJ) (HFONT) ((hfont)))

При его использовании строка кода в программе станет такой:

HFONT hFontOrig = SelectFont(hDC, hFontNew);

Этот код читать гораздо легче, и он меньше подвержен ошибкам.

В файле WindowsX.h есть еще несколько API-макросов, помогающих в реализации распространенных операций. Ознакомьтесь с ними самостоятельно и чаще их используйте.

Соседние файлы в предмете Программирование на C++