    Глава 6. Работа с библиотеками динамической компоновки	141 

    Глава 6.   Работа с библиотеками динамической компоновки 

    Одно из самых больших преимуществ использования Visual Basic — в том, что 
с его помощью можно создавать сложные приложения для Windows, совершенно не 
вникая в тонкости интерфейса программирования приложений Windows (API). 
    Если требуется, чтобы приложение включало функциональные возможности, 
которые_не o6ecn^4jiвеются.JVJsuaL.Basic, можно использовать библиотеки 
динамической компоновки Windows (DLL) для обращения.непосредственно к Windows API. 
    Например, можно использовать DLL при создании формы, которая всегда 
остается на экране поверх остальных форм, даже когдаj-fejiMeeT фокуса. 
    В этой главе показано, как использовать DLL для расширения функциональных 
возможностей приложения Visual Basic, объясняются базовые шаги объявления и 
вызова процедур DLL и другие вопросы. 

    6.1. Обзор DLL 

    Библиотеки DLL могут обеспечивать разработчика многими возможностями, 
которые в Visual Basic непосредственно не доступны. Библиотека динамической 
компоновки"—"набор проц^дур.'внешнйх по отношению к приложению, которые могут 
вызываться из приложения. DLL не связаны с исполняемым файлом приложения; они 
могут компоноваться с ним в период выполнения вместо загрузки во время 
компиляции. Библиотеки могут обновляться незавйсймо~от~приложения, и несколько 
приложений могут совместно использовать одну и ту же DLL. 

    6.1.1. Преимущества использования DLL 

    С помощью DLL можно: 
    •  решать 3afla4i^j^o^iej4eBO3Mo>KHopeujHTb,cpeflCTBa^Visual Basic; 
    •  повышать производительность приложения. Код в DLL часто выполняется 
быстрее, чем код Visual Basic. Для процедур, в которых требуется высокая 
скорость выполнения, можно написать DLL и затем вызывать DLL из Visual Basic; 
    «  модификация независимо от приложения. DLL можно модифицировать без 
перекомпиля-и,т_пр\лпожен\ля, которое вызывает DLL. Это облегчает 
сопровождение приложения. 

    6.1.2. Библиотеки Windows API 

    Windows обеспечивает ряд полезных DLL, которые можно вызывать из Visual 
Basic. Эти DLL создают интерфейс программирования приложений Windows (Windows API). 
    32-разрядные версии операционной системы Windows (Windows 95 и Windows NT) 
состоят из трех основных DLL: User32, GDI32 и Kernel32. Эти DLL обеспечивают 
большую часть функциональных возможностей Windows API: 
    User32	Модули библиотеки User32.dll решают задачи, связанные с управлением 
окнами, меню, элементами управления и окнами диалога. Например, процедура 
FlashWindow в User32.dll обусловливает вывод окна. 
    GDI32	Библиотека GDI32.dll отвечает за вывод графики. 


    142 Обзор DLL 

    Kernel32	Библиотека Kernel32.dll управляет задачами операционной системы. 
На-1 пример, в Kernel32.dll можно вызвать процедуру GetWindowsDirectory, что| 
бы получить текущий путь папки Windows. 
    В дополнение к этим трем DLL Windows 95 и Windows NT содержат много других 
библиотек которые обеспечивают расширение функциональных возможностей Visual Basic. 

    6.1.3. Использование API Viewer 

    Отобрать соответствующие объявления для процедур Windows API можно с 
помощью утилиты API Viewer (Apiload.exe), поставляемой с Visual Basic. 
    При загрузке такстовогд^айла API, такого, как файл Win32api.txt, API 
