Написание процедуры окна

Функция DispatchMessage вызывает процедуру окна окна, которое является целью сообщения. Процедура окна имеет следующую подпись.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

Существует четыре параметра:

  • Hwnd — это дескриптор окна.
  • UMsg — это код сообщения, например сообщение WM_SIZE указывает, что окно было изменено.
  • wParam и lParam содержат дополнительные данные, относящиеся к сообщению. Точное значение зависит от кода сообщения.

LRESULT — это целочисленное значение, которое программа возвращает в Windows. Он содержит ответ вашей программы на определенное сообщение. Значение этого значения зависит от кода сообщения. CALLBACK — это соглашение о вызовах для функции.

Обычная процедура окна — это просто большая инструкция коммутатора, которая переключается на код сообщения. Добавьте варианты для каждого сообщения, которое требуется обрабатывать.

switch (uMsg)
{
    case WM_SIZE: // Handle window resizing

    // etc
}

Дополнительные данные для сообщения содержатся в параметрах lParam и wParam. Оба параметра представляют собой целочисленные значения размера ширины указателя (32 бита или 64 бита). Значение каждого зависит от кода сообщения (uMsg). Для каждого сообщения необходимо найти код сообщения в MSDN и привести параметры к правильному типу данных. Обычно данные являются числовым значением или указателем на структуру. Некоторые сообщения не имеют данных.

Например, в документации по сообщению WM_SIZE указано следующее:

  • wParam — это флаг, указывающий, был ли окно свернуто, развернуто или изменено.
  • lParam содержит новую ширину и высоту окна в виде 16-разрядных значений, упакованных в один 32-или 64-разрядный номер. Чтобы получить эти значения, потребуется выполнить некоторые битовые сдвиги. К счастью, файл заголовка WinDef.h включает вспомогательные макросы, которые делают это.

Типичная процедура окна обрабатывает десятки сообщений, поэтому она может расти довольно долго. Один из способов сделать код более модульным — поместить логику обработки каждого сообщения в отдельную функцию. В процедуре окна приведите параметры wParam и lParam к правильному типу данных и передайте эти значения в функцию. Например, чтобы обработать сообщение WM_SIZE , процедура окна будет выглядеть следующим образом:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SIZE:
        {
            int width = LOWORD(lParam);  // Macro to get the low-order word.
            int height = HIWORD(lParam); // Macro to get the high-order word.

            // Respond to the message:
            OnSize(hwnd, (UINT)wParam, width, height);
        }
        break;
    }
}

void OnSize(HWND hwnd, UINT flag, int width, int height)
{
    // Handle resizing
}

Макросы LOWORD и HIWORD получают 16-разрядные значения ширины и высоты из lParam. (Эти сведения можно найти в документации MSDN по каждому коду сообщения.) Процедура окна извлекает ширину и высоту, а затем передает эти значения OnSize функции.

Обработка сообщений по умолчанию

Если вы не обрабатываете определенное сообщение в процедуре окна, передайте параметры сообщения непосредственно в функцию DefWindowProc. Эта функция выполняет действие по умолчанию для сообщения, которое зависит от типа сообщения.

return DefWindowProc(hwnd, uMsg, wParam, lParam);

Предотвращение узких мест в процедуре окна

Хотя процедура окна выполняется, она блокирует любые другие сообщения для окон, созданных в том же потоке. Поэтому избегайте длительной обработки в процедуре окна. Например, предположим, что программа открывает TCP-подключение и ожидает неограниченное время, пока сервер будет отвечать. Если это делается в процедуре окна, пользовательский интерфейс не будет отвечать до завершения запроса. В течение этого времени окно не может обрабатывать ввод мыши или клавиатуры, перезапугать себя или даже закрыть.

Вместо этого следует переместить работу в другой поток, используя одну из многозадаочных средств, встроенных в Windows:

  • Создайте новый поток.
  • Использование пула потоков.
  • Используйте асинхронные вызовы ввода-вывода.
  • Используйте асинхронные вызовы процедур.

Следующий

Рисование окна