1
0
mirror of https://github.com/soukoku/ntwain.git synced 2025-04-05 20:59:23 +08:00

Updated string read and fixed sample.

This commit is contained in:
soukoku 2014-04-10 07:30:00 -04:00
parent 9d30efe92a
commit f861cd8c60
13 changed files with 175 additions and 79 deletions

View File

@ -266,16 +266,16 @@ namespace NTwain.Data
frame.Bottom = (TWFix32)ReadValue(baseAddr, ref offset, ItemType.Fix32);
return frame; // no need to update offset again after reading fix32
case ItemType.String128:
val = ReadString(baseAddr, offset, 128);
val = ReadString(baseAddr, offset, TwainConst.String128 - 2);
break;
case ItemType.String255:
val = ReadString(baseAddr, offset, 255);
val = ReadString(baseAddr, offset, TwainConst.String255 - 1);
break;
case ItemType.String32:
val = ReadString(baseAddr, offset, 32);
val = ReadString(baseAddr, offset, TwainConst.String32 - 2);
break;
case ItemType.String64:
val = ReadString(baseAddr, offset, 64);
val = ReadString(baseAddr, offset, TwainConst.String64 - 2);
break;
case ItemType.Handle:
val = new IntPtr(baseAddr.ToInt64() + offset);
@ -294,16 +294,21 @@ namespace NTwain.Data
/// <returns></returns>
static string ReadString(IntPtr baseAddr, int offset, int maxLength)
{
// todo: add support for other platform
var sb = new StringBuilder(maxLength);
byte bt;
while (sb.Length < maxLength &&
(bt = Marshal.ReadByte(baseAddr, offset++)) != 0)
// does this work cross-platform?
var val = Marshal.PtrToStringAnsi(new IntPtr(baseAddr.ToInt64() + offset));
if (val.Length > maxLength)
{
sb.Append((char)bt);
// bad source, whatever
}
return sb.ToString();
return val;
//var sb = new StringBuilder(maxLength);
//byte bt;
//while (sb.Length < maxLength &&
// (bt = Marshal.ReadByte(baseAddr, offset++)) != 0)
//{
// sb.Append((char)bt);
//}
//return sb.ToString();
}

View File

@ -1,4 +1,5 @@
using System;
using NTwain.Data;
using System;
namespace NTwain
{
@ -8,30 +9,36 @@ namespace NTwain
public class DataTransferredEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="DataTransferredEventArgs" /> class.
/// </summary>
/// <param name="data">The data pointer.</param>
/// <param name="filePath">The file.</param>
internal DataTransferredEventArgs(IntPtr data, string filePath)
{
Data = data;
FilePath = filePath;
}
/// <summary>
/// Gets pointer to the image data if applicable.
/// Gets pointer to the complete data if the transfer was native.
/// The data will be freed once the event handler ends
/// so consumers must complete whatever processing
/// required by then.
/// so consumers must complete whatever processing before then.
/// For image type this data is DIB (Windows), PICT (old Mac), and TIFF (Linux/OSX).
/// </summary>
/// <value>The data pointer.</value>
public IntPtr Data { get; private set; }
public IntPtr NativeData { get; internal set; }
/// <summary>
/// Gets the filepath to the transferrerd data if applicable.
/// Gets the file path to the complete data if the transfer was file or memory-file.
/// </summary>
/// <value>
/// The file.
/// </value>
public string FilePath { get; private set; }
public string FilePath { get; internal set; }
/// <summary>
/// Gets the memory data if the transfer was memory.
/// </summary>
/// <value>
/// The memory data.
/// </value>
public byte[] MemData { get; internal set; }
/// <summary>
/// Gets the final image information if applicable.
/// </summary>
/// <value>
/// The final image information.
/// </value>
public TWImageInfo FinalImageInfo { get; internal set; }
}
}

View File

@ -11,7 +11,7 @@
<!--<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>-->
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>V0.9 release is updated for TWAIN 2.3 and contains some refactoring that may require updating existing code.</releaseNotes>
<releaseNotes>This release supports TWAIN 2.3.</releaseNotes>
<copyright>$copyright$</copyright>
<tags>twain scan</tags>
</metadata>

View File

@ -39,7 +39,7 @@ namespace NTwain
/// <summary>
/// Gets the tentative image information for the current transfer if applicable.
/// This may differ from the final image depending on the transfer mode used.
/// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer).
/// </summary>
/// <value>
/// The image info.

View File

@ -11,10 +11,11 @@ namespace NTwain.Triplets
{
internal ExtImageInfo(ITwainStateInternal session) : base(session) { }
public ReturnCode Get(TWExtImageInfo info)
public ReturnCode Get(out TWExtImageInfo info)
{
Session.VerifyState(7, 7, DataGroups.Image, DataArgumentType.ExtImageInfo, Message.Get);
return PInvoke.DsmEntry(Session.GetAppId(), Session.SourceId, Message.Get, info);
info = new TWExtImageInfo();
return PInvoke.DsmEntry(Session.GetAppId(), Session.SourceId, Message.Get, info);
}
}
}

View File

