Функции обратного вызова
Функция обратного вызова — это программный код в управляемом приложении, который помогает неуправляемой функции DLL выполнить задачу. Вызовы функции обратного вызова косвенно, через функцию DLL, передаются из управляемого приложения и возвращаются в управляемую реализацию. Лишь некоторые из многих функций DLL, вызываемых в вызове неуправляемого кода, требуют для своего выполнения наличия в управляемом коде функции обратного вызова.
Для вызова большинства функций DLL из управляемого кода нужно создать управляемое определение функции и затем выполнить сам вызов. Этот процесс достаточно прост.
Применение функции DLL, требующей наличия функции обратного вызова, предполагает выполнение некоторых дополнительных шагов. Во-первых, необходимо определить, требуется ли для функции обратный вызов. Это можно выяснить в документации по функции. Далее нужно создать функцию обратного вызова в управляемом приложении. И, наконец, вы вызываете функцию DLL, передавая указатель на функцию обратного вызова в качестве аргумента.
На рисунке ниже показана функция обратного вызова и этапы ее реализации:
Функции обратного вызова — идеальное средство для многократного выполнения некоторой задачи. Другая область их применения — с функциями перечисления API Windows, такими как EnumFontFamilies, EnumPrinters и EnumWindows. Функция EnumWindows выполняет перечисление всех существующих на компьютере окон, используя функцию обратного вызова, чтобы выполнить задачу для каждого окна. Инструкции и примеры см. в разделе Практическое руководство. Реализация функций обратного вызова.
См. также
- Практическое руководство. Реализация функций обратного вызова
- Вызов функции DLL
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
The .NET documentation is open source. Provide feedback here.
Обратная связь
Отправить и просмотреть отзыв по
Оператор Function
Объявляет название, аргументы и код, которые составляют основной текст процедурыFunction.
Синтаксис
[Public | Private | Friend] [ Static ] Имяфункции [ ( arglist ) ] [ Astype ]
[ операторы ]
[ имя=выражение ]
[ Выход из Function ]
[ операторы ]
[ имя=выражение ]
End Function
Синтаксис оператора Function содержит такие части:
| Part | Описание |
|---|---|
| Public | Необязательный параметр. Указывает на то, что процедура Function доступна для всех других процедур во всех модулях. При использовании в модуле, который содержит Option Private, процедура недоступна вне проекта. |
| Private | Необязательный параметр. Указывает на то, что процедура Function доступна только для других процедур в том модуле, в котором была объявлена. |
| Friend | Необязательный параметр. Используется только в модуле класса. Указывает на то, что процедура Function видима повсюду в проекте, но невидима для контроллера экземпляра объекта. |
| Static | Необязательный параметр. Указывает на то, что локальные переменные процедуры Function сохраняются между вызовами. Атрибут Static не влияет на переменные, которые были объявлены вне Function, даже если они используются в процедуре. |
| name | Обязательно. Название Function; соответствует стандарту соглашений об именовании переменных. |
| arglist | Необязательный параметр. Список переменных, представляющих аргументы, которые передаются в процедуру Function при вызове. В качестве разделителя переменных используется запятая. |
| type | Необязательный параметр. Тип данных значения, возвращаемого процедурой Function; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (в настоящее время не поддерживается), Date, String (кроме фиксированной длины), Object, Variant или любым пользовательским типом. |
| Операторы | Необязательный параметр. Любая группа операторов, которая будет выполняться в процедуре Function. |
| выражение | Необязательный параметр. Возвращаемое значение Function. |
Аргумент arglist имеет следующий синтаксис и элементы:
[ Необязательный ] [ ByVal | ByRef ] [ ParamArray ] varname [ ( ) ] [ Кактип ] [ =defaultvalue ]
| Part | Описание |
|---|---|
| Необязательное | Необязательный параметр. Указывает, что аргумент не является обязательным. Если он используется, все последующие аргументы в arglist тоже должны быть необязательными и объявляться с использованием ключевого слова Optional. Optional не может использоваться для каких-либо аргументов, если используется ParamArray. |
| ByVal | Необязательный параметр. Указывает, что аргумент передается значением. |
| ByRef | Необязательный параметр. Указывает, что аргумент передается по ссылке. ByRef является значением по умолчанию в Visual Basic. |
| ParamArray | Необязательный параметр. Используется как последний аргумент в arglist, чтобы указать, что последний аргумент является массивом Optional элементов Variant. Ключевое слово ParamArray позволяет предоставлять произвольное число аргументов. Не может использоваться с аргументами ByVal, ByRef или Optional. |
| varname | Обязательно. Имя переменной, представляющее аргумент; соответствует стандарту соглашений об именовании переменных. |
| type | Необязательный параметр. Тип данных аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (в настоящее время не поддерживается), Date, String (только переменная длина), Object, Variant или определенный тип объекта. Если параметр объявлен без ключевого слова Optional, можно также указать тип, определяемый пользователем. |
| defaultvalue | Необязательный параметр. Любая константа или константное выражение. Действительно только для параметров Optional. Если типом является Object, явным значением по умолчанию может быть только Nothing. |
Замечания
Если обратное не указано явно с помощью параметров Public, Private, или Friend, процедуры Function общедоступны по умолчанию.
Если Static не используется, значение локальных переменных не сохраняется между вызовами.
Ключевое слово Friend может использоваться только в модулях классов. Однако доступ к процедурам Friend может осуществляться в любом модуле проекта. Процедура Friend не отображается в библиотеке типов своего родительского класса; процедура Friend не может быть привязана позднее.
Процедуры Function могут быть рекурсивными, то есть они могут вызывать сами себя для выполнения поставленной задачи. Однако рекурсия может стать причиной переполнения стека. Ключевое слово Static обычно не используется с рекурсивными процедурами Function.
Весь выполняемый код должен быть в процедурах. Нельзя определить процедуру Function внутри другой процедуры Function, Sub, или Property.
Оператор Exit Function вызывает немедленный выход из процедуры Function. Выполнение программы продолжается с оператором, следующим за оператором, который вызвал процедуру Function. В любом месте процедуры Function может появится любое количество операторов Exit Function.
Как и Sub, Function является отдельной процедурой, которая может содержать аргументы, выполнять наборы операторов и изменять значения их аргументов. Однако в отличие от Sub, процедуру Function можно использовать справа от выражения, как и при использовании любой встроенной функции, например Sqr, Cos или Chr, если необходимо использовать значение, возвращенное функцией.
Процедура Function вызывается с помощью имени функции, за которым следует список аргументов в круглых скобках в выражении. Ознакомьтесь с информацией об операторе Call, чтобы подробнее узнать о вызове процедур Function.
Чтобы вернуть значение функции, присвойте значение названию функции. В любом месте процедуры может появится любое количество таких назначений. Если параметру name не присвоено значение, процедура вернет значение по умолчанию: числовая функция вернет 0, строковая функция вернет строку нулевой длины («»), а функция Variant вернет значение Empty. Функция, которая возвращает объектную ссылку, возвращает значение Nothing, если для параметра name не присвоено ни одной объектной ссылки (с помощью Set) в Function.
В следующем примере показано, как присвоить функции возвращаемое значение. В этом случае значение False присваивается названию, чтобы указать, что некоторые значения не были найдены.
Function BinarySearch(. . .) As Boolean '. . . ' Value not found. Return a value of False. If lower > upper Then BinarySearch = False Exit Function End If '. . . End Function
Переменные, которые используются в процедурах Function, делятся на две категории: те, которые явно объявлены в процедуре, и те, которые нет.
Переменные, которые явно объявлены в процедуре (с помощью оператора Dim или его эквивалента), всегда являются локальными в процедуре. Переменные, которые используются, но не были явно объявлены в процедуре, также являются локальными, если они не были объявлены на более высоком уровне вне процедуры.
В процедуре может использоваться переменная, которая не была явно объявлена в процедуре, но если какой-либо элемент, который был определен на уровне модуля, имеет такое же название, может возникнуть конфликт. Если ваша процедура ссылается на необъявленную переменную, которая называется так же, как и другая процедура, константа или переменная, система посчитает, что ваша процедура ссылается на это название на уровне модуля. Следует явно объявлять переменные, чтобы избежать таких конфликтов. Используйте оператор Option Explicit для принудительного явного объявления переменных.
Visual Basic может менять порядок арифметических выражений для повышения внутренней эффективности. Избегайте использования процедуры Function в арифметических выражениях, если функция меняет значение переменных в одном выражении. Подробнее об арифметических операторах см. в разделе Операторы.
Пример
В этом примере оператор Function используется для объявления названия, аргументов и кода, которые составляют основной текст процедуры Function. В последнем примере используются фиксированные инициализированные аргументы Optional.
' The following user-defined function returns the square root of the ' argument passed to it. Function CalculateSquareRoot(NumberArg As Double) As Double If NumberArg < 0 Then ' Evaluate argument. Exit Function ' Exit to calling procedure. Else CalculateSquareRoot = Sqr(NumberArg) ' Return square root. End If End Function
Использование ключевых слов ParamArray позволяет функции принимать переменное число аргументов. В следующем определении он передается по значению.
Function CalcSum(ByVal FirstArg As Integer, ParamArray OtherArgs()) Dim ReturnValue ' If the function is invoked as follows: ReturnValue = CalcSum(4, 3, 2, 1) ' Local variables are assigned the following values: FirstArg = 4, ' OtherArgs(1) = 3, OtherArgs(2) = 2, and so on, assuming default ' lower bound for arrays = 1.
Необязательные аргументы могут иметь значения по умолчанию и типы, отличные от Variant.
' If a function's arguments are defined as follows: Function MyFunc(MyStr As String,Optional MyArg1 As _ Integer = 5,Optional MyArg2 = "Dolly") Dim RetVal ' The function can be invoked as follows: RetVal = MyFunc("Hello", 2, "World") ' All 3 arguments supplied. RetVal = MyFunc("Test", , 5) ' Second argument omitted. ' Arguments one and three using named-arguments. RetVal = MyFunc(MyStr:="Hello ", MyArg1:=7)
См. также
- Вызов процедур Sub и Function
- Общие сведения об именованных и необязательных аргументах
- Написание процедуры Function
- Типы данных
- Операторы
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Обратная связь
Были ли сведения на этой странице полезными?
Создание функций обратного вызова состояния
В этом руководстве описывается, как создать функцию обратного вызова состояния, используемую для мониторинга состояния интернет-запроса.
Функции обратного вызова состояния получают обратные вызовы состояния во всех интернет-запросах, исходящих из любой функции WinINet, передавшей ненулевое значение контекста.
Для создания функции обратного вызова состояния необходимо выполнить следующие действия.
- Определите значение контекста.
- Создайте функцию обратного вызова состояния.
Определение значения контекста
Значение контекста может быть любым длинным целым числом без знака. В идеале значение контекста должно определять, какой запрос был только что выполнен, и расположение всех связанных ресурсов, если это необходимо.
Одним из наиболее полезных способов использования контекстного значения является передача адреса структуры и его приведение к DWORD_PTR. Структура может использоваться для хранения сведений о запросе, чтобы они передавались в функцию обратного вызова состояния.
Следующая структура является примером возможного значения контекста. Члены структуры выбираются с учетом функции InternetOpenUrl .
typedef struct < HWND hWindow; // Window handle int nStatusList; // List box control to hold callbacks HINTERNET hResource; // HINTERNET handle created by InternetOpenUrl char szMemo[512]; // String to store status memo >REQUEST_CONTEXT;
В этом примере функция обратного вызова состояния будет иметь доступ к дескриптору окна, что позволит ей отображать пользовательский интерфейс. Дескриптор HINTERNET, созданный InternetOpenUrl, можно передать другой функции, которая может скачать ресурс и массив символов, который можно использовать для передачи сведений о запросе.
Члены структуры можно изменить в соответствии с потребностями конкретного приложения, поэтому не чувствуйте себя ограниченными в этом примере.
Создание функции обратного вызова состояния
Функция обратного вызова состояния должна иметь формат InternetStatusCallback. Для этого выполните следующие действия.
-
Напишите объявление функции для функции обратного вызова состояния. В следующем примере показан пример объявления.
void CALLBACK CallMaster( HINTERNET, DWORD_PTR, DWORD, LPVOID, DWORD );
switch (dwInternetStatus) < case INTERNET_STATUS_REQUEST_COMPLETE: // Add code break; default: // Add code break; >
void __stdcall CallMaster( HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength ) < UNREFERENCED_PARAMETER(hInternet); UNREFERENCED_PARAMETER(lpvStatusInformation); UNREFERENCED_PARAMETER(dwStatusInformationLength); REQUEST_CONTEXT *cpContext; cpContext = (REQUEST_CONTEXT*)dwContext; char szStatusText[80]; switch (dwInternetStatus) < case INTERNET_STATUS_CLOSING_CONNECTION: StringCchPrintfA( szStatusText, 80, "%s CLOSING_CONNECTION", cpContext->szMemo); break; case INTERNET_STATUS_CONNECTED_TO_SERVER: StringCchPrintfA( szStatusText, 80, "%s CONNECTED_TO_SERVER", cpContext->szMemo ); break; case INTERNET_STATUS_CONNECTING_TO_SERVER: StringCchPrintfA( szStatusText, 80, "%s CONNECTING_TO_SERVER", cpContext->szMemo ); break; case INTERNET_STATUS_CONNECTION_CLOSED: StringCchPrintfA( szStatusText, 80, "%s CONNECTION_CLOSED", cpContext->szMemo ); break; case INTERNET_STATUS_HANDLE_CLOSING: StringCchPrintfA( szStatusText, 80, "%s HANDLE_CLOSING", cpContext->szMemo ); break; case INTERNET_STATUS_HANDLE_CREATED: StringCchPrintfA( szStatusText, 80, "%s HANDLE_CREATED", cpContext->szMemo); break; case INTERNET_STATUS_INTERMEDIATE_RESPONSE: StringCchPrintfA( szStatusText, 80, "%s INTERMEDIATE_RESPONSE", cpContext->szMemo ); break; case INTERNET_STATUS_NAME_RESOLVED: StringCchPrintfA( szStatusText, 80, "%s NAME_RESOLVED", cpContext->szMemo); break; case INTERNET_STATUS_RECEIVING_RESPONSE: StringCchPrintfA( szStatusText, 80, "%s RECEIVING_RESPONSE", cpContext->szMemo); break; case INTERNET_STATUS_RESPONSE_RECEIVED: StringCchPrintfA( szStatusText, 80, "%s RESPONSE_RECEIVED", cpContext->szMemo); break; case INTERNET_STATUS_REDIRECT: StringCchPrintfA( szStatusText, 80, "%s REDIRECT", cpContext->szMemo ); break; case INTERNET_STATUS_REQUEST_COMPLETE: StringCchPrintfA( szStatusText, 80, "%s REQUEST_COMPLETE", cpContext->szMemo); break; case INTERNET_STATUS_REQUEST_SENT: StringCchPrintfA( szStatusText, 80, "%s REQUEST_SENT", cpContext->szMemo); break; case INTERNET_STATUS_RESOLVING_NAME: StringCchPrintfA( szStatusText, 80, "%s RESOLVING_NAME", cpContext->szMemo ); break; case INTERNET_STATUS_SENDING_REQUEST: StringCchPrintfA( szStatusText, 80, "%s SENDING_REQUEST", cpContext->szMemo ); break; case INTERNET_STATUS_STATE_CHANGE: StringCchPrintfA( szStatusText, 80, "%s STATE_CHANGE", cpContext->szMemo ); break; default: StringCchPrintfA( szStatusText, 80, "%s Unknown Status %d Given", cpContext->szMemo, dwInternetStatus); break; > SendDlgItemMessage( cpContext->hWindow, cpContext->nStatusList, LB_ADDSTRING, 0, (LPARAM)szStatusText ); >
HINTERNET hOpen; // Root HINTERNET handle INTERNET_STATUS_CALLBACK iscCallback; // Holds the callback function // Create the root HINTERNET handle. hOpen = InternetOpen( TEXT("Test Application"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // Set the status callback function. iscCallback = InternetSetStatusCallback( hOpen, (INTERNET_STATUS_CALLBACK)CallMaster );
WinINet не поддерживает реализации сервера. Кроме того, его не следует использовать из службы. Для серверных реализаций или служб используйте службы Microsoft Windows HTTP (WinHTTP).
Процедуры функций (Visual Basic)
Процедура Function — это ряд операторов Visual Basic, заключенных в операторы Function и End Function . Процедура Function выполняет задачу, а затем возвращает управление вызывающему коду. При возврате элемента управления он также возвращает значение вызывающему коду.
При каждом вызове процедуры выполняются ее инструкции, начиная с первого исполняемого оператора после Function оператора и заканчивая первым End Function встречным оператором , Exit Function или Return .
Процедуру Function можно определить в модуле, классе или структуре. Public По умолчанию это означает, что вы можете вызывать его из любого места в приложении, которое имеет доступ к модулю, классу или структуре, в которой они определены.
Процедура Function может принимать аргументы, такие как константы, переменные или выражения, которые передаются ей вызывающим кодом.
Синтаксис объявления
Синтаксис объявления Function процедуры выглядит следующим образом:
[Modifiers] Function FunctionName [(ParameterList)] As ReturnType [Statements] End Function
Модификаторы могут указывать уровень доступа и сведения о перегрузке, переопределении, совместном использовании и теневом режиме. Дополнительные сведения см. в разделе Function Statement.
Каждый параметр объявляется так же, как и для вложенных процедур.
Тип данных
Каждая Function процедура имеет тип данных, как и каждая переменная. Этот тип данных задается предложением As в инструкции Function и определяет тип данных значения, возвращаемого функцией в вызывающий код. Это иллюстрируют следующие примеры объявлений.
Function Yesterday() As Date End Function Function FindSqrt(radicand As Single) As Single End Function
Дополнительные сведения см. в разделе "Parts" раздела Function Statement.
Возврат значений
Значение, отправляемое процедурой Function обратно в вызывающий код, называется его возвращаемым значением. Процедура возвращает это значение одним из двух способов:
-
Он использует оператор для Return указания возвращаемого значения и немедленно возвращает управление вызывающей программе. Это показано в следующем примере.
Function FunctionName [(ParameterList)] As ReturnType ' The following statement immediately transfers control back ' to the calling code and returns the value of Expression. Return Expression End Function
Function FunctionName [(ParameterList)] As ReturnType ' The following statement does not transfer control back to the calling code. FunctionName = Expression ' When control returns to the calling code, Expression is the return value. End Function
Преимущество назначения возвращаемого значения имени функции заключается в том, что элемент управления не возвращается из процедуры до тех пор, пока не будет обнаружен Exit Function оператор или End Function . Это позволяет назначить предварительное значение и при необходимости скорректировать его позже.
Дополнительные сведения о возврате значений см. в разделе Function Statement. Сведения о возврате массивов см. в разделе Массивы.
Синтаксис вызова
Процедура вызывается Function путем включения ее имени и аргументов в правой части оператора присваивания или в выражении. Необходимо указать значения для всех аргументов, которые не являются необязательными, а также заключить список аргументов в круглые скобки. Если аргументы не указаны, при необходимости можно опустить круглые скобки.
Синтаксис вызова Function процедуры выглядит следующим образом.
Lvalue = имя_ [( функции список аргументов )]
If (( имя_ [( функции список аргументов )] / 3) Выражение ) Then
При вызове Function процедуры не нужно использовать ее возвращаемое значение. В противном случае выполняются все действия функции, но возвращаемое значение игнорируется. MsgBox часто вызывается таким образом.
Иллюстрация объявления и вызова
Function Следующая процедура вычисляет самую длинную сторону правого треугольника( гипотенузу) с учетом значений двух других сторон.
Function Hypotenuse(side1 As Double, side2 As Double) As Double Return Math.Sqrt((side1 ^ 2) + (side2 ^ 2)) End Function
В следующем примере показан типичный вызов метода hypotenuse .
Dim testLength, testHypotenuse As Double testHypotenuse = Hypotenuse(testLength, 10.7)
См. также раздел
- Процедуры
- Подпрограммы
- Процедуры свойств
- Процедуры операторов
- Параметры и аргументы процедуры
- Оператор Function
- Практическое руководство. Создание процедуры, возвращающей значение
- Практическое руководство. Возврат значения из процедуры
- Практическое руководство. Вызов процедуры, возвращающей значение
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
The .NET documentation is open source. Provide feedback here.
Обратная связь
Отправить и просмотреть отзыв по
