Esempio n. 1
0
 public static extern ReturnCode DsmWinOld(
     [In, Out] TWIdentity origin,
     [In, Out] TWIdentity destination,
     DataGroups dg,
     DataArgumentType dat,
     Message msg,
     [In, Out] TWCallback2 data);
Esempio n. 2
0
 public static extern ReturnCode DsmLinux(
     [In, Out] TWIdentity origin,
     [In, Out] TWIdentity destination,
     DataGroups dg,
     DataArgumentType dat,
     Message msg,
     [In, Out] TWDeviceEvent data);
Esempio n. 3
0
 public static extern ReturnCode DsmWinNew(
     [In, Out] TWIdentity origin,
     [In, Out] TWIdentity destination,
     DataGroups dg,
     DataArgumentType dat,
     Message msg,
     [In, Out] TWEntryPoint data);
Esempio n. 4
0
        private ScanForm()
        {
            InitializeComponent();
            appId   = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly());
            session = new TwainSession(appId);

            session.TransferReady   += new EventHandler <TransferReadyEventArgs>(session_TransferReady);
            session.DataTransferred += new EventHandler <DataTransferredEventArgs>(session_DataTransferred);

            session.Open();

            scanner = session.ShowSourceSelector();

            if (scanner == null)
            {
                this.DialogResult = DialogResult.Abort;
                session.Close();
                return;
            }

            ReturnCode rc = scanner.Open();

            if (rc != ReturnCode.Success)
            {
                this.DialogResult = System.Windows.Forms.DialogResult.Abort;
                session.Close();
                return;
            }
        }
Esempio n. 5
0
 public static ReturnCode DsmEntry(
     TWIdentity origin,
     TWIdentity destination,
     DataGroups dg,
     DataArgumentType dat,
     Message msg,
     ref DataGroups data)
 {
     if (PlatformInfo.Current.IsWindows)
     {
         if (PlatformInfo.Current.UseNewWinDSM)
         {
             return(NativeMethods.DsmWinNew(origin, destination, dg, dat, msg, ref data));
         }
         else
         {
             return(NativeMethods.DsmWinOld(origin, destination, dg, dat, msg, ref data));
         }
     }
     else if (PlatformInfo.Current.IsLinux)
     {
         return(NativeMethods.DsmLinux(origin, destination, dg, dat, msg, ref data));
     }
     throw new PlatformNotSupportedException();
 }
Esempio n. 6
0
        ReturnCode HandleCallback(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, IntPtr data)
        {
            if (origin != null && CurrentSource != null && origin.Id == CurrentSource.Identity.Id && _state >= 5)
            {
                PlatformInfo.Current.Log.Debug("Thread {0}: CallbackHandler at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, msg);
                // spec says we must handle this on the thread that enabled the DS.
                // by using the internal dispatcher this will be the case.

                // In any event the trick to get this thing working is to return from the callback first
                // before trying to process the msg or there will be unpredictable errors.

                // changed to sync invoke instead of begininvoke for hp scanjet.
                if (origin.ProductName.IndexOf("scanjet", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    _msgLoopHook?.Invoke(() =>
                    {
                        HandleSourceMsg(msg);
                    });
                }
                else
                {
                    _msgLoopHook?.BeginInvoke(() =>
                    {
                        HandleSourceMsg(msg);
                    });
                }
                return(ReturnCode.Success);
            }
            return(ReturnCode.Failure);
        }
Esempio n. 7
0
        private static TwainSession InitTwain()
        {
            var twain = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()));

            twain.TransferReady += (s, e) =>
            {
                Console.WriteLine("Got xfer ready on thread {0}.", Thread.CurrentThread.ManagedThreadId);
            };
            twain.DataTransferred += (s, e) =>
            {
                if (e.NativeData != IntPtr.Zero)
                {
                    Console.WriteLine("SUCCESS! Got twain data on thread {0}.", Thread.CurrentThread.ManagedThreadId);
                }
                else
                {
                    Console.WriteLine("BUMMER! No twain data on thread {0}.", Thread.CurrentThread.ManagedThreadId);
                }
            };

            twain.SourceDisabled += (s, e) =>
            {
                Console.WriteLine("Source disabled on thread {0}.", Thread.CurrentThread.ManagedThreadId);
                var rc = twain.CurrentSource.Close();
                rc = twain.Close();
            };
            return(twain);
        }
Esempio n. 8
0
 public static extern ReturnCode DsmWinNew(
     [In, Out] TWIdentity origin,
     IntPtr zero,
     DataGroups dg,
     DataArgumentType dat,
     Message msg,
     [In, Out] TWIdentity data);
