Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ООП / Заочники / ООП_ЛабРаб_Методичка

.pdf
Скачиваний:
30
Добавлен:
08.06.2015
Размер:
770.97 Кб
Скачать

3.13.Разработайте процедуру обработки события OnClick для кнопки сортировки объектов в списке. Используйте обработчик события OnCompare и метод

AlphaSort компонента TListView.

4.Содержание отчета

Отчет готовится один на бригаду в рукописном или печатном виде и должен содержать следующие разделы:

-задание;

-листинг программы с подробными комментариями;

-копию экранной формы с реальным списком объектов заданной предметной области.

5.Контрольные вопросы

5.1.Как выполняется перегрузка статических методов?

5.2.Как выполняется перегрузка виртуальных методов?

5.2.Чем отличаются виртуальные и динамические методы?

5.3.Что такое полиморфизм раннего связывания?

5.4.Что такое полиморфизм позднего связывания?

5.5.Какие методы называются абстрактными?

5.6.Для чего предназначены абстрактные классы, их основые особенности?

5.7.Каковы достоинства и недостатки полиморфизма позднего связывания?

Лабораторная работа № 6

События, сообщения, обработчики событий и сообщений

Цель работы: освоение на практике правил создания событий и обработчиков событий и

сообщений и использование механизма событийного управления в приложениях в языке

Object Pascal.

1. Задание

Пользуясь средствами Borland Delphi, разработать Windows-приложение c графическим интерфейсом пользователя (окно Windows) для демонстрации следующих возможностей:

-управление с помощью сообщений из приложения другим приложением Windows (Calc.exe или Notepad.exe) - запуск, изменение положения и размеров, изменение активности, закрытие;

-обмен сообщениями между двумя своими приложениями (разработать дополнительное приложение);

-использование собственных сообщений и обработчиков сообщений;

-использование собственных обработчиков событий;

-изменение реакции приложения на события в ходе работы программы.

2.Краткая теория

События

Событие это специальное свойство, являющееся указателем функции. Тип обобщенного указателя на функцию, которой передается один параметр типа TObject (обычно Self — данный объект), — TNotifyEvent. Подобный тип используется в Delphi для событий типа OnClick и многих других, которые передают в обработчик только один параметр Sender: TObject. Если требуется ввести в класс подобное событие, достаточно определить в объявлении класса соответствующее поле и метод работы с ним. Например:

private

FMyEvent:TNotifyEvent; published

property OnMyEvent:TNotifyEvent read FMyEvent write FMyEvent;

Остается только вызвать в нужный момент обработчик событий пользователя, если пользователь его предусмотрел. Проверка, имеется ли обработчик пользователя,

осуществляется функцией assigned, которая возвращает true, если пользователь предусмотрел свой обработчик. Значит, при возникновении события надо проверять, имеется ли обработчик пользователя, и, если имеется, то вызвать его. Для этого можно использовать оператор вида:

if assigned(FMyEvent) then OnMyEvent(Self);

Место, куда надо включать подобный оператор, зависит от вида события. Если событие вызывается каким-то из ваших методов, то вызов обработчика пользователя надо осуществлять из этого метода. Если событие связано с какими-то сообщениями,

поступающими от других приложений или от Windows, то надо предусмотреть обработчик соответствующего сообщения и из него вызывать обработчик пользователя.

Если в обработчик события надо передать какие-то параметры помимо Self, то тип функции TNotifyEvent уже не подходит и надо объявить свой собственный тип. Это объявление должно предшествовать объявлению класса. Например:

type

TMyEvent = procedure(Sender:TObject; var CanEvent:boolean) of object; Т = class(TObject)

private

FMyEvent: TMyEvent; published

property MyEvent: TMyEvent read FmyEvent write FMyEvent;

end;

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

Обработка сообщений в приложениях Delphi

Приложения Windows состоят из множества объектов, которые взаимодействуют друг с другом, обмениваясь сообщениями (messages). Источниками этих сообщений могут быть: пользователь, оперирующий с клавиатурой и мышью, среда Windows, посылающая сообщения приложениям, другие приложения, обменивающиеся информацией с вашим приложением и, наконец, ваше приложение, посылающее сообщения компонентам.

Большинство сообщений, которые вам могут потребоваться, Delphi обрабатывает сама, так что вам достаточно использовать обработчики стандартных событий компонентов. Но иногда вам может потребоваться самому обрабатывать сообщения Windows. Такая необходимость возникает, если нужное вам сообщение пока еще компонентами Delphi не обрабатывается, или если вы определили свое собственное сообщение.

Сообщение Windows представляет собой структуру, содержащую поля. Наиболее важное из них содержит целое значение, идентифицирующее данное сообщение. В модуле Messages.pas в Delphi содержатся объявления множества идентификаторов, позволяющие оперировать с мнемоническими именами сообщений, а не с какими-то целыми значениями. Важная информация о сообщении содержится также в двух полях параметров и в поле результата. Параметры имеют имена wParam и lParam, что существенно упрощает работу с ними.

Последовательность обработки сообщений Windows следующая. При создании объекта оконного компонента-потомка TWinControl он регистрируется в Windows и получает уникальный идентификатор - дескриптор (handle). Вы можете получить к нему доступ через свойство Handle (только для чтения). При регистрации окно передает Windows указатель на процедуру, которая будет вызываться при получении им сообщений от Windows. Это метод MainWndProc. Его назначение - вызов метода обработки

сообщений через свойство WindowProc. По умолчанию в этом свойстве хранится процедура WndProc, но пользователь может изменить ее на свою во время выполнения приложения. Метод WndProc содержит оператор case, анализирующий идентификатор сообщения и производящий соответствующие действия. В итоге все сообщения

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

Таким образом, обработка сообщения Windows происходит по цепочке:

Событие->MainWndProc->WndProc->Dispatch->обработчик события

Для сообщений, обрабатываемых компонентами Delphi, вам достаточно написать свой обработчик события. Для сообщений, не предусмотренных в Delphi, вам надо вмешаться в эту цепочку раньше, перегрузив метод WndProc.

Если объект не имеет дескриптора, то цепочка остается той же, только сообщение получает оконный компонент, вмещающий данный объект (например, форма).

В Windows предусмотрено множество сообщений. Описание некоторых из них приводится далее.

Посылка сообщений

В Windows API определен ряд функций, позволяющих послать сообщение. Это

прежде всего функция SendMessage, которая посылает указанное в ней сообщение окну или множеству окон и не возвращается, пока это сообщение обрабатывается. Этим она отличается от похожей на нее функции PostMessage, которая возвращается сразу после передачи сообщения.

Объявление функции SendMessage:

function SendMessage(hWnd: HWnd; Msg, wParam: word; lParam:LongInt): LongInt;

Параметр hWnd - дескриптор окна, которому передается сообщение. Параметр Msg определяет передаваемое сообщение. Параметры wParam и lParam могут содержать дополнительную информацию.

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

Во всех оконных компонентах предусмотрены обработчики сообщений Windows по умолчанию. Однако, вы можете определить и свои собственные обработчики, заменив ими обработчики по умолчанию, или дополнив их. Объявление своего обработчика помещается в описание класса оконного компонента, как правило, в раздел private. Синтаксис объявления:

procedure <имя>(var <параметр>: <тип параметра>) ; message <сообщение>;

Здесь <имя> обозначает имя процедуры обработки сообщения. Имя может быть любым, но обычно принято делать его тождественным имени обрабатываемого сообщения, исключив из него символ подчеркивания. Передаваемый в обработчик параметр также может иметь любое имя. Этот параметр представляет собой запись, через которую в обработчик передаются параметры сообщения, а из обработчика возвращается значение поля Result, фиксирующее результат обработки. <тип параметра> - это тип структуры параметров сообщения. Практически всегда имя этого типа тождественно

имени обрабатываемого сообщения с исключенным из него символ подчеркивания и добавленным префиксом Т. После ключевого слова message записывается тип сообщения.

Определение собственных сообщений

Вы можете описать свои собственные сообщения и работать с ними так же, как с предопределенными. Номера своих собственных сообщений вы должны отсчитывать от константы WM_USER, которая соответствует первому номеру сообщения пользователя.

Например, вы можете определить в своем приложении константы

const WM_MyMessl = WM_USER; WM_MyMess2 = WM_USER+1;

и затем оперировать с сообщениями WM_MyMessl и WM_MyMess2 как с предопределенными в Windows.

Сообщения, функции, константы и типы API Windows

В данном разделе приводятся некоторые дополнительные справочные сведения о функциях API Windows, упоминаемых при рассмотрении работы с сообщениями, и список некоторых часто используемых сообщений Windows.

WinExec – функция

Запускает указанное приложение.

Объявление

function WinExec(CmdLine:PChar; CmdShow : integer) : integer;

Описание

Параметр CmdLine является указателем на строку с нулевым символом в конце, содержащую имя выполняемого файла и, если необходимо, параметры командной строки. Параметр CmdShow определяет форму представления окна запускаемого приложения. Некоторые значения:

SW_HIDE – невидимое окно; SW_MINIMIZE – свертывает окно; SW_MAXIMIZE – развертывает окно;

SW_RESTORE, SW_SHOWNORMAL - активизирует и отображает окно в первоначальной позиции с первоначальными размерами;

SW_SHOW – активизирует и отображает окно в текущей позиции с текущими размерами.

Пример

WinExec('Calc',SW_RESTORE) ;

Этот оператор загружает с помощью функции WinExec программу «Калькулятор».

SendMessage – функция

Функция посылает указанное в ней сообщение окну или множеству окон и не возвращается, пока это сообщение обрабатывается.

Объявление

function SendMessage(hWnd: HWnd; Msg, wParam: word; lParam:LongInt): LongInt;

Параметры

Параметр hWnd - дескриптор окна, которому передается сообщение. Если этот параметр равен HWND_BROADCAST, то сообщение передается всем окнам верхнего

уровня в системе, включая недоступные, невидимые, перекрытые другими и всплывающие, за исключением дочерних окон. Широковещательными сообщениями (HWND_BROADCAST) нужно пользоваться очень осторожно, так как сообщение будет обработано ВСЕМИ окнами Windows, что может привести к нарушению работы системы.

Параметр Msg определяет передаваемое сообщение. Параметры wParam и lParam могут содержать дополнительную информацию.

Возвращаемое значение

Значение, возвращаемое функцией, зависит от вида сообщения.

Описание

Функция SendMessage посылает указанное в ней сообщение окну или всем окнам верхнего уровня в системе, включая недоступные и невидимые, кроме дочерних. Функция не возвращается, пока это сообщение обрабатывается. Таким образом, приложение, пославшее сообщение, блокируется на время его обработки. Этим функция SendMessage отличается от функции РоstMessage, которая возвращается сразу после передачи сообщения.

Приложения, использующие hWnd = HWND_BROADCAST для связи между

окнами разных приложений должны предварительно зарегистрировать уникальность своих сообщений функцией RegisterWindowMessage.

RegisterWindowMessage - функция

Функция определяет новое оконное сообщения с гарантированной уникальностью его в системе, которое может использоваться в функциях SendMessage и PostMessage.

Объявление

UINT RegisterWindowMessage(LPCTSTR lpString);

Параметры

lpString - указатель на строку с нулевым символом, содержащую регистрируемое сообщение.

Возвращаемое значение

Если регистрация прошла успешно, то возвращается идентификатор сообщения в диапазоне от 0xC000 до 0xFFFF. Если регистрация завершилась аварийно, то возвращается нулевое значение.

Описание

Функция используется для регистрации сообщений, предназначенных для связи между различными совместно работающими приложениями. Если два приложения регистрируют одну и ту же строку сообщения, то им возвращается одинаковый номер этого сообщения. Регистрация действительна до конца сеанса работы Windows.

Функцию RegisterWindowMessage следует использовать только в случаях, когда несколько приложений должны обрабатывать одно и то же сообщение. Для посылки

собственных сообщений внутри данного класса оконных компонентов следует использовать любое целое в диапазоне от WM_USER до 0x7FFF.

WM_USER – константа

Константа используется приложениями для определения своих частных сообщений

Описание

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

от 0 до WM_USER - 1 Номера сообщений, используемые Windows

 

 

 

 

от

WM_USER

до

Номера частных сообщений внутри данного класса оконных

0x7FFF

 

компонентов

от 0x8000 до 0xBFFF

 

Номера, зарезервированные для будущего использования в

 

 

 

Windows

от 0xC000 до 0xFFFF

 

Номера, соответствующие строкам сообщений, используемым

 

 

 

для обмена между приложениями и зарегистрированным

 

 

 

функцией RegisterWindowMessage

свыше 0xFFFF

 

Номера, зарезервированные для будущего использования в

 

 

 

Windows

