Передача сообщений функции окна
Общепринятый способ взаимодействия окон в системе Presentation Manager основан на передаче сообщений . Конкретнее, функция main или обработчик сообщения функции любого окна может послать сообщение другому окну. При этом передаваемое сообщение попадет в функцию этого окна.
Существует два принципиально разных способа передачи сообщений - передача через очередь приложения и непосредственная передача.
Передача сообщений через очередь приложения выполняется функцией WinPostMsg , прототип которой приведен ниже:
BOOL WinPostMsg ( HWND hwnd, // идентификатор окна ULONG ulMsgid, // код сообщения MPARAM mpParam1, // первый параметр MPARAM mpParam2); // второй параметр
Функция WinPostMsg посылает сообщение в функцию окна с идентификатором hwnd, причем код передаваемого сообщения определяется параметром ulMsgid, а первый и второй параметры сообщения - параметрами mpParam1 и mpParam2, соответственно.
Процедура посылки сообщения при помощи функции WinPostMsg выглядит следующим образом: функция записывает сообщение в очередь приложения и сразу же возвращает управление, не дожидаясь завершения обработки переданного сообщения. Если сообщение записано в очередь, функция WinPostMsg возвращает значение TRUE. В том случае, когда сообщение невозможно записать в очередь (например, по причине ее переполнения), функция возвращает значение FALSE.
Второй способ передачи сообщений основан на использовании функции WinSendMsg , прототип которой аналогичен прототипу функции WinPostMsg :
BOOL WinSendMsg ( HWND hwnd, // идентификатор окна ULONG ulMsgid, // код сообщения MPARAM mpParam1, // первый параметр MPARAM mpParam2); // второй параметр
Вызов функции WinSendMsg приводит к тому, что Presentation Manager выполняет непосредственный вызов функции окна, идентификатор которого задан параметром hwnd. При этом функции окна передается сообщение с кодом ulMsgid и параметрами mpParam1, mpParam2.
В отличие от функции WinPostMsg , функция WinSendMsg возвращает управление только после того, как передаваемое сообщение будет обработано соответствующей функцией окна.
При этом она возвращает то значение, которое было передано через оператор return обработчиком сообщения при возврате управления из функции окна.
Ниже мы привели фрагмент исходного текста приложения, в котором окну hWndChildFrame передается сообщение WM_SETICON :
WinSendMsg (hWndChildFrame, WM_SETICON , (MPARAM)WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE), NULL);
Первый параметр этого сообщения равен значению, полученному от функции WinQuerySysPointer (подробнее эту функцию мы рассмотрим позже), второй равен NULL.
Функция WinBroadcastMsg позволяет передавать сообщения одним из двух описанных выше методов одновременно всем дочерним окнам любого родительского окна:
BOOL WinBroadcastMsg ( HWND hwnd, // идентификатор родительского окна ULONG ulMsgid, // код сообщения MPARAM mpParam1, // первый параметр MPARAM mpParam2, // второй параметр ULONG flCmd); // команда
В зависимости от значения параметра flCmd функция WinBroadcastMsg использует различный способ передачи сообщения дочерним окнам. Ниже мы привели список возможных значений для этого параметра.
Значение | Описание |
BMSG_POST | Передача сообщения через очередь сообщения. Этот параметр несовместим с параметрами BMSG_SEND и BMSG_POSTQUEUE |
BMSG_SEND | Непосредственная передача сообщения. Этот параметр несовместим с параметрами BMSG_POST и BMSG_POSTQUEUE |
BMSG_POSTQUEUE | Передача сообщения всем задачам процесса, имеющим очередь сообщений. Этот параметр несовместим с параметрами BMSG_POST и BMSG_SEND |
BMSG_DESCENDANTS | Сообщение передается всем дочерним окнам родительского окна hwnd |
BMSG_FRAMEONLY | Сообщение передается только окнам, имеющим стиль CS_FRAME (только окнам Frame Window ) |
В случае успешного завершения функция WinBroadcastMsg возвращает значение TRUE, при ошибке - FALSE.
Еще одна функция, которую мы рассмотрим в этом разделе, называется WinPostQueueMsg . Она позволяет записывать сообщение в заданную очередь сообщений:
BOOL WinPostQueueMsg ( HMQ hmq, // идентификатор очереди сообщений ULONG ulMsgid, // код сообщения MPARAM mpParam1, // первый параметр MPARAM mpParam2); // второй параметр
Обратите внимание, что этой функции не передается идентификатор окна.
Обработка сообщения WM_COMMAND
Сообщение с кодом WM_COMMAND передается в функцию главного окна приложения, когда пользователь выбирает одну из строк меню верхнего уровня.
Первый параметр сообщения содержит код выбранной строки, поэтому обработку сообщения WM_COMMAND можно выполнять, например, так (фрагмент кода взят из приложения MENUAPP):
case WM_COMMAND : { switch(LOUSHORT(mp1)) { case IDM_FILE_NEW: case IDM_FILE_OPEN: . . . case IDM_HELP_KEYS: { WinMessageBox (HWND_DESKTOP, hWnd, "Функция не реализована", szAppTitle, 0, MB_INFORMATION | MB_OK); break; }
case IDM_HELP_ABOUT: { WinMessageBox (HWND_DESKTOP, hWnd, "Приложение MenuApp, (C) Frolov A., 1996", szAppTitle, 0, MB_INFORMATION | MB_OK); break; }
case IDM_FILE_EXIT: { WinPostMsg (hWnd, WM_QUIT , 0L, 0L); break; } } return(WinDefWindowProc (hWnd, msg, mp1, mp2)); }
Что же касается второго параметра сообщения WM_COMMAND , то через него передается код источника сообщения WM_COMMAND, а также признак, с помощью которого можно определить, появилось это сообщение в результате действий пользователя мышью или клавиатурой.
Заметим, что сообщение WM_COMMAND передается в родительское окно не только от меню, но также и от других органов управления, таких как кнопки, акселераторы и т. д. Однако в приложении MENUAPP источником сообщения WM_COMMAND служит только меню, поэтому вторым параметром этого сообщения мы пренебрегаем.
Функция GpiCharString At
В нашем первом приложении, рисующем текст, мы будем использовать функцию GpiCharString At . Префикс имени Gpi означает, что эта функция относится к функциям графического интерфейса GPI.
Прототип функции GpiCharString At , выполняющей рисование текстовой строки, начиная с заданной позиции, приведен ниже:
LONG GpiCharString At ( HPS hps, // иднетификатор пространства отображения PPOINTL pptlPoint, // начальная позиция LONG lCount, // количество символов в строке PCH pchString); // адрес текстовой строки
Параметр hps определяет пространство отображения, в котором будет нарисована текстовая строка. Размер этой строки в байтах задается параметром lCount, а адрес - параметром pchString.
Начальная позиция, в которой будет отображена строка, должна быть записана перед вызовом функции в структуру типа POINTL , содержащей поля x и y типа LONG. Адрес этой структуры передается через параметр pptlPoint.
Ниже приведен фрагмент кода, отображающий текстовую строку Hello, PM!. Нижний левый угол воображаемого прямоугольника, в пределах которого будет нарисована строка, расположен в точке с координатами (10, 10):
POINTL ptl; ptl.x = 10L; ptl.y = 10L; GpiCharString At (hps, &ptl, 10, "Hello, PM!");
Сообщение WM_CHAR
Вместе с параметрами сообщения WM_CHAR передается такая информация, как скан-код клавиши, код символа (для символьных клавиш), виртуальный код клавиши и слово флагов.
Сообщение WM_TIMER
Сообщение WM_TIMER имеет один параметр - идентификатор таймера. Этот параметр передается через младшее слово параметра mp1 и может быть извлечен следующим образом:
idTimer = SHORT1FROMMP (mp1);
Если ваше приложение запускает несколько таймеров, например, идущих с разным периодом времени, обработчик сообщения WM_TIMER должен анализировать содержимое параметра mp1.
Заметим, что функция главного окна вашего приложения может получать сообщения WM_TIMER даже в том случае, если вы не запускали ни одного таймера. Эти сообщения могут попадать в функцию окна из различных орагнов управления, создаваемых вашим приложением. Поэтому в общем случае обработчик сообщения WM_TIMER должен всегда проверять параметр mp1, передавая все необработанные сообщения от таймеров, которые ваше приложение не создавало, функции WinDefWindowProc . В противном случае некоторые органы управления, созданные в вашем приложении, будут работать неправильно.
Базовые понятия и определения
Прежде чем мы перейдем к описанию исходных текстов нашего первого приложения Presentation Manager, необходимо сделать некоторые определения. Если не все будет понятно сразу, не стоит беспокоиться, так как мы еще не раз вернемся к этому материалу, рассмотрев его на конкретных примерах.
БЛАГОДАРНОСТИ
Мы выражаем признательность сотруднику московского представительства IBM Николаю Смирнову, который оказал существенную помощь в подборе материала для этой книги, а также предоставил в наше распоряжение все необходимое программное обеспечение.
Мы также благодарим корректора Кустову В. С. и сотрудников издательского отдела АО "Диалог-МИФИ" Голубева О. А., Дмитриеву Н. В., Виноградову Е. К., Кузьминову О. А.
Цикл обработки сообщений
Что делает приложение с сообщениями, поступающими в его очередь?
Функция main приложения Presentation Manager после создания и инициализации окна организует цикл . В этом цикле она с помощью специальной функции Presentation Manager выбирает сообщения из очереди и затем снова отдает их системе Presentation Manager, для того чтобы та передала их на обработку функции главного окна приложения.
Таким образом, при возникновении событий, имеющих отношение к приложению, в его очередь записываются соответствующие сообщения. С помощью цикла обработки сообщений функция main организует выборку этих сообщений из очереди с последующей передачей функции главного окна приложения. Функция главного окна выполняет обработку сообщений в зависимости от их кода (например, с помощью обычного оператора case).
Диапазон изменения значений
Для установки диапазона изменения значений регулятору с помощью функции WinSendMsg посылается сообщение CSM_SETRANGE :
WinSendMsg(hWndCirc1, CSM_SETRANGE, MPFROMLONG(0L), MPFROMLONG(255L));
Через параметр mp1 этого сообщения передается начальное значение, а через параметр mp2 - конечное значение позиции. В приведенном выше примере при вращении ручки регулятора текущая позиция будет изменяться в диапазоне от 0 до 255.
Посылая окну регулятора сообщение CSM_QUERYRANGE , приложение может определить диапазон изменения значений. Через параметр mp1 при этом необходимо передать указатель на переменную типа USHORT, в которую будет записано начальное значение позиции, а через параметр mp2 - указатель на переменную такого же типа для записи конечной позиции регулятора.
Динамическое создание меню
Очень часто приложения изменяют свое меню верхнего уровня в зависимости от текущего режима работы или других обстоятельств. При необходимости ваше приложение может создать меню "на пустом месте" без использования шаблона, определенного в файле описания ресурсов.
В качестве примера опишем процедуру добавления нового временного меню Edit в уже существующее меню верхнего уровня, созданного обычным образом.
Для начала нам нужно определить идентификатор окна меню верхнего уровня. Это можно сделать таким же образом, каким мы определяли этот идентификатор для системного меню:
HWND hwndMenu; hwndMenu = WinWindowFromID ( WinQueryWindow (hWnd, QW_PARENT ), FID_MENU );
Напомним, что окно меню верхнего уровня имеет идентификатор ресурсов FID_MENU .
Следующим нашим действием будет создание пустого меню Edit с помощью функции WinCreateMenu :
HWND hwndEditMenu; hwndEditMenu = WinCreateMenu (HWND_OBJECT , NULL);
Через первый параметр этой функции передается идентификатор родительского окна, которое будет также и окном-владельцем. Второй параметр представляет собой указатель на шаблон меню, подготовленный в оперативной памяти, и в нашем случае не используется.
Так как созданное меню будет иметь идентификатор ресурсов FID_MENU , заменяем этот идентификатор на IDM_EDIT с помощью функции WinSetWindowUShort:
WinSetWindowUShort(hwndEditMenu, QWS_ID, IDM_EDIT);
Теперь можно приступать к добавлению строк в созданное нами пустое меню. Это делается таким же образом, что и добавление строк в системное меню:
mi.iPosition = MIT_END; mi.afStyle = MIS_TEXT; mi.afAttribute = 0; mi.hwndSubMenu = 0; mi.hItem = 0; mi.id = IDM_EDIT_UNDO;
WinSendMsg (hwndEditMenu, MM_INSERTITEM , MPFROMP(&mi), "~Undo");
mi.id = IDM_EDIT_REDO; WinSendMsg (hwndEditMenu, MM_INSERTITEM , MPFROMP(&mi), "~Redo");
После того как все строки добавлены, нужно вставить меню Edit в меню верхнего уровня. Эта операция выполняется аналогично операции вставки строк, с тем лишь исключением, что в поле hwndSubMenu структуры MENUITEM мы должны указать идентификатор окна временного меню Edit:
mi.iPosition = 1; mi.afStyle = MIS_TEXT | MIS_SUBMENU; mi.afAttribute = 0; mi.id = IDM_EDIT; mi.hwndSubMenu = hwndEditMenu;
WinSendMsg (hwndMenu, MM_INSERTITEM , MPFROMP(&mi), "~Edit");
Так как мы добавляем меню, то в поле стилей дополнительно указывается константа MIS_SUBMENU.
В поле iPosition мы указали значение, равное единице, поэтому меню Edit будет вставлено во вторую позицию слева. Это стандартное расположение для меню Edit, так как перавая позиция (имеющая нулевой порядковый номер), предназначена для меню File.
Для удаления строки из меню или временного меню вы можете воспользоваться сообщением MM_DELETEITEM .
Через младшее слово первого параметра с этим сообщением передается идентификатор удаляемой строки или меню. Если старшее слово первого параметра содержит значение TRUE, при удалении меню будут удалены все связанные с ним вложенные меню, если FALSE - вложенные меню останутся нетронутыми.
Во второй параметр для сообщения MM_DELETEITEM вам нужно записать адрес заполненной структуры MENUITEM .
Другие фукнции для рисования текста
Кроме изученной нами функции GpiCharString At приложения Presentation Manager могут использовать для рисования текста еще несколько функций.
Функция GpiCharString отображает строку текста с текущей позиции и имеет следующий прототип:
LONG GpiCharString ( HPS hps, // идентификатор пространства отображения LONG lCount, // размер текстовой строки PCH pchString); // адрес текстовой строки
Текущая позиция для вывода текста устанавливается функцией GpiMove . После рисования строки текста текущая позиция устанавливается в конце этой строки, так что с помощью последующих вызовов функции GpiCharString вы можете дописать строку.
Функция GpiMove имеет два параметра:
BOOL GpiMove ( HPS hps, // идентификатор пространства отображения PPOINTL pptlPoint); // новая позиция
Ниже мы привели пример совместного использования фукнций GpiMove и GpiCharString :
HPS hps; POINTL ptl;
ptl.x = 10L; ptl.y = 10L; GpiMove (hps, &ptlStart); GpiCharString (hps, 5L, "Hello"); GpiCharString (hps, 8L, ", world!");
Нетрудно заметить, что рассмотренная нами ранее функция GpiCharString At является комбинацией функций GpiMove и GpiCharString.
Для рисования текста вы также можете использовать функции GpiCharString Pos, GpiCharStringPosAt и WinDrawText . Эти функции предназначены для форматного вывода текста и допускают выбор индивидуальной позиции для каждого отображаемого символа и использование таких элементов оформления текста, как подчеркивание и перечеркивание.
Расскажем подробнее о функции WinDrawText , которая предназначена для вывод текста в прямоугольную область окна и имеет некоторые возможности форматирования. Прототип этой функции приведен ниже:
LONG WinDrawText ( HPS hps, // идентификатор пространства отображения LONG cchText, // длина текстовой строки в байтах PCH lpchText, // адрес отображаемой текстовой строки PRECTL prcl, // прямоугольная область LONG clrFore, // цвет текста LONG clrBack, // цвет фона ULONG flCmd); // флаги режима отображения текста
Параметр hps задает идентификатор пространства отображения, который необходимо получить перед использованием этой фукнции.
При помощи параметра cchText необходимо задать длину отображаемой текстовой строки, адрес которой передается через параметр lpchText. Если эта строка закрыта двоичным нулем, вместо реальной длины строки можно указать значение -1, что очень удобно. Кроме двоичного нуля, строка может быть закрыта символом возврата каретки или перевода строки.
Перед вызовом функции WinDrawText необходимо подготовить структуру типа RECTL, записав в нее координаты прямоугольной области, внутри которой будет отображаться текст. Адрес этой структуры следует передать через параметр prcl.
Если текст не помещается по длине окна, он будет обрезан.
После возвращения из функции WinDrawText содержимое указанной выше структуры изменится. В ней будет записана высота прямоугольной области, занятая текстовой строкой (если в параметре flCmd указан флаг DT_QUERYEXTENT ).
Параметры clrFore и clrBack используются только в том случае, если в параметре flCmd указан флаг DT_TEXTATTRS . С помощью этих параметров вы можете задать, соответственно, цвет текста и цвет фона, которые будут использованы при выводе.
И, наконец, с помощью параметра flCmd вы можете указывать различные флаги, объединяя их при помощи логической операции ИЛИ. Эти флаги, определяющие режим работы функции WinDrawText , перечислены ниже.
Флаг | Описание |
DT_LEFT | Выравнивание строки по левой границе заданной прямоугольной области |
DT_RIGHT | Аналогично, но по правой границе |
DT_TOP | Аналогично, но по верхней границе |
DT_BOTTOM | Аналогично, но по нижней границе |
DT_CENTER | Центрирование строки по горизонтали |
DT_VCENTER | Центрирование строки по вертикали |
DT_HALFTONE | Отображение текста с исользованием полутонов |
DT_MNEMONIC | Отображение мнемонических символов |
DT_QUERYEXTENT | После возвращения из функции WinDrawText содержимое структуры, адрес которой передается через параметр prcl, изменяется таким образом, чтобы отражать реальную высоту нарисованной строки символов |
DT_WORDBREAK | Если строка символов, состоящая из отдельных слов, не помещается в окне, она будет обрезана таким образом, что в окне будут отображаться только полные слова текста |
DT_EXTERNALLEADING | Используется вместе с флагами DT_TOP и DT_QUERYEXTENT. Если указан этот флаг, возвращаемая в структуре prcl высота символов будет увеличена на размер выступающей части символов |
DT_TEXTATTRS | При отображении текста необходимо использовать цвета символов и фона, указанные в параметрах функции clrFore и clrBack |
DT_ERASERECT | Перед отображением текста содержимое прямоугольной области prcl будет стерто |
DT_UNDERSCORE | Символы текста выделяются подчеркиванием |
DT_STRIKEOUT | Символы текста выделяются перечеркиванием |
Флаги DT_LEFT, DT_CENTER и DT_RIGHT нельзя использовать вместе, точно также, как и флаги DT_TOP, DT_VCENTER и DT_BOTTOM.
Ниже мы привели пример использования функции WinDrawText для отображения текста в центре окна, размеры которого определяются при помощи функции WinQueryWindow Rect:
WinQueryWindow Rect(hWnd, &rec); WinDrawText (hps, -1, pszText, &rec, 0L, 0L, DT_WORDBREAK | DT_CENTER | DT_VCENTER | DT_TEXTATTRS | DT_ERASERECT);
Другие функции для работы с таймером
В этом разделе мы расскажем о других функциях, предназначенных для работы с таймером, для определения текущего времени и даты.
Другие сообщения
Одна из часто выполняемых с помощью мыши операций - перемещение объектов (drag and drop). Для выполнения этой операции вы можете использовать сообщения WM_BUTTON1MOTIONSTART и WM_BUTTON1MOTIONEND и аналогичные для кнопок с другими номерами. Первое из этих сообщений передается функции окна когда пользователь начинает операцию перемещения, нажав кнопку с соответствующим номером.
Через параметр mp1 этих сообщений передаются координаты курсора мыши, а через младшее слово параметра mp2 - результаты теста Hit Test.
Кроме этого, для обработки операций перемещения можно использовать сообщения WM_BEGINDRAG и WM_ENDDRAG . Через параметр mp1 сообщений WM_BEGINDRAG и WM_ENDDRAG передаются координаты курсора мыши, а через младшее слово параметра mp2 - флаг, определяющий устройство ввода, которое было использовано для выполнения операции перемещения. Если это была мышь, флаг равен TRUE, если клавиатура - FALSE.
Есть еще одно сообщение, имеющее отношение к мыши. Это сообщение с кодом WM_MOUSEMAP , позволяющее определить отображение клавиш мыши в сообщениях, проходящих через очередь. Однако это сообщение не рекомендуется к использованию обычными приложениями.
Файл beep.def
Файл определения модуля приложения beep.def представлен в листинге 7.4.
Листинг 7.4. Файл beep\beep.def
NAME BEEP WINDOWAPI DESCRIPTION 'Beep Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл beep.h
Файл beep.h (листинг 7.2) содержит определения константы ID_APP_FRAMEWND, а также идентификаторов двух таймеров ID_APP_TIMER1 и ID_APP_TIMER2.
Листинг 7.2. Файл beep\beep.h
#define ID_APP_FRAMEWND 1 #define ID_APP_TIMER1 1 #define ID_APP_TIMER2 2
Файл beep.rc
Файл описания ресуросв приложения beep.rc приведен в листинге 7.3.
Листинг 7.3. Файл beep\beep.rc
#include <os2.h> #include "beep.h" ICON ID_APP_FRAMEWND BEEP.ICO
Файл button.def
Файл определения модуля button.def приложения BUTTON приведен в листинге8.4.
Листинг 8.4. Файл button\button.def
NAME BUTTON WINDOWAPI DESCRIPTION 'Button Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл button.h
Файл button.h (листинг 8.2) содержит описание идентификатора главного окна приложения ID_APP_FRAMEWND, а также идентификаторов двух кнопок BTN1_ID и BTN2_ID.
Листинг 8.2. Файл button\button.h
#define ID_APP_FRAMEWND 1 #define BTN1_ID 100 #define BTN2_ID 101
Файл button.rc
В файле button.rc (листинг 8.3) описана пиктограмма приложения BUTTON.
Листинг 8.3. Файл button\button.rc
#include <os2.h> #include "button.h" ICON ID_APP_FRAMEWND BUTTON.ICO
Файл check.def
Файл определения модуля прилоджения check.def приведен в листинге8.8.
Листинг 8.8. Файл check\check.def
NAME CHECK WINDOWAPI DESCRIPTION 'Check Box Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл check.h
Файл check.h (листинг 8.6) содержит определения константы ID_APP_FRAMEWND и идентификаторов органов управления BTN1_ID, BTN2_ID и BTN3_ID.
Листинг 8.6. Файл check\check.h
#define ID_APP_FRAMEWND 1 #define BTN1_ID 100 #define BTN2_ID 101 #define BTN3_ID 102
Файл check.rc
Файл описания ресурсов приложения check.rc (листинг 8.7) содержит только описание пиктограммы.
Листинг 8.7. Файл check\check.rc
#include <os2.h> #include "check.h" ICON ID_APP_FRAMEWND CHECK.ICO
Файл clock.h
Файл clock.h (листинг 7.6) содержит определения константы ID_APP_FRAMEWND, идентификатора таймера ID_APP_TIMER, идентификаторов двух курсоров ID_APP_POINTER и ID_APP_POINTER1, которые используются для перемещения окна приложения, а также прототипы функций SetCourierFont и ResetFont.
Листинг 7.6. Файл clock\clock.h
#define ID_APP_FRAMEWND 1 #define ID_APP_TIMER 1 #define ID_APP_POINTER 2 #define ID_APP_POINTER1 3
void SetCourierFont(HPS hps); void ResetFont(HPS hps);
Файл kbdmsg.def
Файл определения модуля приложения kbdmsg.def представлен в листинге 5.4.
Листинг 5.4. Файл kbdmsg\kbdmsg.def
NAME KBDMSG WINDOWAPI DESCRIPTION 'KbdMsg Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл kbdmsg.h
Файл kbdmsg.h (листинг 5.2) содержит определение константы ID_APP_FRAMEWND, а также прототипы функций SetCourierFont и ResetFont.
Листинг 5.2. Файл kbdmsg\kbdmsg.h
#define ID_APP_FRAMEWND 1 void SetCourierFont(HPS hps); void ResetFont(HPS hps);
Файл kbdmsg.rc
Файл описания ресурсов приложения KBDMSG с именем kbdmsg.rc представлен в листинге5.3.
Листинг 5.3. Файл kbdmsg\kbdmsg.rc
#include <os2.h> #include "kbdmsg.h" ICON ID_APP_FRAMEWND KBDMSG.ICO
Файл menuapp.h
В файле menuapp.h (листинг 3.2) сделаны определения всех необходимых констант, таких как идентификатор ресурсов главного окна приложения ID_APP_FRAMEWND, а также идентификаторы временных меню, идентификаторы строк меню и идентификатор плавающего меню.
Листинг 3.2. Файл menuapp\menuapp.h
#define ID_APP_FRAMEWND 1
#define IDM_FILE 100 #define IDM_FILE_NEW 101 #define IDM_FILE_OPEN 102 #define IDM_FILE_SAVE 103 #define IDM_FILE_SAVEAS 104 #define IDM_FILE_EXIT 105
#define IDM_EDIT 200 #define IDM_EDIT_UNDO 201 #define IDM_EDIT_REDO 202 #define IDM_EDIT_CUT 203 #define IDM_EDIT_COPY 204 #define IDM_EDIT_PASTE 205 #define IDM_EDIT_CLEAR 206 #define IDM_EDIT_DUPLICATE 207 #define IDM_EDIT_SELECTALL 208
#define IDM_HELP 300 #define IDM_HELP_INDEX 301 #define IDM_HELP_GENERAL 302 #define IDM_HELP_USING 303 #define IDM_HELP_KEYS 304 #define IDM_HELP_ABOUT 305
#define POPUP_MENU 400
#define IDM_OPTIONS 500 #define IDM_OPTIONS_FONT_NORMAL 501 #define IDM_OPTIONS_FONT_BOLD 502 #define IDM_OPTIONS_FONT_ITALIC 503 #define IDM_OPTIONS_FONT_UNDERLINE 504
#define IDM_OPTIONS_PARA_LEFT 505 #define IDM_OPTIONS_PARA_CENTER 506 #define IDM_OPTIONS_PARA_RIGHT 507 #define IDM_OPTIONS_PARA_JUSTIFY 508
Файл menumod.h
Файл menumod.h, содержащий определения всех необходимых констант, представлен в листинге 3.6.
Листинг 3.6. Файл menumod\menumod.h
#define ID_APP_FRAMEWND 1
#define IDM_FILE 100 #define IDM_FILE_NEW 101 #define IDM_FILE_OPEN 102 #define IDM_FILE_SAVE 103 #define IDM_FILE_SAVEAS 104 #define IDM_FILE_EXIT 105
#define IDM_EDIT 200 #define IDM_EDIT_UNDO 201 #define IDM_EDIT_REDO 202 #define IDM_EDIT_CUT 203 #define IDM_EDIT_COPY 204 #define IDM_EDIT_PASTE 205 #define IDM_EDIT_CLEAR 206 #define IDM_EDIT_DUPLICATE 207 #define IDM_EDIT_SELECTALL 208
#define IDM_HELP 300 #define IDM_HELP_INDEX 301 #define IDM_HELP_GENERAL 302 #define IDM_HELP_USING 303 #define IDM_HELP_KEYS 304 #define IDM_HELP_ABOUT 305
#define IDM_OPTIONS 500 #define IDM_OPTIONS_FONT 501 #define IDM_OPTIONS_FONT_NORMAL 502 #define IDM_OPTIONS_FONT_BOLD 503 #define IDM_OPTIONS_FONT_ITALIC 504 #define IDM_OPTIONS_FONT_UNDERLINE 505
#define IDM_OPTIONS_PARA 600 #define IDM_OPTIONS_PARA_LEFT 601 #define IDM_OPTIONS_PARA_CENTER 602 #define IDM_OPTIONS_PARA_RIGHT 603 #define IDM_OPTIONS_PARA_JUSTIFY 604
Файл mousemov.h
В файле mousemov.h определены символичесике константы для ресурсов приложения (листинг 6.2).
Листинг 6.2. Файл mousemov\mousemov.h
#define ID_APP_FRAMEWND 1 #define ID_APP_POINTER 2 #define ID_APP_POINTER1 3
Файл mousemov.rc
В файле описания ресурсов приложения mousemov.rc (листинг 6.3) помимо пиктограммы определены два указателя мыши, для чего использован оператор POINTER .
Листинг 6.3. Файл mousemov\mousemov.rc
#include <os2.h> #include "mousemov.h" ICON ID_APP_FRAMEWND MOUSEMOV.ICO POINTER ID_APP_POINTER MOUSEMOV.PTR POINTER ID_APP_POINTER1 MOUSE1.PTR
Файл описания ресурсов clock.rc
Файл описания ресурсов clock.rc (листинг 7.7) содержит описание пиктограммы приложения и двух курсоров мыши с идентификаторами ID_APP_POINTER и ID_APP_POINTER1.
Листинг 7.7. Файл clock\clock.rc
#include <os2.h> #include "clock.h"
ICON ID_APP_FRAMEWND CLOCK.ICO POINTER ID_APP_POINTER MOUSEMOV.PTR POINTER ID_APP_POINTER1 MOUSE1.PTR
Файл определения модуля
Еще один файл, который используется редактором связей при создании загрузочного модуля приложения IBM OS/2 и который не имеет аналога в операционной системе MS-DOS, называется файлом определения модуля . В этом файле указывается имя загрузочного модуля, строка описания, режим работы приложения, размер областей памяти, выделенных для кучи и стека, а также перечисляются имена функций обратного вызова.
Файл определения модуля mywindow.def для нашего приложения представлен в листинге 1.4.
Листинг 1.4. Файл mywindow\mywindow.def
NAME MYWINDOW WINDOWAPI DESCRIPTION 'MyWindow Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
В строке описания имени приложения есть параметр WINDOWAPI , который означает, что данное приложение является приложением Presentation Manager.
Описание, которое приведено в строке DESCRIPTION , попадает в файл загрузочного модуля приложения и может быть использовано для указания авторских прав или любой другой произвольной информации о приложении.
С помощью строки EXPORTS имя функции WndProc попадает в таблицу экспортируемых имен. Обычно такое описание используется для функций, экспортируемых библиотеками динамической загрузки.
Файл определения модуля приложения не имеет никаких особенностей и приведен в листинге 3.4.
Листинг 3.4. Файл menuapp\menuapp.def
NAME MENUAPP WINDOWAPI DESCRIPTION 'MenuApp Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл определения модуля приложения MENUMOD представлен в листинге 3.8.
Листинг 3.8. Файл menumod\menumod.def
NAME MENUMOD WINDOWAPI DESCRIPTION 'MenuMod Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл определения модуля clock.def
Файл определения модуля приложения clock.def приведен в листинге 7.8.
Листинг 7.8. Файл clock\clock.def
NAME CLOCK WINDOWAPI DESCRIPTION 'Clock Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл определения модуля mousemov.def
Файл определения модуля приложения представлен в листинге 6.4.
Листинг 6.4. Файл mousemov\mousemov.def
NAME MOUSEMOV WINDOWAPI DESCRIPTION 'MouseMov Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл pointer.def
Файл определения модуля приложения pointer.def представлен в листинге 6.8.
Листинг 6.8. Файл pointer\pointer.def
NAME POINTER WINDOWAPI DESCRIPTION 'Pointer Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл pointer.h
Файл pointer.h (листинг 6.6) содержит определение константы ID_APP_FRAMEWND, а также прототип функции DrawMousePtr.
Листинг 6.6. Файл pointer\pointer.h
#define ID_APP_FRAMEWND 1 void DrawMousePtr(HPS hps, LONG x, LONG y, LONG lPtrId);
Файл pointer.rc
В файле описания ресуросв приложения pointer.rc (листинг 6.7) определена пиктограмма с идентификатором ID_APP_FRAMEWND.
Листинг 6.7. Файл pointer\pointer.rc
#include <os2.h> #include "pointer.h" ICON ID_APP_FRAMEWND POINTER.ICO
Файл ресурсов menumod.rc
Файл описания ресурсов приложения menumod.rc (листинг 3.7) содержит описание пиктограммы и меню верхнего уровня. Обратите внимание, что в меню Options определены два вложенных меню Font и Alighnment.
Определение временного меню Edit отсутствует, так как это меню создается динамически при обработке сообщения WM_CREATE .
Листинг 3.7. Файл menumod\menumod.rc
#include <os2.h> #include "menumod.h"
ICON ID_APP_FRAMEWND MENUMOD.ICO
MENU ID_APP_FRAMEWND BEGIN SUBMENU "~File", IDM_FILE BEGIN MENUITEM "~New...", IDM_FILE_NEW MENUITEM "~Open...", IDM_FILE_OPEN MENUITEM SEPARATOR MENUITEM "~Save...", IDM_FILE_SAVE MENUITEM "Save ~as...", IDM_FILE_SAVEAS MENUITEM SEPARATOR MENUITEM "~Exit", IDM_FILE_EXIT END
SUBMENU "~Options", IDM_OPTIONS BEGIN SUBMENU "~Font",IDM_OPTIONS_FONT BEGIN MENUITEM "~Normal", IDM_OPTIONS_FONT_NORMAL MENUITEM "~Bold", IDM_OPTIONS_FONT_BOLD MENUITEM "~Italic", IDM_OPTIONS_FONT_ITALIC MENUITEM "~Underline",IDM_OPTIONS_FONT_UNDERLINE END
SUBMENU "~Alighnment",IDM_OPTIONS_PARA BEGIN MENUITEM "~Left", IDM_OPTIONS_PARA_LEFT MENUITEM "~Center", IDM_OPTIONS_PARA_CENTER MENUITEM "~Right", IDM_OPTIONS_PARA_RIGHT MENUITEM "~Justify", IDM_OPTIONS_PARA_JUSTIFY END END
SUBMENU "~Help", IDM_HELP BEGIN MENUITEM "Help ~index...", IDM_HELP_INDEX MENUITEM "~General help...", IDM_HELP_GENERAL MENUITEM "~Using help...", IDM_HELP_USING MENUITEM "~Keys help...", IDM_HELP_KEYS MENUITEM SEPARATOR MENUITEM "~Product information...",IDM_HELP_ABOUT END END
Файл ресурсов приложения MENUAPP
Файл ресурсов приложения MENUAPP представлен в листинге 3.3.
Листинг 3.3. Файл menuapp\menuapp.rc
#include <os2.h> #include "menuapp.h"
ICON ID_APP_FRAMEWND MENUAPP.ICO
MENU ID_APP_FRAMEWND BEGIN SUBMENU "~File", IDM_FILE BEGIN MENUITEM "~New...", IDM_FILE_NEW MENUITEM "~Open...", IDM_FILE_OPEN MENUITEM SEPARATOR MENUITEM "~Save...", IDM_FILE_SAVE MENUITEM "Save ~as...", IDM_FILE_SAVEAS MENUITEM SEPARATOR MENUITEM "~Exit", IDM_FILE_EXIT END
SUBMENU "~Edit", IDM_EDIT BEGIN MENUITEM "~Undo", IDM_EDIT_UNDO MENUITEM "~Redo", IDM_EDIT_REDO MENUITEM SEPARATOR MENUITEM "Cu~t", IDM_EDIT_CUT MENUITEM "~Copy", IDM_EDIT_COPY MENUITEM "~Paste", IDM_EDIT_PASTE MENUITEM "Cl~ear", IDM_EDIT_CLEAR MENUITEM "~Duplicate", IDM_EDIT_DUPLICATE MENUITEM SEPARATOR MENUITEM "~Select all", IDM_EDIT_SELECTALL END
SUBMENU "~Options", IDM_OPTIONS BEGIN MENUITEM "Font", -1, MIS_STATIC, MIA_FRAMED MENUITEM "~Normal", IDM_OPTIONS_FONT_NORMAL MENUITEM "~Bold", IDM_OPTIONS_FONT_BOLD MENUITEM "~Italic", IDM_OPTIONS_FONT_ITALIC MENUITEM "~Underline",IDM_OPTIONS_FONT_UNDERLINE MENUITEM "Alighnment", -1, MIS_BREAKSEPARATOR | MIS_STATIC, MIA_FRAMED MENUITEM "~Left", IDM_OPTIONS_PARA_LEFT MENUITEM "~Center", IDM_OPTIONS_PARA_CENTER MENUITEM "~Right", IDM_OPTIONS_PARA_RIGHT MENUITEM "~Justify", IDM_OPTIONS_PARA_JUSTIFY END
SUBMENU "~Help", IDM_HELP BEGIN MENUITEM "Help ~index...", IDM_HELP_INDEX MENUITEM "~General help...", IDM_HELP_GENERAL MENUITEM "~Using help...", IDM_HELP_USING MENUITEM "~Keys help...", IDM_HELP_KEYS MENUITEM SEPARATOR MENUITEM "~Product information...", IDM_HELP_ABOUT END END
MENU POPUP_MENU BEGIN MENUITEM "~New...", IDM_FILE_NEW MENUITEM "~Open...", IDM_FILE_OPEN MENUITEM SEPARATOR MENUITEM "~Save...", IDM_FILE_SAVE MENUITEM "Save ~as...", IDM_FILE_SAVEAS MENUITEM SEPARATOR MENUITEM "~Exit", IDM_FILE_EXIT END
В меню верхнего уровня с идентификатором ID_APP_FRAMEWND определены четыре временных меню с идентификаторами IDM_FILE, IDM_EDIT, IDM_OPTIONS и IDM_HELP.
Временное меню IDM_OPTIONS отображается в виде таблицы, состоящей из двух столбцов, озаглавленных, соответственно, Font и Alighnment.
Строка Font имеет атрибуты MIS_STATIC и MIA_FRAMED , поэтому ее нельзя выбрать и вокруг этой строки нарисована рамка:
MENUITEM "Font", -1, MIS_STATIC, MIA_FRAMED
Строка Alighnment дополнительно имеет атрибут MIS_BREAKSEPARATOR , поэтому она отображается в отдельном столбце:
MENUITEM "Alighnment", -1, MIS_BREAKSEPARATOR | MIS_STATIC, MIA_FRAMED
В файле описания ресурсов приложения также определено плавающее меню с идентификатором POPUP_MENU, которое полностью повторяет временное меню File.
Файл scroll.def
Файл определения модуля scroll.def приведен в листинге 8.12.
Листинг 8.12. Файл scroll\scroll.def
NAME SCROLL WINDOWAPI DESCRIPTION 'Scroll Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл scroll.h
Файл scroll.h содержит определения константы ID_APP_FRAMEWND, а также прототипы функций, определенных в приложении SCROLL (листинг 8.10).
Листинг 8.10. Файл scroll\scroll.h
#define ID_APP_FRAMEWND 1 void SetCourierFont(HPS hps); void ResetFont(HPS hps); void PrintString(HPS hps, PSZ pszValue, PSZ pszName); void PrintLong(HPS hps, LONG lValue, PSZ pszName);
Файл scroll.rc
Файл описания ресурсов приложения scroll.rc представлен в листинге8.11.
Листинг 8.11. Файл scroll\scroll.rc
#include <os2.h> #include "scroll.h" ICON ID_APP_FRAMEWND SCROLL.ICO
Файл slider.def
Файл определения модуля приложения slider.def приведен в листинге 8.16.
Листинг 8.16. Файл slider\slider.def
NAME SLIDER WINDOWAPI DESCRIPTION 'Slider Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл slider.h
Файл slider.h (листинг 8.14) содержит определения константы ID_APP_FRAMEWND, а также идентификаторов круглых регуляторов цвета CIRCSLD1_ID, CIRCSLD2_ID и CIRCSLD3_ID.
Листинг 8.14. Файл slider\slider.h
#define ID_APP_FRAMEWND 1 #define CIRCSLD1_ID 100 #define CIRCSLD2_ID 101 #define CIRCSLD3_ID 102
Файл slider.rc
Файл описания ресурсов приложения slider.rc представлен в листинге8.15.
Листинг 8.15. Файл slider\slider.rc
#include <os2.h> #include "slider.h" ICON ID_APP_FRAMEWND SLIDER.ICO
Файл textout.def
Файл определения модуля textout.def приведен в листинге 4.4.
Листинг 4.4. Файл textout\textout.def
NAME TEXTOUT WINDOWAPI DESCRIPTION 'TextOut Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc
Файл textout.h
В файле textout.h (листинг 4.2) определена константа ID_APP_FRAMEWND, которая используется при создании главного окна приложения.
Листинг 4.2. Файл textout\textout.h
#define ID_APP_FRAMEWND 1
Файл textout.rc
В файле описания ресурсов textout.rc (листинг 4.3) определена только пиктограмма приложения.
Листинг 4.3. Файл textout\textout.rc
#include <os2.h> #include "textout.h" ICON ID_APP_FRAMEWND TEXTOUT.ICO
Файл wintree.def
В файле определения модуля (листинг 2.4) в секции EXPORTS перечислены имена всех функций обратного вызова. В роли этих функций выступают функции окон верхнего уровня WndProc1 и WndProc2, а также функция дочернего окна WndProcChild.
Листинг 2.4. Файл wintree\wintree.def
NAME WINTREE WINDOWAPI DESCRIPTION 'WinTree Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc1 WndProc2 WndProcChild
Файл wintree.h
Файл wintree.h, приведенный в листинге 2.2, содержит определение констант ID_APP_FRAMEWND и ID_CHILDWND (идентификаторы ресурсов для окон верхнего уровня и дочернего окна).
Листинг 2.2. Файл wintree\wintree.h
#define ID_APP_FRAMEWND 1 #define ID_CHILDWND 2