Esempio n. 9
0
        public void VerifyState_No_Throws_When_State_Is_Not_Enforced()
        {
            ITwainSessionInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));

            session.EnforceState = false;
            session.ChangeState(4, false);

            session.VerifyState(6, 6, DataGroups.Image, DataArgumentType.ImageNativeXfer, Message.Get);
        }
Esempio n. 10
0
        public void Enforce_Manufacturer_String_Length()
        {
            TWIdentity target = new TWIdentity();

            var overLength = TwainConst.String32;

            string badString = new String('a', overLength);

            target.Manufacturer = badString;
        }
Esempio n. 11
0
        public void Enforce_ProductName_String_Length()
        {
            TWIdentity target = new TWIdentity();

            var overLength = TwainConst.String32;

            string badString = new String('a', overLength);

            target.ProductName = badString;
        }
Esempio n. 12
0
        public void Scan()
        {
            var applicationID = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly());

            Session = new TwainSession(applicationID);
            Session.TransferReady   += Session_TransferReady;
            Session.DataTransferred += Session_DataTransferred;
            Session.SourceDisabled  += Session_SourceDisabled;
            Session.Open();
            DataSource dataSource = Session.FirstOrDefault();

            dataSource.Open();
            dataSource.Enable(SourceEnableMode.NoUI, false, WindowHandle);
        }
Esempio n. 13
0
        public TwainVM()
        {
            DataSources    = new ObservableCollection <DataSourceVM>();
            CapturedImages = new ObservableCollection <ImageSource>();

            //this.SynchronizationContext = SynchronizationContext.Current;
            var appId = TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Audio, Assembly.GetEntryAssembly());

            session = new TwainSession(appId);
            session.TransferError   += Session_TransferError;
            session.TransferReady   += Session_TransferReady;
            session.DataTransferred += Session_DataTransferred;
            session.SourceDisabled  += Session_SourceDisabled;
            session.StateChanged    += (s, e) => { RaisePropertyChanged(() => State); };
        }
Esempio n. 14
0
        private static TwainSession InitTwain()
        {
            var twain = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()));

            twain.TransferReady += (s, e) =>
            {
                Console.WriteLine("Got xfer ready on thread {0}.", Thread.CurrentThread.ManagedThreadId);
            };

            twain.SourceDisabled += (s, e) =>
            {
                Console.WriteLine("Source disabled on thread {0}.", Thread.CurrentThread.ManagedThreadId);
                var rc = twain.CurrentSource.Close();
                rc = twain.Close();
            };
            return(twain);
        }
Esempio n. 15
0
        DataSource GetSourceInstance(ITwainSessionInternal session, TWIdentity sourceId)
        {
            DataSource source = null;

            PlatformInfo.Current.Log.Debug("Source id = {0}", sourceId.Id);
            var key = string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}|{3}", sourceId.Id, sourceId.Manufacturer, sourceId.ProductFamily, sourceId.ProductName);

            if (_ownedSources.ContainsKey(key))
            {
                source = _ownedSources[key];
            }
            else
            {
                _ownedSources[key] = source = new DataSource(session, sourceId);
            }
            return(source);
        }
Esempio n. 16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TwainSession" /> class.
        /// </summary>
        /// <param name="appId">The app id that represents calling application.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public TwainSession(TWIdentity appId)
        {
            if (appId == null)
            {
                throw new ArgumentNullException("appId");
            }

            _appId        = appId;
            _ownedSources = new Dictionary <string, DataSource>();
            if (PlatformInfo.Current.IsSupported)
            {
                ((ITwainSessionInternal)this).ChangeState(2, false);
            }
#if DEBUG
            // defaults to false on release since it's only useful during dev
            EnforceState = true;
#endif
        }
Esempio n. 17
0
        public void Setting_and_Unsetting_the_Shared_Flag_Properties_Works()
        {
            TWIdentity id = new TWIdentity();

            // these 2 flag properties are store in same int value so needs to test together

            id.DataFunctionalities = DataFunctionalities.App2;
            id.DataGroup           = DataGroups.Audio;
            Assert.AreEqual(DataFunctionalities.App2, id.DataFunctionalities);
            Assert.AreEqual(DataGroups.Audio, id.DataGroup);

            // clear needs to be tested
            id.DataFunctionalities = DataFunctionalities.None;
            Assert.AreEqual(DataFunctionalities.None, id.DataFunctionalities);
            Assert.AreEqual(DataGroups.Audio, id.DataGroup, "Cleared incorrectly.");

            id.DataGroup = DataGroups.None;
            Assert.AreEqual(DataGroups.None, id.DataGroup);
        }
    void Scan()
    {
        var identity = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly());
        var twain    = new TwainSession(identity);

        twain.Open();
        twain.DataTransferred += (s, e) =>
        {
            var stream = e.GetNativeImageStream();
            var image  = Image.FromStream(stream);
            // Do things with the image...
        };
        var source = twain.First();

        Console.WriteLine($"Scanning from {source.Name}...");
        var openCode = source.Open();

        Console.WriteLine($"Open: {openCode}");
        source.Enable(SourceEnableMode.NoUI, false, IntPtr.Zero);
    }
Esempio n. 19
0
 public static ReturnCode DsmEntry(
     TWIdentity origin,
     Message msg,
     TWIdentity data)
 {
     if (PlatformInfo.Current.IsWindows)
     {
         if (PlatformInfo.Current.UseNewWinDSM)
         {
             return(NativeMethods.DsmWinNew(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data));
         }
         else
         {
             return(NativeMethods.DsmWinOld(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data));
         }
     }
     else if (PlatformInfo.Current.IsLinux)
     {
         return(NativeMethods.DsmLinux(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data));
     }
     throw new PlatformNotSupportedException();
 }
Esempio n. 20
0
        static void Main(string[] args)
        {
            if (PlatformInfo.Current.IsApp64Bit)
            {
                Console.WriteLine("Platform: 64 bit");
            }
            else
            {
                Console.WriteLine("Platform: 32 bit");
            }
            var twain = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()));

            twain.Open();
            Console.WriteLine("Listing TWAIN devices...");
            foreach (var device in twain)
            {
                Console.WriteLine($"Device: {device.Name}");
                Console.WriteLine($"\tId: {device.Id}");
                Console.WriteLine($"\tManufacturer: {device.Manufacturer}");
                Console.WriteLine($"\tProductFamily: {device.ProductFamily}");
                Console.WriteLine($"\tProtocolVersion: {device.ProtocolVersion}");
            }
            twain.Close();
        }
Esempio n. 21
0
        private void FormScan_Load(object sender, EventArgs e)
        {
            var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly());

            session = new TwainSession(appId);
            session.TransferReady   += Session_TransferReady;
            session.DataTransferred += Session_DataTransferred;
            session.TransferError   += Session_TransferError;
            session.SourceDisabled  += Session_SourceDisabled;
            session.Open();

            foreach (DataSource ds in session)
            {
                cboxScanner.Items.Add(ds.Name);
            }

            cboxScanner.Text  = mSettings.ScannerName;
            cbDuplex.Checked  = mSettings.ScannerDuplex;
            cboxFlipType.Text = mSettings.ScannerFlipType;
            // FIXME: Allow BW pixel type
            //cboxPixelType.Text = mSettings.ScannerPixelType;
            cboxPixelType.Text    = "Color";
            cboxPixelType.Enabled = false;
        }
