Сканирование WIA-драйвером в Библиотеке Стандартных Подсистем

Программирование - Практика программирования

TWAIN WIA

24
Не секрет, что в БСП не реализована функция получения изображений посредством WIA-драйвера. Однако такая потребность частенько появляется. К примеру, сетевые принтеры и веб-камеры, работающие через стандартный Windows-интерфейс WIA, остаются не у дел. Давайте исправим такую несправедливость!

Описанный прием работает в любой конфигурации, использующей подсистему Работа с файлами из состава БСП.

Внимание! Для этого нам понадобится вмешаться в работу общего модуля РаботаСФайламиСлужебныйКлиент и форму РезультатСканирования обработки Сканирование. Имейте это в виду при обновлении БСП.

Итак, начнем.

1. В общем модуле РаботаСФайламиСлужебныйКлиент нам надо модифицировать экспортную функцию ПроинициализироватьКомпоненту. Суть модификации - если компонента TWAIN не была установлена, то попытаться подсунуть вместо нее нашу компоненту WIA. В разных версиях БСП код незначительно различается, но у меня это выглядит так:

Для БСП 2.4.х.х:

// Инициализация компоненты сканирования.
Функция ПроинициализироватьКомпоненту() Экспорт
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Если СистемнаяИнформация.ТипПлатформы <> ТипПлатформы.Windows_x86
		Или ОбщегоНазначенияКлиентСервер.ЭтоВебКлиент() Тогда 
		Возврат Ложь;
	КонецЕсли;
	
	ИмяПараметра = "СтандартныеПодсистемы.КомпонентаTwain";
	Если ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
		
		// Вызов метода ОбщегоНазначенияКлиент.ПодключитьКомпонентуИзМакета не требуется т.к.
		// Внешняя компонента подключается из макета и сканирование не доступно в веб-клиенте.
		КодВозврата = ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаTWAIN", "twain", ТипВнешнейКомпоненты.Native);
		Если Не КодВозврата Тогда
			Попытка
				ПроверкаНаличияИнтерфейсов = СканированиеWIAКлиент.ПолучитьИнтерфейсWIA();
				ПараметрыПриложения.Вставить(ИмяПараметра, СканированиеWIAКлиент.ЭтотОбъект);
				ПараметрыПриложения.Вставить("СтандартныеПодсистемы.ИнтерфейсWIA", СканированиеWIAКлиент.ПолучитьИнтерфейсWIA());
				Возврат Истина;
			Исключение
				Возврат Ложь;
			КонецПопытки;
		КонецЕсли;
		
		ПараметрыПриложения.Вставить(ИмяПараметра, Новый("AddIn.twain.AddInNativeExtension"));
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

Для БСП 3.0.х.х:

// Инициализация компоненты сканирования.
Функция ПроинициализироватьКомпоненту(ПопытатьсяУстановитьКомпоненту = Истина) Экспорт
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Если СистемнаяИнформация.ТипПлатформы <> ТипПлатформы.Windows_x86
		Или ОбщегоНазначенияКлиентСервер.ЭтоВебКлиент() Тогда 
		Возврат Ложь;
	КонецЕсли;
	
	ИмяПараметра = "СтандартныеПодсистемы.КомпонентаTwain";
	Если ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
		
		// Вызов метода ОбщегоНазначенияКлиент.ПодключитьКомпонентуИзМакета не требуется т.к.
		// Внешняя компонента подключается из макета и сканирование не доступно в веб-клиенте.
		КодВозврата = ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаTWAIN", "twain");
		Если Не КодВозврата Тогда
				
			Если Не ПопытатьсяУстановитьКомпоненту Тогда
				Попытка
					ПроверкаНаличияИнтерфейсов = СканированиеWIAКлиент.ПолучитьИнтерфейсWIA();
					ПараметрыПриложения.Вставить(ИмяПараметра, СканированиеWIAКлиент.ЭтотОбъект);
					ПараметрыПриложения.Вставить("СтандартныеПодсистемы.ИнтерфейсWIA", СканированиеWIAКлиент.ПолучитьИнтерфейсWIA());
					Возврат Истина;
				Исключение
					Возврат Ложь;
				КонецПопытки;
			КонецЕсли;
			
			НачатьУстановкуВнешнейКомпоненты(, "ОбщийМакет.КомпонентаTWAIN");
			
			Возврат ПроинициализироватьКомпоненту(Ложь); // Рекурсивно.
			
		КонецЕсли;
		
		ПараметрыПриложения.Вставить(ИмяПараметра, Новый("AddIn.twain.AddInNativeExtension"));
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

2. В форме РезультатСканирования обработки Сканирование добавляем обработчик события ОбработкаОповещения, который будет перенаправлять реакцию от диалогового окна сканирования WIA на стандартный обработчик ВнешнееСобытие.

&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
	
	Если Источник = "WIA" Тогда
		ВнешнееСобытие("TWAIN", ИмяСобытия, Параметр);
	КонецЕсли;
	
КонецПроцедуры

3. Добавляем общий модуль СканированиеWIAКлиент с флажками Клиент (управляемое приложение) и Клиент (обычное приложение) и следующим нехитрым содержанием:


Функция ПолучитьИнтерфейсWIA() Экспорт
	
	Соответсвие = Новый Соответствие;
	
	Соответсвие.Вставить("DeviceManager", Новый COMОбъект("WIA.DeviceManager"));
	Соответсвие.Вставить("ImageFile", Новый COMОбъект("WIA.ImageFile"));
	Соответсвие.Вставить("CommonDialog", Новый COMОбъект("WIA.CommonDialog"));
	Соответсвие.Вставить("ImageProcess", Новый COMОбъект("WIA.ImageProcess"));
	
	Возврат Соответсвие;
	
