From cc58a6e093d2d4d4c743d15d878d24cc050b7982 Mon Sep 17 00:00:00 2001 From: Eugene Wang <8755753+soukoku@users.noreply.github.com> Date: Sun, 25 Apr 2021 20:54:25 -0400 Subject: [PATCH] First attempt on writing one value on cap. --- samples/Net5Console/Program.cs | 13 ++- src/NTwain/CapWrapper.cs | 8 +- src/NTwain/Capabilities.cs | 6 +- src/NTwain/ValueReader.cs | 15 ++-- src/NTwain/ValueWriter.cs | 146 +++++++++++++++++++++++++++++++-- 5 files changed, 166 insertions(+), 22 deletions(-) diff --git a/samples/Net5Console/Program.cs b/samples/Net5Console/Program.cs index e5ba5f3..8674444 100644 --- a/samples/Net5Console/Program.cs +++ b/samples/Net5Console/Program.cs @@ -83,7 +83,18 @@ namespace Net5Console } Console.WriteLine(); - var sts = session.StartCapture(false); + var sts = caps.CAP_XFERCOUNT.SetOrConstraint(MSG.SET, 2); + if (sts == STS.SUCCESS) + { + Console.WriteLine("Successfully set xfercount to 2."); + } + else + { + Console.WriteLine($"Failed set xfercount: {sts}."); + } + Console.WriteLine(); + + sts = session.StartCapture(false); if (sts == STS.SUCCESS) { Console.Error.WriteLine("Waiting for capture to complete."); diff --git a/src/NTwain/CapWrapper.cs b/src/NTwain/CapWrapper.cs index 2f5e2f8..54633b4 100644 --- a/src/NTwain/CapWrapper.cs +++ b/src/NTwain/CapWrapper.cs @@ -204,7 +204,7 @@ namespace NTwain }; try { - ValueWriter.WriteOneValue(_twain, twCap, value); + ValueWriter.WriteOneValue(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -233,7 +233,7 @@ namespace NTwain }; try { - ValueWriter.WriteArray(_twain, twCap, values); + ValueWriter.WriteArray(_twain, ref twCap, values); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -262,7 +262,7 @@ namespace NTwain }; try { - ValueWriter.WriteRange(_twain, twCap, value); + ValueWriter.WriteRange(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -291,7 +291,7 @@ namespace NTwain }; try { - ValueWriter.WriteEnum(_twain, twCap, value); + ValueWriter.WriteEnum(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally diff --git a/src/NTwain/Capabilities.cs b/src/NTwain/Capabilities.cs index bf15a02..2d48925 100644 --- a/src/NTwain/Capabilities.cs +++ b/src/NTwain/Capabilities.cs @@ -902,12 +902,12 @@ namespace NTwain #region mandatory - private CapWrapper _xferCount; - public CapWrapper CAP_XFERCOUNT + private CapWrapper _xferCount; + public CapWrapper CAP_XFERCOUNT { get { - return _xferCount ?? (_xferCount = new CapWrapper(_twain, CAP.CAP_XFERCOUNT)); + return _xferCount ?? (_xferCount = new CapWrapper(_twain, CAP.CAP_XFERCOUNT)); } } diff --git a/src/NTwain/ValueReader.cs b/src/NTwain/ValueReader.cs index 263ec3b..131a799 100644 --- a/src/NTwain/ValueReader.cs +++ b/src/NTwain/ValueReader.cs @@ -41,11 +41,11 @@ namespace NTwain lockedPtr += Marshal.SizeOf(onevalue); } - return ReadContainerData(lockedPtr, itemType); + return ReadContainerData(lockedPtr, itemType, 0); } finally { - twain.DsmMemUnlock(cap.hContainer); + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(cap.hContainer); if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } } @@ -112,7 +112,7 @@ namespace NTwain } finally { - twain.DsmMemUnlock(cap.hContainer); + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(cap.hContainer); if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } return retVal; @@ -155,7 +155,7 @@ namespace NTwain } finally { - twain.DsmMemUnlock(cap.hContainer); + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(cap.hContainer); if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } } @@ -248,7 +248,7 @@ namespace NTwain } finally { - twain.DsmMemUnlock(cap.hContainer); + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(cap.hContainer); if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } } @@ -318,7 +318,7 @@ namespace NTwain } finally { - twain.DsmMemUnlock(cap.hContainer); + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(cap.hContainer); if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } return null; @@ -330,7 +330,7 @@ namespace NTwain /// The twain type. /// Index of the item if pointer is array. /// - static TValue ReadContainerData(IntPtr intptr, TWTY type, int itemIndex = 0) where TValue : struct + static TValue ReadContainerData(IntPtr intptr, TWTY type, int itemIndex) where TValue : struct { var isEnum = typeof(TValue).IsEnum; @@ -338,6 +338,7 @@ namespace NTwain { default: throw new NotSupportedException($"Unsupported item type {type} for reading."); + // TODO: verify if needs to read int32 for small types case TWTY.INT8: intptr += 1 * itemIndex; if (isEnum) diff --git a/src/NTwain/ValueWriter.cs b/src/NTwain/ValueWriter.cs index 0f7b9c6..51414f3 100644 --- a/src/NTwain/ValueWriter.cs +++ b/src/NTwain/ValueWriter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using TWAINWorkingGroup; @@ -13,23 +14,154 @@ namespace NTwain public static class ValueWriter { - public static void WriteOneValue(TWAIN twain, TW_CAPABILITY twCap, TValue value) where TValue : struct + public static void WriteOneValue(TWAIN twain, ref TW_CAPABILITY twCap, TValue value) where TValue : struct + { + IntPtr lockedPtr = IntPtr.Zero; + try + { + TWTY itemType = GetItemType(); + if (PlatformTools.GetPlatform() == Platform.MACOSX) + { + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE_MACOSX)) + Marshal.SizeOf(default(TW_STR255)))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + + TW_ONEVALUE_MACOSX twonevaluemacosx = default(TW_ONEVALUE_MACOSX); + twonevaluemacosx.ItemType = (uint)itemType; + Marshal.StructureToPtr(twonevaluemacosx, lockedPtr, true); + + lockedPtr += Marshal.SizeOf(twonevaluemacosx); + } + else + { + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE)) + Marshal.SizeOf(default(TW_STR255)))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + + TW_ONEVALUE twonevalue = default(TW_ONEVALUE); + twonevalue.ItemType = itemType; + Marshal.StructureToPtr(twonevalue, lockedPtr, true); + + lockedPtr += Marshal.SizeOf(twonevalue); + } + + WriteContainerData(lockedPtr, itemType, value, 0); + } + finally + { + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(twCap.hContainer); + } + } + + public static void WriteArray(TWAIN twain, ref TW_CAPABILITY twCap, TValue[] values) where TValue : struct { throw new NotImplementedException(); } - public static void WriteArray(TWAIN twain, TW_CAPABILITY twCap, TValue[] values) where TValue : struct - { - throw new NotImplementedException(); - } - public static void WriteRange(TWAIN twain, TW_CAPABILITY twCap, Range value) where TValue : struct + public static void WriteRange(TWAIN twain, ref TW_CAPABILITY twCap, Range value) where TValue : struct { throw new NotImplementedException(); } - public static void WriteEnum(TWAIN twain, TW_CAPABILITY twCap, Enumeration value) where TValue : struct + public static void WriteEnum(TWAIN twain, ref TW_CAPABILITY twCap, Enumeration value) where TValue : struct { throw new NotImplementedException(); } + + static TWTY GetItemType() where TValue : struct + { + var type = typeof(TValue); + if (type == typeof(BoolType)) return TWTY.BOOL; + if (type == typeof(TW_FIX32)) return TWTY.FIX32; + if (type == typeof(TW_STR32)) return TWTY.STR32; + if (type == typeof(TW_STR64)) return TWTY.STR64; + if (type == typeof(TW_STR128)) return TWTY.STR128; + if (type == typeof(TW_STR255)) return TWTY.STR255; + if (type == typeof(TW_FRAME)) return TWTY.FRAME; + + if (type.IsEnum) + { + type = type.GetEnumUnderlyingType(); + } + + if (type == typeof(ushort)) return TWTY.UINT16; + if (type == typeof(short)) return TWTY.INT16; + if (type == typeof(uint)) return TWTY.UINT32; + if (type == typeof(int)) return TWTY.INT32; + if (type == typeof(byte)) return TWTY.UINT8; + if (type == typeof(sbyte)) return TWTY.INT8; + + throw new NotSupportedException($"{type.Name} is not supported for writing."); + } + + /// + /// Writes single piece of value to the container pointer. + /// + /// + /// A locked pointer to the container's data pointer. If data is array this is the 0th item. + /// The twain type. + /// + /// Index of the item if pointer is array. + static void WriteContainerData(IntPtr intptr, TWTY type, TValue value, int itemIndex) where TValue : struct + { + switch (type) + { + default: + throw new NotSupportedException($"Unsupported item type {type} for writing."); + // TODO: for small types needs to fill whole int32 before writing? + case TWTY.INT8: + intptr += 1 * itemIndex; + //int intval = Convert.ToSByte(value); + //Marshal.StructureToPtr(intval, intptr, false); + Marshal.StructureToPtr(Convert.ToSByte(value), intptr, false); + break; + case TWTY.UINT8: + intptr += 1 * itemIndex; + //uint uintval = Convert.ToByte(value); + //Marshal.StructureToPtr(uintval, intptr, false); + Marshal.StructureToPtr(Convert.ToByte(value), intptr, false); + break; + case TWTY.INT16: + intptr += 2 * itemIndex; + //intval = Convert.ToInt16(value); + //Marshal.StructureToPtr(intval, intptr, false); + Marshal.StructureToPtr(Convert.ToInt16(value), intptr, false); + break; + case TWTY.BOOL: + case TWTY.UINT16: + intptr += 2 * itemIndex; + //uintval = Convert.ToUInt16(value); + //Marshal.StructureToPtr(uintval, intptr, false); + Marshal.StructureToPtr(Convert.ToUInt16(value), intptr, false); + break; + case TWTY.INT32: + case TWTY.UINT32: + intptr += 4 * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.FIX32: + intptr += 4 * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.FRAME: + intptr += 16 * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR32: + intptr += TW_STR32.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR64: + intptr += TW_STR64.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR128: + intptr += TW_STR128.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR255: + intptr += TW_STR255.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + } + } } }