Integrated message thread inside TwainAppSession as a different OpenDSM method.

This commit is contained in:
Eugene Wang 2023-04-15 06:33:12 -04:00
parent 0e5aef00e5
commit 1364150697
8 changed files with 142 additions and 34 deletions

View File

@ -28,74 +28,96 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinForm64", "samples\WinFor
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csizes", "csizes\csizes.vcxproj", "{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csizes", "csizes\csizes.vcxproj", "{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinConsole32", "samples\WinConsole32\WinConsole32.csproj", "{4E2417E7-FDC3-46D7-B976-84A97B500B74}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinConsole32", "samples\WinConsole32\WinConsole32.csproj", "{4E2417E7-FDC3-46D7-B976-84A97B500B74}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|ARM64.Build.0 = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.ActiveCfg = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.ActiveCfg = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.Build.0 = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.Build.0 = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.ActiveCfg = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.ActiveCfg = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.Build.0 = Debug|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.Build.0 = Debug|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.Build.0 = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.Build.0 = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|ARM64.ActiveCfg = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|ARM64.Build.0 = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.ActiveCfg = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.ActiveCfg = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.Build.0 = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.Build.0 = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.ActiveCfg = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.ActiveCfg = Release|Any CPU
{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.Build.0 = Release|Any CPU {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.Build.0 = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|ARM64.Build.0 = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.ActiveCfg = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.ActiveCfg = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.Build.0 = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.Build.0 = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.ActiveCfg = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.ActiveCfg = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.Build.0 = Debug|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.Build.0 = Debug|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.ActiveCfg = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.Build.0 = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.Build.0 = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|ARM64.ActiveCfg = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|ARM64.Build.0 = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.ActiveCfg = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.ActiveCfg = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.Build.0 = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.Build.0 = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.ActiveCfg = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.ActiveCfg = Release|Any CPU
{7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.Build.0 = Release|Any CPU {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.Build.0 = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|ARM64.Build.0 = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.ActiveCfg = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.ActiveCfg = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.Build.0 = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.Build.0 = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.ActiveCfg = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.ActiveCfg = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.Build.0 = Debug|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.Build.0 = Debug|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.Build.0 = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.Build.0 = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|ARM64.ActiveCfg = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|ARM64.Build.0 = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.ActiveCfg = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.ActiveCfg = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.Build.0 = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.Build.0 = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.ActiveCfg = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.ActiveCfg = Release|Any CPU
{C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.Build.0 = Release|Any CPU {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.Build.0 = Release|Any CPU
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.ActiveCfg = Debug|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.ActiveCfg = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.Build.0 = Debug|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.Build.0 = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|ARM64.ActiveCfg = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|ARM64.Build.0 = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.ActiveCfg = Debug|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.ActiveCfg = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.Build.0 = Debug|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.Build.0 = Debug|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.ActiveCfg = Debug|Win32 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.ActiveCfg = Debug|Win32
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.Build.0 = Debug|Win32 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.Build.0 = Debug|Win32
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.ActiveCfg = Release|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.ActiveCfg = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.Build.0 = Release|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.Build.0 = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|ARM64.ActiveCfg = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|ARM64.Build.0 = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.ActiveCfg = Release|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.ActiveCfg = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.Build.0 = Release|x64 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.Build.0 = Release|x64
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.ActiveCfg = Release|Win32 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.ActiveCfg = Release|Win32
{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.Build.0 = Release|Win32 {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.Build.0 = Release|Win32
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|ARM64.Build.0 = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.ActiveCfg = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.ActiveCfg = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.Build.0 = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.Build.0 = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.ActiveCfg = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.ActiveCfg = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.Build.0 = Debug|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.Build.0 = Debug|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.Build.0 = Release|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.Build.0 = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|ARM64.ActiveCfg = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|ARM64.Build.0 = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.ActiveCfg = Release|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.ActiveCfg = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.Build.0 = Release|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.Build.0 = Release|Any CPU
{4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x86.ActiveCfg = Release|Any CPU {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x86.ActiveCfg = Release|Any CPU

View File

@ -11,14 +11,13 @@ namespace WinConsole32
var libVer = FileVersionInfo.GetVersionInfo(typeof(TwainAppSession).Assembly.Location).ProductVersion; var libVer = FileVersionInfo.GetVersionInfo(typeof(TwainAppSession).Assembly.Location).ProductVersion;
Console.WriteLine($"Console sample {(TWPlatform.Is32bit ? " 32bit" : " 64bit")} on NTwain {libVer}"); Console.WriteLine($"Console sample {(TWPlatform.Is32bit ? " 32bit" : " 64bit")} on NTwain {libVer}");
MessagePumpThread pump = new MessagePumpThread();
TwainAppSession session = new TwainAppSession(Environment.ProcessPath!); TwainAppSession session = new TwainAppSession(Environment.ProcessPath!);
session.StateChanged += Session_StateChanged; session.StateChanged += Session_StateChanged;
session.SourceDisabled += Session_SourceDisabled1; session.SourceDisabled += Session_SourceDisabled1;
session.Transferred += Session_Transferred; session.Transferred += Session_Transferred;
var sts = await pump.AttachAsync(session); var sts = await session.OpenDSMAsync();
if (sts.IsSuccess) if (sts.IsSuccess)
{ {

View File

@ -19,7 +19,6 @@ namespace WinFormSample
public partial class Form1 : Form public partial class Form1 : Form
{ {
bool useDiyPump = true; bool useDiyPump = true;
MessagePumpThread pump;
TwainAppSession twain; TwainAppSession twain;
readonly string saveFolder; readonly string saveFolder;
readonly Stopwatch watch = new(); readonly Stopwatch watch = new();
@ -36,7 +35,6 @@ namespace WinFormSample
var libVer = FileVersionInfo.GetVersionInfo(typeof(TwainAppSession).Assembly.Location).ProductVersion; var libVer = FileVersionInfo.GetVersionInfo(typeof(TwainAppSession).Assembly.Location).ProductVersion;
Text += $"{(TWPlatform.Is32bit ? " 32bit" : " 64bit")} on NTwain {libVer}"; Text += $"{(TWPlatform.Is32bit ? " 32bit" : " 64bit")} on NTwain {libVer}";
pump = new MessagePumpThread();
TWPlatform.PreferLegacyDSM = false; TWPlatform.PreferLegacyDSM = false;
twain = new TwainAppSession(Assembly.GetExecutingAssembly().Location); twain = new TwainAppSession(Assembly.GetExecutingAssembly().Location);
@ -87,35 +85,29 @@ namespace WinFormSample
} }
} }
protected override void OnHandleCreated(EventArgs e) protected override async void OnHandleCreated(EventArgs e)
{ {
base.OnHandleCreated(e); base.OnHandleCreated(e);
if (useDiyPump) if (useDiyPump)
{ {
_ = pump.AttachAsync(twain); var sts = await twain.OpenDSMAsync();
Debug.WriteLine($"OpenDSMAsync={sts}");
} }
else else
{ {
var hwnd = this.Handle; var hwnd = this.Handle;
var rc = twain.OpenDSM(hwnd, SynchronizationContext.Current!); var sts = twain.OpenDSM(hwnd, SynchronizationContext.Current!);
twain.AddWinformFilter(); twain.AddWinformFilter();
Debug.WriteLine($"OpenDSM={rc}"); Debug.WriteLine($"OpenDSM={sts}");
} }
} }
protected override void OnClosing(CancelEventArgs e) protected override void OnClosing(CancelEventArgs e)
{ {
if (useDiyPump) var finalState = twain.TryStepdown(STATE.S2);
{ Debug.WriteLine($"Stepdown result state={finalState}");
pump.Detatch(); twain.RemoveWinformFilter();
}
else
{
var finalState = twain.TryStepdown(STATE.S2);
Debug.WriteLine($"Stepdown result state={finalState}");
twain.RemoveWinformFilter();
}
base.OnClosing(e); base.OnClosing(e);
} }

View File

@ -1017,7 +1017,7 @@ namespace NTwain.Data
/// For pointers you'd read it yourself with /// For pointers you'd read it yourself with
/// <see cref="ValueReader.ReadTWTYData{TValue}(IntPtr, TWTY, int)"/>. /// <see cref="ValueReader.ReadTWTYData{TValue}(IntPtr, TWTY, int)"/>.
/// Unless it's a handle (<see cref="TWTY.HANDLE"/>) to non-twain-strings, then you'd use /// Unless it's a handle (<see cref="TWTY.HANDLE"/>) to non-twain-strings, then you'd use
/// <see cref="ReadHandleString(IMemoryManager, int)"/>. /// <see cref="ReadHandleString"/>.
/// </summary> /// </summary>
/// <typeparam name="TValue"></typeparam> /// <typeparam name="TValue"></typeparam>
/// <returns></returns> /// <returns></returns>

View File

@ -12,7 +12,7 @@ namespace NTwain
/// For use under Windows to host a message pump in non-winform/wpf apps. /// For use under Windows to host a message pump in non-winform/wpf apps.
/// This is highly experimental. /// This is highly experimental.
/// </summary> /// </summary>
public class MessagePumpThread class MessagePumpThread
{ {
DummyForm? _dummyForm; DummyForm? _dummyForm;
TwainAppSession? _twain; TwainAppSession? _twain;
@ -70,11 +70,32 @@ namespace NTwain
/// <summary> /// <summary>
/// Detatches a previously attached session and stops the thread. /// Detatches a previously attached session and stops the thread.
/// </summary> /// </summary>
public void Detatch() public async Task<STS> DetatchAsync()
{ {
STS sts = default;
if (_dummyForm != null && _twain != null) if (_dummyForm != null && _twain != null)
{ {
_dummyForm.BeginInvoke(_dummyForm.Close); TaskCompletionSource<bool> tcs = new();
_dummyForm.BeginInvoke(() =>
{
sts = _twain.CloseDSMReal();
if (sts.IsSuccess)
{
_twain.RemoveWinformFilter();
_dummyForm.Close();
_twain = null;
}
});
await tcs.Task;
}
return sts;
}
public void BringWindowToFront()
{
if (_dummyForm != null)
{
_dummyForm.BeginInvoke(_dummyForm.BringToFront);
} }
} }
@ -84,13 +105,6 @@ namespace NTwain
_dummyForm = new DummyForm(); _dummyForm = new DummyForm();
_dummyForm.FormClosed += (s, e) => _dummyForm.FormClosed += (s, e) =>
{ {
if (_twain != null)
{
_twain.TryStepdown(STATE.S4);
_twain.RemoveWinformFilter();
_twain.CloseDSM();
_twain = null;
}
_dummyForm = null; _dummyForm = null;
}; };
Application.Run(_dummyForm); Application.Run(_dummyForm);
@ -104,6 +118,12 @@ namespace NTwain
ShowInTaskbar = false; ShowInTaskbar = false;
WindowState = FormWindowState.Minimized; WindowState = FormWindowState.Minimized;
} }
protected override void OnShown(EventArgs e)
{
BringToFront();
base.OnShown(e);
}
} }
} }
} }

View File

@ -21,11 +21,11 @@
<ItemGroup Condition=" '$(TargetFramework)' != 'net462'"> <ItemGroup Condition=" '$(TargetFramework)' != 'net462'">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup Condition="'$(Configuration)'!='Release'">
<None Remove="runtimes\win-x64\native\TWAINDSM.dll" /> <None Remove="runtimes\win-x64\native\TWAINDSM.dll" />
<None Remove="runtimes\win-x86\native\TWAINDSM.dll" /> <None Remove="runtimes\win-x86\native\TWAINDSM.dll" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup Condition="'$(Configuration)'!='Release'">
<Content Include="runtimes\win-x64\native\TWAINDSM.dll"> <Content Include="runtimes\win-x64\native\TWAINDSM.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

View File

@ -35,7 +35,7 @@ namespace NTwain
/// <summary> /// <summary>
/// Registers this session for use in a WPF UI thread. /// Registers this session for use in a WPF UI thread.
/// This requires the hwnd used in <see cref="OpenDSM(IntPtr)"/> /// This requires the hwnd used in <see cref="OpenDSM"/>
/// be a valid WPF window handle. /// be a valid WPF window handle.
/// </summary> /// </summary>
public void AddWpfHook() public void AddWpfHook()

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.Xml; using System.Xml;
namespace NTwain namespace NTwain
@ -99,6 +100,7 @@ namespace NTwain
internal IntPtr _hwnd; internal IntPtr _hwnd;
internal TW_USERINTERFACE _userInterface; // kept around for disable to use internal TW_USERINTERFACE _userInterface; // kept around for disable to use
#if WINDOWS || NETFRAMEWORK #if WINDOWS || NETFRAMEWORK
MessagePumpThread? _selfPump;
TW_EVENT _procEvent; // kept here so the alloc/free only happens once TW_EVENT _procEvent; // kept here so the alloc/free only happens once
#endif #endif
// test threads a bit // test threads a bit
@ -146,7 +148,6 @@ namespace NTwain
{ {
// this will end the bg thread // this will end the bg thread
_xferReady.Dispose(); _xferReady.Dispose();
//_bgPendingMsgs.CompleteAdding(); //_bgPendingMsgs.CompleteAdding();
} }
#if WINDOWS || NETFRAMEWORK #if WINDOWS || NETFRAMEWORK
@ -170,6 +171,45 @@ namespace NTwain
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
#if WINDOWS || NETFRAMEWORK
/// <summary>
/// Loads and opens the TWAIN data source manager in a self-hosted message queue thread.
/// Highly experimental and only use if necessary. Must close with <see cref="CloseDSMAsync"/>
/// if used.
/// </summary>
/// <returns></returns>
public async Task<STS> OpenDSMAsync()
{
if (_selfPump == null)
{
var pump = new MessagePumpThread();
var sts = await pump.AttachAsync(this);
if (sts.IsSuccess)
{
_selfPump = pump;
}
return sts;
}
return new STS { RC = TWRC.FAILURE, STATUS = new TW_STATUS { ConditionCode = TWCC.SEQERROR } };
}
/// <summary>
/// Closes the TWAIN data source manager if opened with <see cref="OpenDSMAsync"/>.
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task<STS> CloseDSMAsync()
{
if (_selfPump == null) throw new InvalidOperationException($"Cannot close if not opened with {nameof(OpenDSMAsync)}().");
var sts = await _selfPump.DetatchAsync();
if (sts.IsSuccess)
{
_selfPump = null;
}
return sts;
}
#endif
/// <summary> /// <summary>
/// Loads and opens the TWAIN data source manager. /// Loads and opens the TWAIN data source manager.
@ -210,8 +250,21 @@ namespace NTwain
/// Closes the TWAIN data source manager. /// Closes the TWAIN data source manager.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public STS CloseDSM() public STS CloseDSM()
{ {
#if WINDOWS || NETFRAMEWORK
if (_selfPump != null) throw new InvalidOperationException($"Cannot close if opened with {nameof(OpenDSMAsync)}().");
#endif
return CloseDSMReal();
}
/// <summary>
/// Closes the TWAIN data source manager.
/// </summary>
/// <returns></returns>
internal STS CloseDSMReal()
{
var rc = DGControl.Parent.CloseDSM(ref _appIdentity, _hwnd); var rc = DGControl.Parent.CloseDSM(ref _appIdentity, _hwnd);
if (rc == TWRC.SUCCESS) if (rc == TWRC.SUCCESS)
{ {
@ -312,7 +365,29 @@ namespace NTwain
CloseSource(); CloseSource();
break; break;
case STATE.S3: case STATE.S3:
#if WINDOWS || NETFRAMEWORK
if (_selfPump != null)
{
try
{
_ = CloseDSMAsync();
}
catch (InvalidOperationException) { }
}
else
{
CloseDSM();
}
#else
CloseDSM(); CloseDSM();
#endif
break;
case STATE.S2:
// can't really go lower
if (targetState < STATE.S2)
{
return State;
}
break; break;
} }
if (oldState == State) if (oldState == State)