Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы по МП / API / Methods.doc
Скачиваний:
42
Добавлен:
11.05.2015
Размер:
233.47 Кб
Скачать

Глава 1

Взаимодействие приложений С++Builder с операционной системой

1.1 Обработка ошибок выполнения функций api Windows

При работе вашего приложения могут возникать всевозможные ошибки, связанные с неправильными исходными данными, ошибками пользователя, ограничениями системы и т.д. Имеется несколько механизмов обработки подобных ошибок. Ошибки выполнения операций и библиотечных функций С++ обычно обрабатываются с помощью механизма исключений. Работа е исключениями подробно рассмотрена в источниках, так что останавливаться на этом достаточно хорошо известном вопросе мы не будем. Не будем обсуждать и вопросы, связанные с управляющим словом FPU, которое определяет обработку ошибок выполнения операций с плавающей запятой. Эти вопросы также подробно рассмотрены в источниках. В данной книге в основном будут использоваться функцииAPIWindows. А в них принят несколько иной подход к фиксации и обработке ошибок.

Большинство функций APIWindowsвозвращают результат, который позволяет понять, произошла ли ошибка при выполнении функции. Это может быть булево значениеFalse, свидетельствующее об ошибке, значенияNULL.,0xFFFFFFFF, -1 и др. При этом система вырабатывает некоторый код ошибки в виде 32-разрядного числа.

Выполнив вызов какой-то функции APIWindowsи поняв по возвращенному результату, что произошла ошибка, код этой ошибки можно определить, вызвав функциюGetLastError. Она объявлена в файлеwinbase.hследующим образом:

DWORD GetLastError (VOID);

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

Вы можете и в своих собственных функциях использовать аналогичный механизм сообщений об ошибках. Это делается с помощью функции SetLastError:

VOID SetLastError (In DWORD dwERRCode);

Аргументом при вызове этой функции задается устанавливаемый вами код ошибки. Код должен содержать 1 в 29-ом бите. Этот бит указывает, что код задан приложением. Во всех системных кодах 29-ый бит равен 0. Так что установка его в 1 гарантирует, что ваш код не перекроется с каким-то системным кодом.

Список системных кодов ошибок дается в файле WINNT.Hэтот список кодов мало о чем говорит. ВC++Builderимеется функцииSysErrorMessage, которая позволяет получить текстовое объяснение ошибки, причем на русском языке. Функция объявлена в файлеSysUtils.hppследующим образом

AnsiString __fastcall SysErrorMessage (int ErrorCode);

Единственный параметр этой функции — код ошибки. А возвращаемое ею значение — это текстовое пояснение.

Вызовы функций GetLastErrorиSetLastErrorудобно объединить, введя в свою библиотеку, например, следующую функцию:

AnsiString ErrorCode (void)

{

Return SysErrorMessage (GetLastError);

}

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

ShowMessage (“Ошибка: ” + ErrorCode());

Можете проверить работу этой функции на простом примере. Перенесите на форму окно редактирования Editи кнопку, в обработчике щелчка на которой напишите код:

AnsiString S = Edit1->Text;

If (! DeleteFile (S))

ShowMessage (“Ошибка при удалении файла ‘“ + S + “’:\n” + ErrorCode ();

В этом коде вызывается функция APIWindowsDeleteFile, которая удаляет файл, имя которого передано в нее в качестве аргумента. Функция возвращаетfalse, если при ее выполнении произошла ошибка. В этом случае в приведенном коде вызывается функцияShowMessage, в которую передается сообщение об ошибке, возвращаемое нашей функциейErrorCode. Выполните приложение и посмотрите на его реакцию при различных текстах в окнеEdit1. Вы получите сообщения "Не удается найти указанный файл", "Синтаксическая ошибка в имени файла, имени папки или метке тома", "Отказано в доступе" и др. Как видите, очень простым оператором безо всяких проверок типаifилиswitchвы получили очень неплохую и разнообразную диагностику ошибок.

Иногда в приложений все-таки надо знать, о каких ошибках сообщает тот или иной код. Тогда в зависимости от значения кода можно с помощью операторов ifиswitchпредусмотреть те или иные действия. Приводить в данной книге полный перечень ошибок очень накладно: он займет более 70 страниц — целую главу. Но вы легко можете получить подобный перечень сами. Поместите на форму компонентMemoи кнопкуButton, в обработчик щелчка которой запищите код:

AnsiString S = Edit1->Text;

for (DWORD err=0; err < 600000; err++)

{

Buff = SysErrorMessage (err);

if (Buff != “”)

Memo1->Lines->Add (AnsiString (err) + “ ” + Buff);

}

Вы получите в окнеMemo1список всех ошибок в формате: код ошибки, пояснение. Можете сохранить его в текстовом документе и использовать, когда потребуется. Часть этого списка приведена ниже:

0Операция успешно завершена

1 Неверная функция

2 Не удается найти указанный файл

3 Системе не удается найти указанный путь

4 Системе не удается открыть файл

5 Отказано в доступе

6 Неверный дескриптор

7 Повреждены управляющие блоки памяти

8 Недостаточно памяти для обработки команды

Помимо функции SystemErrorMessage, введенной в С++Builder, имеется более мощная функция FormatMessage, объявленная в API Windows:

DWODR FormatMessage (DWORD ddwFlags, LPCVOID lpSource,

DWORD dwMessageId, DWORD dwLanguageId,

LPTSYR lpBuffer, DWORD nSize,

Va_list *Arguments);

Параметр dwFlagsявляетсямножеством флагов, определяющих параметры процесса форматирования. ПараметрdwMessageIdопределяет идентификатор требуемого сообщения, параметрdwLanguageIdзадает идентификатор языка выдаваемого сообщения. ПараметрыlpBuffer иnSizeопределяют буфер, в который будет помещено .сообщение, и его размер. ПараметрArgumentsявляется указателем на массив значений, которые используются для вставки в отформатированное сообщение. Честно говоря, я так и не смог придумать разумный пример, когда имело бы смысл использовать функциюFormatMessageвместо рассмотренной выше функцииSysErrorMessage. Так что не будем останавливаться на описании многочисленных параметров этой функции. Вы можете "посмотреть их во встроенной справке С++Builder. Ограничусь примером задавив этих параметров, который чаще всего используется на практике:

LPTSTR MsgBuf;

FormatMessage (FORMAT_MESSAGE_ALLCOTE_BUFFER |

FORMAT_MESSAGE_FORM_SYSTEM, NULL, GetLastError (),

0, (LPTSTR) & MsgBuf, 0, NULL);

Label1->Caption = MsgBuf;

В первом аргументе задан флаг FORMAT_MESSAGE_ALLCOTE_BUFFER, указывающий, что сообщение должно заноситься в буфер, и флагFORMAT_MESSAGE_FORM_SYSTEM, определяющий, что берутся системные сообщения. Функция может брать и другие виды сообщений из модулей, ресурсов и т.п., но на этой экзотике мы не будем останавливаться. В качестве индекса сообщенияdwMessageIdзадается значение, возвращающееся функциейGetLastError. ПеременнаяMsgBufуказывает на буфер, в который заносится сообщение. Остальные аргументы в вызове функции заданы нулевыми, что обеспечивает стандартный вид сообщения на языке, установленном по умолчанию. Как видите, даже упрощенный вариант использованияFormatMessageнамного более громоздкий, чем вызов функцииSysErrorMessage, при тех же результатах.

Соседние файлы в папке API