КонецФункции

Функция ЕстьУстройства() Экспорт
	
	DeviceInfos = ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["DeviceManager"].DeviceInfos();
	Возврат DeviceInfos.Count() > 0;
	
КонецФункции

Функция ПолучитьУстройства() Экспорт
	
	Массив = Новый Массив;
	
	Для Каждого DeviceInfo Из ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["DeviceManager"].DeviceInfos() Цикл
		Массив.Добавить(DeviceInfo.Properties("Name").Value);
	КонецЦикла;
	
	Возврат СтрСоединить(Массив, Символы.ПС);
	
КонецФункции

Функция ПолучитьУстройство(ИмяУстройства)
	
	Для Каждого DeviceInfo Из ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["DeviceManager"].DeviceInfos() Цикл
		Если DeviceInfo.Properties("Name").Value = ИмяУстройства Тогда
			Возврат DeviceInfo;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Неопределено;
	
КонецФункции

Функция ПолучитьНастройку(ИмяУстройства, ИмяНастройки) Экспорт
	
	CurrentDeviceInfo = ПолучитьУстройство(ИмяУстройства);
	
	Если CurrentDeviceInfo = Неопределено Тогда
		Возврат -1;
	КонецЕсли;
	
	Если ИмяНастройки = "XRESOLUTION" Тогда
		
	ИначеЕсли ИмяНастройки = "YRESOLUTION" Тогда
		
	КонецЕсли;
	
	Возврат -1;
	
КонецФункции

Процедура НачатьСканирование(ПоказыватьДиалог,
								ИмяУстройства, 
								ФорматКартинки, 
								Разрешение, 
								Цветность, 
								Поворот, 
								РазмерБумаги,
								ПараметрСжатие,
								ДвустороннееСканирование) Экспорт
	
	CurrentDeviceInfo = ПолучитьУстройство(ИмяУстройства);
	
	Если CurrentDeviceInfo = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СоответствиеФорматID = Новый Соответствие;
	СоответствиеФорматID.Вставить(-1, "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("BMP", "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("PNG", "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("GIF", "{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("JPG", "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("JPEG", "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}");
	СоответствиеФорматID.Вставить("TIFF", "{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}");
	
	СоответствиеЦветностьID = Новый Соответствие;
	СоответствиеЦветностьID.Вставить(-1, 0);	//Не задано
	СоответствиеЦветностьID.Вставить(0, 4);		//Монохромное (текст)
	СоответствиеЦветностьID.Вставить(1, 2);		//Чернобелое
	СоответствиеЦветностьID.Вставить(2, 1);		//Цветное

	ImageFile = ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["ImageFile"];
	CommonDialog = ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["CommonDialog"];
	
	WiaDeviceType = 1; //Сканер
	WiaImageIntent = СоответствиеЦветностьID.Получить(Цветность);
	WiaMaximizeQuality = 131072;
	WiaMinimizeSize = 65536;
	WiaImageBias = ?(Разрешение = -1 ИЛИ Разрешение > 300, WiaMaximizeQuality, WiaMinimizeSize);
	
	Image = CommonDialog.ShowAcquireImage(WiaDeviceType, WiaImageIntent, WiaImageBias, СоответствиеФорматID.Получить(ФорматКартинки));
	Если Image = Неопределено Тогда
		Оповестить("UserPressedCancel", Неопределено, "WIA");
		Возврат;
	КонецЕсли;
	//ImageProcess = ПараметрыПриложения["СтандартныеПодсистемы.ИнтерфейсWIA"]["ImageProcess"];
	//ImageProcess.Filters.Add(ImageProcess.FilterInfos("Convert").FilterID);
	//ImageProcess1 = ImageProcess.Filters(1);
	//Для К = 1 По ImageProcess1.Properties.Count Цикл
	//	Если ImageProcess1.Properties(К).Name = "FormatID" Тогда
	//		ImageProcess1.Properties(К).Value = СоответствиеФорматID.Получить(ФорматКартинки);
	//		Прервать;
	//	КонецЕсли;
	//КонецЦикла;
	//
	//Image = ImageProcess.Apply(Image); //применяем фильтр на изображение
	
	ИмяФайла = ПолучитьИмяВременногоФайла(ФорматКартинки);
	
    Image.SaveFile(ИмяФайла); //сохраним на жесткий диск объект WIA
	
	Оповестить("ImageAcquired", ИмяФайла, "WIA");
	
КонецПроцедуры

Вуаля!

24

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. DmitrySinichnikov 156 10.10.18 00:42 Сейчас в теме
Доброй ночи! Спасибо за описание работы с компонентой.
Вы не могли бы подсказать где вы нашли документацию по работе с ней. Я перечитал всю портянку мелкомягких https://docs.microsoft.com/ru-ru/windows/desktop/wia/-wia-startpage но не нашел описания работы с wia через ком. Например WIA.CommonDialog, откуда вы взяли данную команду, что она выполняет и т.д. Очень хотелось бы разобраться самому досконально, но либо я туплю либо инфа "секретная".
2. nuctoh 24 10.10.18 10:47 Сейчас в теме
(1) День добрый! Мне на глаза в свое время попался макрос на VB. Кто его писал - ХЗ. Когда у меня возникла вышеописанная задача в 1С, я просто нашел его и портировал.
Оставьте свое сообщение