Дело в том, что потребовалось получать и обрабатывать несколько снимков за раз. Я думал обойтись штатным OpenFileDialog. Ведь цифровая камера, будучи подключенной по USB к компьютеру, притворяется обычной папкой. Но, оказалось, "папка" эта не совсем обычная. В частности, например, при попытке доступа к изображению система создает его копию во временных файлах, и позволяет работать уже с этой копией. Если же выбрать несколько изображений, то OpenFileDialog вернёт вместо путей что-то маловразумительное типа "004\Root\IMG_1111" "004\Root\IMG_1112" "004\Root\IMG_1113".
Поэтому возникла мысль использовать обходной путь. В Windows есть нечто под названием Windows Image Acquisition. Статус этой технологии мне остался до конца неясным - то ли она уже устарела, то ли еще нет - но и в XP, и в 7 эта штука присутствует, хоть и двух разных версий.
Сначала попытался использовать WIA первой версии. Думал, обратная совместимость вывезет. Работаю я на WinXP, там WIA 1.0, что называется, "из коробки". Итак, добавляю в проект ссылку на Microsoft Windows Image Acquisition 1.01 Type Library (Add Reference, вкладка COM), получаю пространство имен WIALib и в нем кучку классов, с которыми уже можно работать:
using WIALib; ... private void button1_Click(object sender, EventArgs e) { object selectUsingUI = System.Reflection.Missing.Value; try { // создаем класс для работы с WIA WiaClass wiamanager = new WiaClass(); // выводим диалог выбора цифровой камеры ItemClass wiaRoot = (ItemClass)wiamanager.Create(ref selectUsingUI); if (wiaRoot == null) return; // выводим диалог выбора изображений, хранящихся в камере CollectionClass wiaPics = (CollectionClass)wiaRoot.GetItemsFromUI(WiaFlag.UseCommonUI, WiaIntent.ImageTypeColor); // каждое выбранное изображение копируем в каталог с нашей программой if (wiaPics != null) foreach (object wiaObj in wiaPics) { ItemClass wiaItem = (ItemClass)Marshal.CreateWrapperOfType(wiaObj, typeof(ItemClass)); string tmpFileName = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + wiaItem.Name; wiaItem.Transfer(tmpFileName, false); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }Всё работает чудесно. Но обнаружились два момента. Первое: без дополнительной обработки изображения получаются чудовищного размера (без всякого сжатия), и второе, самое главное: этот способ не сработал в Windows 7. А именно, при запуске своей программы на Windows 7 64bit я получил такое сообщение об ошибке: Сбой при получении производства объектов класса COM для компонента с CLSID {4EC4272E-2E6F-4EEB-91D0-EBC4D58E8DEE} в результате следующей ошибки: 80040154. В общем, похоже, в современных виндах WIA 1.0 нет.
Пришлось обратиться к WIA 2.0. Под Windows XP потребовалось её установить дополнительно. Я брал дистрибутив отсюда: http://vbnet.mvps.org/files/updates/wiaautsdk.zip. Дальше добавляю в проект ссылку на Microsoft Windows Image Acquisition Library v2.0 (всё на той же вкладке COM) и получаю пространство имен WIA. Использовал это примерно так:
using WIA; ... private void button1_Click(object sender, EventArgs e) { // создаем класс для работы с камерой WIA.CommonDialogClass dlg = null; try { dlg = new WIA.CommonDialogClass(); } catch(Exception ex) { MessageBox.Show("Невозможно подключиться к интерфейсу работы с камерой:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } if (dlg == null) return; // выбираем камеру WIA.DeviceClass d = null; try { d = (WIA.DeviceClass)dlg.ShowSelectDevice(WIA.WiaDeviceType.CameraDeviceType, true, false); } catch (Exception ex) { MessageBox.Show("Невозможно подключиться к камере:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } if (d == null) return; // выбираем изображения WIA.Items items = dlg.ShowSelectItems(d, WIA.WiaImageIntent.ColorIntent, WIA.WiaImageBias.MinimizeSize, false, true, false); if (items != null) foreach (WIA.Item item in items) { WIA.ImageFile img = (WIA.ImageFile)item.Transfer(WIA.FormatID.wiaFormatJPEG); // выясняем имя и расширение выбранного изображения string tmpFileName = "", tmpFileExt = ""; foreach (WIA.Property prop in item.Properties) { if (prop.Name == "Item Name") tmpFileName = prop.get_Value().ToString(); if (prop.Name == "Filename extension") tmpFileExt = prop.get_Value().ToString(); } if (tmpFileExt == "") tmpFileExt = img.FileExtension; if (Path.HasExtension(tmpFileName)) tmpFileExt = ""; // копируем выбранное изображение в каталог с нашей программой string tmpFullName = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + tmpFileName + ((tmpFileExt != "") ? "." : "") + tmpFileExt; img.SaveFile(tmpFullName); } }Код получился немного длинее, но это из-за проверок. Основной плюс - помимо того, что эта конструкция сработала и в Windows 7 - возможность сохранять изображения в формате JPEG.
Кстати, во втором примере в свойствах изображения есть много интересного. Я себе на память сделал скриншот: