Здравствуйте, уважаемые коллеги!

Столкнулся с ситуацией: требуется вставить в ImageDataСontrol на карточке картинку из буфера обмена. Не важно, напрямую или через временный файл. Я испытал три различных способа, но все три - безуспешно:

http://community.terrasoft.ua/blogs/6286

Подскажите, пожалуйста, где я ошибся; возможно, кто-то уже решил подобную задачу. Версия 3.2.1.58

Нравится

3 комментария

Судя по Вашему блогу, данные в датасет записались. А если попробовать переприсвоить DataField для контрола картинки?

edtScreenShot.DataField = System.EmptyValue;
edtScreenShot.DataField = Dataset.DataFields('ScreenShot');

Идея интересная, только, конечно, не датафилд обратить в Null, а просто поле отключить-подключить. Вот так:

edtScreenShot.DataFieldName = '';
edtScreenShot.DataFieldName = 'ScreenShot';

Но толку никакого. Мне кажется, что картинка не отрисовывается не из-за отсутствия данных, а именно из-за того, что двоичный Stream не содержит правильного заголовка картинки. Контрол просто не знает, что от него ожидают. Сунули, мол, каких-то каракатиц, а к чему они - неизвестно.

По идее, все дело в том, как сохраняется в буфер обмена само изображение. Думаю, нужно ждать совета разработчиков ядра, которые бы объяснили происходящее с точки зрения контрола.

Показать все комментарии

Здравствуйте, уважаемые коллеги!

Столкнулся с ситуацией: требовалось вставить в ImageDataСontrol на карточке картинку из буфера обмена. К примеру, нажал пользователь PrintScreen, щёлкнул на карточке кнопку, картинка и вставилась. Казалось бы, чего проще... А не тут-то было!

Самый очевидный способ не сработал. Пишет в ответ: "Разрушительный сбой":

var Stream = System.CopyClipboardToStream();
edtScreenShot.DataField.SetValAsBlob(Stream);

Stream этот какой-то странный, ни свойств, ни методов, просто кусок двоичного кода. Я этот код увидел, когда сделал так:

System.StreamToMime(Stream);

На восемь мегабайт каракатиц. Но где наша не пропадала! Есть ведь путь посложнее, взять ImageList, и через Image прочитать картинку из Stream, сохранить в файл, а потом этот файл автоматически открыть методом поля типа Blob.

Написал так:

var Stream = System.CopyClipboardToStream();
var ImageList = Services.CreateItem('ImageList');  
var Image = ImageList.CreateImage();
Image.ImageType = 1;
Image.LoadFromStream(Stream);
Image.SaveToFile('c:\Temp.bmp');

Система всё это лихо выполнила, ни разу не кашлянула. Но файл получился нулевой длины. Так что вставлять в Blob после этой операции уже было нечего...

Наконец (верно от отчаяния) я решил подсунуть вместо этого таинственного Stream известный и понятный ADODB.Stream. Только как бы в него засунуть то, что в буфере обмена? Я написал такое:

var Stream = System.CopyClipboardToStream();
var Mime = System.StreamToMime(Stream);
var ADODBStream = new ActiveXObject('ADODB.Stream');
ADODBStream.Mode = 3;//Кстати, кто знает, что означают эти числа?
ADODBStream.Type = 1;//Расскажите, а то я просто скопировал из другого примера...
ADODBStream.Open();
System.MimeToStream(Mime, ADODBStream);
ADODBStream.SaveToFile('c:\Temp1.bmp');

Способ сработал, все весемь мегабайт каракатиц выгрузились в Temp1.bmp, только файл был не в формате BMP, а именно в виде строки Mime. Естественно, картинку прочитать невозможно.

Итак, у меня ничего не получилось. Но, может быть, я просто пошёл неправильным путём? Кто подскажет, вдруг эта задача уже решалась? Кто что знает о сохранении картинок из буфера обмена, либо об их вставке в Blob-поле? Использовал версию 3.2.1.58.

Нравится

Поделиться

2 комментария

"Будак Анатолий Васильевич" написал:Пишет в ответ: "Разрушительный сбой":

Анатолий, а вы уверены что контрол подключен к DataSet, в корректном состоянии?

Спасибо, Саша, что обратили моё внимание на этот момент! Действительно, здесь стоит посмотреть внимательно. Вот, что я выяснил. Если ставить в контроле по умолчанию ImageType = itBMP, то сообщение о разрушительном сбое пропадает. Его нет и при использовании itJPG (хотя скриншот явно не в виде jpg попадает в Stream). Сообщение о разрушительном сбое бывает только при itPNG. Однако вставки картинки всё равно не происходит, хотя сообщение об ошибке я убрал, принудительно устанавливая ему itBMP перед вставкой. Так что мы на правильном пути!

Датасет, по-видимому, подключен корректно. Рядом с кнопкой "Вставить из буфера" размещена кнопка "Вставить из файла". Там стоит такая конструкция для того же поля того же датасета:

edtScreenShot.DataField.LoadFromFile(FilePath);

Работает безупречно, картинка загружается.

Но ни в чём нельзя быть уверенным до конца. С моим-то склерозом :) Для эксперимента попробовал и такое обращение:

var Dataset = dlData.Dataset;
Dataset.DataFields('ScreenShot').LoadFromFile(FilePath);

Тоже отлично работает.

Ну, и чем чёрт не шутит:

var Dataset = dlData.Dataset;
var Stream = System.CopyClipboardToStream();
Dataset.DataFields('ScreenShot').SetValAsBlob(Stream);

Увы, хоть сообщения об ошибке нет, картинка не видна...

Однако самое поразительное - вот что! Хоть картинки в контроле и не видно, если сделать

Dataset.DataFields('ScreenShot').SaveToFile('c:\Test3.bmp');

то по указанному пути появится восьмимегабайтный файл, со структурой, похожей на bmp (куча каракатиц стройными рядами), но без характерного bmp-заголовка. Который, увы, ни одна графическая программа не считает bmp-файлом. Удивительно ещё и то, что запись сохраняется, и в blob двоичные данные попадают, это видно как в таблице, так и при открытии карточки (ощутимо замедленном из-за такого объёма картинки). Но саму картинку по-прежнему не видно.

Мне кажется, что добавив в Stream правильный заголовок bmp проблема бы решилась. Он явно идёт без него, хотя структура bmp-шная. Но как бы его добавить?

Показать все комментарии