Сканирование картинок при помощи TWAIN-драйвера в .NET

В Windows-приложениях, предназначенных для обработки графики, чаще всего используются TWAIN API-функции. К сожалению, .NET Framework не имеет встроенной поддержки для TWAIN, поэтому с TWAIN приходится работать через методы фреймворка для доступа к этим API. В приведённом примере не содержится готовой библиотеки, а только некоторые существенные шаги по минимальной адаптации к TWAIN приложений написанных в .NET.

Детали

Первым шагом было портирование самых важных частей TWAIN.H, они находятся в TwainDefs.cs . Основная логика для вызова TWAIN расположена в классе Twain, в файле TwainLib.cs . Так как TWAIN API предоставляются в виде Windows DLL (twain_32.dll), то необходимо использовать механизм DllImport для взаимодействия со старым кодом. Эта DLL имеет центральную DSM_Entry() с порядковым номером функции №1, экспортируемым в качестве отправной точки для TWAIN. Эта функция имеет множество параметров, последний из которых является переменной типа!

[DllImport("twain_32.dll", EntryPoint="#1")]
private static extern TwRC DSMparent(
    [In, Out] TwIdentity origin,
    IntPtr zeroptr,
    TwDG dg, TwDAT dat, TwMSG msg,
    ref IntPtr refptr );
Класс Twain имеет простой 5-ступенчатый интерфейс:

class Twain
{
    Init();
    Select();
    Acquire();
    PassMessage();
    TransferPictures();
}
Для различных колбэков, TWAIN использует специальные Windows-сообщения, которые должны быть пойманы из цикла сообщений приложения. В .NET нашёлся единственный подходящий для этого способ IMessageFilter.PreFilterMessage(), который активируется вызовом Application.AddMessageFilter(). В фильтре мы должны направлять каждое сообщение в Twain.PassMessage().