/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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)); }
/////////////////////////////////////////////////////////////////////////////// // 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); }
/// <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)); }
/// <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)); } }
/// <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)); } }
/// <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; }
/// <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); } }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/////////////////////////////////////////////////////////////////////////////// // 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..."); } }
/// <summary> /// Shutdown the TWAIN driver... /// </summary> public void Cleanup() { if (m_twain != null) { m_twain.Rollback(TWAIN.STATE.S2); m_twain = null; } }