Viewer читает фаиг к выводит на экран константы, типы и операторы Declare для 
процедуры в Windows API. В APi Viewer можно скопировать объявление в буфер 
обмена и затем вставить его в приложение Visual Basic. 

    <| Text API Viewei    C:\VBSWINAPI4Wm32api.tKl 
    File   Edit API Type: 
    Help 
    Line Hem 
    zJ 
    Available Items: 
    AbortDoc AbortPath AbortPrinter AbortSysternShutdown AccessCheck		?l 
    Add        | 
    iAccess	CheckAndAuditAlarm	^^Ш 
    1 f 
    ActivateKeyboardLayout AddAccessAllowedAce 
    Selected Items: 
    d 
    Declare Function AccessCheckAnd Audit Alarm Lib "advapi32.dll" Alias	•*•[ 
"AccessCheckAndAuditAlarmA" (ByVal SubsystemName As String, Handleld As Any, 
ByVal ObjectTypeName As String, ByVal ObjectName As String,                   
i SecurityDescriptor As SECURITY J)ESCRIPTOR,Bj/Val DesiredAccess As Long, 
GenericMapping As GENERIC_MAPPIWG, ByVal ObjectCreation As Long, GrantedAccess 
As Long, ByVal AccessStatus As Long, ByVal pfGenerateQnClo—I As Long) As Long 
    Remove 
    Copy 
    d 
    Search by typing directly into the list box.,, 

    Рис. 6.1. Окно API Viewer. 


    6.1.4. Загрузка объявления из базы данных 

    Для ускорения поиска определенных объявлений DLL лучше загрузить и 
просматривав файл базы данных (.mdb), чем искать вхождение в текстовом файле 
(.txt). API Vie/ г позволяет либо загрузить и просмотреть текстовый файл API, 
либо преобразовать ег. в файл базы данных формата Jet. Преобразованный файл 
базы данных .mdb можно бу;:ь~ загружать всякий раз при использовании API Viewer. 


    Глава 6. Работа с библиотеками динамической компоновки 143 

    6.1.5. Использование DLL с Visual Basic 

    При использовании процедуры DLL имеется два базовых шага: 
    1. С помощью оператора Declare сообщить Visual Basic, какую процедуру 
требуется использовать. 
    2. Вызвать процедуру DLL из соответствующего места в программном коде. Эти 
шаги обсуждаются ниже. 

    6.2. Объявление процедуры DLL 

    Процедуры DLL располагаются во внешних по отношению к приложению Visual 
Basic файлах, поэтому, прежде чем можно будет вызывать процедуру, ее 
необходимо объявить. Объявление процедуры обеспечивает Visual Basic 
информацией, необходимой для нахождения и выполнения процедуры. При объявлении 
процедуры DLL оператор Declare следует поместить в разделе_0ес!ага1юпз формы, 
стандартного модуля или модуля класса. 
    Если DLL объявляется в стандартном модуле, процедура DLL — Public по 
умолчанию и может вызываться кодом отовсюду в приложении Visual Basic. Чтобы 
ограничить область определения процедуры DLL формой или модулем класса, в 
объявлении необходимо поместить ключевое слово Private. 
    Синтаксис оператора Declare: 

    [Public|Private] Declare Sub имя Lib "имя_библиотеки" [Alias 
"имя_псевдонима"] [(список_параметров)] 

    или 
    
    [Public|Private] Declare Function имя Lib "имя_библиотеки" [Alias 
"имя_псевдонима"] [(список_параметров)] [As тип] 

    Элементы оператора Declare: 

    Элемент	Описание 

    имя	Имя процедуры, используемой в коде. 

    Lib "имя библиотеки"	Имя библиотеки, в которой находится процедура. Если 
построена пользовательская DLL, специфицируется ее имя. Например: Function 
Declare AddNum Lib "c:\add.dll" (ByVal a as long) As long. Если полный путь к 
DLL не специфицируется, DLL должна находиться на пути системной переменной PATH. 
    список_параметров	Параметры, требуемые процедурой. Тип данных каждого 
параметра должен соответствовать типу данного, специфицированного в 
объявлении. Параметр может быть передан по значению или по ссылке. 
    Alias "имя_псевдонима"	Если DLL содержит имя, которое представляет 
недопустимый идентификатор в Visual Basic, то для идентификации вызываемой 
процедуры можно использовать ключевое слово Alias. Ключевое     слово     
Alias     определяет     альтернативное     имя используемой процедуры. 
    В следующем примере объявляется процедура API AccessCheckAndAuditAlarm: 
    '   Поместить   в  раздел  General   Declarations   стандартного  модуля   

