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

  • 1.7. Создание приложения с главным окном

  • 1.7.1. Окна сообщений

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


    Скачать 0.78 Mb.
    НазваниеWin32 api программирование
    Дата02.02.2018
    Размер0.78 Mb.
    Формат файлаpdf
    Имя файлаitmo426.pdf
    ТипУчебное пособие
    #35685
    страница3 из 8
    1   2   3   4   5   6   7   8
    1.6. Сообщения Windows
    Процедура формирования аппаратного сообщения включает следующие этапы:
    1) аппаратное прерывание;

    22 2) формирование драйвером пакета данных;
    3) установка сообщения в системную очередь;
    4) пересылка сообщения в очередь потока;
    5) вызов оконной функции.
    Сообщение WM_MOUSMOVE генерируется системой при перемеще- нии мыши по клиентской области окна.
    Структурная переменная Msg (тип MSG) при формировании сооб- щения WM_MOUSEMOVE заполнится следующей информацией:
    1. Msg.hWnd – дескриптор окна под курсором мыши;
    2. Msg.message – код сообщения (0x200);
    3. Msg.wParam – комбинация битовых флагов, индицирующих со- стояния клавиш мыши (нажаты/не нажаты), а также клавиш Ctrl и
    Shift
    ;
    4. Msg.lParam – позиция курсора мыши относительно клиенской области окна;
    5. Msg.time – время отправления сообщения;
    6. Msg.pt – позиция курсора мыши относительно границ экрана.
    Вообще манипуляции с мышью порождают следующие сообщения:
    • WM_LBUTTONDOWN (201h) – нажатие левой кнопки мыши;
    • WM_LBUTTONUP (202h) – отпускание левой кнопки мыши;
    • WM_RBUTTONDOWN (204h) – нажатие правой кнопки мыши;
    • WM_RBUTTONUP – отпускание правой кнопки мыши;
    • WM_LBUTTONDBLCLK (203h) – двойное нажатие левой кнопки мы- ши.
    Для всех вышеперечисленных сообщений структурная переменная типа MSG заполняется одинаковой информацией, т.е. пакеты данных этих сообщений не различаются.
    Параметр lParam содержит координаты курсора мыши, а именно, младшее слово lParam содержит координату
    x
    , а старшее слово lParam
    – координату
    y
    . Отсчет координат ведется относительно левого верхнего угла клиентской области окна. Для выделения значений, находящихся в старшем и младшем словах параметра lParam, предназначены макроко- манды LOWORD и HIWORD.
    Значение параметра wParam показывает состояние кнопок мыши, а также клавиш Shift и Ctrl. Если кнопка мыши или клавиша нажата, то значения соответствующих им полей устанавливаются равными едини- це
    , иначе – нулю. Параметр wParam можно проверить при помощи со- ответствующих битовых масок, используя побитовую операцию ИЛИ.
    Битовые маски:
    MK_LBUTTON
    – левая клавиша нажата;
    MK_MBUTTON
    – средняя клавиша нажата;
    MK_RBUTTON
    – правая клавиша нажата ;
    MK_SHIFT
    – клавиша Shift нажата;
    MK_CONTROL
    – клавиша Ctrl нажата.

    23
    Например, как можно определить, была ли нажата клавиша Shift во время нажатия левой кнопки мыши (сообщение WM_LBUTTONDOWM):
    Case WM_LBUTTONDOWM:
    //… if(wParam & MK_SHIFT)
    {
    /*нажата клавиша Shift*/
    }
    //…
    Двойной щелчок левой клавишей мыши порождает четыре сообще- ния:
    WM_LBUTTONDOWN;
    WM_LBUTTONUP;
    WM_LBUTTONDBLCLK;
    WM_LBUTTONUP.
    Можно обрабатывать все четыре, а можно только
    WM_LBUTTONDBLCLK
    . Необходимо отметить, что окно будет получать сообщение о двойном щелчке (DBLCLK) только в том случае, если стиль класса окна содержит флаг CS_DBLCLK.
    Cообщения от клавиатуры:
    • WM_KEYDOWN – нажатие несистемной клавиши (любая клавиша без сопровождения с Alt);
    • WM_KEYUP – отпускание несистемной клавиши;
    • WM_SYSKEYDOWN – нажатие системной клавиши (любая клавиша с сопровождением клавиши Alt);
    • WM_SYSKEYUP – отпускание системной клавиши.
    Для всех сообщений от клавиатуры параметр lParam содержит семь полей:
    1) поле (от 0 до15 бита) – содержит счетчик повторений дан- ного сообщения: равен либо единице, либо числу нажатий в режиме авто- повтора, а для WM_KEYUP всегда равен единице;
    2) поле (от 16 до 23 бита) – содержит скан-код;
    3) поле (24–й бит) – флаг расширенной клавиатуры, бит устанав- ливается в 1 для функциональных клавиш и клавиш Alt и Ctrl на пра- вой стороне клавиатуры;
    4) поле (от 25 до 28 бита) – не используется;
    5) поле (29–й бит) – установленный бит означает, что клавиша
    Alt нажата (бит всегда сброшен для сообщений WM_KEYDOWN и
    WM_KEYUP
    , т.е. 0);
    6) поле (30–й бит) – установленный бит означает, что клавиша была нажата до отправки сообщения, а 0 – отпущена;
    7) поле (31–й бит) – флаг нового состояния клавиатуры, т.е. 0 – клавиша нажата, 1 – отпущена.
    Параметр wParam содержит виртуальный код клавиши, который идентифицирует нажатую или отпущенную клавишу. Например, вирту- альные десятичные коды для следующих клавиш (полный список см. в
    MSDN.):

    24
    • Shift – идентификатор VK_SHIFT (код – 16);
    • Ctrl – идентификатор VK_CONTROL (код – 17);
    • Alt – идентификатор VK_MENU (код – 18);
    • Esc – идентификатор VK_ESCAPE (код – 27);
    • F1…F12 – идентификаторы VK_F1…VK_F12, (коды – 112…123).
    Сообщение WM_CHAR обрабатывается при вводе информации от символьных клавиш. Функция TranslateMessage() преобразует аппа- ратное сообщение от клавиатуры в символьное сообщение WM_CHAR, ко- торое содержит код символа (wParam). Сообщение WM_CHAR помещается в очередь, а на следующей итерации цикла функция GetMessage() из- влекает его для последующей обработки.
    Параметр lParam сообщения WM_CHAR имеет то же значение, что и параметр lParam породившего его аппаратного сообщения.
    Параметр wParam сообщения WM_CHAR содержит код символа.
    Например, если нажимается и отпускается клавиша A в нижнем регистре, то генерируются три сообщения в следующем порядке:
    1. WM_KEYDOWN – виртуальная клавиша A;
    2. WM_CHAR – ANSI код символа ‘a’;
    3. WM_KEYUP – виртуальная клавиша A.
    Сообщение WM_COMMAND формируется во время нажатия левой клавиши мыши над строкой меню, т.е. аппаратное прерывание поглоща- ется системой и вместо сообщения WM_LBUTTONDOWN формируется со- общение WM_COMMAND. При выборе пунктов системного меню вместо сообщения
    WM_COMMAND
    системой генерируется сообщение
    WM_SYSCOMMAND
    Непосредственно перед активизацией главного меню или всплы- вающего меню системой посылаются сообщения WM_INITMENU или
    WM_INITMENUPOPUP
    соответственно. Они позволяют приложению изме- нить меню перед тем, как оно будет отображено на экране. Для обоих со- общений параметр wParam содержит дескриптор активизируемого меню, а параметр lParam – следующую информацию:
    • в младшем слове lParam – относительная позиция пункта меню
    (отсчет от нуля), который открывает подменю;
    • в старшем слове lParam – TRUE, если раскрывающее меню – ме- ню окна.
    Источниками сообщения WM_COMMAND могут быть:
    1) пункты меню, определяющие команды, при этом параметры wParam и lParam принимают следующие значения:
    • младшее слово wParam содержит идентификатор пункта меню
    (wid);
    • старшее слово wParam содержит нуль (wCmd);
    • параметр lParam содержит нуль.
    2) быстрые клавиши (keyboard accelerator), при этом парамет- ры wParam и lParam принимают следующие значения:

    25
    • младшее слово wParam содержит идентификатор быстрой клавиши
    (wid);
    • старшее слово wParam содержит единицу (wCmd);
    • параметр lParam содержит нуль.
    3) элементы управления (кнопки, списки, текстовые поля и т.д.), при этом параметры wParam и lParam принимают следующие значения:
    • младшее слово wParam содержит идентификатор элемента управ- ления (wid);
    • старшее слово wParam содержит код извещения, т.е. действия, вы- полненные над элементом управления (wCmd);
    • параметр lParam содержит дескриптор элемента управления
    (hWnd).
    Приложение должно разбирать сообщение WM_COMMAND на со- ставные части следующим образом: case WM_COMMAND: wid = LOWORD(wParam); hWnd = (HWND)(UINT)lParam; wCmd = HIWORD(wParam);
    //…
    Сообщение WM_CLOSE генерируется, когда пользователь щелкает мышью по кнопке закрытия окна или нажимает комбинацию клавиш
    Alt+F4
    , при этом окно еще не разрушено. Если обработка этого сообще- ния отсутствует, то функция DefWindowPro() вызывает по умолчанию функцию DestroyWindow(), которая посылает окну (потом дочерним окнам, если они есть у этого окна) сообщение WM_DESTROY. Функция
    DestroyWindow()
    завершит свою работу только после уничтожения всех дочерних окон. Но если необходимо предусмотреть вывод преду- преждающих сообщений типа «Вы уверены?», то это можно сделать, ко- гда окно еще не разрушено, т.е. при обработке сообщения WM_CLOSE, например: case WM_CLOSE: if(MessageBox(hWnd,” ВЫ уверены?”, ” ”,
    MB_YESNO | ICONQUESTION) == IDYES)
    DestroyWindow(hWnd); break;
    Сообщение WM_SIZE посылается окну после изменения его разме- ра. Параметр wParam этого сообщения содержит следующие значения
    (полный список см. в MSDN):

    SIZE_MAXIMIZED
    – окно было развернуто;

    SIZE_MINIMIZED
    – окно было свернуто;

    SIZE_RESTORED
    – окно было изменено, но не SIZE_MAXIMIZED и не SIZE_MINIMIZED.
    Параметр lParam в младшем слове содержит новую ширину кли- ентской области окна, в старшем слове – новую высоту.

    26
    Сообщение WM_MOVE посылается окну после его перемещения. Па- раметр lParam этого сообщения содержит следующие значения:
    • младшее слово lParam содержит x-координату левого верхнего угла клиентской области окна;
    • старшее слово lParam содержит y- координату левого верхнего угла клиентской области окна.
    Сообщение WM_CREATE генерируется системой в процессе созда- ния окна. Перехватив это сообщение, можно выполнить некоторые ини- циализирующие действия, например: установить системный таймер, за- грузить требуемые ресурсы (шрифты, растровые изображения), открыть файлы с данными и т.д.
    Параметр lParam сообщения WM_CREATE содержит указатель на структуру типа CREATESTRUCT, параметры которой аналогичны пара- метрам функции CreateWindowEx().
    Сообщение WM_CREATE не поступает в очередь сообщений, т.е.
    Windows непосредственно вызывает оконную функцию WndProc и пере- дает ей необходимые параметры. Следует иметь в виду, что во время об- работки сообщения, например WM_MOUSMOVE, все его содержимое нахо- дится в структурной переменной типа MSG. При обработке же сообщения
    WM_CREATE
    мы имеем дело только с параметрами, переданными Win- dows в оконную процедуру.
    Аналогично, помимо очереди сообщений, обрабатываются другие сообщения, например:
    • WM_INITDIALOG (инициализация диалога);
    • WM_SYSCOMMAND (выбор пунктов системного меню);
    • WM_DESTROY (уничтожение окна).
    Сообщение WM_PAINT уведомляет программу, что часть или вся клиентская область окна недействительна (invalid) и ее следует пере- рисовать. Клиентская область окна становится недействительной, и сис- тема генерирует сообщение WM_PAINT в следующих случаях:
    • при создании окна;
    • при минимизации окна и последующем его разворачивании;
    • при перемещении порожденного окна по пространству главного ок- на;
    • при изменении размеров и местоположения окна и т.д.
    Общее правило рисования заключается в том, что вывод в окно приложения любых графических объектов должен выполняться исклю- чительно в блоке обработки сообщения WM_PAINT. Только в этом случае графическое содержимое клиентской области окна не будет теряться, на- пример, при перечисленных выше случаях. При этом восстановление не- рабочей области окна берет на себя система.
    Обработка сообщения WM_PAINT связана с так называемым кон- текстом устройства. Контекст устройства (device context) описывает физическое устройство вывода информации, например дисплей или

    27
    принтер. Это некоторая внутренняя структура данных, в которой хранят- ся, например, текущее значение режимов рисования, дескрипторы инст- рументов рисования: кисти, перья, шрифты, и др. Все графические функции используют контекст устройства для опредения режимов рисования и характеристик применяемых ими инструментов.
    Обработку сообщения WM_PAINT рекомендуется всегда начинать с вызова функции BeginPaint(), которая имеет следующий прототип:
    HDC BeginPaint(HWND hWnd,
    LPPAINSTRUCT lpPaintStruct);
    Первый параметр hWnd представляет собой дескриптор того уст- ройства вывода, в котором предполагается рисовать, т.е. для которого требуется контекст устройства. Второй параметр lpPaintStruct – ад- рес структурной переменной типа PAINTSTRUCT, которая заполняется
    Windows всякий раз, когда приложение перехватывает обработку сооб- щения WM_PAINT.
    Структура типа PAINTSTRUCT описана в файле winuser.h и содер- жит следующие элементы: typedef struct tagPAINTSTRUCT
    {
    HDC hDc;
    //дескриптор контекста устройства
    BOOL fErase; //флаг перерисовки фона клиентской
    //области окна
    RECT rcPaint;
    //область вырезки, т.е.границы
    //недействительного прямоугольника
    BOOL fRestor;
    //зарезервировано
    BOOL fIncUpdate; //зарезервировано
    BYTE rgbReserved[32]; //зарезервировано
    } PAINSTRUCT;
    Флаг перерисовки окна fErase обычно равен TRUE. Это означает, что обновляемый регион помечен для стирания и система Windos обнов- ляет фон клиентской области. По умолчанию для этого используется кисть, заданная полем wc.hbrBackground.
    Область вырезки rcPaint представляет собой структуру типа
    RECT, которая содержит координаты обновляемого прямоугольника в пикселях относительно левого верхнего угла клиентской области.
    Координаты прямоугольника определяются системой или задаются при вызове функций InvalidateRect() или InvalidateRgn().
    Один из параметров этих функций разрешает или запрещает стирание фона. Если задано стирание фона, то функция BeginPaint() посылает оконной процедуре сообщение WM_ERASEBKGND. Приложение может обрабатывать это сообщение, чтобы отобразить однородный или растро- вый фон. Обычно это сообщение обрабатывается по умолчанию функци- ей
    DefWindowProc().
    До своего завершения функция
    BeginPaint() посылает оконной процедуре сообщение WM_NCPAINT, которое определяет обновление неклиентской области окна.
    Структура, описывающая прямоугольник (rectangle), определена в заголовочном файле следующим образом:

    28
    typedef struct tagRECT {
    LONG left; //x–координата верхнего левого угла
    //прямоугольнка
    LONG top; //y–координата верхнего левого угла
    //прямоугольника
    LONG right; //x–координата правого нижнего угла
    //прямоугольника
    LONG bottom //y–координата правого нижнего
    //угла прямоугольника
    }RECT;
    Переменные типа RECT часто используются в приложениях, так как области экрана в Windows всегда имеют прямоугольную форму.
    По окончании работы с графическими функциями в блоке обработ- ки сообщения WM_PAINT необходимо освободить полученный контекст устройства с помощью функции EndPaint(), которая имеет следующий прототип:
    BOOL EndPaint(HWND hWnd,CONST PAINTSTRUCT* lpPaintStruct);
    Типичная обработка сообщения WM_PAINT:
    Case WM_PAINT: hDc=BeginPaint(hWnd, &ps);
    //использование функций GDI
    //…
    EndPaint(hWnd, &ps);
    //…
    Основным средством программного взаимодействия между разны- ми окнами приложения является посылка сообщений. Для отправки со- общений используется функция SendMessage(), которая имеет сле- дующий прототип:
    LRESULT SendMessage(
    HWND hWnd, //дескриптор окна получателя
    UINT Msg, //код сообщения
    WPARAM wParam, //первый параметр сообщения
    LPARAM lParam //второй параметр сообщения
    );
    Функция SendMessage() посылает сообщение указанному окну или нескольким окнам. Параметры функции те же, что и параметры, пе- редаваемые в оконную функцию. Когда приложение вызывает функцию
    SendMessage(), то в свою очередь Windows вызывает оконную про- цедуру с этими четырьмя параметрами. После того, как оконная процеду- ра завершит обработку сообщения, система передаст управление инст- рукции следующей за вызовом функции SendMessage().
    1.7. Создание приложения с главным окном
    Текст программы размещается в листинге 1.1, в котором располо- жены две функции: WinMain и WndProc. Данное приложение создает ок- но со строкой заголовка, стандартным набором управляющих кнопок и выводит в нем текущую дату и время и периодически, каждую секунду, обновляет эту информацию.

    29
    1.7.1. Окна сообщений
    Окна сообщений – это средства диалога системы и прикладной про- граммы с пользователем. В прикладных программах окна сообщений удобно использовать, например, для вывода результатов вычислений или информации о ходе выполнении программы.
    Для исследования адресного пространства программы воспользуемся окном сообщений. Выведем содержимое сегментных реги- стров: команд (CS), данных (DS) и стека (SS), а также смещение главной функции WinMain и смещение строки с именем класса.
    В главную функцию вставим следующий фрагмент (см. листинг
    1.1):
    TCHAR szText [80];
    USHORT regCS,regDS,regSS;
    __asm{ mov regCS,CS mov regDS,DS mov regSS,SS
    } wsprintf(szText, _T(” CS=%X, DS=%X, SS=%X\n
    WinMain=%X\n szClassName=%X”), regCS, regDS, regSS, WinMain, szClassName);
    MessageBox(NULL, szText, _T(“ Регистры”),
    MB_ICONINFORMATION);
    Результат выполнения этого фрагмента – окно сообщения (рис. 1)
    Рис. 1
    Функция wsprintf() имеет следущий прототип: int wsprintf(LPSTR lpBuffer,
    LPCTSTR lpszFormatString,
    [arguments]
    );
    Функция wsprintf() форматирует данные ([arguments]) с использованием заданной строки формата (lpszFormatString) и раз- мещает полученные данные в символьном буфере (lpBuffer).
    Второй аргумент lpszFormatString – это указатель на строку с нулевым символом в конце, которая содержит формат выходного резуль- тата. Синтаксис произвольной строки формата:
    %[-][#][.],

    30
    где [−] – префикс, изменяет выравнивание поля по правому краю на выравнивание поля по левому краю; [#] – модификатор шестна- дцатеричных данных – добавляет перед числом 0X; []
    – ширина поля, т.е. минимальное число символов, которые копируются в выходной буфер; <.field_precession> – точка и число – определяет точность представления данных, т.е. минимальное количество цифр, ко- торые копируются в выходной буфер: – каким образом интерпретируются предыдущие два поля, например:
    (szText,”Это строка %S, а это ее адрес %#X”,lpStr, lpStr).
    Третий параметр [arguments] – это список элементов данных, ко- торые должны форматироваться и пересылаться в символьный буфер.
    Функция wsprintf() возвращает количество символов, сохра- ненных в буфере.
    Функция MessageBox() создает и выводит на экран в требуемой точке служебное окно с заданным текстом. Прототип этой функции: int MessageBox(
    HWND hWnd, //дескриптор родительского окна
    LPCTSTR lpText, //выводимый текст
    LPCTSTR lpCaption, //заголовок окна сообщения
    UINT uType
    //стиль окна сообщения
    );
    Первый параметр hWnd идентифицирует окно, которое является для окна сообщения родительским. В большинстве случаев этому пара- метру можно присвоить значение NULL.
    Второй параметр lpText представляет собой адрес строки с тек- стом, выводимым в окно, или саму строку, заключенную в кавычки.
    Третий параметр lpCaption – это адрес строки или сама строка с текстом заголовка сообщения.
    Четвертый параметр uType определяет вид и поведение окна со- общения, т.е. вид пиктограммы, характеризующей тип сообщения, набор управляющих кнопок, а также кнопку, выбранную по умолчанию. Этот параметр может принимать следующие значения:
    • MB_YESNO – окно сообщения содержит две кнопки: Yes и No;
    • MB_OKCANCEL – окно сообщения содержит две кнопки: Ok и Can- cel;
    • MB_YESNOCANCEL – окно сообщения содержит три кнопки: Yes,
    No и Cansel.
    • MB_ICONINFORMATION – пиктограмма со знаком вопроса;
    • MB_ICONSTOP – пиктограмма со знаком крестика.
    Константы, относящиеся к разным элементам окна, могут объеди- няться с помощью операции побитового ИЛИ.
    Функция MessageBox() возвращает нуль, если недостаточно па- мяти, в ином случае:
    • IDCANCEL – была нажата кнопка Cancel;
    • IDNO – была нажата кнопка NO;
    • IDOK – была нажата кнопка OK;

    31
    • IDES – была нажата кнопка YES.
    Полный список констант см. в MSDN.
    Windows XP выделяет сегменту команд (CS) селектор 0x1B, а сег- ментам данных (DS, ES) – селектор 0x23. Необходимо отметить, что ба- зовые линейные адреса сегментов команд и данных равны нулю, вирту- альные смещения с которыми работает программа, совпадают с абсолют- ными линейными адресами. Следовательно, плоское виртуальное адрес- ное пространство программы совпадает с плоским линейным адресным пространством.
    1   2   3   4   5   6   7   8


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