Пример #1
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_SETUPFILEXFER / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatSetupfilexfer(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_SETUPFILEXFER twsetupfilexfer;

            // Clear or get...
            a_szStatus = "";
            twsetupfilexfer = default(TWAIN.TW_SETUPFILEXFER);
            if (a_msg == TWAIN.MSG.SET)
            {
                if (!m_twain.CsvToSetupfilexfer(ref twsetupfilexfer, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatSetupfilexfer(a_dg, a_msg, ref twsetupfilexfer);
            if (sts == TWAIN.STS.SUCCESS)
            {
                // Get the data...
                a_szMemref = m_twain.SetupfilexferToCsv(twsetupfilexfer);

                // Squirrel this away for DAT_IMAGEFILEXFER...
                m_twsetupfilexfer = twsetupfilexfer;
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #2
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_SETUPMEMXFER / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatSetupmemxfer(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_SETUPMEMXFER twsetupmemxfer;

            // Issue the command...
            a_szStatus = "";
            twsetupmemxfer = default(TWAIN.TW_SETUPMEMXFER);
            sts = m_twain.DatSetupmemxfer(a_dg, a_msg, ref twsetupmemxfer);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.SetupmemxferToCsv(twsetupmemxfer);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #3
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_IDENTITY / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatIdentity(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_IDENTITY twidentity;

            // Clear or get...
            a_szStatus = "";
            twidentity = default(TWAIN.TW_IDENTITY);
            if (    (a_msg == TWAIN.MSG.SET)
                ||  (a_msg == TWAIN.MSG.OPENDS)
                ||  (a_msg == TWAIN.MSG.CLOSEDS))
            {
                if (!m_twain.CsvToIdentity(ref twidentity, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatIdentity(a_dg, a_msg, ref twidentity);
            if (sts == TWAIN.STS.SUCCESS)
            {
                // Get the data...
                a_szMemref = m_twain.IdentityToCsv(twidentity);

                // If we're pre-MSG_OPENDS, then save the results in
                // our DS identity variable, so it'll be there when
                // we make the call to MSG_OPENDS...
                if (m_twain.GetState() <= TWAIN.STATE.S3)
                {
                    m_twidentityDs = twidentity;
                }

                // If we're MSG_OPENDS and callbacks aren't in use, then
                // we need to activate the message filter...
                if ((a_msg == TWAIN.MSG.OPENDS)
                    && (!m_blUseCallbacks))
                {
                    SetMessageFilter(true);
                }
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #4
0
        /// <summary>
        /// Handle DG_IMAGE / DAT_IMAGELAYOUT / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatImagelayout(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_IMAGELAYOUT twimagelayout;

            // Clear or get...
            a_szStatus = "";
            twimagelayout = default(TWAIN.TW_IMAGELAYOUT);
            if (a_msg == TWAIN.MSG.SET)
            {
                if (!m_twain.CsvToImagelayout(ref twimagelayout, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatImagelayout(a_dg, a_msg, ref twimagelayout);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.ImagelayoutToCsv(twimagelayout);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #5
0
 /// <summary>
 /// Log after sending to the TWAIN driver...
 /// </summary>
 /// <param name="sts">status</param>
 /// <param name="a_szMemref">data</param>
 public static void LogSendAfter(TWAIN.STS sts, string a_szMemref)
 {
     if ((a_szMemref != null) && (a_szMemref != "") && (a_szMemref[0] != '('))
     {
         Log.Msg(Log.Severity.Info, "twn> " + a_szMemref);
     }
     Log.Msg(Log.Severity.Info, "twn> " + sts);
 }
Пример #6
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_FILESYSTEM / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatFilesystem(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_FILESYSTEM twfilesystem;

            // Clear or get...
            a_szStatus = "";
            twfilesystem = default(TWAIN.TW_FILESYSTEM);
            if ((a_msg == TWAIN.MSG.CHANGEDIRECTORY)
                || (a_msg == TWAIN.MSG.CREATEDIRECTORY)
                || (a_msg == TWAIN.MSG.DELETE))
            {
                if (!m_twain.CsvToFilesystem(ref twfilesystem, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatFilesystem(a_dg, a_msg, ref twfilesystem);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.FilesystemToCsv(twfilesystem);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #7
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_CUSTOMDSDATA / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatCustomdsdata(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_CUSTOMDSDATA twcustomdsdata;

            // Clear or get...
            a_szStatus = "";
            twcustomdsdata = default(TWAIN.TW_CUSTOMDSDATA);
            if (a_msg == TWAIN.MSG.SET)
            {
                if (!m_twain.CsvToCustomdsdata(ref twcustomdsdata, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatCustomdsdata(a_dg, a_msg, ref twcustomdsdata);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.CustomdsdataToCsv(twcustomdsdata);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #8
0
        ///////////////////////////////////////////////////////////////////////////////
        // Private Functions, the device event and scanner callbacks are located
        // here...
        ///////////////////////////////////////////////////////////////////////////////
        #region Private Functions...

        /// <summary>
        /// Convert TWAIN's status to our own.  I wouldn't normally cheat like
        /// this (a switch statement is appropriate), but we are dealing with a
        /// well established enumeration, so while it's still a bit skanky, we
        /// can get away with just mapping theirs to ours...
        /// </summary>
        /// <param name="a_sts">Status to convert</param>
        /// <returns>Our status</returns>
        private STS CvtSts(TWAIN.STS a_sts)
        {
            return ((STS)a_sts);
        }
Пример #9
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_CALLBACK2 / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatCallback2(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_CALLBACK2 twcallback2;

            // Clear or get...
            a_szStatus = "";
            twcallback2 = default(TWAIN.TW_CALLBACK2);
            if (a_msg == TWAIN.MSG.SET)
            {
                if (!m_twain.CsvToCallback2(ref twcallback2, a_szMemref))
                {
                    return (STS.BADVALUE);
                }
            }

            // Issue the command...
            sts = m_twain.DatCallback2(a_dg, a_msg, ref twcallback2);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.Callback2ToCsv(twcallback2);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #10
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_CAPABILITY / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatCapability(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            bool blResult;
            TWAIN.STS sts;
            TWAIN.TW_CAPABILITY twcapability;

            // Built the capability structure for a MSG_SET...
            a_szStatus = "";
            if (a_msg == TWAIN.MSG.SET)
            {
                try
                {
                    twcapability = default(TWAIN.TW_CAPABILITY);
                    blResult = m_twain.CsvToCapability(ref twcapability, ref a_szStatus, a_szMemref);
                    if (!blResult)
                    {
                        a_szStatus = "(error in the capability data)";
                        return (STS.BADVALUE);
                    }
                }
                catch
                {
                    a_szStatus = "(error in the capability data)";
                    return (STS.BADVALUE);
                }
            }

            // We don't need or expect a capability for MSG_RESETALL, so
            // just drop one in...
            else if (a_msg == TWAIN.MSG.RESETALL)
            {
                twcapability = default(TWAIN.TW_CAPABILITY);
                twcapability.Cap = TWAIN.CAP.ICAP_XFERMECH;
            }

            // Everything else can come here...
            else
            {
                try
                {
                    twcapability = default(TWAIN.TW_CAPABILITY);
                    twcapability.Cap = GetCapabilityNumber(a_szMemref);
                }
                catch
                {
                    a_szStatus = "(number isn't a valid capability or hexidecimal value)";
                    return (STS.BADVALUE);
                }
            }

            // Do the command...
            try
            {
                // Make the call...
                if (twcapability.Cap == TWAIN.CAP.ICAP_COMPRESSION)
                {
                    sts = TWAIN.STS.BADCAP;
                }
                sts = m_twain.DatCapability(a_dg, a_msg, ref twcapability);
                if ((a_msg == TWAIN.MSG.RESETALL) || ((sts != TWAIN.STS.SUCCESS) && (sts != TWAIN.STS.CHECKSTATUS)))
                {
                    return (CvtSts(sts));
                }

                // Convert the value to something we can put on our form...
                a_szMemref = m_twain.CapabilityToCsv(twcapability);
                m_twain.DsmMemFree(ref twcapability.hContainer);
                return (CvtSts(sts));
            }
            catch
            {
                a_szStatus = "(capability command failed)";
                sts = TWAIN.STS.BADVALUE;
                return (CvtSts(sts));
            }
        }
Пример #11
0
        /// <summary>
        /// Send a generic DAT (we can use this to process any operation
        /// using an IntPtr for the TW_MEMREF argument)...
        /// </summary>
        /// <param name="a_dg"></param>
        /// <param name="a_dat"></param>
        /// <param name="a_msg"></param>
        /// <param name="a_szStatus"></param>
        /// <param name="a_szMemref"></param>
        /// <returns></returns>
        private STS SendDat(TWAIN.DG a_dg, TWAIN.DAT a_dat, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            IntPtr twmemref;

            // State 2 and 3, we don't have a destination...
            a_szStatus = "";
            if (m_twain.GetState() < TWAIN.STATE.S4)
            {
                twmemref = Marshal.AllocHGlobal(8192);
                if (twmemref == IntPtr.Zero)
                {
                    Log.Error("AllocHGlobal failed...");
                    return (STS.LOWMEMORY);
                }
                sts = m_twain.DsmEntryNullDest(a_dg, a_dat, a_msg, twmemref);
                Marshal.FreeHGlobal(twmemref);
                return (CvtSts(sts));
            }

            // State 4,5,6 and 7...
            else
            {
                twmemref = Marshal.AllocHGlobal(8192);
                if (twmemref == IntPtr.Zero)
                {
                    Log.Error("AllocHGlobal failed...");
                    return (STS.LOWMEMORY);
                }
                sts = m_twain.DsmEntry(a_dg, a_dat, a_msg, twmemref);
                Marshal.FreeHGlobal(twmemref);
                return (CvtSts(sts));
            }
        }
Пример #12
0
 /// <summary>
 /// Register the TWAIN object so we can get some extra info...
 /// </summary>
 /// <param name="a_twain">twain object or null</param>
 private static void RegisterTwainLocal(TWAIN a_twain)
 {
     ms_twain = a_twain;
 }
Пример #13
0
 /// <summary>
 /// Log before sending to the TWAIN driver...
 /// </summary>
 /// <param name="a_szDg">data group</param>
 /// <param name="a_szDat">data argument type</param>
 /// <param name="a_szMsg">message</param>
 /// <param name="a_szMemref">data</param>
 public static void LogSendBefore(TWAIN.DG a_dg, TWAIN.DAT a_dat, TWAIN.MSG a_msg, string a_szMemref)
 {
     Log.Msg(Log.Severity.Info, "");
     Log.Msg(Log.Severity.Info, "twn> DG_" + a_dg + "/DAT_" + a_dat + "/MSG_" + a_msg);
     if ((a_szMemref != null) && (a_szMemref != "") && (a_szMemref[0] != '('))
     {
         Log.Msg(Log.Severity.Info, "twn> " + a_szMemref);
     }
 }
Пример #14
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_USERINTERFACE / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatUserinterface(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_USERINTERFACE twuserinterface;

            // Clear or get...
            a_szStatus = "";
            twuserinterface = default(TWAIN.TW_USERINTERFACE);
            if (!m_twain.CsvToUserinterface(ref twuserinterface, a_szMemref))
            {
                return (STS.BADVALUE);
            }

            // Issue the command...
            sts = m_twain.DatUserinterface(a_dg, a_msg, ref twuserinterface);
            if (sts == TWAIN.STS.SUCCESS)
            {
                // The state we want to rollback to when scanning is complete...
                if ((a_msg == TWAIN.MSG.ENABLEDS) && (twuserinterface.ShowUI != 0))
                {
                    m_stateAfterScan = TWAIN.STATE.S5;
                }
                else
                {
                    m_stateAfterScan = TWAIN.STATE.S4;
                }
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #15
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_DEVICEEVENT / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatDeviceevent(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_DEVICEEVENT twdeviceevent;

            // Issue the command...
            a_szStatus = "";
            twdeviceevent = default(TWAIN.TW_DEVICEEVENT);
            sts = m_twain.DatDeviceevent(a_dg, a_msg, ref twdeviceevent);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.DeviceeventToCsv(twdeviceevent);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #16
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_XFERGROUP / MSG_*
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatXfergroup(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            UInt32 u32;

            // Clear or get...
            a_szStatus = "";
            u32 = 0;
            if (!m_twain.CsvToXfergroup(ref u32, a_szMemref))
            {
                return (STS.BADVALUE);
            }

            // Issue the command...
            sts = m_twain.DatXferGroup(a_dg, a_msg, ref u32);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.XfergroupToCsv(u32);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #17
0
        /// <summary>
        /// Handle DG_CONTROL / DAT_ENTRYPOINT / MSG_GET
        /// </summary>
        /// <param name="a_dg">Data group</param>
        /// <param name="a_msg">Operation</param>
        /// <param name="a_szStatus">Result of operation</param>
        /// <param name="a_szMemref">Pointer to data</param>
        /// <returns>TWAIN status</returns>
        private STS SendDatEntrypoint(TWAIN.DG a_dg, TWAIN.MSG a_msg, ref string a_szStatus, ref string a_szMemref)
        {
            TWAIN.STS sts;
            TWAIN.TW_ENTRYPOINT twentrypoint;

            // Issue the command...
            a_szStatus = "";
            twentrypoint = default(TWAIN.TW_ENTRYPOINT);
            twentrypoint.Size = (uint)Marshal.SizeOf(twentrypoint);
            sts = m_twain.DatEntrypoint(a_dg, a_msg, ref twentrypoint);
            if (sts == TWAIN.STS.SUCCESS)
            {
                a_szMemref = m_twain.EntrypointToCsv(twentrypoint);
            }

            // All done...
            return (CvtSts(sts));
        }
Пример #18
0
        ///////////////////////////////////////////////////////////////////////////////
        // Public Functions.  This is the stuff we want to expose to the
        // application...
        ///////////////////////////////////////////////////////////////////////////////
        #region Public Functions...

        /// <summary>
        /// Instantiate TWAIN and open the DSM.  This looks like a ridiculously
        /// complex function, so lets talk about it for a moment.
        /// 
        /// There are four groupings in the argument list (and wouldn't it be nice
        /// it they were all together):
        /// 
        /// The Application Identity (TW_IDENTITY)
        /// a_szManufacturer, a_szProductFamily, a_szProductName, a_u16ProtocolMajor,
        /// a_u16ProtocolMinor, a_aszSupportedGroups, a_szTwcy, a_szInfo, a_szTwlg,
        /// a_u16MajorNum, a_u16MinorNum.
        /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /// One of the goals of the TWAINWorkingGroupToolkit namespace is to make it
        /// unnecessary for the caller to include the TWAINWorkingGroup namespace.
        /// So there's no appeal to the TW_IDENTITY structure, instead it's broken
        /// out piecemeal.  The structure has been unchanged since 1993, so I think
        /// we can trust that these arguments won't change.  You can read about
        /// TW_IDENTITY in the TWAIN Specification, but essentially these arguments
        /// identify the application to the TWAIN DSM and the TWAIN driver.
        /// 
        /// The Flags
        /// a_blUseLegacyDSM, a_blUseCallbacks, a_setmessagefilterdelegate
        /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /// a_blUseLegacyDSM should be false on Windows and Linux and true on the
        /// Mac (until we get a new DSM).  This causes the toolkit to invoke the
        /// open source DSM provided by the TWAIN Working Group, which can be found
        /// here: https://sourceforge.net/projects/twain-dsm/.  a_blUseCallbacks
        /// should be true, since the callback system is easier to manage and less
        /// likely to cause an application's user interface to lock up while they
        /// are scanning (the alternative is the Windows POST message system).  If
        /// the value is false, then a_setmessagefilterdelegate must point to a
        /// function that will filter Window's messages sent from the application
        /// to the driver.
        /// 
        /// The Callback Functions
        /// a_writeoutputdelegate, a_reportimagedelegate
        /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /// a_writeoutputdelegate is only used by the TWAINCStst application to show
        /// information in the status window.  A regular application might find that
        /// useful for diagnostics, but it's not necessary, and the value can be set
        /// to null.  a_reportimagedelegate is the really interesting function, this
        /// is what's called for every image while scanning.  It receives both the
        /// metadata and the image.  You'll want to carefully look at the function
        /// that's used for the TWAINCSscan application.
        /// 
        /// Windows Cruft
        /// a_intptrHwnd, a_runinuithreaddelegate, a_objectRunInUiThreadDelegate
        /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /// TWAIN has been around since 1992, and it's one architectural drawback
        /// comes from how it tied itself to the Windows message loop (which I'm
        /// sure seemed like a very good idea at the time).  We have three functions,
        /// and the motivation for this is to avoid accessing System.Windows.Forms
        /// inside of TWAINCSToolkit, so that we can seamlessly work with other
        /// graphical windowing systems, such as are provided with Mono).  I won't
        /// go into too much detail here.  You must have a Form on Windows.  The
        /// the this.Handle is passed to a_intptrHwnd, which is used by both the
        /// DAT_PARENT and DAT_USERINTERFACE operations. a_objectRunInUiThreadDelegate
        /// is the this value, itself, and is used by the a_runinuithreaddelegate to
        /// invoke DAT_USERINTERFACE and DAT_IMAGE*XFER calls into the form's main
        /// UI thread, where the Windows message loop resides.  This is necessary,
        /// because some TWAIN driver's hook into that message loop, and will crash
        /// or hang, if not properly invoked from that thread.  If you run into this
        /// kind of situation, take of note of the operation that caused the problem,
        /// and if it's clearly an invokation issue it can be fixed by adding new
        /// TWAIN CS operations to this kind of callback route.  As for the function
        /// itself, just copy the RunInThreadUi function from TWAINCSscan, and use
        /// it as-is.
        /// 
        /// </summary>
        /// <param name="a_intptrHwnd">Parent window (needed for Windows)</param>
        /// <param name="a_writeoutputdelegate">Optional text output callback</param>
        /// <param name="a_reportimagedelegate">Optional report image callback</param>
        /// <param name="m_setmessagefilterdelegate">Optional message filter callback</param>
        /// <param name="a_szManufacturer">Application manufacturer</param>
        /// <param name="a_szProductFamily">Application family</param>
        /// <param name="a_szProductName">Name of the application</param>
        /// <param name="a_u16ProtocolMajor">TWAIN protocol major (doesn't have to match TWAINH.CS)</param>
        /// <param name="a_u16ProtocolMinor">TWAIN protocol minor (doesn't have to match TWAINH.CS)</param>
        /// <param name="a_aszSupportedGroups">Bitmask of DG_ flags</param>
        /// <param name="a_szTwcy">Application's country code</param>
        /// <param name="a_szInfo">Info about the application</param>
        /// <param name="a_szTwlg">Application's language</param>
        /// <param name="a_u16MajorNum">Application's major version</param>
        /// <param name="a_u16MinorNum">Application's minor version</param>
        /// <param name="a_blUseLegacyDSM">The the legacy DSM (like TWAIN_32.DLL)</param>
        /// <param name="a_blUseCallbacks">Use callbacks (preferred)</param>
        /// <param name="a_runinuithreaddelegate">delegate for running in the UI thread</param>
        /// <param name="a_objectRunInUiThreadDelegate">the form from that thread</param>
        public TWAINCSToolkit
        (
            IntPtr a_intptrHwnd,
            WriteOutputDelegate a_writeoutputdelegate,
            ReportImageDelegate a_reportimagedelegate,
            SetMessageFilterDelegate a_setmessagefilterdelegate,
            string a_szManufacturer,
            string a_szProductFamily,
            string a_szProductName,
            ushort a_u16ProtocolMajor,
            ushort a_u16ProtocolMinor,
            string[] a_aszSupportedGroups,
            string a_szTwcy,
            string a_szInfo,
            string a_szTwlg,
            ushort a_u16MajorNum,
            ushort a_u16MinorNum,
            bool a_blUseLegacyDSM,
            bool a_blUseCallbacks,
            TWAINCSToolkit.RunInUiThreadDelegate a_runinuithreaddelegate,
            Object a_objectRunInUiThreadDelegate
        )
        {
            TWAIN.STS sts;
            uint u32SupportedGroups;

            // Init stuff...
            m_intptrHwnd = a_intptrHwnd;
            if (a_writeoutputdelegate == null)
            {
                WriteOutput = WriteOutputStub;
            }
            else
            {
                WriteOutput = a_writeoutputdelegate;
            }
            ReportImage = a_reportimagedelegate;
            SetMessageFilter = a_setmessagefilterdelegate;
            m_szImagePath = null;
            m_iImageCount = 0;
            m_runinuithreaddelegate = a_runinuithreaddelegate;
            m_objectRunInUiThreadDelegate = a_objectRunInUiThreadDelegate;

            // Convert the supported groups from strings to flags...
            u32SupportedGroups = 0;
            foreach (string szSupportedGroup in a_aszSupportedGroups)
            {
                TWAIN.DG dg = (TWAIN.DG)Enum.Parse(typeof(TWAIN.DG), szSupportedGroup.Remove(0, 3));
                if (Enum.IsDefined(typeof(TWAIN.DG), dg))
                {
                    u32SupportedGroups |= (uint)dg;
                }
            }

            // Instantiate TWAIN, and register ourselves...
            m_twain = new TWAIN
            (
                a_szManufacturer,
                a_szProductFamily,
                a_szProductName,
                a_u16ProtocolMajor,
                a_u16ProtocolMinor,
                u32SupportedGroups,
                (TWAIN.TWCY)Enum.Parse(typeof(TWAIN.TWCY), a_szTwcy),
                a_szInfo,
                (TWAIN.TWLG)Enum.Parse(typeof(TWAIN.TWLG), a_szTwlg),
                a_u16MajorNum,
                a_u16MinorNum,
                a_blUseLegacyDSM,
                a_blUseCallbacks,
                DeviceEventCallback,
                ScanCallback,
                RunInUiThread,
                m_intptrHwnd
            );

            // Store some values...
            m_blUseCallbacks = a_blUseCallbacks;

            // Our default transfer mechanism...
            m_twsxXferMech = TWAIN.TWSX.NATIVE;

            // Our default file transfer info...
            m_twsetupfilexfer = default(TWAIN.TW_SETUPFILEXFER);
            m_twsetupfilexfer.Format = TWAIN.TWFF.TIFF;
            if (TWAIN.GetPlatform() == TWAIN.Platform.WINDOWS)
            {
                m_twsetupfilexfer.FileName.Set(Path.GetTempPath() + "img");
            }
            else if (TWAIN.GetPlatform() == TWAIN.Platform.LINUX)
            {
                m_twsetupfilexfer.FileName.Set(Path.GetTempPath() + "img");
            }
            else if (TWAIN.GetPlatform() == TWAIN.Platform.MACOSX)
            {
                m_twsetupfilexfer.FileName.Set("/var/tmp/img");
            }
            else
            {
                Log.Assert("Unsupported platform..." + TWAIN.GetPlatform());
            }

            // We've not been in the scan callback yet...
            m_blScanStart = true;

            // Open the DSM...
            try
            {
                sts = m_twain.DatParent(TWAIN.DG.CONTROL, TWAIN.MSG.OPENDSM, ref m_intptrHwnd);
            }
            catch (Exception exception)
            {
                Log.Error("OpenDSM exception: " + exception.Message);
                sts = TWAIN.STS.FAILURE;
            }
            if (sts != TWAIN.STS.SUCCESS)
            {
                Log.Error("OpenDSM failed...");
                Cleanup();
                throw new Exception("OpenDSM failed...");
            }
        }
Пример #19
0
 /// <summary>
 /// Shutdown the TWAIN driver...
 /// </summary>
 public void Cleanup()
 {
     if (m_twain != null)
     {
         m_twain.Rollback(TWAIN.STATE.S2);
         m_twain = null;
     }
 }