.ВАЗ Declare   Function  AccessCheckAndAuditAlarm _ 

    Lib   "advapi32.dll"   Alias   "AccessCheckAndAuditAlarmA" 



    144 Объявление процедуры DLL 


    (ByVal SubsystemName As String, Handleld As Any, _ ByVal ObjectTypeName As 
String, ByVal ObjectName As String, _ SecurityDescriptor As SECURITY_DESCRIPTOR, _ 
    ByVal DesiredAccess As Long, GenericMapping As GENERIC_MAPPING, ByVal 
ObjectCreation As Long, GrantedAccess As Long, _ ByVal AccessStatus As Long, _ 
ByVal pfGenerateOnClose As Long) As Long 

    6.2.1. Преобразование объявлений С в типы данных Visual Basic 

    Обычно процедуры DLL пишутся на языке программирования С, поэтому их парамет, 
    "Определяются типами данных С. Когда используется оператор Declare для DLL 
в VisBasic, необходимо спроецировать типы данных параметров на типы данных С. 
    В следующей таблице перечислены обычно используемые объявления языка С и 
их эквиваленты Visual Basic для 32-разрядных компиляторов: 

    Объявление языка С    Объявление Visual Basic        Вызов Указатель на строку        

ByVal <переменная> As String с переменной String или Variant 1 (LPSTR) 1 NULL                                 
ByVal <переменная> As String с константой VbNullString            | char
ByVal <переменная> As Byte    с выражением, которое оценивается как тип данного Byte | Integer
ByVal <переменная> As Long    с выражением, которое оценивается как тип данного Long | Дескриптор Windows       
ByVal <переменная> As Long   с выражением, которое оценивается как тип данного Long (hWnd, hDC, hMenu)

    Примечание: В 16-разрядных компиляторах С тип данного int соответствует 
типу данного Inte Visual Basic. В 32-разрядных компиляторах С тип данного int 
соответствует типу данного Lo Visual Basic. 


    6.2.2. Гибкие типы параметров 

    В DLL тип данного параметра определяет тип данного, возвращаемого 
процедурой, i 
    в Visual Basic можно определять процедуру таким образом, чтобы параметр 
мог принимат 
    любой тип данных. 
    Для объявления параметра, который может принимать более одного типа 
данного, можн использовать тиги^днного Any; при этом Visual Basic не будет 
выполнять контроль соответ-j ствия типов и позволит передавать для этого 
параметра переменную любого типа. 

    Примечание: Используя предложение Alias, можно объявить DLL дважды и в 
каждом объявлении! обеспечить явные типы данных, чтобы избежать синтаксиса 
Any. Использование явных типов \ данных гарантирует, что, если передается 
параметр неправильного типа данного, возвращается I ошибка компиляции, а не 
ошибка_^шомнёния. Следует, однако, удостовериться, что DLL может! 
прин!магпъ1Тарамётр такого типа данного. Если передается неправильный тип 
данного, обраще-] ние к DLL может обусловить блокировку по общей защите. 


    6.2.3. Библиотеки ANSI и Unicode 

    Каждая процедура Win32 API, которая принимает в качестве параметра строку, 
реализуется] в двух версиях: в символьном наборе ANSI и Unicode. В ANSI каждый 
символ представлен] одним байтом. В Unicode для представления каждого символа 
используются два байта. 


    Глава 6. Работа с библиотеками динамической компоновки	145 

    Трансляция между ANSI и Unicode 

    В Visual Basic версии 5.0 для хранения строк внутренне используется 
символьный набор Unicode. О,днако_при вызове функции в Win32 API необходимо 
использовать версию ANSI функции API. При вызове процедуры DLL Visual Basic 
автоматически преобразует строку в код ANSI. При возвращении из процедуры DLL 
Visual Basic транслирует строку обратно в Unicode. 
    Функции Windows API обычно именуются с суффиксами 'А' и 'W для ANSI и Wide 
(Unicode) соответственно. При вставке оператора Declare из API Viewer будет 
получено правильное имя функции ANSI. 
    Например, чтобы использовать функцию Win32 API SetWindowText, правильным 
будет объявление: 
    Declare   Function   SetWindowText   Lib   "user32"   Alias   
"SetWindowTextA"   _ (ByVal  hwnd As   Long,   ByVal   IpString  As   String)  
 as   Long 
    Хотя приложение Visual Basic вызовет SetWindowText, фактически будет 
вызвана версия ANSI функции, SetWindowTextA. 

    6.3. Вызов DLL 

    После объявления процедуры ее можно вызывать точно так же, как если бы это 
была процедура Visual Basic, как показано в следующем операторе: 

    result  =  AccessCheckAndAuditAlarm(Subsysteml,,   Objectl) 


    Примечание: Если функция объявлена в модуле, для вставки вызова процедуры 