Esempio n. 22
0
        void DoTwainWork()
        {
            try
            {
                eventLog1.WriteEntry("Getting ready to do twain stuff on thread " + Thread.CurrentThread.ManagedThreadId);
                //Thread.Sleep(1000);
                twain = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()));
                twain.TransferReady += (s, e) =>
                {
                    eventLog1.WriteEntry("Got xfer ready on thread " + Thread.CurrentThread.ManagedThreadId);
                };
                twain.DataTransferred += (s, e) =>
                {
                    if (e.NativeData != IntPtr.Zero) //else if (!string.IsNullOrWhiteSpace(e.FileDataPath))
                    {
                        eventLog1.WriteEntry("SUCCESS! Got twain data on thread " + Thread.CurrentThread.ManagedThreadId);

                        try
                        {
                            byte[] msg = EncodeOutgoingMessage(e.DataSource.Name);

                            stream.Write(msg, 0, msg.Length);
                            stream.Flush();

                            eventLog1.WriteEntry("Attempting to read the image");

                            Stream imgStr = e.GetNativeImageStream();

                            if (imgStr != null)
                            {
                                eventLog1.WriteEntry("Attempting to read the image 1, length:" + imgStr.Length);

                                var imglen = EncodeOutgoingMessage("Img length:" + imgStr.Length.ToString());
                                stream.Write(imglen, 0, imglen.Length);
                                stream.Flush();

                                using (var memoryStream = new MemoryStream())
                                {
                                    // !!!
                                    imgStr.CopyTo(memoryStream);
                                    var imgBytes      = memoryStream.ToArray();
                                    var b64img        = Convert.ToBase64String(imgBytes);
                                    var preparedBytes = EncodeOutgoingMessage(b64img);
                                    stream.Write(preparedBytes, 0, preparedBytes.Length);
                                    stream.Flush();
                                    eventLog1.WriteEntry("Attempting to read the image 2");
                                }
                            }
                            else
                            {
                                eventLog1.WriteEntry("Attempting to read the image 3");

                                byte[] msgNoImg = EncodeOutgoingMessage("No image!?");

                                stream.Write(msgNoImg, 0, msgNoImg.Length);
                                stream.Flush();
                            }
                        }
                        catch (Exception ex)
                        {
                            eventLog1.WriteEntry("Error writing response! " + ex.Message + "\n" + ex.StackTrace);
                        }
                    }
                    else
                    {
                        eventLog1.WriteEntry("BUMMER! No twain data on thread " + Thread.CurrentThread.ManagedThreadId);
                    }
                };

                twain.SourceDisabled += (s, e) =>
                {
                    eventLog1.WriteEntry("Source disabled on thread " + Thread.CurrentThread.ManagedThreadId);
                    var rc = twain.CurrentSource.Close();
                    rc = twain.Close();
                };
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error creating twain! " + ex.Message);
            }
            /////////////
            try
            {
                var rc = twain.Open();

                if (rc == ReturnCode.Success)
                {
                    var hit = twain.FirstOrDefault(s => string.Equals(s.Name, SAMPLE_SOURCE));
                    if (hit == null)
                    {
                        eventLog1.WriteEntry("The sample source \"" + SAMPLE_SOURCE + "\" is not installed.");
                        twain.Close();
                    }
                    else
                    {
                        rc = hit.Open();

                        if (rc == ReturnCode.Success)
                        {
                            eventLog1.WriteEntry("Starting capture from the sample source...");
                            rc = hit.Enable(SourceEnableMode.NoUI, false, IntPtr.Zero);
                        }
                        else
                        {
                            twain.Close();
                        }
                    }
                }
                else
                {
                    eventLog1.WriteEntry("Failed to open dsm with rc=" + rc);
                }
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error opening twain: " + ex.Message);
            }
        }
Esempio n. 23
0
        private void SetupTwain()
        {
            var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly());

            _twain = new TwainSession(appId);
            _twain.StateChanged += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("State changed to " + _twain.State + " on thread " + Thread.CurrentThread.ManagedThreadId);
            };
            _twain.TransferError += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Got xfer error on thread " + Thread.CurrentThread.ManagedThreadId);
            };
            _twain.DataTransferred += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Transferred data event on thread " + Thread.CurrentThread.ManagedThreadId);

                // example on getting ext image info
                var infos = e.GetExtImageInfo(ExtendedImageInfo.Camera).Where(it => it.ReturnCode == ReturnCode.Success);
                foreach (var it in infos)
                {
                    var values = it.ReadValues();
                    PlatformInfo.Current.Log.Info(string.Format("{0} = {1}", it.InfoID, values.FirstOrDefault()));
                    break;
                }

                // handle image data
                Image img = null;
                if (e.NativeData != IntPtr.Zero)
                {
                    var stream = e.GetNativeImageStream();
                    if (stream != null)
                    {
                        img = Image.FromStream(stream);
                    }
                }
                else if (!string.IsNullOrEmpty(e.FileDataPath))
                {
                    img = new Bitmap(e.FileDataPath);
                }
                if (img != null)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        if (pictureBox1.Image != null)
                        {
                            pictureBox1.Image.Dispose();
                            pictureBox1.Image = null;
                        }
                        pictureBox1.Image = img;
                    }));
                }
            };
            _twain.SourceDisabled += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Source disabled event on thread " + Thread.CurrentThread.ManagedThreadId);
                this.BeginInvoke(new Action(() =>
                {
                    btnStopScan.Enabled     = false;
                    btnStartCapture.Enabled = true;
                    panelOptions.Enabled    = true;
                    LoadSourceCaps();
                }));
            };
            _twain.TransferReady += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Transferr ready event on thread " + Thread.CurrentThread.ManagedThreadId);
                e.CancelAll = _stopScan;
            };

            // either set sync context and don't worry about threads during events,
            // or don't and use control.invoke during the events yourself
            PlatformInfo.Current.Log.Info("Setup thread = " + Thread.CurrentThread.ManagedThreadId);
            _twain.SynchronizationContext = SynchronizationContext.Current;
            if (_twain.State < 3)
            {
                // use this for internal msg loop
                _twain.Open();
                // use this to hook into current app loop
                //_twain.Open(new WindowsFormsMessageLoopHook(this.Handle));
            }
        }
