Поделиться через


Оператор AddressOf

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

Синтаксис

AddressOfprocedurename

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

Замечания

Если имя процедуры отображается в списке аргумента, как правило, выполняется проверка процедуры и передача адреса возвращаемого значения процедуры. AddressOf позволяет передавать адрес процедуры в функцию API Windows в библиотеке динамической компоновки (DLL) вместо передачи возвращаемого значения процедуры. После этого функция API может использовать адрес для вызова процедуры Basic (обратный вызов). Оператор AddressOf отображается только в вызове процедуры API.

Хотя оператор AddressOf можно использовать для передачи указателей функций в процедурах Basic, вызов функции с помощью этого указателя из процедуры Basic не допускается. Это означает, например, что класс , написанный на языке Basic, не может выполнить обратный вызов к своему контроллеру с помощью такого указателя. При использовании оператора AddressOf для передачи указателя процедуры в процедурах Basic, параметр вызываемой процедуры должен принадлежать к типу As Long.

Использование AddressOf может привести к непредсказуемым результатам, если вы не до конца понимаете концепцию обратного вызова функции. Необходимо понять, как работает часть Basic обратного вызова, а также код DLL, в который передается адрес функции. Отладка таких взаимодействий затруднена, так как программа выполняется в том же процессе, что и среда разработки. В отдельных случаях систематическая отладка может быть недоступна.

Примечание.

Можно создавать собственные прототипы функции обратного вызова в библиотеках DLL, скомпилированных с помощью Microsoft Visual C++ или аналогичных инструментов. Для работы с оператором AddressOf прототип должен использовать соглашение о вызовах __stdcall. Соглашение о вызовах по умолчанию (__cdecl) не поддерживает работу с оператором AddressOf.

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

Пример

В следующем примере показано создание формы с полем списка, в котором содержится список системных шрифтов, отсортированный по алфавиту.

Для выполнения действий, указанных в этом примере, необходимо создать форму с полем списка. Используется следующий код формы:

Option Explicit

Private Sub Form_Load()
    Module1.FillListWithFonts List1
End Sub

Разместите в модуле следующий код. Третьим аргументом в определении функции EnumFontFamilies является аргумент Long, представляющий процедуру. Аргумент должен содержать адрес процедуры, а не значение, возвращаемое процедурой. В вызове функции EnumFontFamilies третьему аргументу требуется оператор AddressOf для возврата адреса процедуры EnumFontFamProc, который является именем процедуры обратного вызова, указанным при вызове функции Windows API (EnumFontFamilies). Windows выполняет вызов EnumFontFamProc один раз для каждого из семейств шрифтов в системе, когда оператор AddressOf EnumFontFamProc передается в EnumFontFamilies. Последний аргумент, переданный в EnumFontFamilies, задает поле списка, в котором отображаются данные.

'Font enumeration types
Public Const LF_FACESIZE = 32
Public Const LF_FULLFACESIZE = 64

Type LOGFONT
        lfHeight As Long
        lfWidth As Long
        lfEscapement As Long
        lfOrientation As Long
        lfWeight As Long
        lfItalic As Byte
        lfUnderline As Byte
        lfStrikeOut As Byte
        lfCharSet As Byte
        lfOutPrecision As Byte
        lfClipPrecision As Byte
        lfQuality As Byte
        lfPitchAndFamily As Byte
        lfFaceName(LF_FACESIZE) As Byte
End Type

Type NEWTEXTMETRIC
        tmHeight As Long
        tmAscent As Long
        tmDescent As Long
        tmInternalLeading As Long
        tmExternalLeading As Long
        tmAveCharWidth As Long
        tmMaxCharWidth As Long
        tmWeight As Long
        tmOverhang As Long
        tmDigitizedAspectX As Long
        tmDigitizedAspectY As Long
        tmFirstChar As Byte
        tmLastChar As Byte
        tmDefaultChar As Byte
        tmBreakChar As Byte
        tmItalic As Byte
        tmUnderlined As Byte
        tmStruckOut As Byte
        tmPitchAndFamily As Byte
        tmCharSet As Byte
        ntmFlags As Long
        ntmSizeEM As Long
        ntmCellHeight As Long
        ntmAveWidth As Long
End Type

' ntmFlags field flags
Public Const NTM_REGULAR = &H40&
Public Const NTM_BOLD = &H20&
Public Const NTM_ITALIC = &H1&

'  tmPitchAndFamily flags
Public Const TMPF_FIXED_PITCH = &H1
Public Const TMPF_VECTOR = &H2
Public Const TMPF_DEVICE = &H8
Public Const TMPF_TRUETYPE = &H4

Public Const ELF_VERSION = 0
Public Const ELF_CULTURE_LATIN = 0

'  EnumFonts Masks
Public Const RASTER_FONTTYPE = &H1
Public Const DEVICE_FONTTYPE = &H2
Public Const TRUETYPE_FONTTYPE = &H4

Declare Function EnumFontFamilies Lib "gdi32" Alias _
     "EnumFontFamiliesA" _
     (ByVal hDC As Long, ByVal lpszFamily As String, _ 
     ByVal lpEnumFontFamProc As Long, LParam As Any) As Long
Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, _
     ByVal hDC As Long) As Long

Function EnumFontFamProc(lpNLF As LOGFONT, lpNTM As NEWTEXTMETRIC, _ 
     ByVal FontType As Long, LParam As ListBox) As Long
Dim FaceName As String
Dim FullName As String
    FaceName = StrConv(lpNLF.lfFaceName, vbUnicode)
    LParam.AddItem Left$(FaceName, InStr(FaceName, vbNullChar) - 1)
    EnumFontFamProc = 1
End Function

Sub FillListWithFonts(LB As ListBox)
Dim hDC As Long
    LB.Clear
    hDC = GetDC(LB.hWnd)
    EnumFontFamilies hDC, vbNullString, AddressOf EnumFontFamProc, LB
    ReleaseDC LB.hWnd, hDC
End Sub

См. также

Поддержка и обратная связь

Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.