в коде приложения можно использовать Object Browser. 

    При вызове процедуры DLL имеется несколько аспектов, связанных с передачей 
параметров. Они включают: 
    •	передача в процедуру DLL пустого значения; 
    •	выбор передачи параметров с их значением или по ссылке на это значение; 
    •	обеспечение в Visual Basic строк, размер которых достаточен для 
размещения строк С. 
    В этом разделе освещаются некоторые различия в обработке значений 
параметров в процедурах Visual Basic и Windows API. 

    6.3.1. Передача нулевых значений 

    Когда процедура DLL принимает параметр с пустым значением, она ^ожидает 
нулевое значение (0) вместо пустой строки (NULL). Чтобы передать пустое 
значение, следует oбъявить napaметр ByVal As String и передать константу 
vbString, как показано в следующем примере: 

    Declare   Function   FindWindow  Lib   "User32"  _ Alias   "FindWindowA"   
_ (ByVal   IpClassName  As   String,   _ ByVal   IpCaption  As   String)   As  
 Integer 
    re   =   FindWindow   (vbNullString,    "Microsoft  Word") 

    Примечание: В Visual Basic версии 3.0 единственым способом передать пустое 
значение было ByVal 0&. Если использовались DLL, которые требовали строку или 
NULL, нужно было либо объявить параметр As Any, либо объявить DLL дважды, один 
раз с параметром String и второй раз — с параметром Long. 


    146__________________________________________Вызов DLL I 

    Начиная с Visual Basic 4.0, можно объявлять параметр как String и 
передавать стандартна константу Visual Basic vbNullString. 

    6.3.2. Передача параметров по значению и по ссылке 

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

    Передача параметров по значению 

    При передаче параметра по значению процедуре передается копия 
оригинального значения данного. Если процедура изменяет значение, на 
оригинальную переменную это изменение не воздействует. 
    Чтобы передать параметр по значению, необходимо в операторе Declare перед 
объявлением параметра поместить ключевое слово ByVal, как показано в следующем фрагменте: 
    Declare   Function   FlashWindow  Lib   "User32"   _ (ByVal   hwnd  as   
Long,   _ ByVal   blnvert   As   Long)   As   Long 

    Передача параметров по ссылке 

    При передаче параметра по ссылке в процедуру передается адрес памяти 
оригинальной переменной. Если процедура изменяет значение этой переменной, 
оригинальное значение также изменяется. 
    В объявлении процедуры можно специфицировать ByVal или ByRef. Если 
ключевое слово не специфицируется, Visual Basic автоматически передает 
параметры по ссылке. Хотя включать ByRef в объявлении не требуется, текст кода 
будет более читабельным, если явно используется или ByRef, или ByVal. 

    6.3.3. Передача строковых значений 

    Строковые типы данных в Visual Basic хранятся в формате, отличном от 
эквивалентных типов данных языка С. Большинство DLL и все процедуры в Windows 
API распознают формат строки языка С. При передаче строковых значений в Visual 
Basic необходимо учитывать эти различия, объявляя строковые параметры по 
значению, принимая во внимание при этом различия в длине строковых значений. 

    Объявление строковых параметров по значению 

    Если процедура DLL ожидает в качестве параметра строку формата_С, 
необходимо объявить параметр Visual Basic как String, которому предшествуют 
ключевое слово ByVa Значение строковой переменной — это фактически указатель 
на область в памяти, которая содержит строку. Следовательно, процедура DLL 
может изменять строковую переменную Visual Basic, полученную как параметр. 

    Учет различий в длине строк 

    DLL не может увеличить длину строки Visual Basic и производит запись вне 
конца строки, если она"недостаточно длинная. Чтобы обеспечить достаточно 
пространства для строки любой длины, можно использовать один из следующих методов: 


    Глава 6. Работа с библиотеками динамической компоновки	147 

    Заполнить символьную строку максимальным ожидаемым числом символов: 

    Dim  FilePath  As   String FilePath  =   String   (255,    0) 

    Определить строку фиксированной длины с максимально возможной длиной: 

    Dim  FilePath  As   String   *   255 

    Строки, возвращаемые процедурой DLL, в конце строки содержат символ 