Esempio n. 24
0
 internal DataSource(ITwainSessionInternal session, TWIdentity sourceId)
 {
     _session        = session;
     Identity        = sourceId;
     ProtocolVersion = new Version(sourceId.ProtocolMajor, sourceId.ProtocolMinor);
 }
Esempio n. 25
0
 /// <summary>
 /// The application may obtain the next Source that are currently available on the system which
 /// match the application’s supported groups.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <returns></returns>
 public ReturnCode GetNext(out TWIdentity source)
 {
     Session.VerifyState(3, 7, DataGroups.Control, DataArgumentType.Identity, Message.GetNext);
     source = new TWIdentity();
     return(Dsm.DsmEntry(Session.AppId, Message.GetNext, source));
 }
Esempio n. 26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TwainSession"/> class.
 /// </summary>
 /// <param name="supportedGroups">The supported groups.</param>
 public TwainSession(DataGroups supportedGroups)
     : this(TWIdentity.CreateFromAssembly(supportedGroups, Assembly.GetEntryAssembly()))
 {
 }
 static TwainScanner()
 {
     TwainAppId = TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Control, Assembly.GetEntryAssembly());
 }
Esempio n. 28
0
 /// <summary>
 /// It allows an application to set the
 /// default TWAIN driver, which is reported back by GetDefault.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <returns></returns>
 public ReturnCode Set(TWIdentity source)
 {
     Session.VerifyState(3, 3, DataGroups.Control, DataArgumentType.Identity, Message.Set);
     return(Dsm.DsmEntry(Session.AppId, Message.Set, source));
 }
        private void SetupTwain()
        {
            var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly());

            _twain = new TwainSession(appId);
            _twain.StateChanged += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("State changed to " + _twain.State + " on thread " + Thread.CurrentThread.ManagedThreadId);
            };
            _twain.TransferError += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Got xfer error on thread " + Thread.CurrentThread.ManagedThreadId);
            };

            _twain.DataTransferred += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Transferred data event on thread " + Thread.CurrentThread.ManagedThreadId);

                // example on getting ext image info
                var infos = e.GetExtImageInfo(ExtendedImageInfo.Camera).Where(it => it.ReturnCode == ReturnCode.Success);
                foreach (var it in infos)
                {
                    var values = it.ReadValues();
                    PlatformInfo.Current.Log.Info(string.Format("{0} = {1}", it.InfoID, values.FirstOrDefault()));
                    break;
                }

                // handle image data
                Image img = null;
                if (e.NativeData != IntPtr.Zero)
                {
                    var stream = e.GetNativeImageStream();
                    if (stream != null)
                    {
                        img = Image.FromStream(stream);
                    }
                }
                else if (!string.IsNullOrEmpty(e.FileDataPath))
                {
                    img = new Bitmap(e.FileDataPath);
                }
                if (img != null)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        Scan.Images.IScannedImage imagen = new Scan.Images.ScannedImage(new Bitmap(img), ScanBitDepth.C24Bit, false);
                        imagenesCapturadas.Images.Add(imagen);
                        frmPreview.tblPreview.AppendImage(imagen);
                    }));
                }
            };

            _twain.SourceDisabled += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Source disabled event on thread " + Thread.CurrentThread.ManagedThreadId);
                this.BeginInvoke(new Action(() =>
                {
                    //Se detuvo el proceso de Digitalizacion.
                    //Poner controles para digitalizar de nuevo.

                    btnDigitalizar.Enabled = true;

                    if (frmPreview != null)
                    {
                        frmPreview.Close();
                        frmPreview.Dispose();
                    }

                    tblImagenes.UpdateImages(imagenesCapturadas.Images);
                    LoadSourceCaps();
                }));
            };
            _twain.TransferReady += (s, e) =>
            {
                PlatformInfo.Current.Log.Info("Transferr ready event on thread " + Thread.CurrentThread.ManagedThreadId);
                e.CancelAll = _stopScan;
            };

            // either set sync context and don't worry about threads during events,
            // or don't and use control.invoke during the events yourself
            PlatformInfo.Current.Log.Info("Setup thread = " + Thread.CurrentThread.ManagedThreadId);
            _twain.SynchronizationContext = SynchronizationContext.Current;
            if (_twain.State < 3)
            {
                // use this for internal msg loop
                _twain.Open();
                // use this to hook into current app loop
                //_twain.Open(new WindowsFormsMessageLoopHook(this.Handle));
            }
        }