Win32 api программирование
Скачать 0.78 Mb.
|
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ, МЕХАНИКИ И ОПТИКИ В.А. Безруков WIN32 API ПРОГРАММИРОВАНИЕ Учебное пособие Санкт-Петербург 2009 2 УДК 681.3.06(035.5) Безруков В.А. Win32 API. Программирование /учебное пособие. – СПб: СПбГУ ИТМО, 2009. – 90 с. Рассмотрены основные принципы программирования в среде Microsoft Windows на языке C++ с применением Win32 API. Пособие предназначено для студентов, обучающихся по специально- стям 210202.65 «Проектирование и технология вычислительных средств» и 0900104.65 «Комплексная защита объектов информации», а также для студентов других специальностей изучающих дисциплину «Программи- рование на языках высокого уровня». Рекомендовано к печати Советом факультета компьютерных технологии и управления, протокол № 5 от 08 декабря 2009 г. СПбГУ ИТМО стал победителем конкурса инновационных образо- вательных программ вузов России на 2007-2008 годы и успешно реализо- вал инновационную образовательную программу «Инновационная систе- ма подготовки специалистов нового поколения в области информацион- ных и оптических технологий», что позволило выйти на качественно но- вый уровень подготовки выпускников и удовлетворять возрастающий спрос на специалистов в информационной, оптической и других высоко- технологичных отраслях науки. Реализация этой программы создала ос- нову формирования программы дальнейшего развития вуза до 2015 года, включая внедрение современной модели образования. ©Санкт-Петербургский государственный университет информа- ционных технологий, механики и оптики, 2009 ©Безруков В.А., 2009 3 ВВЕДЕНИЕ В операционной системе Windows реализована объектно- ориентированная идеология. Базовый объект системы – окно, поведение которого определяется методом, называемым функцией окна. Графиче- ский образ окна на экране дисплея – прямоугольная рабочая область. Независимо от своего типа любой объект Windows идентифициру- ется описателем или дескриптором (handle). Дескриптор – это ссылка на объект. Все взаимоотношения программного кода с объектом осущест- вляются только через его дескриптор. Интерфейс прикладного программирования (API – Application Pro- gramming Interface) представляет собой совокупность 32-битных функций (Win32 API), которые предназначены для создания приложений (программ), работающих под управлением Microsoft Win- dows. Функции объявлены в заголовочных файлах. Главный из них − файл windows.h, в котором содержатся ссылки на другие заголовочные файлы. В Win32 единицей работы компьютера является поток − ход вы- полнения программы в рамках процесса (в контексте процесса). Поток выполняет программный код, принадлежащий процессу. Процесс − это экземпляр выполняемой программы (но не ход ее выполнения). Он не яв- ляется динамическим объектом и включает виртуальное адресное про- странство, код и данные, файлы, синхронизирующие объекты, динамиче- ские библиотеки. Каждое приложение создает, по меньшей мере, один первичный поток, но может создать и много потоков. Любое приложение Windows представлено на экране дисплея как минимум одним окном с набором стандартных элементов управления. Различают следующие типы окон: • перекрывающие (overlapped window); • всплывающие (pop–up window); • дочерние (child window); • слоистые (layered window) – особые окна, которые позволяют улучшить визуальный эффект, включая прозрачность. Перекрывающие окна создаются функцией CreateWindowEx() со стилем WS_OVERLAPPEDWINDOW. Этот стиль определяет наличие за- головка, системного меню, кнопок минимизации и максимизации, кнопки закрытия окна и «толстой» рамки, позволяющей изменять размеры окна. Перекрывающие окна предназначены для главных окон приложений и могут иметь меню. Всплывающие окна создаются функцией CreateWindowEx() со стилем WS_POPUP и предназначены для окон диалогов, окон сообщений и других окон временного использования, которые могут находиться вне главного окна приложения. Для того чтобы временное окно имело заго- 4 ловок, рамку и системное меню, необходимо при его создании использо- вать комбинацию стилей WS_POPUPWINDOW | WS_CAPTION. Дочерние окна создаются функцией CreateWindowEx() со стилем WS_CHILD и обычно используются для разделения клиентской области родительского окна на отдельные функциональные области. Дочерние окна могут иметь заголовок, системное меню, кнопки минимизации и максимизации, рамку и полосы прокрутки, но не могут иметь меню. Дочерние окна всегда находятся в пределах клиентской области родитель- ского окна, т.е. их координаты всегда отсчитываются от левого верхнего угла родительского окна. Родительское окно может быть перекрывающим, всплывающим или даже другим дочерним окном. Виды приложений: • SDI (Single Document Interface) – приложение с одно–документным интерфейсом; • MDI (Multiple Document Interface) – приложение с многодокумент- ным интерфейсом; • диалоговое приложение (Based Dialog) − содержит только диалого- вое окно с элементами управления, не имеет главного окна, а значит, не имеет меню. Windows поддерживает работу с символами как в традиционной ANSI кодировке, так и в кодировке UNICODE. В стандарте UNICODE каждый символ кодируется двумя байтами, что позволяет определить 65536 символов. Чтобы была возможность компилировать приложение как ANSI версию или как UNICODE версию без изменения приложения необхо- димо: 1. включить в приложение файл tchar.h; 2. при определении символов и строк использовать типы TCHAR, LPTSTR и LPCTSTR; 3. при определении символьных или строковых литералов исполь- зовать макрос _TEXT (или просто _T); 4. необходимо помнить, что sizeof(szBuffer) – размер буфера в бай- тах, а sizeof(szBuffer)/sizeof(TCHAR) – размер буфера в симво- лах. Типы данных TCHAR, LPTSTR и LPCTSTR определены следую- щим образом: typedef unsigned short wchar_t; typedef wchar_t WCHAR; #define UNICODE typedef WCHAR TCHAR; //UNICODE кодировка #else typedef char TCHAR; //ANSI кодировка #endif 5 typedef WCHAR* LPWSTR; typedef CHAR* LPSTR; #define UNICODE typedef LPWSTR LPTSTR; //UNICODE кодировка #else typedef LPSTR LPTSTR; //ANSI кодировка #endif typedef CONST WCHAR* LPCWSTR; #define UNICODE typedef LPCWSTR LPCTSTR; //UNICODE кодировка #else typedef LPCSTR LPCTSTR; //ANSI кодировка #endif Почти все функции, получающие в качестве аргумента адрес строки, имеют ANSI и UNICODE версии, например, прототип функ- ции lstrcat конкатенации символьных строк имеет вид: LPTSTR lstrcat ( LPTSTR lpString1, LPTSTR lpString2 ); Функции Win32 также имеют ANSI и UNICODE версии, на- пример, функция DispatchMessage(): # ifdef UNICODE #define DispatchMessage DispatchMessageW #else #define DispatchMessage DispatchMessageA #endif Приложения, приведенные как примеры в пособии, могут компи- лироваться без изменения исходного текста в ANSI версии или в UNICODE версии, и протестированы на компьютере с операционной сис- темой Microsoft Windows XP Professional в среде Microsoft Visual Studio 2005. 1. ОБЩАЯ СТРУКТУРА ПРИЛОЖЕНИЯ WINDOWS Windows накладывает жесткие ограничения на структуру приложе- ния, которое, как правило, содержит минимум две принципиально важ- ные функции: главную WinMain() и функцию окна WndPoc(). 1.1. Главная функция WinMain() Функция WinMain() должна быть в каждом приложении. Ее прото- тип описан в файле winbase.h следующим образом: int WINAPI WinMain( HINSTANCE hInstance, //дескриптор экземпляра //приложения HINSTANCE hPrevInstance, //дескриптор предыдущего //экземпляра приложения LPSTR lpszCmdLine, //указатель на параметры //командной строки int nCmdShow //константа, характеризующая 6 //начальный вид окна ); Спецификатор WINAPI определяет соглашение о вызове, т.е. при- нятый в Win32 порядок передачи параметров при вызове функций. Па- раметры передаются через стек, справа налево, т.е. первый параметр по- мещается в стек последним, а очистку стека осуществляет вызываемая процедура. Вызывая функцию WinMain(), Windows передает ей четыре пара- метра (аргумента). Первый параметр hInstance типа HINSTANCE представляет со- бой дескриптор данного экземпляра приложения. Он назначается прило- жению при его запуске системой Windows и служит для его идентифика- ции. Многие функции Win32 API используют этот дескриптор в качест- ве одного из параметров. Если значение дескриптора (hInstance) ис- пользуется в другой функции, т.е. не в главной, то получить значение hInstance можно следующими способами: • объявить глобальную переменную HINSTANCE hInst; • значение дескриптора определить при помощи функции GetClassLong(), например: hInst=(HINSTANCE)GetClassLong(hWnd,GCL_HMODULE); • значение дескриптора определить при помощи функции GetModuleHandle() следующим образом: hInst= GetModuleHandle(NULL);. Второй параметр − hPrevInstance − всегда равен нулю и не имеет смысла. Третий параметр − lpszCmdLine − представляет собой указатель на строку, содержащую параметры командной строки запуска приложе- ния, если они при запуске были указаны. Четвертый параметр − nCmdShow − характеризует режим запуска. Внутренние, действующие в программе имена для параметров функции WinMain(), как и для любой другой, можно выбирать по сво- ему усмотрению. В типичном приложении Windows главная функция WinMain() должна выполнить как минимум три процедуры: 1) зарегистрировать в системе класс главного окна приложения; ес- ли при этом необходимо вывести на экран внутренние порожденные ок- на, то их классы также следует зарегистрировать (Windows выводит на экран и обслуживает только зарегистрированные ок- на); 2) создать главное и порожденные окна и показать их на экране (порожденные окна можно создать и позже и необязательно в главной функции); 3) организовать главный цикл обработки сообщений, поступающих в приложение. 7 1.2. Класс окна и его характеристики Оконный класс (window class), или класс окна, – это структура типа WNDCLASSEX, определяющая основные характеристики окна. На базе од- ного и того же класса можно создать несколько окон, например с разны- ми именами заголовков, и, следовательно, использовать одну и ту же оконную функцию. Для главного окна приложения обычно создается соб- ственный класс окна, учитывающий индивидуальные требования к про- грамме. Регистрация класса окна заключается в заполнении структурной переменной типа WNDCLASSEX и вызове функции RegisterClassEx(), аргументом которой служит адрес этой пере- менной. Структура определена в файле winuser.h: typedef struct tagWNDCLASSEX { UINT cbSize; //размер структуры в байтах UINT style; //стиль класса окна WNDPROC lpfnWndProc; //указатель на функцию окна int cbClsExtra; //дополнительная память в байтах //для класса окна int cbWndExtra; //дополнительная память в байтах //для каждого окна этого класса HINSTANCE hInstance; //дескриптор экземпляра //приложения HICON hIcon; //дескриптор пиктограммы приложения HCURSOR hCursor; //дескриптор курсора приложения HBRUSH hbrBackground; //дескриптор кисти для //закраски фона окна LPCTSTR lpszMenuName; //указатель на строку //с именем меню окна LPCTSTR lpszClassName; //указатель на строку //с именем класса окна HICON hIconSm; //дескриптор малой пиктограммы } WNDCLASSEX; Все элементы в структуре WNDCLASSEX представляют собой 32- разрядные значения. В большинстве случаев нет необходимости определять все члены этой структуры. При заполнении переменной типа WNDCLASSEX необ- ходимо обеспечить нулевое значение тем элементам структуры, которым не присваиваются конкретные значения. Нулевое значение означает для Windows, что характеристики этого элемента должны устанавливаться по умолчанию. Это правило характерно и для других структур, например OPENFILENAME, служащей для вывода на экран стандартного диалога «Открытие файла», или LOGFONT, позволяющей создать шрифт требуе- мого начертания. Предварительное обнуление всей структурной переменной перед ее инициализацией можно осуществить с помощью функций memset()или ZeroMemory() , которые имеют следующие прототипы: VOID ZeroMemory( PVOID pBuffer, //указатель на блок памяти, который //заполняется нулями 8 SIZE_T length //размер в байтах блока памяти ); void *memset( void *dest, int c, size_t count ); Например: memset(&wc, 0, sizeof(wc)); После обнуления следует присвоить значения только тем элемен- там структуры WNDCLASSEX, которые определяют конкретные свойства класса. Значение первого поля cbSize структуры WNDCLASSEX должно быть равно ее размеру в байтах. Это поле служит для обеспечения со- вместимости в случае будущих изменений. Второе поле style структуры WNDCLASSEX представляет собой целое число (32 бита). Каждый разряд числа закреплен за той или иной характеристикой окна (или окон). При этом каждому биту числа соответ- ствует своя символическая константа. В заголовочных файлах Windows такие идентификаторы начинаются с префикса CS_. Например: • CS_DBLCLKS – установлен третий бит (0x00000008), что по- зволяет программе реагировать на двойные щелчки мышью в области окна; • CS_VREDRAW – установлен нулевой бит (0x00000001), что за- ставляет перерисовывать окно заново при каждом изменении его размера по вертикали; • CS_HREDRAW – установлен первый бит (0x00000002), что за- ставляет перерисовывать окно заново при каждом изменении его размера по горизонтали; • CS_NOCLOSE – установлен девятый бит (0x00000200), что за- прещает закрытие окна пользователем. Объединение констант операцией «побитовое ИЛИ» языка C++ по- зволяет набрать требуемый комплект свойств (style). Наиболее важными для функционирования программы являются следующие поля структуры WNDCLASSEX: • lpfnWndProc – адрес оконной процедуры (третье поле); • hInstance – дескриптор данного приложения (шестое поле); • lpszClassName – указатель на строку с именем класса (11-е поле). С помощью структурной переменной типа WNDCLASSEX (параметр lpfnWndProc) операционная система определяет адрес оконной функ- ции, которую она должна вызвать при поступлении в окно сообщений. Седьмое поле структуры − hIcon − содержит дескриптор пикто- граммы. Пиктограмма – это маленькая битовая картинка, которая хранит- ся в файле ресурсов приложения. Пиктограммы могут иметь следующие размеры: • 16x16 пикселей – малые пиктограммы, обычно 16-цветные; • 32x32 пикселя – стандартные пиктограммы, обычно 16-цветные; • 48x48 пикселей – могут использовать 256 цветов. 9 Для получения дескриптора пиктограммы вызывают функцию HICON LoadIcon( HINSTANCE hInst, //дескриптор экземпляра //приложения LPCTSTR lpszIcon //указатель на строку, //которая содержит имя ресурса // пиктограмм ); Эта функция загружает ресурс пиктограммы из выполняемого фай- ла (.exe) – экземпляра приложения (hInst), например: wc.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_APPICON)); Второй параметр − lpszIcon, определяющий имя ресурса, – стро- ка с завершающим нулевым символом. В файле описания ресурсов, под- готовленном с помощью редактора ресурсов, имя ресурса для пиктограм- мы представляет собой целочисленный идентификатор. Для преобразова- ния целого числа в указатель на строку ресурса используют макрос MAKEINTRESOURCE, который определен в файле winuser.h следующим образом: #define MAKEINTRESOURCE(i) \ ( LPSTR ) (( DWORD )(( WORD )(i))) Макрос преобразует число в указатель, при этом старшие 16 разря- дов устанавливаются в нулевое значение. Для загрузки предопределенных пиктограмм параметр hInst функции LoadIcon() должен иметь значение NULL. В этом случае вто- рой аргумент функции содержит константу, идентификатор которой на- чинается с префикса IDI_ (ID for icon), например: wc.hIcon = LoadIcon(hInst, IDI_APLICATION); Предопределенные идентификаторы пиктограмм см. в MSDN. Воз- вращаемое значение при успешном завершении функции LoadIcon() – дескриптор пиктограммы, а в случае неудачи – NULL. Необходимо отметить, что функция LoadIcon() предназначена только для загрузки стандартных пиктограмм, т.е. загрузить с ее помо- щью пиктограмму размером 16x16 невозможно. Для загрузки пиктограмм произвольных размеров, курсоров или битовых изображений использует- ся функция LoadImage(), которая имеет следующий прототип: HANDLE LoadImage( HINSTANCE hInst, //дескриптор экземпляра //приложения LPCTSTR lpszName, //указатель на строку, которая //содержит имя изображения, //подлежащее загрузке UINT uType, //тип загружаемого изображения int cxDesired, //желаемая ширина изображения //в пикселях int cyDesired, //желаемая высота изображения //в пикселях UINT fuLoad //способ загрузки изображения ); Второй параметр − lpszName функции определяет загружаемое изображение. Но если первый параметр hInst равен NULL, а последний параметр fuLoad содержит флаг LR_LOADFROMFILE, то параметр 10 lpszName задает имя файла, в котором хранится изображение загружае- мого ресурса. Третий параметр − uType − определяет тип изображения и может принимать следующие значения: IMAGE_BITMAP; IMAGE_CURSOR; IMAGE_ICON. Четвертый и пятый параметры − cxDesired, cyDesired − за- дают ширину и высоту изображения в пикселях. Если оба параметра рав- ны нулю, то функция использует фактическую ширину и высоту изобра- жения. Шестой параметр − fuLoad − указывает опции загрузки, который может содержать один или несколько следующих флагов: • LR_DEFAULTCOLOR – флаг по умолчанию, для отображения ис- пользуется текущий цветовой формат (или нуль); • LR_DEFAULTSIZE – если значения параметров cxDesired и cyDe- sired равны нулю, то при загрузке изображения используются раз- меры по умолчанию; • LR_LOADTRANSPARENT – загрузка в «прозрачном» режиме (цвет окна по умолчанию – COLOR_WINDOW); • LR_LOADFROMFILE – функция загружает изображение из файла. Загрузку маленькой пиктограммы размером 16x16 пикселей можно осуществить следующим образом: wc.hIcon = (HICON)LoadImage( Inst, MAKEINTRESOURCE(IDI_APPICON_SM), IMAGE_ICON,16, 16,0); Загрузка битового изображения из файла: HBITMAP hBitmap (HBITMAP)LoadImage(hInst, FILE_NAME, IMAGE_BITMAP, 100, 100, LR_LOADFROMFILE); Восьмое поле hCursor структуры WNDCLASSEX содержит деск- риптор курсора мыши. Курсор относится к ресурсам Windows − это бито- вое изображение размером 32x32 пикселя. Загрузка ресурса курсора про- изводится функцией LoadCursor(), которая имеет следующий прото- тип: HCURSOR LoadCursor( HINSTANCE hInst, //дескриптор экземпляра //приложения LPCTSTR lpszCursor //указатель на строку, ); //содержащую имя ресурса курсора Функция загружает ресурс курсора, заданный вторым параметром lpszCursor из экземпляра приложения, заданного первым параметром hInst. При загрузке одного из системных (встроенных) курсоров необхо- димо первому параметру передать значение NULL, а второй должен со- держать константу, идентификатор которой начинается с префикса IDC_. 11 Очевидно, что для главного окна приложения целесообразно выбирать стандартный курсор IDC_ARROW. Например, загрузку курсора, исполь- зуемого по умолчанию, можно выполнить следующим образом: wc.hCursor = LoadCursor(NULL, IDC_ARROW); Встроенные курсоры и их символические имена: IDC_ARROW – стандартная стрелка; IDC_CROSS – перекрестие; IDC_SIZEALL – четырехконечная стрелка; IDC_SIZENS – двухконечная стрелка (север–юг); IDC_IBEAM – текстовый двутавр; IDC_WAIT – песочные часы. Для динамического изменения формы курсора в зависимости от его местонахождения применяется функция SetCursor(), которая имеет следующий прототип: HCURSOR SetCursor(HCURSOR hCursor); Функция SetCursor делает текущим курсор, который передается ей в качестве параметра, и при этом возвращается дескриптор предшест- вующего курсора. Положение курсора отслеживается при обработке сообщения WM_MOUSMOVE. Позиция курсора определяется относительно левого верхнего угла клиентской области. Например, для изменения формы курсора в верхней и нижней об- ластях окна необходимо обработать сообщения WM_CREATE, WM_SIZE и WM_MOUSMOVE следующим образом (переменные hCursor1, hCursor2, wClient, hClient, xPos и yPos должны быть объяв- лены в оконной процедуре с модификатором static): Case WM_CREATE: //… hCursor1 = LoadCursor(NULL,IDC_SIZEALL); hCursor2 = LoadCursor(NULL, IDC_WAIT); //… case WM_SIZE: //определяем размеры клиентской области окна wClient = LOWORD(lParam); hClient = HIWORD(lParam); break; case WM_MOUSMOVE: //определяем координаты курсора xPos = LOWORD(lParam); yPos = HIWORD(lParam); if(yPos < 32) //изменяем форму курсора SetCursor(hCursor1); if(yPos > hClient – 32) //изменяем форму курсора SetCursor(hCursor2); break; //… Цвет фона окна определяется дескриптором кисти, записанным в поле hbrBackground структуры WNDCLASSEX. 12 Кисть (brush) – это графический объект, который представляет собой шаблон пикселей различных цветов. Для описания графических объектов, таких как перо, кисть, растро- вое изображение, палитра, шрифт или регион, в Windows используется обобщенный тип HGDIOBJ. Функция GetStockObject() возвращает такой обобщенный дескриптор объекта и имеет следующий прототип: HGDIOBJ GetStockObject(int nObjectTyp); Поэтому при использовании функции GetStockObject() необ- ходимо явное преобразование типа (HPEN,HBRUSH, HBITMAP, HPALETTE, HFONT, HRGN). Например, загрузка встроенной белой кис- ти может быть осуществлена следующим образом: ws.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH). В файле windowsx.h включены макросы GetStockBrush, GetStockPen и GetStockFont, выполняющие такое преобразование типа, например: #define GetStoсkBrush(i)(HBRUSH)GetStockObject(i)) Эти макросы можно использовать вместо функции GetStockObject() следующим образом: ws.hbrBackground = GetStockBrush(WHITE_BRUSH); В Windows имеется несколько встроенных (предопределенных) кистей: WHITE_BRUSH – белый цвет; DKGRAY_BRUSH – темно-серый цвет; LTGRAY_BRUSH – светло-серый цвет; GRAY_BRUSH – серый цвет; BLACK_BRUSH – черный цвет; NULL_BRUSH – прозрачный. Создание кисти произвольного цвета осуществляется вызовом функ- ции CreateSolidBrush(), которая имеет следующий прототип: HBRUSH CreateSolidBrush(COLORREF crColor); Аргумент crColor – значение RGB для цвета кисти. Цвет задается в виде трех целых чисел, характеризующих интенсивность красной, зеле- ной и синей составляющих цвета. Для упаковки этих трех чисел в двой- ное слово (4 байта) служит макрос RGB, например: ws.hbrBackground= CreateSolidBrush(RGB(0,255,255)); Регистрация класса окна производится вызовом функции Regis- terClassEx(), которая имеет следующий прототип: ATOM RegisterClassEx(CONST WNDCLASSEX* lpwc); Аргумент функции lpwс – адрес структурной переменной типа WNDCLASSEX. Функция RegisterClassEx() возвращает атомарное значение ATOM (WORD – 16 бит), которое является уникальным идентификатором зарегистрированного класса. Модификация характеристик оконного класса производится всегда только при обработке сообщения WM_CREATE функцией 13 SetClassLong() или SetWindowLong(), которые имеют следую- щие прототипы: DWORD SetClassLong( HWND hWnd, //дескриптор окна int nIndex, //индекс значения, которое //необходимо изменить LONG dwNewLong //новое значение ); LONG SetWindowLong( HWND hWnd, //дескриптор окна int nIndex, //индекс значения, которое //необходимо изменить LONG dwNewLong //новое значение ); Параметр nIndex функции SetClassLong() может принимать следующие значения: • GCL_HBRBACKGROUND – изменить дескриптор кисти цвета фо- на; • GCL_HCURSOR – изменить дескриптор курсора; • GCL_HICON – изменить дескриптор пиктограммы; • GCL – HICONSM – изменить дескриптор малой пиктограммы; • GCL_MENUNAME – изменить адрес ресурса меню; • GCL_STYLE – изменить стиль класса окна; • GCL_WNDPROC –изменить адрес оконной процедуры, связанной с окном. Например, для изменения дескриптора кисти цвета фона необходи- мо ввести следующие строки: Case WM_CREATE: SeClassLong(hWnd,GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(0,250,250))); return TRUE; //… |