пробела. При объединении нескольких строк потребуется удалять"3тот символ 
пробела. Так как имеются процедуры, которые возвращают целое число, 
указывающее длину строки, можно либо использовать функцию Left, чтобы удалить 
символ пробела, либо искать символ пробела, используя Chr(O). 
    /' 

    Пример передачи строкового значения 

    Процедура GetWindowsDirectory используется для возвращения пути папки 
Windows. При этом для пути папки Windows необходимо обеспечить пустую строку 
достаточной длины, чтобы принять самое длинное возможное имя папки. 
    Процедура GetWindowsDirectory возвращает целое число, которое указывает 
фактическое число символов в изменяемой строке. Эта строка будет 
содержать,Ы1_^ в качестве последнего символа. NULL можно удалить, найдя его 
или используя функцию Left, как показано в следующем примере: 

    Declare   Function   GetWindowsDirectory  Lib   "Kernel32"   _ Alias   
"GetWindowsDirectoryA"   _ (ByVal   f   as   String,   ByVal   fLen  as   
Long)   As   Long 
    Sub  Commandl_Click   () 
    Dim  sWinDir  As   String 
    Dim   ILen   As   Long 
    sWinDir   =   String(255,0) 
    ILen   =  GetWindowsDirectory(sWinDir,   Len (sWinDir)) 
    sWinDir   =   Left (sWinDir,    ILen) 
    sWinDir   =   sWinDir   +   "\" 
    MsgBox   "Windows   находится  в   "   f   sWinDir End   Sub 


    6.4. Дополнительная информация по DLL 

    В этом разделе дается информация по использованию DLL, которая выходит за 
рамки базовых способов объявления и вызова процедур DLL. Знакомство с этими 
механизмами использования процедур DLL будет весьма полезным при создании 
приложений Visual Basic. 

    6.4.1. Процедуры обратного вызова 

    DLL может сообщать или давать информацию клиенту, вызывая подпрограмму, 
обеспечи-ваемую клиентом. Эта подпрограмма клиента известна как функция 
обратного вызова. В течение одного вызова Windows API эта функция обратного 
вызова может вызываться несколько раз. 
    Процедуры-перечисления, в которых перечисляется набор элементов, являются 
общим примером DLL, использующих функции обратного вызова для передачи 
информации клиенту. 


    148 Дополнительная информация по DLL 


    Обратные вызовы в Visual Basic 

    Visual Basic позволяет создавать процедуры обратного вызова, которые 
обеспечивают сообщение клиенту. 
    Например, можно создать процедуру обратного вызова, которая будет посылать 
сообщение клиенту каждый раз, когда сервер выполнит некоторую операцию. Затем 
для вызова этой процедуры используется DLL. 
    На следующей иллюстрации показано, как процедуры обратного вызова работают 
в Visual Basic: 

    Описание процедуры обратного вызова 
    
    Передача адреса обратного вызова 
    Сохранение обратного вызова 
    Вызов процедуры обратного вызова 
    Function Callback'1 (...) End Function 
    Sub Routine! 0 
    /SetCallK..., AddressOf Callbackl) End Sub 
    SetCall1(..., IpCallbackl) 
    { 
    'Сохранить адрес обратного 
    ' вызова 
    Callbackl =lpCallback1 
    } 
    // Вызов процедуры обратного // вызова 
    Callbackl (...) 
    Приложение Visual Basic 
    DLL 

    Рис. 6.2. Обратные вызовы в Visual Basic. 


    Передача процедуры обратного вызова к DLL 

    Для передачи процедуры обратного вызова к DLL Visual Basic использует 
операцию AddressOf. Процедура обратного вызова должна быть размещена в 
стандартном модуле и иметь правильный синтаксис.	——— 
    Нахождение точного синтаксиса для процедуры обратного вызова может быть 
довольно трудной задачей, так как обычно указания на этот счет можно найти 
только в документации к DLL. Использование правильного синтаксиса важно, так 
как Visual Basic не обеспечивает контроль синтаксиса и ничего не сообщает 
относительно ошибок. 

    Примечание: Использование неправильного синтаксиса в процедуре обратного 
вызова наиболее вероятно обусловит в приложении фатальную ошибку в период выполнения. 

    При специфицировании обратных вызовов из Visual Basic следует убедиться в 
том, что выполнены следующие два требования: 
    •  функция обратного вызова должна быть размещена в стандартном модуле; 
    •  для передачи процедуры обратного вызова к DLL должна использоваться 