@ -31,6 +31,10 @@ namespace NTwain.Triplets
File.Exists(path);
}
static readonly bool IsWin = Environment.OSVersion.Platform == PlatformID.Win32NT;
static readonly bool IsOSX = Environment.OSVersion.Platform == PlatformID.MacOSX;
static readonly bool IsLinux = Environment.OSVersion.Platform == PlatformID.Unix;
// define sig for each different data type since "object" doesn't work
#region wrapped calls

View File

@ -37,6 +37,7 @@ namespace NTwain
object _callbackObj; // kept around so it doesn't get gc'ed
TWUserInterface _twui;
static readonly CapabilityId[] _emptyCapList = new CapabilityId[0];
private IList<CapabilityId> _supportedCaps;
/// <summary>
@ -53,7 +54,7 @@ namespace NTwain
{
_supportedCaps = this.GetCapabilities();
}
return _supportedCaps ?? new CapabilityId[0];
return _supportedCaps ?? _emptyCapList;
}
private set
{
@ -289,6 +290,7 @@ namespace NTwain
if (rc == ReturnCode.Success)
{
_callbackObj = null;
SupportedCaps = null;
}
return rc;
}
@ -776,7 +778,7 @@ namespace NTwain
{
lockedPtr = MemoryManager.Instance.Lock(dataPtr);
}
OnDataTransferred(new DataTransferredEventArgs(lockedPtr, null));
OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr });
}
}
finally
@ -808,7 +810,7 @@ namespace NTwain
var xrc = DGAudio.AudioFileXfer.Get();
if (xrc == ReturnCode.XferDone)
{
OnDataTransferred(new DataTransferredEventArgs(IntPtr.Zero, filePath));
OnDataTransferred(new DataTransferredEventArgs { FilePath = filePath });
}
}
@ -826,11 +828,16 @@ namespace NTwain
if (xrc == ReturnCode.XferDone)
{
State = 7;
TWImageInfo imgInfo;
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
imgInfo = null;
}
if (dataPtr != IntPtr.Zero)
{
lockedPtr = MemoryManager.Instance.Lock(dataPtr);
}
OnDataTransferred(new DataTransferredEventArgs(lockedPtr, null));
OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, FinalImageInfo = imgInfo });
}
}
finally
@ -862,13 +869,93 @@ namespace NTwain
var xrc = DGImage.ImageFileXfer.Get();
if (xrc == ReturnCode.XferDone)
{
OnDataTransferred(new DataTransferredEventArgs(IntPtr.Zero, filePath));
TWImageInfo imgInfo;
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
imgInfo = null;
}
OnDataTransferred(new DataTransferredEventArgs { FilePath = filePath, FinalImageInfo = imgInfo });
}
}
private void DoImageMemoryXfer()
{
throw new NotImplementedException();
TWSetupMemXfer memInfo;
if (DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success)
{
TWImageMemXfer xferInfo = new TWImageMemXfer();
try
{
xferInfo.Memory = new TWMemory
{
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
Length = memInfo.Preferred,
TheMem = MemoryManager.Instance.Allocate(memInfo.Preferred)
};
var xrc = ReturnCode.Success;
do
{
xrc = DGImage.ImageMemFileXfer.Get(xferInfo);
if (xrc == ReturnCode.Success ||
xrc == ReturnCode.XferDone)
{
State = 7;
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
// todo: need lock before use?
IntPtr lockPtr = IntPtr.Zero;
try
{
lockPtr = MemoryManager.Instance.Lock(xferInfo.Memory.TheMem);
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
}
finally
{
if (lockPtr != IntPtr.Zero)
{
MemoryManager.Instance.Unlock(lockPtr);
}
}
// now what?
}
} while (xrc == ReturnCode.Success);
if (xrc == ReturnCode.XferDone)
{
TWImageInfo imgInfo;
//TWExtImageInfo extInfo;
//if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
//{
// if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
// {
// extInfo = null;
// }
//}
if (DGImage.ImageInfo.Get(out imgInfo) == ReturnCode.Success)
{
//OnDataTransferred(new DataTransferredEventArgs(IntPtr.Zero, null));
}
else
{
Trace.TraceError("Failed to get image info after ImageMemXfer.");
imgInfo = null;
}
}
}
finally
{
State = 6;
if (xferInfo.Memory.TheMem != IntPtr.Zero)
{
MemoryManager.Instance.Free(xferInfo.Memory.TheMem);
}
}
}
}
private void DoImageMemoryFileXfer()
@ -886,6 +973,7 @@ namespace NTwain
{
xferInfo.Memory = new TWMemory
{
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
Length = memInfo.Preferred,
TheMem = MemoryManager.Instance.Allocate(memInfo.Preferred)
};
@ -900,8 +988,22 @@ namespace NTwain
if (xrc == ReturnCode.Success ||
xrc == ReturnCode.XferDone)
{
State = 7;
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
Marshal.Copy(xferInfo.Memory.TheMem, buffer, 0, buffer.Length);
// todo: need lock before use?
IntPtr lockPtr = IntPtr.Zero;
try
{
lockPtr = MemoryManager.Instance.Lock(xferInfo.Memory.TheMem);
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
}
finally
{
if (lockPtr != IntPtr.Zero)
{
MemoryManager.Instance.Unlock(lockPtr);
}
}
outStream.Write(buffer, 0, buffer.Length);
}
} while (xrc == ReturnCode.Success);
@ -962,6 +1064,7 @@ namespace NTwain
}
finally
{
State = 6;
if (xferInfo.Memory.TheMem != IntPtr.Zero)
{
MemoryManager.Instance.Free(xferInfo.Memory.TheMem);
@ -974,7 +1077,12 @@ namespace NTwain
if (File.Exists(finalFile))
{
OnDataTransferred(new DataTransferredEventArgs(IntPtr.Zero, finalFile));
TWImageInfo imgInfo;
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
imgInfo = null;
}
OnDataTransferred(new DataTransferredEventArgs { FilePath = finalFile, FinalImageInfo = imgInfo });
}
}
}

