Применение функций Windows API
ИФ Гортис, Санкт-Петербург
В этом разделе вы познакомитесь с некоторыми полезными Windows API функциями. Для каждой функции сначала приводится её прототип на Си, а затем - объявление на Visual FoxPro и примеры использования.
Функции LoadKeyboardLayout и UnloadKeyboardLayout
Функция LoadKeyboardLayout из библиотеки User32.dll загружает новую языковую раскладку клавиатуры. Вот её прототип:
HKL LoadKeyboardLayout( LPCTSTR pwszKLID, // Наименование загружаемой языковой раскладки UINT Flags // Флаг );
Объявление функции в Visual FoxPro:
DECLARE Long LoadKeyboardLayout IN WIN32API String KLID, Long Flags
Функция возвращает дескриптор раскладки клавиатуры (32-х разрядное целое) или ноль в случае ошибки.
Передаваемый функции параметр KLID определяет язык раскладки клавиатуры. Вот некоторые допустимые значения параметра:
Параметр KLID | Описание |
"00000407" | Немецкий (стандартный) |
"00000409" | Английский (США) |
"0000040C" | Французский (стандартный) |
"0000040D" | Финский |
"00000410" | Итальянский |
"00000415" | Польский |
"00000419" | Русский |
"00000422" | Украинский |
"00000423" | Белорусский |
"00000425" | Эстонский |
"00000426" | Латвийский |
"00000427" | Литовский |
Второй параметр, Flags, указывает, как будет загружаться раскладка клавиатуры. Для приложений на Visual FoxPro его значение всегда равно единице.
Для удаления клавиатурной раскладки используется функция UnloadKeyboardLayout. Она так же находится в библиотеке User32.dll. Вот её прототип:
BOOL UnloadKeyboardLayout( HKL hkl // Дескриптор раскладки клавиатуры );
Объявление функции в Visual FoxPro:
DECLARE Long UnloadKeyboardLayout IN WIN32API Long hkl
Передаваемый функции параметр hkl - дескриптор выгружаемой клавиатурной раскладки. Функция возвращает отличное от нуля значение при успешном выполнении или ноль в случае ошибки.
В следующем примере загружается раскладка клавиатуры для немецкого языка:
HKL = LoadKeyboardLayout("00000407", 1)
В следующем примере показано, как удалить существующую раскладку клавиатуры:
UnloadKeyboardLayout(HKL)
Функция GetLocalTime
Функция GetLocalTime из библиотеки Kernel32.dll возвращает текущие дату и время в формате UTC (Universal Time Coordinated). Вот её прототип:
VOID GetLocalTime( LPSYSTEMTIME lpSystemTime // Адрес структуры SystemTime );
Тип данных LPSYSTEMTIME - это указатель на структуру SystemTime:
typedef struct _SYSTEMTIME { WORD wYear; // Год WORD wMonth; // Месяц WORD wDayOfWeek; // День недели WORD wDay; // День месяца WORD wHour; // Часы WORD wMinute; // Минуты WORD wSecond; // Секунды WORD wMilliseconds; // Миллисекунды } SYSTEMTIME;
Как видите, все поля структуры - это 16-ти разрядные целые числа. Месяцы нумеруются начиная с единицы, то есть для января wMonth=1 и так далее. Номера дней недели начинаются с нуля, то есть для воскресенья wDayOfWeek=0, для понедельника wDayOfWeek=1, и так далее.
Функция GetLocalTime не возвращает никаких значений. Вот её объявление в Visual FoxPro:
DECLARE GetSystemTime IN WIN32API String @ SystemTime
В следующем примере показан код функции LocalTime. Функция получает массив, переустанавливает его размер и заполняет его элементы значениями даты и времени:
FUNCTION LocalTime PARAMETERS taTimeArray EXTERNAL ARRAY taTimeArray DIMENSION taTimeArray[8] DECLARE GetLocalTime IN WIN32API String @ LOCAL lcSystemTime && Для структуры SYSTEMTIME lcSystemTime = REPLICATE(CHR(0), 16) && Размечаем память для структуры GetLocalTime(@lcSystemTime) && Заполняем поля структуры * Заполняем переданный функции массив значениями полей структуры taTimeArray[1] = CTOBIN(LEFT(lcSystemTime,2), '2RS') && Год taTimeArray[2] = CTOBIN(SUBSTR(lcSystemTime,3,2), '2RS') && Месяц taTimeArray[3] = CTOBIN(SUBSTR(lcSystemTime,5,2), '2RS') && День недели taTimeArray[4] = CTOBIN(SUBSTR(lcSystemTime,7,2), '2RS') && День месяца taTimeArray[5] = CTOBIN(SUBSTR(lcSystemTime,9,2), '2RS') && Часы taTimeArray[6] = CTOBIN(SUBSTR(lcSystemTime,11,2), '2RS') && Минуты taTimeArray[7] = CTOBIN(SUBSTR(lcSystemTime,13,2), '2RS') && Секунды taTimeArray[8] = CTOBIN(SUBSTR(lcSystemTime,15,2), '2RS') && Миллисекунды RETURN ENDFUNC
Пример вызова функции LocalTime из вашего приложения:
LOCAL laTime[1], laDayOfWeek[7], laMonth[12], lcResult laDayOfWeek[1] = 'воскресенье' laDayOfWeek[2] = 'понедельник' laDayOfWeek[3] = 'вторник' laDayOfWeek[4] = 'среда' laDayOfWeek[5] = 'четверг' laDayOfWeek[6] = 'пятница' laDayOfWeek[7] = 'суббота' laMonth[1] = 'января' laMonth[2] = 'февраля' laMonth[3] = 'марта' laMonth[4] = 'апреля' laMonth[5] = 'мая' laMonth[6] = 'июня' laMonth[7] = 'июля' laMonth[8] = 'августа' laMonth[9] = 'сентября' laMonth[10] = 'октября' laMonth[11] = 'ноября' laMonth[12] = 'декабря' = LocalTime(@laTime) lcResult = 'Сейчас ' + STR(laTime[4],2) + ' ' + laMonth[laTime[2]] + ; STR(laTime[1],4) + ' года, ' + laDayOfWeek[laTime[3]+1] + CHR(13) + ; LTRIM(STR(laTime[5])) + ' час ' + LTRIM(STR(laTime[6])) + ' мин' = MESSAGEBOX(lcResult)
Обратите внимание: массив laTime передаётся по ссылке.
Функция GetTickCount
Функция GetTickCount из библиотеки Kernel32.dll возвращает количество миллисекунд, прошедшее с момента запуска системы. Минимальный интервал времени в Windows - около 55 миллисекунд. Вот её прототип:
DWORD GetTickCount(VOID)
Объявление функции в Visual FoxPro:
DECLARE Long GetTickCount IN WIN32API
Пример вызова функции из вашего приложения:
nMilliSeconds = GetTickCount()
Функция GlobalMemoryStatus
Функция GlobalMemoryStatus из библиотеки Kernel32.dll предоставляет информацию об использовании физической и виртуальной памяти компьютера. Вот её прототип:
VOID GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer // Адрес структуры MemoryStatus );
Тип данных LPMEMORYSTATUS - это указатель на структуру MemoryStatus:
typedef struct _MEMORYSTATUS { DWORD dwLength; // Размер структуры DWORD dwMemoryLoad; // Процент использования памяти DWORD dwTotalPhys; // Физическая память, байт DWORD dwAvailPhys; // Свободная физическая память, байт DWORD dwTotalPageFile; // Размер файла подкачки, байт DWORD dwAvailPageFile; // Свободных байт в файле подкачки DWORD dwTotalVirtual; // Виртуальная память, используемая процессом DWORD dwAvailVirtual; // Свободная виртуальная память } MEMORYSTATUS, *LPMEMORYSTATUS;
Функция не возвращает никаких значений. Вот её объявление в Visual FoxPro:
DECLARE GlobalMemoryStatus IN WIN32API String @ MemoryStatus
В следующем примере показан код функции GlobalMemory, которая вызывает Windows API функцию GlobalMemoryStatus и заполняет массив taMemoryStatus данными из структуры MemoryStatus:
FUNCTION GlobalMemory PARAMETERS taMemoryStatus EXTERNAL ARRAY taMemoryStatus DIMENSION taMemoryStatus[7] LOCAL lcMemoryStatus DECLARE GlobalMemoryStatus IN WIN32API String @ lcMemoryStatus = CHR(32) + REPLICATE(CHR(0), 31) && Подготовка структуры GlobalMemoryStatus(@lcMemoryStatus) taMemoryStatus[1] = CTOBIN(SUBSTR(lcMemoryStatus,5,4), '4RS') taMemoryStatus[2] = CTOBIN(SUBSTR(lcMemoryStatus,9,4), '4RS') taMemoryStatus[3] = CTOBIN(SUBSTR(lcMemoryStatus,13,4), '4RS') taMemoryStatus[4] = CTOBIN(SUBSTR(lcMemoryStatus,17,4), '4RS') taMemoryStatus[5] = CTOBIN(SUBSTR(lcMemoryStatus,21,4), '4RS') taMemoryStatus[6] = CTOBIN(SUBSTR(lcMemoryStatus,25,4), '4RS') taMemoryStatus[7] = CTOBIN(SUBSTR(lcMemoryStatus,29,4), '4RS') RETURN ENDFUNC
Структура MemoryStatus формируется в переменной lcMemoryStatus. В первое поле структуры заносится значение её длины (32 байта). Остальные поля заполняются нулями.
После выполнения функции GlobalMemoryStatus структура MemoryStatus "расшифровывается" при помощи функции CTOBIN.
Пример вызова функции GlobalMemory из вашего приложения:
LOCAL lcInfo, laMemoryStatus[1] DECLARE GlobalMemoryStatus IN WIN32API String @ GlobalMemory(@laMemoryStatus) lcInfo = 'Физическая память, байт: ' + LTRIM(STR(laMemoryStatus[2])) + ; ', свободно: ' + LTRIM(STR(laMemoryStatus[3])) + CHR(13) + ; 'Виртуальная память, байт: ' + LTRIM(STR(laMemoryStatus[6])) + ; ', свободно: ' + LTRIM(STR(laMemoryStatus[7])) = MESSAGEBOX(lcInfo)
Функция Sleep
Функция Sleep из библиотеки Kernel32.dll приостанавливает выполнение приложения на указанное количество миллисекунд. Вот её прототип:
VOID Sleep( DWORD dwMilliseconds // "Время сна" в миллисекундах );
А вот объявление этой функции в Visual FoxPro:
DECLARE Sleep IN WIN32API Long Milliseconds
Пример вызова функции Sleep из вашего приложения:
FUNCTION ToSleep(tnMilliseconds) DECLARE Sleep IN WIN32API Long Sleep(tnMilliseconds) ENDFUNC
Функции для работы с GUID
GUID (Global Unique ID), он же UUID, он же ClsID - глобальный идентификатор, представляющий собой двоичный тип данных длиной 16 байт. Microsoft гарантирует уникальность значения GUID на всей Земле в течение обозримого будущего. В Windows существует достаточное количество функций, генерирующих и преобразующих значения уникальных идентификаторов. Здесь мы рассмотрим три из них:
- CoCreateGUID
- StringFromGUID2
- CLSIDFromString
Эти функции находятся в библиотеке Ole32.dll.
Функция CoCreateGUID генерирует новое значение GUID в виде двоичной строки длиной 16 байт. Вот её прототип:
HRESULT CoCreateGuid( GUID *pguid // Указатель на строку с GUID );
Объявление функции в Visual FoxPro:
DECLARE Long CoCreateGuid IN Ole32.dll String @ guid
Функция возвращает ноль при успешном выполнении либо отличное от нуля значение в случае ошибки.
Пример использования функции:
lqGUID = REPLICATE(CHR(0), 16)) nReturn = CoCreateGuid(@lqGUID)
Полученное значение может быть использовано как уникальный индекс. Хранить такие индексы можно в полях таблиц типа Character Binary.
Функция StringFromGUID2 преобразует двоичное значение GUID в его символьное представление, которое, например, может выглядеть так: {c200e360-38c5-11ce-ae62-08002b2b79ef}. Вот её прототип:
int StringFromGUID2( REFGUID rguid, // Двоичное значение GUID LPOLESTR lpsz, // Указатель на строку с символьным // значением GUID (в Unicode) int cchMax // Количество 16-ти битовых символов в строке );
Объявление этой функции в Visual FoxPro выглядит так:
DECLARE Long StringFromGUID2 IN Ole32.dll String guid, String @ unicodeGuid, Integer cchMaxФункция возвращает количество символов, включая нулевой завершающий символ, в случае успешного выполнения, и ноль, если произошла ошибка.
Формируемое функцией символьное представление GUID может быть использовано, например, для формирования веток ClsID в реестре Windows. Ниже показан пример кода функции GuidToString, показывающий применение функции StringFromGUID2. Функция получает двоичное значение уникального идентификатора и возвращает его символьное представление.
FUNCTION GuidToString(tqGuid) LOCAL unicodeGuid, lnResult DECLARE Long StringFromGUID2 IN Ole32.dll String, String @, Integer unicodeGuid = REPLICATE(CHR(0), 80) lnResult = StringFromGUID2(qGuid, @unicodeGuid, 40) IF lnResult > 0 RETURN STRCONV(LEFT(unicodeGuid,(lnResult-1)*2,6) ELSE RETURN '' ENDIF ENDFUNC
Так как функция StringFromGUID2 при работе с символьными строками использует формат Unicode, то применяем функцию STRCONV для конвертирования результата в формат ANSI.
Функция CLSIDFromString преобразует символьное представление уникального идентификатора в двоичную 16-ти байтовую строку. Вот её прототип:
HRESULT CLSIDFromString( LPOLESTR lpsz, // Указатель на строку с символьным представлением GUID LPCLSID pclsid // Указатель на строку с двоичным представлением GUID );
Объявление функции в Visual FoxPro:
DECLARE Long CLSIDFromString IN Ole32.dll String unicodeGuid, String @ qGuid
Функция возвращает ноль при успешном выполнении и отличное от нуля значение в случае ошибки.
Вот пример кода функции StringToGuid, показывающий применение функции CLSIDFromString. Функция получает символьное представление уникального идентификатора и возвращает его двоичное значение:
FUNCTION StringToGuid(tcGuid) LOCAL lqGUID, lnResult DECLARE Long StringToGuid IN Ole32.dll String, String @ lqGUID = REPLICATE(CHR(0), 16) lnResult = StringToGuid(STRCONV(tcGuid,5), @lqGUID) IF lnResult = 0 RETURN lqGuid ELSE RETURN '' ENDIF ENDFUNC
Функция ShellExecute
Функция ShellExecute из библиотеки Shell32.dll выполняет операцию над указанным файлом. Вот её прототип:
HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd );
Объявление функции в Visual FoxPro:
DEСLARE Long ShellExecute IN Shell32.dll Long hwnd, String Operation, String File, ; String Parameters, String Directory, Integer ShowCmd
В случае успешного завершения функция возвращает значение, большее 32. При возникновении ошибки функция вернёт одно из следующих значений:
Код ошибки |
Описание |
0 | Недостаточно памяти или ресурсов Windows |
2 | Указанный файл не найден |
3 | Указанный путь не существует |
5 | Операционная система не имеет доступа к указанному файлу |
8 | Недостаточно памяти для завершения операции |
26 | Невозможен совместный доступ к файлу |
27 | Невозможно загрузить приложение, ассоциированное с типом файла |
28 | DDE транзакция не может быть завершена из-за истечения времени |
29 | Неудача при выполнении DDE транзакции |
30 | DDE транзакция не может быть завершена, так как обрабатываются другие DDE-транзакции |
31 | Нет никакого приложения, ассоциированного с расширением файла |
32 | Не найдена указанная DLL-библиотека |
Функции передаются следующие параметры:
Параметр | Описание |
hwnd | Дескриптор родительского окна. При вызове функции из Visual FoxPro должен быть равен нулю. |
Operation | Может принимать одно из следующих значений: "find", "explore", "edit", "open" или "print" |
File | Имя файла или папки - в зависимости от значения параметра Operation. |
Parameters | Список параметров, передаваемых загружаемому приложению |
Directory | Путь к файлу, указанному в File |
ShowCmd | Определяет вид главного окна загружаемого приложения |
Если Operation="find", функция выводит диалоговое окно для поиска файлов по условиям. Параметр File должен указывать путь к папке, начиная с которой будет выполняться поиск. Остальные параметры не используются.
Если Operation="explore", функция выводит диалоговое окно - список папок. Параметр File должен указывать путь к папке, содержимое которой нужно посмотреть. Остальные параметры не используются.
Если Operation="edit", функция открывает файл на редактирование, загружая приложение, ассоциированное с расширением файла. Параметр Edit должен содержать имя файла, параметр Directory - указывать путь к этому файлу; если параметр Directory не используется, то параметр Edit должен указывать путь и имя файла.
Если Operation="open", функция выполняет следующие действия: если в File указан исполняемый файл (например, типа EXE), то он запускается на выполнение; загружаемой программе передаётся список параметров, указанных в Parameters; в противном файл открывается на редактирование.
Если Operation="print", то выполняется печать файла на принтере (фактически загружается ассоциированное с расширением файла приложение, которое и печатает документ).
Параметр ShowCmd может принимать значения от 0 до 10, реальный интерес представляют значения, перечисленные в таблице:
ShowCmd | Описание |
0 | Скрывает окно загружаемого приложения и активизирует другое окно. |
1 | Отображает главное окно приложения и делает его активным. Если окно приложения минимизировано или максимизировано, Windows восстанавливает его первоначальный размер и позицию. |
2 | Окно загружаемого приложения минимизировано. |
3 | Раскрывает окно приложения на весь экран и делает его активным. |
4 | Отображает окно приложения в его последних сохранённых размерах, но не делает его активным. |
Примеры использования функции в вашем приложении.
В следующем примере запускается приложение Notepad (блокнот); окно приложения распахивается на весь экран и становится активным:
nReturn = ShellExecute(0,'open','c:\Windows\Notepad.exe',NULL,NULL,3)
В следующем примере загружается приложение MS Word для редактирования файла MyDocument.doc, расположенного в папке c:\MyDocs:
nReturn = ShellExecute(0,'open','MyDocument.doc', NULL,'c:\MyDocs',1)
И последний пример, в котором при помощи MS Word выполняется печать файла MyDocument.doc. MS Word загружается в скрытом (Hide) режиме (окно не выводится, индикатор в панели "Пуск" не отображается). Документ распечатывается на принтере, используемом по умолчанию.
nReturn = ShellExecute(0,'print','c:\MyDocs\MyDocument.doc',NULL,NULL,0)
Функция SHFileOperation
Функция SHFileOperation из библиотеки Shell32.dll выполняет копирование, перемещение, переименование и удаление объектов файловой системы (папок и файлов). В процессе выполнения выводится стандартное окно Windows для отображения процесса, подобное показанному на рисунке:
Вот её прототип:
int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp );
Тип данных LPSHFILEOPSTRUCT - это указатель на структуру SHFILEOPSTRUCT:
typedef struct _SHFILEOPSTRUCT{ HWND hwnd; UINT wFunc; LPCSTR pFrom; LPCSTR pTo; FILEOP_FLAGS fFlags; BOOL fAnyOperationsAborted; LPVOID hNameMappings; LPCSTR lpszProgressTitle; } SHFILEOPSTRUCT, FAR *LPSHFILEOPSTRUCT;
Описание полей структуры SHFILEOPSTRUCT:
Поле | Описание | ||||||||||
hwnd | Дескриптор родительского окна. Это может быть hWnd вашей формы или главного окна Visual FoxPro. | ||||||||||
wFunc |
|
||||||||||
pFrom | Адрес строки, в которой перечислены один или большее количество наименований исходных файлов (возможно, с указанием путей). Если используется более одного наименования файла, то каждая последующая спецификация отделяется от предыдущей нулевым байтом. Строка должна завершаться двумя нулевыми байтами. | ||||||||||
pTo | Адрес строки, в которой указана конечная папка для перемещения (копирования) файлов.Строка должна завершаться двумя нулевыми байтами. | ||||||||||
fFlags | 16-ти разрядное целое. Конкатенация флагов, определяющих порядок выполнения операции. | ||||||||||
fAnyOperationsAborted | В поле записывается ноль, если пользователь прервал операцию, и отличное от нуля значение, если операция завершена успешно. | ||||||||||
hNameMappings | В приложениях на Visual FoxPro не используется. Должен быть равен нулю. | ||||||||||
lpszProgressTitle | В приложениях на Visual FoxPro не используется. Должен быть равен нулю. |
Параметр fFlags определяется как конкатенация (сложение) значений, перечисленных ниже:
fFlags = 512
Если папка, в которую необходимо копировать
файлы, не существует, выводится диалоговое
окно с запросом о создание папки:
fFlags = 256
Отображает шкалу прогресса, но не показывает имена файлов
fFlags = 128
Операция выполняется только над файлами
указанной папки, если для имени и типа файла
указан шаблон (*.*). Над вложенными папками
никаких действий не выполняется.
fFlags = 8
Если при копировании, перемещении или
переименовании файл с указанным именем
уже существует в папке-адресате, то он
будет заменён без предупреждающего
сообщения. Иначе - выводится диалог для
подтверждения замены:
fFlags = 4
Операция выполняется, окно отображения
процесса не выводится.
Объявление функции SHFileOperation в Visual FoxPro:
DECLARE Long SHFileOperation IN Shell32.dll String @ FileOperation
Функция возвращает ноль при успешном выполнении.
Структура FileOperation может быть сформирована в символьной переменной длиной 26 байт; если вы хотите отслеживать ситуацию, когда пользователь отказался от файловой операции в процессе её выполнения, то передавайте эту переменную по ссылке, так как вам в этом случае потребуется проанализировать значение поля fAnyOperationsAborted.
В следующем примере показан код функции FileOperation, которая выполняет файловые операции, используя возможности, предоставляемые функцией SHFileOperation. Функция возвращает .T. при успешном выполнении операции.
FUNCTION FileOperation LPARAMETER tcFrom, tcTo, tnOper * * tcFrom - спецификация исходных файлов * tcTo - спецификация результирующих файлов (папки) * tnOper - определяет тип операции. * tnOper=1 - переместить файлы * tnOper=2 - копировать файлы * tnOper=3 - удалить файлы * tnOper=4 - переименовать файл * LOCAL lcSHFO, lcFrom, lnLenFrom, lcTo, lnLenTo, hGlobalFrom, hGlobalTo LOCAL lnFlag, lnReturn DECLARE Long SHFileOperation IN Shell32.dll String @ DECLARE Long GlobalAlloc IN WIN32API Long, Long DECLARE Long GlobalFree IN WIN32API Long * Начинаем формировать структуру в переменной lcSHFO lcSHFO = BINTOC(thisform.HWnd, '4RS') && Поле hwnd lcSHFO = lcSHFO + BINTOC(tnOper, '4RS') && Поле wFunc - вид операции * Обработка спецификации исходных файлов tcFrom = tcFrom + CHR(0) + CHR(0) && Дописываем нули lnLenFrom = LEN(tcFrom) && Длина исходной строки hGlobalFrom = GlobalAlloc(0x0040, lnLenFrom) && Выделяем для неё блок памяти SYS(2600, hGlobalFrom, lnLenFrom, tcFrom) && и копируем туда строку lcSHFO = lcSHFO + BINTOC(hGlobalFrom, '4RS') && Поле pFrom * Обработка спецификайии результирующих файлов IF tnOper = 3 lcSHFO = lcSHFO + BINTOC(0, '4RS') && для операции удаления ELSE tcTo = tcTo + CHR(0) + CHR(0) && Дописываем нули lnLenTo = LEN(tcTo) && Длина результирующей строки hGlobalTo = GlobalAlloc(0x0040, lnLenTo) && Выделяем для неё блок памяти SYS(2600, hGlobalFrom, lnLenFrom, tcFrom) && и копируем туда строку lcSHFO = lcSHFO + BINTOC(hGlobalTo, '4RS') && Поле pTo ENDIF lnFlag = 8 + 256 lcSHFO = lcSHFO + BINTOC(lnFlag, '2RS') && Поле fFlags lcSHFO = lcSHFO + REPLICATE(CHR(0), 12) && Последние 3 поля структуры * Выполняем операцию lnReturn = SHFileOperation(@lcSHFO) * Чистим память GlobalFree(hGlobalFrom) IF tnOper != 3 GlobalFree(hGlobalTo) ENDIF * Если lnReturn = 0, то операция завершена успешно IF lnReturn != 0 RETURN .f. ENDIF RETURN .t. ENDFUNC
Проанализируем код.
Структура SHFILEOPSTRUCT для функции SHFileOperation формируется в переменной lcSHFO. Записываем в первые четыре байта переменной значение hwnd, в следующие 4 байта - значение wFunc, определяющее характер операции. Поля pFrom и pTo содержат указатели на строки, содержащие информацию о спецификациях исходных и конечных файлов. Каждая такая строка должна заканчиваться двумя нулевыми байтами. Такой вид окончания строки используется потому, что при задании спецификации, например, исходных файлов, могут быть заданы файлы, расположенные в различных папках. В этом случае спецификации этих файлов разделяются одиночным нулевым байтом. Например:
cFiles = 'c:\Foder1\File1.typ' + CHR(0) + 'd:\Folder2\File2.typ' + CHR(0) + CHR(0)
Выделяем блок в глобальной памяти Windows и получаем указатель на него:
hGlobalFrom = GlobalAlloc(0x0040, lnLenFrom)
Переписываем в выделенный блок памяти значение строки спецификации файла:
SYS(2600, hGlobalFrom, lnLenFrom, tcFrom)
Помещаем полученный указатель в поле структуры. Для преобразования целочисленного значения указателя в строку используем функцию BINTOC:
lcSHFO = lcSHFO + BINTOC(hGlobalFrom, '4RS')
Аналогичные действия выполняем и для получения указателя на строку, содержащую спецификацию конечных файлов - если код операции не удаление файлов. Для операции удаления вместо указателя помещаем в структуру ноль.
Далее формируем значение флага fFlags и добавляем его в структуру. Обратите внимание, что поле для хранения флага - двухбайтовое:
lnFlag = 8 + 256 lcSHFO = lcSHFO + BINTOC(lnFlag, '2RS')
Указанные значения флага определяют, что функция будет запрашивать необходимость создания новой папки и не будет запрашивать необходимость замены при одинаковых именах и типах исходных и конечных файлов.
Дописываем в переменную lcSHFO 12 нулевых байтов - это поля структуры fAnyOperationsAborted, hNameMappings и lpszProgressTitle.
После выполнения файловой операции возвращаем Windows память, выделенную функциями GlobalAlloc:
GlobalFree(hGlobalFrom)
Вы можете проверить содержимое поля fAnyOperationsAborted, которое после успешного выполнения функции будет содержать ноль либо отличное от нуля значение, если операция была прервана пользователем. Вот этот код:
IF CTOBIN(SUBSTR(lcSHFO, 19, 4), '4N') != 0 * Код, выполняющийся, если операция прервана пользователем ENDIF
При написании раздела мною не ставилась цель дать информацию о всех Windows API функциях, которые вы могли бы применять в ваших приложениях. Главная цель - объяснить, как, пользуясь описанием любой такой функции в MSDN, правильно её объявить в Visual FoxPro и, самое главное, правильно использовать. В следующих разделах этого руководства постоянно будут применяться различные Windows API функции, но уже без такого подробного объяснения, как здесь.