операция AddressOf. 


    Глава 6. Работа с библиотеками динамической компоновки	149 


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

    Windows API содержит функцию EnumChildWindows, которая перечисляет все 
окна-потомки родительского окна. Объявление функции следующее: 

    Declare   Function  EnumChildWindows   Lib   "user32"   Alias 
    "EnumChildWindows"    (ByVal   hWndParent  As   Long, 
    ByVal   IpEnumFunc  As   Long,   ByVal   IParam As   Long)   As   Boolean 

    Первый параметр — hWndParent — требует дескриптора родительского окна. 
Второй параметр — IpEnumFunc — требует адреса процедуры обратного вызова. 
Третий параметр — любое 32-разрядное значение, которое хочет передать клиент. 
Это значение впоследствии будет передано в функцию обратного вызова. 

    Написание обратного вызова 

    В следующем примере показано, как подпрограмма обратного вызова 
оформляется в Visual Basic: 

    Public Function EnumProc(ByVal hWndChild as Long , _ 
    ByVal IParam As Long) As Boolean ' Выполнение некоторой обработки Snd Function 


    Вызов DLL 

    Далее следует вызвать процедуру-перечисление и затем специфицировать 
процедуру обратного вызова, используя операцию AddressOf, как показано в 
следующем примере: 

    EnumChildWindows   forml.hWnd,   AddressOf  EnumProc,    0 


    6.4.2. Использование процедур-оболочек 

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

    Написание процедуры-оболочки 

    В следующем примере функция GetWinDir вызывает подпрограмму API GetWindowsDirectory: 

    Public   Function   GetWinDir   ()   As   String 
    sWi-ndir  =   String (255, 0) 
    ILen  =  GetWindowsDirectory   (sWindir,   Len (sWinDir)) 
    sWinDir   =   Left    (sWinDir,    ILen) 
    GetWinDir  =   sWinDir End  Function 

    Каждый раз, когда требуется определить папку Windows, вызывается функция GetWinDir. 

    Вызов процедуры DLL 

    В следующем фрагменте GetWinDir, которая фактически представляет вызов 
подпрограммы API, внедрена в процедуру Click (): 

    Sub  cmdGetWin_Click   () 
    Msgbox  GetWinDir End  Sub 


    150	Дополнительная информация по DLL 


    6.4.3. Полезные DLL 

    Ниже перечислены некоторые процедуры Windows API, которые могут быть 
полезны при написании приложения Visual Basic. Также приводится пример 
использования процедуры Windows API SetWindowPos для создания окна в режиме 
"Поверх остальных". 

    Часто применяемые процедуры Windows API 

    Процедура Windows API     назначение BitBIt                                

        Перемещает растровый рисунок из контекста исходного устройства в 
адресат. Extractlcon, Drawlcon,            Манипулирует пиктограммами.         
                                      L Load Icon                              
                                                                               
                 I FindExecufab/e                      Находит и отбирает имя 
исполняемого файла, ассоцииро-J ванного с файлом определенного формата.        

                | GetSystemDirectory               Возвращает путь системного 
каталога Windows.                  P 

GetSystemMetrics                   
Возвращает ширину и высоту элементов отображения в| Microsoft Windows. 

GetTempFileName                  Возвращает имя и путь временного файла, 
используя сис-i темную переменную TEMP.                                        

              | GetWindowPlacement,            Возвращает или устанавливает 
состояни е, а также позиции SetWin dowPlacement            нормального 
(восстановленного), минимизированного и максимизированного окна. SendMessage   
                      Передает сообщения Windows для управления приложением. 
Например, сообщение LB_SETTABSTOPS устанавливает табулостопы в простом списке. 
LB_FINDSTRING находит первую строку в списке, которая соответствует указанному 
тексту. Здесь также доступны сотни других сообщений.        | 

BringWindowToTop,                Устанавливает фокус на определенное окно. 

SetActiveWindow DragAcceptFiles, DragFinish   Поддерживает функции технологии 
drag-and-rdrop.                

I FindWindow, ShowWindow    Проверяет, 
выполняется или нет в данный момент специфи^ цированное приложение. 

GetActiveWindow, IsWindow Определяет, когда функция системной оболочки 
заканчивает1 загружать программу. 