View File

@ -120,7 +120,7 @@ namespace NTwain
{
lockedPtr = MemoryManager.Instance.Lock(dataPtr);
}
OnDataTransferred(new DataTransferredEventArgs(lockedPtr, file));
OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, FilePath = file });
}
//}
//else if (group == DataGroups.Audio)

View File

@ -1,26 +0,0 @@
using NTwain;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using NTwain.Values;
using System.Runtime.Serialization;
namespace NTwain.Tests
{
[TestClass]
public class DataTransferredEventArgsTests
{
[TestMethod]
public void Constructor_Sets_Correct_Properties()
{
// just some non-default values to test
IntPtr data = new IntPtr(10);
string file = "THIS IS A TEST.";
DataTransferredEventArgs target = new DataTransferredEventArgs(data, file);
Assert.AreEqual(data, target.Data, "Data mismatch.");
Assert.AreEqual(file, target.FilePath, "File mismatch.");
}
}
}

View File

@ -54,9 +54,6 @@
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="DataTransferredEventArgsTests.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Data\TWIdentityTest.cs">
<SubType>Code</SubType>
</Compile>

View File

@ -93,7 +93,7 @@ namespace Tester
static void twain_DataTransferred(object sender, DataTransferredEventArgs e)
{
if (e.Data != IntPtr.Zero)
if (e.NativeData != IntPtr.Zero)
{
Console.WriteLine("Got twain data on thread {0}", Thread.CurrentThread.ManagedThreadId);
}

View File

@ -63,9 +63,9 @@ namespace Tester.WPF
protected override void OnDataTransferred(DataTransferredEventArgs e)
{
if (e.Data != IntPtr.Zero)
if (e.NativeData != IntPtr.Zero)
{
Image = e.Data.GetWPFBitmap();
Image = e.NativeData.GetWPFBitmap();
}
else if (!string.IsNullOrEmpty(e.FilePath))
{

View File

@ -69,10 +69,10 @@ namespace Tester.Winform
pictureBox1.Image.Dispose();
pictureBox1.Image = null;
}
if (e.Data != IntPtr.Zero)
if (e.NativeData != IntPtr.Zero)
{
//_ptrTest = e.Data;
var img = e.Data.GetDrawingBitmap();
var img = e.NativeData.GetDrawingBitmap();
if (img != null)
pictureBox1.Image = img;
}
@ -284,7 +284,7 @@ namespace Tester.Winform
{
var list = _twain.CapGetSupportedSizes();
comboSize.DataSource = list;
var cur = _twain.GetCurrentCap<SupportedSize>(CapabilityId.ICapSupportedSizes);
var cur = _twain.GetCurrentCap(CapabilityId.ICapSupportedSizes).ConvertToEnum<SupportedSize>();
if (list.Contains(cur))
{
comboSize.SelectedItem = cur;
@ -293,7 +293,7 @@ namespace Tester.Winform
private void LoadDuplex()
{
ckDuplex.Checked = _twain.GetCurrentCap<uint>(CapabilityId.CapDuplexEnabled) != 0;
ckDuplex.Checked = _twain.GetCurrentCap(CapabilityId.CapDuplexEnabled).ConvertToEnum<uint>() != 0;
}
private void LoadDPI()
@ -301,7 +301,7 @@ namespace Tester.Winform
// only allow dpi of certain values for those source that lists everything
var list = _twain.CapGetDPIs().Where(dpi => (dpi % 50) == 0).ToList();
comboDPI.DataSource = list;
var cur = _twain.GetCurrentCap<int>(CapabilityId.ICapXResolution);
var cur = (TWFix32)_twain.GetCurrentCap(CapabilityId.ICapXResolution);
if (list.Contains(cur))
{
comboDPI.SelectedItem = cur;
@ -312,7 +312,7 @@ namespace Tester.Winform
{
var list = _twain.CapGetPixelTypes();
comboDepth.DataSource = list;
var cur = _twain.GetCurrentCap<PixelType>(CapabilityId.ICapPixelType);
var cur = _twain.GetCurrentCap(CapabilityId.ICapPixelType).ConvertToEnum<PixelType>();
if (list.Contains(cur))
{
comboDepth.SelectedItem = cur;