Номера второго диапазона от WM_USER до 0x7FFF могут использоваться для определения и посылки сообщений внутри данного класса оконных компонентов. Их нельзя использовать для определения сообщений, предназначенных для обмена между приложениями, поскольку некоторые предопределенные классы оконных компонентов (например, TButton, TEdit, TListBox и TComboBox) уже используют этот диапазон. Сообщения другим приложениям в этом диапазоне могут посылаться только в случае,

если приложения спроектированы с учетом обмена данными сообщениями и одинаково понимают номера этих сообщений.

Если вы посылаете сообщение в диапазоне ниже WM_USER асинхронными функциями PostMessage, SendNotifyMessage или SendMessageCallback, надо быть уверенным, что параметры сообщения не включают указателей. В противном случае из-за немедленного возврата функции может оказаться, что к моменту, когда поток начнет обрабатывать сообщение, приложение, которое его послало, окажется уже удаленным из памяти.

Сообщение WM_ACTIVATE

Сообщение посылается, когда окно переводится в активное или неактивное состояние. Сначала посылается окну, переходящему в неактивное состояние, а потом - активируемому.

Определение

WM_ACTIVATE

fActive = LOWORD(wParam); fMinimized = (BOOL) HIWORD(wParam); hwndPrevious = (HWND) lParam;

Параметры

fActive показывает, как активируется или деактивируется окно. Возможные значения:

WA_ACTIVE

активируется не щелчком мыши (например,функцией

 

SetActiveWindow или клавиатурой)

WA_CLICКACTIVE

активируется щелчком мыши

WA_INACTIVE

декативируется

fMinimized ненулевое значение показывает, что окно минимизировано. hwndPrevious дескриптор, который указывает на окно, из которого фокус

переключился на данное окно, если оно активируется, или на окно, в которое передается управление, если данное окно деактивируется.

Возвращаемое значение

Если приложение обрабатывает это сообщение, оно должно возвращать нуль.

Действие по умолчанию

Если активируемое окно не свернуто, то оно получает фокус.

Примечание

Если окно активируется щелчком мыши, оно получает также сообщение

WM_MOUSEACTIVATE.

Сообщение WM_CLOSE

Сигнализирует, что окно или приложение закрывается.

Определение

WM_CLOSE

Возвращаемое значение

Если приложение обрабатывает это сообщение, оно должно возвращать нуль, т.е. поле Result нужно присвоить 0.

Действие по умолчанию

Вызывается функция DestroyWindow, уничтожающая окно.

Примечания

Приложение при обработке этого сообщения может запросить пользователя о необходимости закрывать окно и вызвать функцию DestroyWindow только при положительном ответе.

Сообщение WM_GETMINMAXINFO

Посылается перед изменением размеров или положения окна. Обработчик

сообщения может использоваться для ограничения допустимых размеров и координат положения на экране.

Определение

WM_GETMINMAXINFO

lpmmi = (LPMINMAXINFO) lParam;

Параметры

Параметр lpmmi указывает на структуру типа MINMAXINFO, содержащую принятые по умолчанию пределы изменения размеров и координат положения окна.

Поля структуры означают следующее:

ptReserved

Зарезервировано и пока не используется

ptMaxSize

Поле типа Point определяет ширину (Point.х) и высоту (Point.у)

 

развернутого окна

ptMaxPosition

Поле типа Point определяет положения левого (Point.х) и верхнего

 

(Point.y) краев развернутого окна

ptMinTrackSize

Поле типа Point определяет минимальную ширину (Point.х) и

 

минимальную высоту (Point.y) окна при изменении пользователем

 

размеров его рамки

ptMaxTrackSize

Поле типа Point определяет максимальную ширину (Point.х) и

 

максимальную высоту (Point.y) окна при изменении пользователем

 

размеров его рамки

Возвращаемое значение

Если приложение обрабатывает это сообщение, оно должно вернуть 0.

Сообщение WM_GETTEXT

Посылается, чтобы скопировать текст, связанный с окном, в указанный буфер.

Определение

WM_GETTEXT

wParam = (WPARAM) cchTextMax; lParam = (LPARAM) lpszText;

Параметры

cchTextMax указывает минимальное число символов, которые должны быть скопированы, включая нулевой конечный символ.

lpszText указывает на буфер, принимающий текст.

Возвращаемое значение

Возвращает число скопированных символов.

Действие по умолчанию

Копируется текст, связанный с окном, в указанный буфер и возвращается число скопированных символов.

Примечания

