diff --git a/samples/ScannerTester/ScannerTester.csproj b/samples/ScannerTester/ScannerTester.csproj
index d779151..41d3ac3 100644
--- a/samples/ScannerTester/ScannerTester.csproj
+++ b/samples/ScannerTester/ScannerTester.csproj
@@ -2,7 +2,7 @@
WinExe
- net8.0-windows
+ net10.0-windows7.0
enable
true
enable
diff --git a/samples/WinConsole32/Program.cs b/samples/WinConsole32/Program.cs
index 24a8831..4f76e2c 100644
--- a/samples/WinConsole32/Program.cs
+++ b/samples/WinConsole32/Program.cs
@@ -127,13 +127,13 @@ namespace WinConsole32
}
static int xferCount = 0;
- static Stopwatch watch;
+ static Stopwatch watch = new Stopwatch();
private static void Session_Transferred(TwainAppSession twain, TransferredEventArgs e)
{
if (e.Data != null)
{
var saveFile = $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount}";
- Console.WriteLine("SUCCESS! Got twain memory data #{0} on thread {1}, saving to {saveFile}.", ++xferCount, Environment.CurrentManagedThreadId, saveFile);
+ Console.WriteLine($"SUCCESS! Got twain memory data #{++xferCount} on thread {Environment.CurrentManagedThreadId}, saving to {saveFile}.");
using (var img = new ImageMagick.MagickImage(e.Data.AsStream()))
{
@@ -157,11 +157,11 @@ namespace WinConsole32
else if (e.FileInfo != null)
{
var fi = e.FileInfo.Value;
- Console.WriteLine("SUCCESS! Got twain file data #{0} on thread {1} as {saveFile}.", ++xferCount, Environment.CurrentManagedThreadId, fi.FileName);
+ Console.WriteLine($"SUCCESS! Got twain file data #{++xferCount} on thread {Environment.CurrentManagedThreadId} as {fi.FileName}.");
}
else
{
- Console.WriteLine("BUMMER! No twain data #{0} on thread {1}.", ++xferCount, Environment.CurrentManagedThreadId);
+ Console.WriteLine($"BUMMER! No twain data #{++xferCount} on thread {Environment.CurrentManagedThreadId}.");
}
e.Dispose();
}
@@ -199,10 +199,10 @@ namespace WinConsole32
twain.Caps.ICAP_PIXELTYPE.Set(TWPT.RGB);
twain.Caps.ICAP_XRESOLUTION.Set(300f);
twain.Caps.ICAP_YRESOLUTION.Set(300f);
- twain.Caps.CAP_XFERCOUNT.Set(100);
+ twain.Caps.CAP_XFERCOUNT.Set(4);
xferCount = 0;
- watch = Stopwatch.StartNew();
+ watch.Restart();
var rc = twain.EnableSource(true, false);
}
}
diff --git a/samples/WinConsole32/WinConsole32.csproj b/samples/WinConsole32/WinConsole32.csproj
index c3e86ff..1a9113f 100644
--- a/samples/WinConsole32/WinConsole32.csproj
+++ b/samples/WinConsole32/WinConsole32.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/samples/WinForm32/Form1.cs b/samples/WinForm32/Form1.cs
index f383f2e..d2b90d1 100644
--- a/samples/WinForm32/Form1.cs
+++ b/samples/WinForm32/Form1.cs
@@ -202,7 +202,7 @@ namespace WinFormSample
// color
saveFile += ".jpg";
format = ImageMagick.MagickFormat.Jpeg;
- img.Quality = _jpegQuality;
+ img.Quality = (uint)_jpegQuality;
}
if (_saveDisk) img.Write(saveFile);
else img.Write(new NoOpStream(), format);
diff --git a/samples/WinForm32/WinForm32.csproj b/samples/WinForm32/WinForm32.csproj
index 8f2b83a..990196f 100644
--- a/samples/WinForm32/WinForm32.csproj
+++ b/samples/WinForm32/WinForm32.csproj
@@ -2,7 +2,7 @@
WinExe
- net8.0-windows
+ net10.0-windows7.0
enable
true
x86
@@ -10,7 +10,7 @@
-
+
diff --git a/samples/WinForm64/WinForm64.csproj b/samples/WinForm64/WinForm64.csproj
index 0733242..a473097 100644
--- a/samples/WinForm64/WinForm64.csproj
+++ b/samples/WinForm64/WinForm64.csproj
@@ -2,7 +2,7 @@
WinExe
- net8.0-windows
+ net10.0-windows7.0
enable
true
x64
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 6b68dc7..4e02bfa 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -2,7 +2,7 @@
4.0.0.0
- alpha.13
+ alpha.14
4.0.0.0
diff --git a/src/NTwain/NTwain.csproj b/src/NTwain/NTwain.csproj
index 01403ab..1c59160 100644
--- a/src/NTwain/NTwain.csproj
+++ b/src/NTwain/NTwain.csproj
@@ -1,52 +1,59 @@
-
- NTwain
- Library containing the TWAIN API for dotnet.
- net8.0;net8.0-windows;net9.0;net9.0-windows;net462;
- enable
- true
-
+
+ NTwain
+ Library containing the TWAIN API for dotnet.
+ net8.0;net8.0-windows;net9.0;net9.0-windows;net10.0;net10.0-windows;net472;
+ enable
+ true
+
-
- true
- true
-
+
+ true
+ true
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
-
-
-
- True
- True
- DSMGenerator.tt
-
-
- TextTemplatingFileGenerator
- DSMGenerator.dummy
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
-
-
-
+
+
+ True
+ True
+ DSMGenerator.tt
+
+
+ TextTemplatingFileGenerator
+ DSMGenerator.dummy
+
+
+
+
+
+
diff --git a/src/NTwain/Native/BITMAP.cs b/src/NTwain/Native/BITMAP.cs
index 3ab1d2a..d83e016 100644
--- a/src/NTwain/Native/BITMAP.cs
+++ b/src/NTwain/Native/BITMAP.cs
@@ -2,339 +2,253 @@
using System.Runtime.InteropServices;
using System.Text;
-namespace NTwain.Native
+namespace Windows.Win32.Graphics.Gdi
{
- // this is a good read
- // http://atlc.sourceforge.net/bmp.html
+ // this is a good read
+ // http://atlc.sourceforge.net/bmp.html
- ///
- /// Defines the dimensions and color information for a DIB.
- ///
- [StructLayout(LayoutKind.Sequential)]
- struct BITMAPINFO
- {
- ///
- /// Structure that contains information about the dimensions of color format.
- ///
- public BITMAPINFOHEADER bmiHeader;
- ///
- /// This contains one of the following:
- /// 1. An array of RGBQUAD. The elements of the array that make up the color table.
- /// 2. An array of 16-bit unsigned integers that specifies indexes into the currently realized logical palette. This use of bmiColors is allowed for functions that use DIBs.
- /// The number of entries in the array depends on the values of the biBitCount and biClrUsed members of the BITMAPINFOHEADER structure.
- ///
- public IntPtr bmiColors;
- };
-
- ///
- /// Structure that contains information about the dimensions and color format of a DIB.
- ///
- [StructLayout(LayoutKind.Sequential)]
- struct BITMAPINFOHEADER
- {
- #region fields
- ///
- /// The number of bytes required by the structure.
- ///
- public uint biSize;
- ///
- /// The width of the bitmap, in pixels.
- /// If Compression is JPEG or PNG, the Width member specifies the width of the decompressed
- /// JPEG or PNG image file, respectively.
- ///
- public int biWidth;
- ///
- /// The height of the bitmap, in pixels. If Height is positive,
- /// the bitmap is a bottom-up DIB and its origin is the lower-left corner.
- /// If Height is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.
- /// If Height is negative, indicating a top-down DIB, Compression must be either RGB or BITFIELDS. Top-down DIBs cannot be compressed.
- /// If Compression is JPEG or PNG, the Height member specifies the height of the decompressed JPEG or PNG image file, respectively.
- ///
- public int biHeight;
- ///
- /// The number of planes for the target device. This value must be set to 1.
- ///
- public ushort biPlanes;
- ///
- /// The number of bits-per-pixel. The BitCount member
- /// determines the number of bits that define each pixel and the maximum number of colors in the bitmap.
- ///
- public ushort biBitCount;
- ///
- /// The type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed).
- ///
- public CompressionType biCompression;
- ///
- /// The size, in bytes, of the image. This may be set to zero for RGB bitmaps.
- /// If Compression is JPEG or PNG, SizeImage indicates the size of the JPEG or PNG image buffer, respectively.
- ///
- public uint biSizeImage;
- ///
- /// The horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
- /// An application can use this value to select a bitmap from a resource group that
- /// best matches the characteristics of the current device.
- ///
- public int biXPelsPerMeter;
- ///
- /// The vertical resolution, in pixels-per-meter, of the target device for the bitmap.
- ///
- public int biYPelsPerMeter;
- ///
- /// The number of color indexes in the color table that are actually used by the bitmap.
- /// If this value is zero, the bitmap uses the maximum number of colors corresponding to
- /// the value of the BitCount member for the compression mode specified by Compression.
- ///
- public uint biClrUsed;
- ///
- /// The number of color indexes that are required for displaying the bitmap.
- /// If this value is zero, all colors are required.
- ///
- public uint biClrImportant;
- #endregion
-
- #region utilities
-
- const double METER_INCH_RATIO = 39.3700787;
-
- ///
- /// Gets the horizontal dpi of the bitmap.
- ///
- ///
- public float GetXDpi()
+ partial struct BITMAPINFOHEADER
{
- return (float)Math.Round(biXPelsPerMeter / METER_INCH_RATIO, 0);
- }
- ///
- /// Gets the vertical dpi of the bitmap.
- ///
- ///
- public float GetYDpi()
- {
- return (float)Math.Round(biYPelsPerMeter / METER_INCH_RATIO, 0);
- }
- ///
- /// Gets the size of the structure.
- ///
- ///
- public static uint GetByteSize()
- {
- return (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
- }
- ///
- /// Checks to see if this structure contain valid data.
- /// It also fills in any missing pieces if possible.
- ///
- ///
- public bool Validate()
- {
- if (biHeight != 0 && biWidth != 0 && biBitCount != 0)
- {
- if (biSize == 0)
+ const double METER_INCH_RATIO = 39.3700787;
+
+ ///
+ /// Gets the horizontal dpi of the bitmap.
+ ///
+ ///
+ public float GetXDpi()
{
- biSize = GetByteSize();
+ return (float)Math.Round(biXPelsPerMeter / METER_INCH_RATIO, 0);
}
- if (biClrUsed == 0)
+ ///
+ /// Gets the vertical dpi of the bitmap.
+ ///
+ ///
+ public float GetYDpi()
{
- switch (biBitCount)
- {
- case 1:
- biClrUsed = 2;
- break;
- case 4:
- biClrUsed = 16;
- break;
- case 8:
- biClrUsed = 256;
- break;
- }
+ return (float)Math.Round(biYPelsPerMeter / METER_INCH_RATIO, 0);
}
- if (biSizeImage == 0)
+ ///
+ /// Gets the size of the structure.
+ ///
+ ///
+ public static uint GetByteSize()
{
- biSizeImage = (uint)((((
- biWidth * biBitCount) + 31) & ~31) >> 3) * (uint)Math.Abs(biHeight);
+ return (uint)Marshal.SizeOf();
+ }
+ ///
+ /// Checks to see if this structure contain valid data.
+ /// It also fills in any missing pieces if possible.
+ ///
+ ///
+ public bool Validate()
+ {
+ if (biHeight != 0 && biWidth != 0 && biBitCount != 0)
+ {
+ if (biSize == 0)
+ {
+ biSize = GetByteSize();
+ }
+ if (biClrUsed == 0)
+ {
+ switch (biBitCount)
+ {
+ case 1:
+ biClrUsed = 2;
+ break;
+ case 4:
+ biClrUsed = 16;
+ break;
+ case 8:
+ biClrUsed = 256;
+ break;
+ }
+ }
+ if (biSizeImage == 0)
+ {
+ biSizeImage = (uint)((((
+ biWidth * biBitCount) + 31) & ~31) >> 3) * (uint)Math.Abs(biHeight);
+ }
+
+ return true;
+ }
+ return false;
}
- return true;
- }
- return false;
+ ///
+ /// Gets the pointer to scan0 given the header pointer.
+ ///
+ /// The header PTR.
+ ///
+ public IntPtr GetScan0(IntPtr headerPtr)
+ {
+ int p = (int)biClrUsed;
+ if ((p == 0) && (biBitCount <= 8))
+ {
+ p = 1 << biBitCount;
+ }
+ p = (p * 4) + (int)biSize + headerPtr.ToInt32();
+ return new IntPtr(p);
+ }
+
+ ///
+ /// Gets whether the bitmap is bottom-up or top-down format.
+ ///
+ ///
+ /// true if this instance is bottom up image; otherwise, false.
+ ///
+ ///
+ public bool IsBottomUpImage
+ {
+ get
+ {
+ return biHeight > 0;
+ }
+ }
+
+
+ /////
+ ///// Gets the System.Drawing pixel format of current structure.
+ /////
+ /////
+ //public PixelFormat GetDrawingPixelFormat()
+ //{
+ // switch (biBitCount)
+ // {
+ // case 1:
+ // return PixelFormat.Format1bppIndexed;
+ // case 4:
+ // return PixelFormat.Format4bppIndexed;
+ // case 8:
+ // return PixelFormat.Format8bppIndexed;
+ // case 16:
+ // return PixelFormat.Format16bppRgb565;
+ // case 24:
+ // return PixelFormat.Format24bppRgb;
+ // case 32:
+ // return PixelFormat.Format32bppRgb;
+ // case 48:
+ // return PixelFormat.Format48bppRgb;
+ // }
+ // return PixelFormat.DontCare;
+ //}
+
+ /////
+ ///// Gets the color palette that's contained in the header.
+ ///// Note not all images will have palette, so check if the return value
+ ///// is null before using it.
+ /////
+ /////
+ //public ColorPalette? GetDrawingPalette(IntPtr headerPtr)
+ //{
+ // //if (format == PixelFormat.Format8bppIndexed)
+ // //{
+ // // // update color palette to grayscale version
+ // // ColorPalette grayPallet = bitmap.Palette;
+ // // for (int i = 0; i < grayPallet.Entries.Length; i++)
+ // // {
+ // // grayPallet.Entries[i] = Color.FromArgb(i, i, i);
+ // // }
+ // // bitmap.Palette = grayPallet; // this is what makes the gray pallet take effect
+ // //}
+
+ // if (biClrUsed > 0)
+ // {
+ // byte[] data = new byte[biClrUsed * 4];
+ // Marshal.Copy(new IntPtr(headerPtr.ToInt32() + biSize), data, 0, data.Length);
+ // var dummy = new System.Drawing.Bitmap(1, 1, GetDrawingPixelFormat());
+ // ColorPalette pal = dummy.Palette;
+ // dummy.Dispose();
+ // int index = 0;
+ // int setCount = data.Length / 4;
+ // for (int i = 0; i < setCount; i++)
+ // {
+ // index = i * 4;
+ // pal.Entries[i] = Color.FromArgb(data[index + 2], data[index + 1], data[index]);
+ // }
+ // return pal;
+ // }
+ // return null;
+ //}
+
+ ///
+ /// Gets the stride size of this bitmap.
+ ///
+ ///
+ public int GetStride()
+ {
+ int bitsPerRow = (biBitCount * biWidth);
+ int strideTest = bitsPerRow / 8 + (bitsPerRow % 8 != 0 ? 1 : 0);
+ int overage = strideTest % 4;
+ if (overage > 0)
+ {
+ strideTest += (4 - overage);
+ }
+ return strideTest;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return new StringBuilder().Append("BitmapInfoHeader:")
+ .Append("\r\n\tSize = " + biSize)
+ .Append("\r\n\tWidth = " + biWidth)
+ .Append("\r\n\tHeight = " + biHeight)
+ .Append("\r\n\tPlanes = " + biPlanes)
+ .Append("\r\n\tBitCount = " + biBitCount)
+ .Append("\r\n\tCompression = " + Compression)
+ .Append("\r\n\tSizeImage = " + biSizeImage)
+ .Append("\r\n\tXPixelsPerMeter = " + biXPelsPerMeter)
+ .Append("\r\n\tYPixelsPerMeter = " + biYPelsPerMeter)
+ .Append("\r\n\tColorUsed = " + biClrUsed)
+ .Append("\r\n\tColorImportant = " + biClrImportant).ToString();
+ }
+
+ ///
+ /// Gets the bitmap compression type.
+ ///
+ public CompressionType Compression { get { return (CompressionType)biCompression; } }
+
+ ///
+ /// Indicates the bitmap compression of .
+ ///
+ public enum CompressionType : uint
+ {
+ ///
+ /// An uncompressed format.
+ ///
+ BI_RGB = 0,
+ ///
+ /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte format consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression.
+ ///
+ BI_RLE8 = 1,
+ ///
+ /// An RLE, format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting of a count byte followed by two word-length color indexes. For more information, see Bitmap Compression.
+ ///
+ BI_RLE4 = 2,
+ ///
+ /// Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components of each pixel.
+ /// This is valid when used with 16- and 32-bpp bitmaps.
+ ///
+ BI_BITFIELDS = 3,
+ ///
+ /// Indicates that the image is a JPEG image.
+ ///
+ BI_JPEG = 4,
+ ///
+ /// Indicates that the image is a PNG image.
+ ///
+ BI_PNG = 5
+ }
}
- ///
- /// Gets the pointer to scan0 given the header pointer.
- ///
- /// The header PTR.
- ///
- public IntPtr GetScan0(IntPtr headerPtr)
- {
- int p = (int)biClrUsed;
- if ((p == 0) && (biBitCount <= 8))
- {
- p = 1 << biBitCount;
- }
- p = (p * 4) + (int)biSize + headerPtr.ToInt32();
- return new IntPtr(p);
- }
-
- ///
- /// Gets whether the bitmap is bottom-up or top-down format.
- ///
- ///
- /// true if this instance is bottom up image; otherwise, false.
- ///
- ///
- public bool IsBottomUpImage
- {
- get
- {
- return biHeight > 0;
- }
- }
-
-
- /////
- ///// Gets the System.Drawing pixel format of current structure.
- /////
- /////
- //public PixelFormat GetDrawingPixelFormat()
+ //[StructLayout(LayoutKind.Sequential, Pack = 1)]
+ //struct BITMAPFILEHEADER
//{
- // switch (biBitCount)
- // {
- // case 1:
- // return PixelFormat.Format1bppIndexed;
- // case 4:
- // return PixelFormat.Format4bppIndexed;
- // case 8:
- // return PixelFormat.Format8bppIndexed;
- // case 16:
- // return PixelFormat.Format16bppRgb565;
- // case 24:
- // return PixelFormat.Format24bppRgb;
- // case 32:
- // return PixelFormat.Format32bppRgb;
- // case 48:
- // return PixelFormat.Format48bppRgb;
- // }
- // return PixelFormat.DontCare;
+ // public ushort bfType;
+ // public uint bfSize;
+ // public ushort bfReserved1;
+ // public ushort bfReserved2;
+ // public uint bfOffBits;
//}
-
- /////
- ///// Gets the color palette that's contained in the header.
- ///// Note not all images will have palette, so check if the return value
- ///// is null before using it.
- /////
- /////
- //public ColorPalette? GetDrawingPalette(IntPtr headerPtr)
- //{
- // //if (format == PixelFormat.Format8bppIndexed)
- // //{
- // // // update color palette to grayscale version
- // // ColorPalette grayPallet = bitmap.Palette;
- // // for (int i = 0; i < grayPallet.Entries.Length; i++)
- // // {
- // // grayPallet.Entries[i] = Color.FromArgb(i, i, i);
- // // }
- // // bitmap.Palette = grayPallet; // this is what makes the gray pallet take effect
- // //}
-
- // if (biClrUsed > 0)
- // {
- // byte[] data = new byte[biClrUsed * 4];
- // Marshal.Copy(new IntPtr(headerPtr.ToInt32() + biSize), data, 0, data.Length);
- // var dummy = new System.Drawing.Bitmap(1, 1, GetDrawingPixelFormat());
- // ColorPalette pal = dummy.Palette;
- // dummy.Dispose();
- // int index = 0;
- // int setCount = data.Length / 4;
- // for (int i = 0; i < setCount; i++)
- // {
- // index = i * 4;
- // pal.Entries[i] = Color.FromArgb(data[index + 2], data[index + 1], data[index]);
- // }
- // return pal;
- // }
- // return null;
- //}
-
- ///
- /// Gets the stride size of this bitmap.
- ///
- ///
- public int GetStride()
- {
- int bitsPerRow = (biBitCount * biWidth);
- int strideTest = bitsPerRow / 8 + (bitsPerRow % 8 != 0 ? 1 : 0);
- int overage = strideTest % 4;
- if (overage > 0)
- {
- strideTest += (4 - overage);
- }
- return strideTest;
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public override string ToString()
- {
- return new StringBuilder().Append("BitmapInfoHeader:")
- .Append("\r\n\tSize = " + biSize)
- .Append("\r\n\tWidth = " + biWidth)
- .Append("\r\n\tHeight = " + biHeight)
- .Append("\r\n\tPlanes = " + biPlanes)
- .Append("\r\n\tBitCount = " + biBitCount)
- .Append("\r\n\tCompression = " + biCompression)
- .Append("\r\n\tSizeImage = " + biSizeImage)
- .Append("\r\n\tXPixelsPerMeter = " + biXPelsPerMeter)
- .Append("\r\n\tYPixelsPerMeter = " + biYPelsPerMeter)
- .Append("\r\n\tColorUsed = " + biClrUsed)
- .Append("\r\n\tColorImportant = " + biClrImportant).ToString();
- }
- #endregion
-
- ///
- /// Indicates the bitmap compression of .
- ///
- public enum CompressionType : uint
- {
- ///
- /// An uncompressed format.
- ///
- BI_RGB = 0,
- ///
- /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte format consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression.
- ///
- BI_RLE8 = 1,
- ///
- /// An RLE, format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting of a count byte followed by two word-length color indexes. For more information, see Bitmap Compression.
- ///
- BI_RLE4 = 2,
- ///
- /// Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components of each pixel.
- /// This is valid when used with 16- and 32-bpp bitmaps.
- ///
- BI_BITFIELDS = 3,
- ///
- /// Indicates that the image is a JPEG image.
- ///
- BI_JPEG = 4,
- ///
- /// Indicates that the image is a PNG image.
- ///
- BI_PNG = 5
- }
- };
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- struct BITMAPFILEHEADER
- {
- public ushort bfType;
- public uint bfSize;
- public ushort bfReserved1;
- public ushort bfReserved2;
- public uint bfOffBits;
- }
}
diff --git a/src/NTwain/Native/ImageTools.cs b/src/NTwain/Native/ImageTools.cs
index d987285..86ceec9 100644
--- a/src/NTwain/Native/ImageTools.cs
+++ b/src/NTwain/Native/ImageTools.cs
@@ -1,145 +1,146 @@
using NTwain.Data;
using System;
using System.Runtime.InteropServices;
+using Windows.Win32.Graphics.Gdi;
namespace NTwain.Native
{
- static class ImageTools
- {
- // this is modified from twain cs sample
- // http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
-
- public static bool IsDib(IntPtr data)
+ static class ImageTools
{
- // a quick check not guaranteed correct,
- // compare first 2 bytes to size of struct (which is also the first field)
- var test = Marshal.ReadInt16(data);
- // should be 40
- return test == BITMAPINFOHEADER.GetByteSize();
- }
- public static bool IsTiff(IntPtr data)
- {
- var test = Marshal.ReadInt16(data);
- // should be II
- return test == 0x4949;
- }
+ // this is modified from twain cs sample
+ // http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
- public static unsafe BufferedData? GetBitmapData(IntPtr data)
- {
- var infoHeader = Marshal.PtrToStructure(data);
- if (infoHeader.Validate())
- {
- var fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
-
- var fileHeader = new BITMAPFILEHEADER
+ public static bool IsDib(IntPtr data)
{
- bfType = 0x4D42, // "BM"
- bfOffBits = (uint)fileHeaderSize +
- infoHeader.biSize +
- (infoHeader.biClrUsed * 4)
- };
- fileHeader.bfSize = fileHeader.bfOffBits + infoHeader.biSizeImage;
-
- var dataCopy = BufferedData.MemPool.Rent((int)fileHeader.bfSize); // new byte[fileHeader.bfSize];
-
- // TODO: run benchmark on which one is faster
-
- // write file header
- //IntPtr tempPtr = Marshal.AllocHGlobal(fileHeaderSize);
- //Marshal.StructureToPtr(fileHeader, tempPtr, true);
- //Marshal.Copy(tempPtr, dataCopy, 0, fileHeaderSize);
- //Marshal.FreeHGlobal(tempPtr);
-
- // would this be faster?
- fixed (byte* p = dataCopy)
+ // a quick check not guaranteed correct,
+ // compare first 2 bytes to size of struct (which is also the first field)
+ var test = Marshal.ReadInt16(data);
+ // should be 40
+ return test == BITMAPINFOHEADER.GetByteSize();
+ }
+ public static bool IsTiff(IntPtr data)
{
- Marshal.StructureToPtr(fileHeader, (IntPtr)p, false);
+ var test = Marshal.ReadInt16(data);
+ // should be II
+ return test == 0x4949;
}
- // write image
- Marshal.Copy(data, dataCopy, fileHeaderSize, (int)fileHeader.bfSize - fileHeaderSize);
- return new BufferedData(dataCopy, (int)fileHeader.bfSize, true);
- }
- return default;
- }
-
- public static BufferedData? GetTiffData(IntPtr data)
- {
- // Find the size of the image so we can turn it into a memory stream...
- var headerSize = Marshal.SizeOf(typeof(TIFFHEADER));
- var tagSize = Marshal.SizeOf(typeof(TIFFTAG));
- var tiffSize = 0;
- var tagPtr = data.ToInt64() + headerSize;
- for (int i = 0; i < 999; i++)
- {
- tagPtr += (tagSize * i);
- var tag = Marshal.PtrToStructure((IntPtr)tagPtr);
-
- switch (tag.u16Tag)
+ public static unsafe BufferedData? GetBitmapData(IntPtr data)
{
- case 273: // StripOffsets...
- case 279: // StripByteCounts...
- tiffSize += (int)tag.u32Value;
- break;
+ var infoHeader = Marshal.PtrToStructure(data);
+ if (infoHeader.Validate())
+ {
+ var fileHeaderSize = Marshal.SizeOf();
+
+ var fileHeader = new BITMAPFILEHEADER
+ {
+ bfType = 0x4D42, // "BM"
+ bfOffBits = (uint)fileHeaderSize +
+ infoHeader.biSize +
+ (infoHeader.biClrUsed * 4)
+ };
+ fileHeader.bfSize = fileHeader.bfOffBits + infoHeader.biSizeImage;
+
+ var dataCopy = BufferedData.MemPool.Rent((int)fileHeader.bfSize); // new byte[fileHeader.bfSize];
+
+ // TODO: run benchmark on which one is faster
+
+ // write file header
+ //IntPtr tempPtr = Marshal.AllocHGlobal(fileHeaderSize);
+ //Marshal.StructureToPtr(fileHeader, tempPtr, true);
+ //Marshal.Copy(tempPtr, dataCopy, 0, fileHeaderSize);
+ //Marshal.FreeHGlobal(tempPtr);
+
+ // would this be faster?
+ fixed (byte* p = dataCopy)
+ {
+ Marshal.StructureToPtr(fileHeader, (IntPtr)p, false);
+ }
+
+ // write image
+ Marshal.Copy(data, dataCopy, fileHeaderSize, (int)fileHeader.bfSize - fileHeaderSize);
+ return new BufferedData(dataCopy, (int)fileHeader.bfSize, true);
+ }
+ return default;
}
- }
- if (tiffSize > 0)
- {
- var dataCopy = BufferedData.MemPool.Rent(tiffSize);// new byte[tiffSize];
- Marshal.Copy(data, dataCopy, 0, tiffSize);
- return new BufferedData(dataCopy, tiffSize, true);
- }
- return default;
+ public static BufferedData? GetTiffData(IntPtr data)
+ {
+ // Find the size of the image so we can turn it into a memory stream...
+ var headerSize = Marshal.SizeOf();
+ var tagSize = Marshal.SizeOf();
+ var tiffSize = 0;
+ var tagPtr = data.ToInt64() + headerSize;
+ for (int i = 0; i < 999; i++)
+ {
+ tagPtr += (tagSize * i);
+ var tag = Marshal.PtrToStructure((IntPtr)tagPtr);
+
+ switch (tag.u16Tag)
+ {
+ case 273: // StripOffsets...
+ case 279: // StripByteCounts...
+ tiffSize += (int)tag.u32Value;
+ break;
+ }
+ }
+
+ if (tiffSize > 0)
+ {
+ var dataCopy = BufferedData.MemPool.Rent(tiffSize);// new byte[tiffSize];
+ Marshal.Copy(data, dataCopy, 0, tiffSize);
+ return new BufferedData(dataCopy, tiffSize, true);
+ }
+ return default;
+ }
+
+ //internal static Bitmap ReadBitmapImage(IntPtr data)
+ //{
+ // Bitmap finalImg = null;
+ // Bitmap tempImg = null;
+ // try
+ // {
+ // var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
+
+ // if (header.Validate())
+ // {
+ // PixelFormat format = header.GetDrawingPixelFormat();
+ // tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data));
+ // ColorPalette pal = header.GetDrawingPalette(data);
+ // if (pal != null)
+ // {
+ // tempImg.Palette = pal;
+ // }
+ // float xdpi = header.GetXDpi();
+ // float ydpi = header.GetYDpi();
+ // if (xdpi != 0 && ydpi == 0)
+ // {
+ // ydpi = xdpi;
+ // }
+ // else if (ydpi != 0 && xdpi == 0)
+ // {
+ // xdpi = ydpi;
+ // }
+ // if (xdpi != 0)
+ // {
+ // tempImg.SetResolution(xdpi, ydpi);
+ // }
+ // if (header.IsBottomUpImage)
+ // {
+ // tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY);
+ // }
+ // finalImg = tempImg;
+ // tempImg = null;
+ // }
+ // }
+ // finally
+ // {
+ // if (tempImg != null)
+ // {
+ // tempImg.Dispose();
+ // }
+ // }
+ // return finalImg;
+ //}
}
-
- //internal static Bitmap ReadBitmapImage(IntPtr data)
- //{
- // Bitmap finalImg = null;
- // Bitmap tempImg = null;
- // try
- // {
- // var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
-
- // if (header.Validate())
- // {
- // PixelFormat format = header.GetDrawingPixelFormat();
- // tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data));
- // ColorPalette pal = header.GetDrawingPalette(data);
- // if (pal != null)
- // {
- // tempImg.Palette = pal;
- // }
- // float xdpi = header.GetXDpi();
- // float ydpi = header.GetYDpi();
- // if (xdpi != 0 && ydpi == 0)
- // {
- // ydpi = xdpi;
- // }
- // else if (ydpi != 0 && xdpi == 0)
- // {
- // xdpi = ydpi;
- // }
- // if (xdpi != 0)
- // {
- // tempImg.SetResolution(xdpi, ydpi);
- // }
- // if (header.IsBottomUpImage)
- // {
- // tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY);
- // }
- // finalImg = tempImg;
- // tempImg = null;
- // }
- // }
- // finally
- // {
- // if (tempImg != null)
- // {
- // tempImg.Dispose();
- // }
- // }
- // return finalImg;
- //}
- }
}
diff --git a/src/NTwain/Native/WIN_MESSAGE.cs b/src/NTwain/Native/WIN_MESSAGE.cs
index 132eb3a..b5a4899 100644
--- a/src/NTwain/Native/WIN_MESSAGE.cs
+++ b/src/NTwain/Native/WIN_MESSAGE.cs
@@ -1,21 +1,21 @@
-using System;
-using System.Runtime.InteropServices;
+//using System;
+//using System.Runtime.InteropServices;
-namespace NTwain.Native
-{
- ///
- /// The MSG structure in Windows for TWAIN use.
- ///
- [StructLayout(LayoutKind.Sequential)]
- struct WIN_MESSAGE
- {
- public IntPtr hwnd;
- public uint message;
- public IntPtr wParam;
- public IntPtr lParam;
- uint _time;
- int _x;
- int _y;
- uint lprivate;
- }
-}
+//namespace NTwain.Native
+//{
+// ///
+// /// The MSG structure in Windows for TWAIN use.
+// ///
+// [StructLayout(LayoutKind.Sequential)]
+// struct WIN_MESSAGE
+// {
+// public IntPtr hwnd;
+// public uint message;
+// public IntPtr wParam;
+// public IntPtr lParam;
+// uint _time;
+// int _x;
+// int _y;
+// uint lprivate;
+// }
+//}
diff --git a/src/NTwain/Native/WinNativeMethods.cs b/src/NTwain/Native/WinNativeMethods.cs
index 8242541..18e80cc 100644
--- a/src/NTwain/Native/WinNativeMethods.cs
+++ b/src/NTwain/Native/WinNativeMethods.cs
@@ -1,97 +1,97 @@
-using System;
-using System.Runtime.InteropServices;
+//using System;
+//using System.Runtime.InteropServices;
-namespace NTwain.Native
-{
- ///
- /// Native methods for windows.
- ///
- static partial class WinNativeMethods
- {
-#if NET7_0_OR_GREATER
- [LibraryImport("kernel32", SetLastError = true)]
- public static partial IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes);
+//namespace NTwain.Native
+//{
+// ///
+// /// Native methods for windows.
+// ///
+// static partial class WinNativeMethods
+// {
+//#if NET7_0_OR_GREATER
+// [LibraryImport("kernel32", SetLastError = true)]
+// public static partial IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes);
- [LibraryImport("kernel32", SetLastError = true)]
- public static partial IntPtr GlobalFree(IntPtr hMem);
+// [LibraryImport("kernel32", SetLastError = true)]
+// public static partial IntPtr GlobalFree(IntPtr hMem);
- [LibraryImport("kernel32", SetLastError = true)]
- public static partial IntPtr GlobalLock(IntPtr handle);
+// [LibraryImport("kernel32", SetLastError = true)]
+// public static partial IntPtr GlobalLock(IntPtr handle);
- [LibraryImport("kernel32", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static partial bool GlobalUnlock(IntPtr handle);
-#else
- [DllImport("kernel32", SetLastError = true)]
- public static extern IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes);
+// [LibraryImport("kernel32", SetLastError = true)]
+// [return: MarshalAs(UnmanagedType.Bool)]
+// public static partial bool GlobalUnlock(IntPtr handle);
+//#else
+// [DllImport("kernel32", SetLastError = true)]
+// public static extern IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes);
- [DllImport("kernel32", SetLastError = true)]
- public static extern IntPtr GlobalFree(IntPtr hMem);
+// [DllImport("kernel32", SetLastError = true)]
+// public static extern IntPtr GlobalFree(IntPtr hMem);
- [DllImport("kernel32", SetLastError = true)]
- public static extern IntPtr GlobalLock(IntPtr handle);
+// [DllImport("kernel32", SetLastError = true)]
+// public static extern IntPtr GlobalLock(IntPtr handle);
- [DllImport("kernel32", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GlobalUnlock(IntPtr handle);
-#endif
-
- [Flags]
- public enum AllocFlag : uint
- {
- ///
- /// Allocates fixed memory. The return value is a pointer.
- ///
- GMEM_FIXED = 0,
- ///
- /// Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap.
- /// The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function.
- ///
- GMEM_MOVEABLE = 2,
- ///
- /// Initializes memory contents to zero.
- ///
- GMEM_ZEROINIT = 0x40,
- GPTR = GMEM_FIXED | GMEM_ZEROINIT,
- GHND = GMEM_MOVEABLE | GMEM_ZEROINIT
- }
+// [DllImport("kernel32", SetLastError = true)]
+// [return: MarshalAs(UnmanagedType.Bool)]
+// public static extern bool GlobalUnlock(IntPtr handle);
+//#endif
// [Flags]
-// public enum PEEK_MESSAGE_REMOVE_TYPE : uint
+// public enum AllocFlag : uint
// {
-// PM_NOREMOVE = 0x00000000,
-// PM_REMOVE = 0x00000001,
-// PM_NOYIELD = 0x00000002,
-// PM_QS_INPUT = 0x04070000,
-// PM_QS_POSTMESSAGE = 0x00980000,
-// PM_QS_PAINT = 0x00200000,
-// PM_QS_SENDMESSAGE = 0x00400000,
+// ///
+// /// Allocates fixed memory. The return value is a pointer.
+// ///
+// GMEM_FIXED = 0,
+// ///
+// /// Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap.
+// /// The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function.
+// ///
+// GMEM_MOVEABLE = 2,
+// ///
+// /// Initializes memory contents to zero.
+// ///
+// GMEM_ZEROINIT = 0x40,
+// GPTR = GMEM_FIXED | GMEM_ZEROINIT,
+// GHND = GMEM_MOVEABLE | GMEM_ZEROINIT
// }
-//#if NET7_0_OR_GREATER
-// [LibraryImport("USER32.dll")]
-// public static partial int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg);
+//// [Flags]
+//// public enum PEEK_MESSAGE_REMOVE_TYPE : uint
+//// {
+//// PM_NOREMOVE = 0x00000000,
+//// PM_REMOVE = 0x00000001,
+//// PM_NOYIELD = 0x00000002,
+//// PM_QS_INPUT = 0x04070000,
+//// PM_QS_POSTMESSAGE = 0x00980000,
+//// PM_QS_PAINT = 0x00200000,
+//// PM_QS_SENDMESSAGE = 0x00400000,
+//// }
-// [LibraryImport("USER32.dll", SetLastError = true)]
-// public static partial int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
+////#if NET7_0_OR_GREATER
+//// [LibraryImport("USER32.dll")]
+//// public static partial int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg);
-// [LibraryImport("USER32.dll")]
-// public static partial int TranslateMessage(ref WIN_MESSAGE lpMsg);
+//// [LibraryImport("USER32.dll", SetLastError = true)]
+//// public static partial int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
-// [LibraryImport("USER32.dll")]
-// public static partial nint DispatchMessageW(ref WIN_MESSAGE lpMsg);
-//#else
-// [DllImport("USER32.dll")]
-// public static extern int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg);
+//// [LibraryImport("USER32.dll")]
+//// public static partial int TranslateMessage(ref WIN_MESSAGE lpMsg);
-// [DllImport("USER32.dll", SetLastError = true)]
-// public static extern int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
+//// [LibraryImport("USER32.dll")]
+//// public static partial nint DispatchMessageW(ref WIN_MESSAGE lpMsg);
+////#else
+//// [DllImport("USER32.dll")]
+//// public static extern int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg);
-// [DllImport("USER32.dll")]
-// public static extern int TranslateMessage(ref WIN_MESSAGE lpMsg);
+//// [DllImport("USER32.dll", SetLastError = true)]
+//// public static extern int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
-// [DllImport("USER32.dll")]
-// public static extern nint DispatchMessageW(ref WIN_MESSAGE lpMsg);
-//#endif
- }
-}
+//// [DllImport("USER32.dll")]
+//// public static extern int TranslateMessage(ref WIN_MESSAGE lpMsg);
+
+//// [DllImport("USER32.dll")]
+//// public static extern nint DispatchMessageW(ref WIN_MESSAGE lpMsg);
+////#endif
+// }
+//}
diff --git a/src/NTwain/NativeMethods.json b/src/NTwain/NativeMethods.json
new file mode 100644
index 0000000..dacdfc7
--- /dev/null
+++ b/src/NTwain/NativeMethods.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "https://aka.ms/CsWin32.schema.json",
+ "allowMarshaling": false
+}
\ No newline at end of file
diff --git a/src/NTwain/NativeMethods.txt b/src/NTwain/NativeMethods.txt
new file mode 100644
index 0000000..0638a0d
--- /dev/null
+++ b/src/NTwain/NativeMethods.txt
@@ -0,0 +1,8 @@
+MSG
+GlobalAlloc
+GlobalFree
+GlobalLock
+GlobalUnlock
+BITMAPINFOHEADER
+BITMAPINFO
+BITMAPFILEHEADER
\ No newline at end of file
diff --git a/src/NTwain/TwainAppSession.Memory.cs b/src/NTwain/TwainAppSession.Memory.cs
index c271d8e..768cd63 100644
--- a/src/NTwain/TwainAppSession.Memory.cs
+++ b/src/NTwain/TwainAppSession.Memory.cs
@@ -1,114 +1,131 @@
using NTwain.Data;
-using NTwain.Native;
using System;
using System.Runtime.InteropServices;
+using Windows.Win32;
+using Windows.Win32.Foundation;
+using Windows.Win32.System.Memory;
namespace NTwain
{
- // this file contains memory methods
+ // this file contains memory methods
- partial class TwainAppSession : IMemoryManager
- {
- TW_ENTRYPOINT_DELEGATES _entryPoint;
-
- public IntPtr Alloc(uint size)
+ partial class TwainAppSession : IMemoryManager
{
- if (_entryPoint.DSM_MemAllocate != null)
- {
- return _entryPoint.DSM_MemAllocate(size);
- }
- else if (TWPlatform.IsWindows)
- {
- return WinNativeMethods.GlobalAlloc(WinNativeMethods.AllocFlag.GHND, (UIntPtr)size);
- }
- else if (TWPlatform.IsLinux)
- {
- return Marshal.AllocHGlobal((int)size);
- }
- else if (TWPlatform.IsMacOSX)
- {
- return Marshal.AllocHGlobal((int)size);
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
+ TW_ENTRYPOINT_DELEGATES _entryPoint;
+
+ public IntPtr Alloc(uint size)
+ {
+ if (_entryPoint.DSM_MemAllocate != null)
+ {
+ return _entryPoint.DSM_MemAllocate(size);
+ }
+ else if (TWPlatform.IsWindows)
+ {
+#pragma warning disable CA1416 // Validate platform compatibility
+ return PInvoke.GlobalAlloc(GLOBAL_ALLOC_FLAGS.GHND, size);
+#pragma warning restore CA1416 // Validate platform compatibility
+ //return WinNativeMethods.GlobalAlloc(WinNativeMethods.AllocFlag.GHND, (UIntPtr)size);
+ }
+ else if (TWPlatform.IsLinux)
+ {
+ return Marshal.AllocHGlobal((int)size);
+ }
+ else if (TWPlatform.IsMacOSX)
+ {
+ return Marshal.AllocHGlobal((int)size);
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public void Free(IntPtr handle)
+ {
+ if (handle == IntPtr.Zero) return;
+
+ if (_entryPoint.DSM_MemFree != null)
+ {
+ _entryPoint.DSM_MemFree(handle);
+ }
+ else if (TWPlatform.IsWindows)
+ {
+#pragma warning disable CA1416 // Validate platform compatibility
+ PInvoke.GlobalFree((HGLOBAL)handle);
+#pragma warning restore CA1416 // Validate platform compatibility
+ //WinNativeMethods.GlobalFree(handle);
+ }
+ else if (TWPlatform.IsLinux)
+ {
+ Marshal.FreeHGlobal(handle);
+ }
+ else if (TWPlatform.IsMacOSX)
+ {
+ Marshal.FreeHGlobal(handle);
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public IntPtr Lock(IntPtr handle)
+ {
+ if (handle == IntPtr.Zero) return IntPtr.Zero;
+
+ if (_entryPoint.DSM_MemLock != null)
+ {
+ return _entryPoint.DSM_MemLock(handle);
+ }
+ else if (TWPlatform.IsWindows)
+ {
+ unsafe
+ {
+#pragma warning disable CA1416 // Validate platform compatibility
+ return (IntPtr)PInvoke.GlobalLock((HGLOBAL)handle);
+#pragma warning restore CA1416 // Validate platform compatibility
+ }
+ //return WinNativeMethods.GlobalLock(handle);
+ }
+ else if (TWPlatform.IsLinux)
+ {
+ return handle;
+ }
+ else if (TWPlatform.IsMacOSX)
+ {
+ return handle;
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public void Unlock(IntPtr handle)
+ {
+ if (handle == IntPtr.Zero) return;
+
+ if (_entryPoint.DSM_MemUnlock != null)
+ {
+ _entryPoint.DSM_MemUnlock(handle);
+ }
+ else if (TWPlatform.IsWindows)
+ {
+#pragma warning disable CA1416 // Validate platform compatibility
+ PInvoke.GlobalUnlock((HGLOBAL)handle);
+#pragma warning restore CA1416 // Validate platform compatibility
+ //WinNativeMethods.GlobalUnlock(handle);
+ }
+ else if (TWPlatform.IsLinux)
+ {
+ }
+ else if (TWPlatform.IsMacOSX)
+ {
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
}
-
- public void Free(IntPtr handle)
- {
- if (handle == IntPtr.Zero) return;
-
- if (_entryPoint.DSM_MemFree != null)
- {
- _entryPoint.DSM_MemFree(handle);
- }
- else if (TWPlatform.IsWindows)
- {
- WinNativeMethods.GlobalFree(handle);
- }
- else if (TWPlatform.IsLinux)
- {
- Marshal.FreeHGlobal(handle);
- }
- else if (TWPlatform.IsMacOSX)
- {
- Marshal.FreeHGlobal(handle);
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public IntPtr Lock(IntPtr handle)
- {
- if (handle == IntPtr.Zero) return IntPtr.Zero;
-
- if (_entryPoint.DSM_MemLock != null)
- {
- return _entryPoint.DSM_MemLock(handle);
- }
- else if (TWPlatform.IsWindows)
- {
- return WinNativeMethods.GlobalLock(handle);
- }
- else if (TWPlatform.IsLinux)
- {
- return handle;
- }
- else if (TWPlatform.IsMacOSX)
- {
- return handle;
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void Unlock(IntPtr handle)
- {
- if (handle == IntPtr.Zero) return;
-
- if (_entryPoint.DSM_MemUnlock != null)
- {
- _entryPoint.DSM_MemUnlock(handle);
- }
- else if (TWPlatform.IsWindows)
- {
- WinNativeMethods.GlobalUnlock(handle);
- }
- else if (TWPlatform.IsLinux)
- {
- }
- else if (TWPlatform.IsMacOSX)
- {
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
- }
}
diff --git a/src/NTwain/TwainAppSession.Windows.cs b/src/NTwain/TwainAppSession.Windows.cs
index 2380f21..cd6f69d 100644
--- a/src/NTwain/TwainAppSession.Windows.cs
+++ b/src/NTwain/TwainAppSession.Windows.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Interop;
+using Windows.Win32.Foundation;
using MSG = NTwain.Data.MSG;
namespace NTwain
@@ -83,11 +84,11 @@ namespace NTwain
bool handled = false;
if (_state >= STATE.S5)
{
- WIN_MESSAGE winMsg = new()
+ Windows.Win32.UI.WindowsAndMessaging.MSG winMsg = new()
{
- hwnd = hWnd,
+ hwnd = (HWND)hWnd,
message = (uint)msg,
- wParam = wParam,
+ wParam = TWPlatform.Is32bit ? new UIntPtr((uint)wParam.ToInt32()) : new UIntPtr((ulong)wParam.ToInt64()),
lParam = lParam
};
// no need to do another lock call when using marshal alloc