А для чего это нужно? ЭКСПЕРИМЕНТЫ!
Конечно же 1С не предоставляет пользователю возможность использования функций Win 32 API. Такую возможность можно решить при помощи ActiveX OLE-клиента такого как dynwrap.dll или dynwrapx.dll, причем dynwrapх.dll намного интересен своими возможностями.
Немного истории: Библиотека dynwrap.dll является результатом труда нескольких разработчиков и была выпущена 10 лет назад. Основное предназначение вызов функций Win 32 API в WHS скриптах. В сентябре 2008 года появился новый расширенный вариант библиотеки dynwrapх.dll, на примере использования которой мы и остановимся.
Пример использования библиотеки для посылки сообщения в mailslot\messngr аля Net Send:
Для начала ее зарегистрируем:
regsvr32.exe <путь-к-компоненту>\dynwrapx.dll - для всех пользователей.
regsvr32.exe /i <путь-к-компоненту>\dynwrapx.dll - для текущего пользователя.
Используем в 1С - Wrap = CreateObject("DynamicWrapperX"); далее регистрируем вызовы функций
Wrap.Register("KERNEL32.DLL", "CreateFile", "i=sllllll", "r=l");
Wrap.Register("KERNEL32.DLL", "WriteFile", "i=lllll", "r=l");
Wrap.Register("KERNEL32.DLL", "CloseHandle", "i=l", "r=l");
Инициализируем переменные
GENERIC_READ = 2147483648;
GENERIC_WRITE = 1073741824;
FILE_SHARE_READ = 1;
FILE_SHARE_WRITE = 2;
OPEN_EXISTING = 3;
FILE_ATTRIBUTE_NORMAL = 128;
MessageText = AnsiToOem("Всем ПРИВЕТ!");
AddFrom = AnsiToOem("От друзей");
AddTo = "SERVER";
MailslotName = "\\" + AddTo+"\mailslot\messngr";
Если Wrap<>0 Тогда
hFile = Wrap.CreateFile(MailslotName, GENERIC_WRITE, FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Если hFile>0 Тогда
// структура MSG должна быть
// FromName + CHR(0) + ToComp + CHR(0) + MSG + CHR(0) + CHR(0)
// длина не более 424 символов
MSG = Wrap.Space(425);
Обязательно запоминаем ссылку на переменную
pStr = Wrap.StrPtr(MSG);
BytesBeSend = 0;
Для i=1 По СтрДлина(AddFrom) Цикл
Wrap.NumPut(КодСимв(Сред(AddFrom,i,1)),pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
КонецЦикла;
Wrap.NumPut(0,pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
Для i=1 По СтрДлина(AddTo) Цикл
Wrap.NumPut(КодСимв(Сред(AddTo,i,1)),pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
КонецЦикла;
Wrap.NumPut(0,pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
Для i=1 По СтрДлина(MessageText) Цикл
КодС = КодСимв(Сред(MessageText,i,1));
Wrap.NumPut(КодС,pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
КонецЦикла;
Wrap.NumPut(0,pStr,BytesBeSend,"b");
ByesBeSend = BytesBeSend +1;
Wrap.NumPut(0,pStr,BytesBeSend,"b");
BytesBeSend = BytesBeSend +1;
cbWritten = " ";
pcbWritten = Wrap.StrPtr(cbWritten);
fResult = Wrap.WriteFile(hFile, pStr, BytesBeSend, pcbWritten, 0);
Wrap.CloseHandle(hFile);
Если fResult=1 Тогда
cbWritten = Wrap.NumGet(pcbWritten,0,"l");
Если cbWritten>0 Тогда
Сообщить("Сообщение доставлено");
Иначе
Сообщить("Сообщение не отправлено");
КонецЕсли;
КонецЕсли;
Вот и все сообщение отправили или не отправили :-) самое главное при использовании функций возвращающих или передаваемых значения пользоваться структурами передачи/приема в данном примере передается указатель на строку содержащую 3 раздела От Кому Сообщение после каждого символ 0 и в конце лидирующий 0. Такую структуру создать штатными средствами 1С "очень сложно".
Это только один из примеров. В библиотека MSDN можно найти множество полезных функций.
Данный пример позволяет реализацию функции "копирования файлов" при чем как показала практика максимальная скорость достигается применение буфера данных 65535 байт при этом возможно отслеживание копирования (%, различные прогресс-бары, докачка) и конечно не забываем про разгрузку процессора 1 мс.
Пример №2 Получение абсолютных координат окна
Регистрируем функцию
Wrap.Register("USER32.DLL", "GetWindowRect", "i=lp", "r=l");
1 параметр дескриптор окна (его можно найти как минимум по 2 параметрам 1 заголовок, 2 класс) или при помощи ВК FormEx (респект! разработчикам)
2 ссылка на структуру Rect (типа)
typedef struct _RECT
{
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;
в 1с будет немного кузяво
Rect = Wrap.Space(256); // необходимо 4 DWord
Обязательно сохраняем указатель на переменную
pStr = Wrap.StrPtr(Rect);
Wrap.GetWindowRect(ДискрипторОкна, Rect);
Учитывая что такой тип данных в 1С не существует, то Rect 1С убила - но идем по сохраненному указателю
и вычитываем Rect только так
left = Wrap.NumGet(pStr,0,"l");
top = Wrap.NumGet(pStr,4,"l");
right = Wrap.NumGet(pStr,8,"l");
bottom = Wrap.NumGet(pStr,12,"l");
Не забываем, что мы получили абсолютные координаты окна (компонента формы и тп) далее мы можем размер окна изменить (как минимум 3 способа Win 32 API + FormEx).
Чуть позже рассмотрим пример как же все таки обработать внешнее событие если окно не имеет фокуса или открыто выпадающее меню на форме (созданное разными вариантами в тч и штатном - ВыбратьЗначение)