Для всех окон редактирования текст - это содержимое окна. Для выпадающих списков текст - это выделенный текст. Для кнопок текст - это имя кнопки. Для остальных оконных компонентов текст - это заголовок окна.

Для копирования обогащенного текста, превышающего 64К, надо использовать

сообщения EM_STREAMOUT или EM_GET-SELTEXT.

Сообщение WM_SETTEXT

Посылается, чтобы задать текст указанного окна.

Определение

WM_SETTEXT

wParam = 0; // не исцользуется, должен равняться 0. lParam = (LPARAM)(LPCTSTR) lpsz;

Параметры

lpsz указатель на строку текста окна с нулевым конечным символом.

Возвращаемое значение

Возвращает true, если текст установлен. В противном случае возвращает false (для окна редактирования), LB_ERRSPACE (для списка) или CB_ERRSPACE (для выпадающего списка) если не хватает места для размещения текста. Возвращает CB_ERR, если сообщение посылается выпадающему списку без окна редактирования.

Действие по умолчанию

Устанавливает и отображает текст окна.

Примечания

Для всех окон редактирования текст - это содержимое окна. Для выпадающих списков текст - это выделенный текст. Для кнопок текст - это имя кнопки. Для остальных оконных компонентов текст - это заголовок окна.

Сообщение не изменяет текущее выделение в списках. Чтобы выделялся элемент списка, соответствующий тексту, надо использовать сообщение CB_SELECTSTRING.

Функция FindWindow

Функция API Windows, возвращает дескриптор окна верхнего уровня, класс и имя которого указаны; функция не ищет дочерние окна.

Объявление

function FindWindow(lpClassName,lpWindowName:PChar) : HWnd;

Параметры

Параметр lpClassName указывает на строку с нулевым конечным символом, содержащую имя класса, или является атомом, указывающим на строку с именем класса. Если этот параметр атом, то это должен быть глобальный атом, созданный предварительно вызовом функции GlobalAddAtom. Атом является 16-битной величиной,

которая должна помещаться в младшие разряды слова lpClassName, а старшие разряды должны быть нулевыми.

Параметр lpWindowName указывает на строку с нулевым конечным символом, содержащую имя окна (это свойство Caption формы, отображаемое в строке заголовка окна). Если этот параметр равен null, то считается, что под критерий поиска подходит любое окно указанного класса.

Возвращаемое значение

Если поиск прошел успешно, то функция возвращает дескриптор окна, имеющего указанное имя класса и имя окна. В противном случае возвращается 0. Тогда расширенную информацию об ошибке можно получить, вызвав функцию GetLastError.

3. Методика выполнения

3.1.Создайте в Delphi новый проект и сохраните его в отдельном каталоге.

3.2.Разместите на форме две кнопки – «Калькулятор» и «Закрыть калькулятор». В обработчике щелчка первой кнопки напишите оператор WinExec('Calc',SW_RESTORE);. В

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

SendMessage(FindWindow('SciCalc','Калькулятор'),WM_CLOSE,0,0);. Откомпилируйте программу, запустите ее на выполнение.

3.3.Добавьте 2 кнопки, которые открывают и закрывают приложение «Блокнот» (имя приложения и класса – Notepad, имя окна – «Безымянный Блокнот»).

3.4.Добавьте в приложение возможность открывать и закрывать любое приложение. Имя запускаемого приложения задавать 2 способами с помощью окна TEdit и компонента TOpenDialog. Имя класса и окна закрывемого приложения задаваейте с помощью окна

TEdit.

3.5.Добавьте кнопку, при нажатии на которую закрываются все открытые копии указанного приложения.

3.6.Добавьте в приложение обработку сообщения WM_CLOSE. Пусть при получении этого сообщения Windows приложение попросит у пользователя подтверждения и только

при его положительном ответе закроется методом Close. Объявление обработчика сообщения поместите в раздел private объявления класса формы:

type

TForm1 = class(TForm)

private procedure WMClose(var a:TWMClose); message WM_CLOSE;

end;

Описание объявленной процедуры поместите в раздел реализации implementation модуля:

procedure TForm1.WMClose(var a:TWMClose); begin

if (Application.MessageBox('Меня хотят закрыть.Согласны?', 'Караул! Закрывают!', MB_YESNO +MB_ICONEXCLAMATION + MB_DEFBUTTON2) = IDYES) then Close; a.Result:=0;

end;