Главная страница
Навигация по странице:

  • 1.4. Обработка сообщений

  • 1.5. Оконная функция

  • Win32 api программирование


    Скачать 0.78 Mb.
    НазваниеWin32 api программирование
    Дата02.02.2018
    Размер0.78 Mb.
    Формат файлаpdf
    Имя файлаitmo426.pdf
    ТипУчебное пособие
    #35685
    страница2 из 8
    1   2   3   4   5   6   7   8
    1.3. Создание и показ окна
    Для создания любых окон, в том числе и окон элементов управле- ния, используется функция Windows CreateWindowEx(), прототип ко- торой приведен ниже:
    HWND CreateWindowEx(
    DWORD dwExStyle, //расширенный стиль окна,
    //применяется совместно
    //со стилем dwStyle
    LPCTSTR lpClassName,
    //адрес строки с именем
    //зарегистрированного класса,
    // либо имя одного из
    //предопределенных классов
    LPCTSTR lpWindowName //адрес строки с
    //заголовком главного окна
    DWORD dwStyle, //стиль окна int x //горизонтальная позиция верхнего
    //левого угла окна int y, //вертикальная позиция верхнего
    //левого угла окна int nWidth, //ширина окна в пикселях

    14
    int nHeight,
    //высота окна в пикселях
    HWND hWndParent,//дескриптор родительского окна
    HMENU hMenu,
    //дескриптор меню окна или
    //идентификатор элемента управления
    HINSTANCE hInstance, //дескриптор
    //экземпляра приложения
    LPVOID lpParam
    //указатель на
    //дополнительные данные
    );
    Первый параметр − dwExStyle − задает расширенный стиль ок- на, который можно задать одним или несколькими флагами, используя побитовую операцию ИЛИ. Флаги расширенных стилей:
    • WS_EX_MDICHILD – создать дочернее окно многодокументного интерфейса;
    • WS_EX_TOOLWINDOW – создать окно с инструментами, предназна- ченное для реализации плавающих панелей инструментов;
    • WS_EX_ACCEPTFILES – создать окно, которое принимает пере- таскиваемые файлы.
    Расширенный стиль dwExStyle применяется совместно со стилем, который определяется четвертым параметром dwStyle. Полный список расширенных стилей см. в MSDN.
    Второй параметр − lpClassName – указатель на строку, содержа- щую имя зарегистрированного функцией RegisterClassEx() класса, либо имя одного из предопределенных классов.
    Вызывая функцию CreateWindowEx() многократно, можно соз- дать много окон данного класса, различающихся, например, размерами и местоположением на экране. Окна предопределенных классов необходи- мо создавать как дочерние. Предопределенные классы окон, реализую- щие различные элементы управления:
    • BUTTON – кнопки, группы, флажки, переключатели или пикто- граммы (префикс в обозначении стиля – BS_);
    • COMBOBOX – комбинированный список с полем редактирования в верхней части или выпадающий список выбора (элементы
    LISTBOX и EDIT) (префикс в обозначении стиля – CBS_);
    • EDIT– поле редактирования , предназначенное для ввода текста с клавиатуры (префикс в обозначении стиля –ES_);
    • LISTBOX – элемент управления списком строк, из которого можно выбрать любую строку или несколько строк (стили
    LBS_OWNERDRAWFIXED и LBS_OWNERDRAW позволяют управ- лять видом строки) (префикс в обозначении стиля –LBS_);
    • MDICLIENT – клиентское окно многодокументного интерфейса;
    • RICHEDIT – элемент управления в дополнение к EDIT − позво- ляет редактировать текст с разными шрифтами и стилями (пре- фикс в обозначении стиля – ES_);
    • RICHEDIT_CLASS – усовершенствованная версия RICHEDIT
    (префикс в обозначении стиля – ES_);

    15
    • SCROLBAR – элемент управления полосой прокрутки (слайдер)
    (префикс в обозначении стиля – SBS_);
    • STATIC – элемент управления статическим текстом − использу- ется для размещения в окне текста, рамок или как контейнер для других элементов управления (префикс в обозначении стиля –
    SS_).
    Третий параметр
    − lpWindowName функции
    CreateWindowEx() − определяет адрес строки с именем окна. Место отображения имени зависит от вида окна, например:
    • главное окно приложения – имя выводится в верхнюю часть ок- на как заголовок окна;
    • дочернее окно класса BUTTON – имя размещается по центру кнопки.
    Четвертый параметр dwStyle определяет стиль окна. С помощью стиля задаются такие характеристики окна, как вид окружающей его рам- ки, наличие системного меню, присутствие линеек вертикальной и гори- зонтальной прокрутки и т.п. Побитовая операция ИЛИ (знак |) позволяет набрать требуемый комплект свойств. Обычно главное окно описывается константой WS_OVERLAPPEDWINDOW(0x00CF0000). Это перекры- вающееся окно с заголовком, системным меню, кнопками минимизации и максимизации, кнопкой закрытия окна и «толстой» рамкой, позволяющей изменять размеры окна.
    Пятый параметр x и шестой параметр y – экранные координаты верхнего левого угла главного окна, т.е. координаты относительно начала экрана в пикселях. Для дочерних окон и элементов управления эти коор- динаты отсчитываются относительно левого верхнего угла родительского окна и измеряются в пикселях. Если позиция x не важна, то можно уста- новить значение x равным CW_USEDEFAULT – значение по умолчанию.
    В этом случае параметр y игнорируется.
    Седьмой и восьмой параметры nWidth и nHeight – ширина и высота окна в пикселях. Если параметрам nWidth и nHeight присвоено значение CW_USEDEFAULT, то для них будут использоваться значения по умолчанию.
    Девятый параметр hWndParent – это дескриптор родительского окна; для главного окна, у которого нет родителя, используется константа
    HWND_DESKTOP или NULL.
    Десятый параметр hMenu функции CreateWindowEx() содержит дескриптор меню окна или идентификатор элемента управления
    Интерпретация значения параметра hMenu зависит от вида окна:
    • приложение использует меню, определенное полем lpszMenu структурной переменной типа WNDCLASSEX (класс окна). В этом случае параметру hMenu необходимо присвоить значение
    NULL;

    16
    • приложение создает элемент управления как дочернее окно. В этом случае параметру hMenu присваивается целочисленное значение, используемое далее как идентификатор созданного элемента (этот идентификатор будет содержаться в сообщении
    WM_COMMAND, поступающего от созданного элемента управле- ния).
    Одиннадцатому параметру hInstance должно быть присвоено значение дескриптора экземпляра приложения (значение аргумента hInstance главной функции WinMain).
    Последний параметр lpParam функции CreateWindowEx() – указатель на дополнительные данные, передаваемые окну в момент его создания при обработке сообщения WM_CREATE, или значение NULL.
    В сообщениях WM_CREATE и WM_NCCREATE параметр lрParam содержит указатель на структуру CREATESTRUCT, в которую будут зане- сены параметры функции CreateWindowEx().
    Символическое обозначение NULL ((void*)0) используется в тех случаях, когда для некоторой функции надо указать нулевое значение параметра, являющегося указателем.
    Функция CreateWindowEx() при успешном завершении возвра- щает дескриптор созданного окна, т.е. локальную переменную hWnd. Де- скриптор окна hWnd передается как параметр в функцию
    ShowWindow(), которая организует вывод созданного окна на экран.
    Функция ShowWindow() имеет следующий прототип:
    BOOL ShowWindow(
    HWND
    hWnd, // дескриптор окна int nCmdShow // вид показанного окна
    );
    Параметр nCmdShow определяет, в каком виде будет показано ок- но. При начальном отображении главного окна рекомендуется присваи- вать второму параметру значение, которое было получено через параметр nCmdShow главной функции WinMain.
    Вызов ShowWindow() влечет за собой генерацию сообщений
    WM_SIZE и WM_MOVE. При обработке сообщения WM_SIZE сис- тема всегда генерирует сообщение WM_PAINT.
    1.4. Обработка сообщений
    В ООП управляющие данные принято называть сообщениями. Эта терминология используется и в Windows. Сообщения являются реакцией системы на происходящие в ней события и единственным средством свя- зи окна (и всего приложения) с операционной системой.
    Коды сообщений Windows имеют единый формат. Это
    32-битные целые без знака (для системных сообщений они принимают значения от 1 до 0x3FF), которым для лучшей читаемос- ти присвоены параметрические имена, т.е. каждому коду соответствует символическая константа. Например, аппаратные сообщения:

    17
    • WM_MOUSMOUVE – 200h (реакция на перемещение мыши);
    • WM_LBUTTONDOWN – 201h (реакция на нажатие левой клавиши мыши);
    • WM_TIMER – 113h (реакция на срабатывания таймера);
    • WM_MOVSEACTIVATE–0021h (активизировать мышь).
    Сообщения могут возникать и в результате программных действий системы. Например, при создании и выводе главного окна система посы- лает в приложение следующие сообщения:
    • WM_GETMINMAXINFO (для уточнения размеров окна);
    • WM_ERASEBKGND (при заполнении окна цветом фона);
    • WM_SIZE (оценка размера рабочей области);
    • WM_PAINT (перерисовка окна).
    Сообщения могут создаваться в прикладной программе и посы- латься в Windows для того, чтобы система выполнила некоторые дейст- вия, например, заполнила информацией окно со списком или сообщила о состоянии элемента управления. Номера таких сообщений превышают значение 0x3FF.
    Сообщения могут создаваться и непосредственно программистом.
    Для каждого потока в Win32 создается своя очередь сообщений, которая не имеет фиксированной длины. Сообщения из системной очере- ди не передаются в приложение в целом, а распределяются по его пото- кам.
    Главный цикл обработки сообщений в простейшем виде состоит из следующих предложений языка:
    2while(GetMessage(&Msg, NULL, 0, 0))
    {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
    }
    Назначение цикла обработки сообщений – получить сообщения, поступающие в приложение, и вызвать в ответ на каждое сообщение оконную функцию. Задача оконной функции – выполнить требуемую об- работку поступившего сообщения.
    В цикле вызывается функция Windows GetMessage(), которая анализирует очередь сообщений своего потока и, если в очереди обнару- живается сообщение, изымает его и переносит в структурную перемен- ную типа MSG, предназначенную для приема сообщений.
    Структура типа MSG описана в файле winuser.h следующим обра- зом: typedef struct tagMSG{
    HWND hWnd;
    //дескриптор (хэндл) окна,
    //которому передано сообщение
    UINT message;
    //код данного сообщения
    //(идентификатор)
    WPARAM wParam;
    //дополнительная информация
    LPARAM lParam;
    //дополнительная информация
    DWORD time;
    //время отправления сообщения
    POINT pt;
    //позиция курсора мыши на момент

    18
    //отправления сообщения
    }Msg; //новое имя для типа tagMSG.
    Интерпретация параметров wParam и lParam зависит от кода со- общения (message).
    Тип данных POINT используется для представления точки парой ее координат и описан следующим образом: typedef struct tagPOINT{
    LONG x;
    LONG y;
    } POINT;
    Из структуры MSG следует, что содержимое сообщения представля- ет собой пакет из шести данных. Прототип функции GetMessage() имеет следующий вид:
    BOOL GetMessage(
    LPMSG lpMsg, //указатель на структуру переменную типа MSG
    HWND hWnd, //дескриптор окна, принимающего cообщение
    UINT uMsgFilterMin,
    //максимальный номер сообщения
    INT uMsgFilterMax
    //минимальный номер сообщения
    );
    Параметр lpMsg задает адрес структурной переменной типа MSG, в которую помещается выбранное из очереди сообщение.
    Параметр hWnd содержит дескриптор окна, принимающего сообще- ние. Если этот параметр равен NULL, функция GetMessage() работает со всеми сообщениями данного приложения.
    Параметры uMsgFilterMin и uMsgFilterMax указывают соот- ветственно минимальный и максимальный номера принимаемого сооб- щения. Если в качестве этих параметров указать константы
    WM_KEYFIRST
    и WM_KEYLAST, функция будет забирать из очереди только сообщения, генерируемые клавиатурой.
    Константы
    WM_MOUSFIRST
    и WM_MOUSLAST позволяют работать только с сообще- ниями от мыши. Чтобы исключить фильтрацию сообщений, необходимо, чтобы оба параметра были равны нулю.
    Функция GetMessage() завершится с возвратом значения TRUE лишь после того, как очередное сообщение попадет в структурную пере- менную Msg.
    Далее вызываются функции Windows TranslateMessage() и DispatchMessage(), которые имеют следующие прототипы:
    BOOL TranslateMessage(CONST MSG* lpMsg);
    LRESULT DispatchMessage(CONST MSG* lpMsg);
    Функция TranslateMessage() преобразует аппаратные сооб- щения от клавиатуры WM_KEYDOWN (клавиша нажата) и WM_KEYUP (кла- виша отпущена) в символьное сообщение WM_CHAR. Параметр wParam этого сообщения содержит код символа. Сообщение WM_CHAR помещает- ся в очередь, и на следующей итерации цикла функция GetMessage() извлекает его для последующей обработки. Вызов функции Translate-
    Message() необходим только в тех приложениях, которые обрабаты- вают ввод данных с клавиатуры.

    19
    Далее функция DispatchMessage() вызывает оконную функ- цию того окна, которому предназначено данное сообщение, и передает ей содержимое сообщения из структурной переменной типа Msg (первые че- тыре поля). Если программе необходимы элементы time и pt, то их можно извлечь непосредственно из структурной переменной. После того как оконная функция обработает сообщение, возврат из нее приводит к возврату из функции DispatchMessage() на продолжение цикла while
    Если функция GetMessage() обнаруживает в очереди сообщение
    WM_QUIT
    (код 0x12), то она завершается с возвратом значения FALSE, что приводит к завершению цикла и переходу на предложение re- turn Msg.wParam;
    т.е. к завершению главной функции и всего при- ложения.
    Если функция GetMessage() не обнаруживает сообщений в оче- реди потока, система останавливает выполнение данного потока и пере- водит его в «спящее» состояние. Такое состояние потока не потребляет процессорного времени и не тормозит работу системы. Поток возобновит свою работу, как только в очереди появится сообщение.
    Вместо функции GetMessage() часто используют функцию
    PeekMessage(), которая имеет следующий прототип:
    BOOL PeekMessage(
    LPMSG
    lpMsg
    , //адрес структурной переменной
    //с сообщением
    HWND
    hWnd
    ,
    //дескриптор окна
    UINT
    wMsgFilterMin
    , //Min номер выбираемого
    //сообщения
    UINT
    wMsgFilterMax
    , //Max номер выбираемого
    //сообщения
    UINT
    wRemoveMsg
    //флаг удаления сообщения
    );
    Первые четыре параметра функции PeekMessage() совпадают с параметрами функции GetMessage().
    Пятый параметр wRemoveMsg определяет, как должно быть вы- брано сообщение из очереди, а именно:
    • PM_NOREMOV – сообщение выбирается и не удаляется из очереди;
    • PM_REMOV – сообщение выбирается и удаляется из очереди.
    Функция PeekMessage() не ждет, когда сообщение поступит в очередь сообщений, а сразу возвращает управление. Если сообщения в очереди нет, то функция возвращает нуль, а если сообщение находится в очереди, оно помещается в структурную переменную типа MSG и удаля- ется из очереди сообщений (флаг PM_REMOV) или не удаляется (флаг
    PM_NOREMOV).
    Функция PeekMessage() часто используется для оптимизации работы программы. Если сообщение не находится в очереди сообщений, то в свободное время можно выполнять какую-либо другую работу. Этот прием часто встречается в программах, выполняющих графическую ани- мацию, и более эффективен, чем использование сообщений от таймера.

    20
    Главный цикл обработки сообщений с применение функции Peek-
    Message() может выглядеть следующим образом: while(1)
    { if(PeekMessage(&Msg,NULL,0,0, PM_REMOV))
    { if(Msg.message==WM_QUIT) break;
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
    }
    }
    1.5. Оконная функция
    Оконная функция – это функция обратного вызова, предназначен- ная для обработки сообщений, адресованных окну того оконного класса, в котором содержится ссылка на данную процедуру.
    Функции обратного вызова – это функции, которые вызывает сама операционная система. Компилятор определяет их по спецификатору
    CALLBACK. Оконная функция получает четыре параметра, а ее заголовок имеет стандартный синтаксис:
    LRESULT CALLBACK Имя_функции(
    HWND hWnd,
    //дескриптор (хэндл) окна, которому
    //предназначено данное сообщение
    UINT uMsg
    //код пришедшего сообщения
    WPARAM wParam
    //дополнительная информация
    //о сообщении
    LPARAM lParam
    //дополнительная информация
    //о сообщении
    );
    Имя функции может быть произвольным, но для главного окна приложения обычно используется имя WndProc. В теле оконной функ- ции после объявления необходимых локальных переменных используется оператор switch…case. Например:
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg,
    WPARAM wParam, LPARAM lParam)
    { switch(Msg)
    { case WM_CREATE:
    //… return TRUE; case WM_KEYDOWN:
    /*
    Обрабатываем сообщение WM_KEYDOWN
    (нажатие клавиши)
    */ switch(wParam)
    {
    /* Клавиша Esc */ case VK_ESCAPE:

    21
    SendMessage(hWnd,WM_CLOSE,0,0); break;
    } break; case WM_DESTROY:
    /*
    Функция PostQuitMessage выполняет только одно действие, ставит в очередь сообщение WM_QUIT.
    Параметр у этой функции - код возврата, кото- рый помещается в Msg.wParam и возвращается главной функцией
    */
    PostQuitMessage(0); break; default:
    /*Обработка прочих сообщений по умолчанию*/ return DefWindowProc(hWnd,msg,wParam,lParam);
    } return 0L;
    }
    Реально в программе требуется обрабатывать конкретные сообще- ния, а для обработки прочих сообщений предназначена функция Def-
    WindowProc()
    (Default Windows Procedure).
    Единственное сообщение, не входящее в «юрисдикцию» DefWin- dowProc,
    –сообщение об уничтожении окна WM_DESTROY, поэтому его обработка должна всегда присутствовать в оконной процедуре.
    Обычно приложения завершают свою работу по команде пользова- теля, например ALT+F4. В этом случае Windows убирает с экрана окно приложения и посылает сообщение WM_DESTROY не в очередь приложе- ния, а воконную функцию с непосредственным ее вызовом.
    Обработка этого сообщения должна состоять в освобождении ресурсов
    Windows. Например, при обработке сообщения WM_CREATE приложение могло создать и использовать в программе кисти, перья, шрифты, устано- вить таймеры, динамически выделить память т.п. При завершении при- ложения эти ресурсы необходимо освободить. Далее необходимо вызвать функцию PostQuitMessage(0);
    Все сообщения, обработанные в оконной процедуре, должны возвращать стандартное значение – нуль по вы- ходу из процедуры. Однако бывают случаи, когда тре- буется возвратить единицу или -1. Например, после обработки сообщения WM_NCCREATE, которое приходит перед сообщением
    WM_CREANT, следует вернуть единицу.
    Оконная функция может вызываться двумя способами: функцией DispatchMessage() и непосредственно программами
    Windows.
    1   2   3   4   5   6   7   8


    написать администратору сайта