GetWindowText                     Возвращает 
заголовок окна или текст в элементе управления, специфицируемым дескриптором окна. 

    Использование функции SetWindowsPos 

    Функция SetWindowPos API создает окно (или форму), которое остается поверх 
других окон даже если не имеет фокуса. 
    Чтобы можно было использовать функцию SetWindowPos, необходимо объявить 
соответствующие константы. С помощью API Viewer из текстового файла 
Win32api.txt можно скопировать константы HWND_TOPMOST, SWP_NOSIZE и SWP_NOMOVE. 
    Пример использования функции SetWindowPos для создания окна "Поверх 
остальных" см. ниже. 


    Глава 6. Работа с библиотеками динамической компоновки 151 


    6.4.4. Пример: Нахождение расположения папки Windows 

    В этом примере для нахождения папки, которая содержит файлы Microsoft 
Windows, используется функция Windows API GetWindowsDirectory. 
    1. Создать новый проект Standard EXE. 
    2. Добавить к форме элементы управления, как показано на рис. 6.3. 
    3. Добавить к проекту стандартный модуль. 
    4. В окне API Viewer скопировать оператор Declare для GetWindowsDirectory. 
    5. Вставить оператор Declare в новый модуль. 

    '   Объявление   DLL  в   стандартном модуле 
    Declare   Function   GetWindowsDirectory  Lib   "kerne!32"   _ Alias   
"GetWindowsDirectoryA"    (ByVal   IpBuffer  As   String,   _ ByVal   nSize  
As   Long)    As   Long 

    6. Создать процедуру обработки события Click для кнопки "Директория Windows". 
    7. В процедуре события добавить код, который выводит путь к папке Windows 
в окне сообщения: 

    Private   Sub   cmdWinDir_Click() Dim  WinDir  As   String Dim  ReturnSize 
 As   Long 
    WinDir  =   String (255,    0)    '   Заполнение   строки  нулями 
    '   Вызов  API   для   получения   каталога  Windows   и  фиксация 
    '   размера  возвращенной  строки 
    ReturnSize   =  GetWindowsDirectory(IpBuffer:=WinDir,   _ nSize:=Len(WinDir)) 
    '   Усечь   строку  до   правильного  размера 
    WinDir   =   Left(WinDir,    ReturnSize) 
    MsgBox   "Директория  Windows:   "   &  WinDir End   Sub 
    Директория Windows  ll 
    Выход 
    Pioject! 
    Директория Windows: C:'\WINDOWS 
    OK 

    Рис. 6.З. Форма и сообщение с директорией Windows. 


    6.4.5. Пример: Создание окна "Поверх остальных" 

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


    152 Дополнительная информация по DLL 

    1. Создать новый проект. 
    2. Добавить к форме элементы управления, как показано на рис. 6.4.      
    3. Добавить к проекту стандартный модуль.    /,   ' 
    4. В API Viewer скопировать требуемые константы (HWND_TOPMOST, SWP_NOSIZE 
и SWP_NOMOVE) и оператор Declare для функции SetWindowPos. 
    5. Вставить оператор Declare в новый модуль. 

    Declare Function SetWindowPos Lib "user32" _ Alias "SetWindowPos" (ByVal 
hwnd As Long, _ ByVal hWndlnsertAfter As Long, ByVal x As Long, _ ByVal у As 
Long, ByVal ex As Long, ByVal cy As Long, _ ByVal wFlags As Long) As Long 
    Const HWND_TOPMOST = -1 Const HWNDJTOTTOPMOST = -2 Const SWP_NOSIZE = 1 
Const SWP_NOMOVE = 2 Dim flags As Integer 

    6. Создать процедуры обработки событий для переключателей "Поверх 
остальных" и "Не поверх остальных". 

    Private Sub optNonTopmost_Click() 
    SetWindowPos frmTopmost.hwnd, _ ' Имя формы - frmTopmost 
    HWND NOTOPMOST, 0, 0, 0, 0, FLAGS End Sub 
    Private Sub optTopmost_Click() SetWindowPos frmTopmost.hwnd, _ 
    HWND_TOPMOST, 0, 0, 0, 0, FLAGS End Sub 
    г Позиция окна 
    j   I*1 [Поверх остальных! 
    i • 
    •   Г" Не поверх остальных 
    Выход 

    Рис. 6.4. Форма "Поверх остальных" и "Не поверх остальных". 

