diff --git a/Build.cmd b/Build.cmd index e12a27c..3aaa299 100644 --- a/Build.cmd +++ b/Build.cmd @@ -1,4 +1,3 @@ @echo off cls dotnet pack src\NTwain -c Release -o build -dotnet pack src\NTwain.Win -c Release -o build diff --git a/samples/WinForm32/Form1.Designer.cs b/samples/WinForm32/Form1.Designer.cs index 275e6c9..9a89251 100644 --- a/samples/WinForm32/Form1.Designer.cs +++ b/samples/WinForm32/Form1.Designer.cs @@ -41,8 +41,9 @@ lblState = new System.Windows.Forms.Label(); label3 = new System.Windows.Forms.Label(); btnOpenDef = new System.Windows.Forms.Button(); - btnClose = new System.Windows.Forms.Button(); btnShowSettings = new System.Windows.Forms.Button(); + btnClose = new System.Windows.Forms.Button(); + btnStart = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); splitContainer1.Panel1.SuspendLayout(); splitContainer1.Panel2.SuspendLayout(); @@ -159,6 +160,7 @@ // // splitContainer1.Panel2 // + splitContainer1.Panel2.Controls.Add(btnStart); splitContainer1.Panel2.Controls.Add(btnShowSettings); splitContainer1.Panel2.Controls.Add(btnClose); splitContainer1.Panel2.Controls.Add(label2); @@ -195,6 +197,16 @@ btnOpenDef.UseVisualStyleBackColor = true; btnOpenDef.Click += btnOpenDef_Click; // + // btnShowSettings + // + btnShowSettings.Location = new System.Drawing.Point(161, 32); + btnShowSettings.Name = "btnShowSettings"; + btnShowSettings.Size = new System.Drawing.Size(132, 23); + btnShowSettings.TabIndex = 5; + btnShowSettings.Text = "Show settings only"; + btnShowSettings.UseVisualStyleBackColor = true; + btnShowSettings.Click += btnShowSettings_Click; + // // btnClose // btnClose.Location = new System.Drawing.Point(13, 32); @@ -205,15 +217,15 @@ btnClose.UseVisualStyleBackColor = true; btnClose.Click += btnClose_Click; // - // btnShowSettings + // btnStart // - btnShowSettings.Location = new System.Drawing.Point(161, 32); - btnShowSettings.Name = "btnShowSettings"; - btnShowSettings.Size = new System.Drawing.Size(132, 23); - btnShowSettings.TabIndex = 5; - btnShowSettings.Text = "Show settings only"; - btnShowSettings.UseVisualStyleBackColor = true; - btnShowSettings.Click += btnShowSettings_Click; + btnStart.Location = new System.Drawing.Point(299, 32); + btnStart.Name = "btnStart"; + btnStart.Size = new System.Drawing.Size(132, 23); + btnStart.TabIndex = 6; + btnStart.Text = "Start acquisition"; + btnStart.UseVisualStyleBackColor = true; + btnStart.Click += btnStart_Click; // // Form1 // @@ -249,5 +261,6 @@ private System.Windows.Forms.Label lblState; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button btnShowSettings; + private System.Windows.Forms.Button btnStart; } } \ No newline at end of file diff --git a/samples/WinForm32/Form1.cs b/samples/WinForm32/Form1.cs index a89d7ed..cee6df7 100644 --- a/samples/WinForm32/Form1.cs +++ b/samples/WinForm32/Form1.cs @@ -46,6 +46,7 @@ namespace WinForm32 var hwnd = this.Handle; var rc = twain.OpenDSM(hwnd); + Application.AddMessageFilter(twain); Debug.WriteLine($"OpenDSM={rc}"); } @@ -54,6 +55,7 @@ namespace WinForm32 var finalState = twain.TryStepdown(STATE.S2); Debug.WriteLine($"Stepdown result state={finalState}"); + Application.RemoveMessageFilter(twain); base.OnClosing(e); } @@ -105,5 +107,10 @@ namespace WinForm32 { twain.EnableSource(true, true); } + + private void btnStart_Click(object sender, EventArgs e) + { + twain.EnableSource(true, false); + } } } \ No newline at end of file diff --git a/src/NTwain/Native/WIN_MESSAGE.cs b/src/NTwain/Native/WIN_MESSAGE.cs new file mode 100644 index 0000000..132eb3a --- /dev/null +++ b/src/NTwain/Native/WIN_MESSAGE.cs @@ -0,0 +1,21 @@ +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; + } +} diff --git a/src/NTwain/Native/WinformPumpTest.cs b/src/NTwain/Native/WinformPumpTest.cs new file mode 100644 index 0000000..f38dd4d --- /dev/null +++ b/src/NTwain/Native/WinformPumpTest.cs @@ -0,0 +1,14 @@ +#if WINDOWS || NETFRAMEWORK +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NTwain.Native +{ + internal class WinformPumpTest + { + } +} +#endif \ No newline at end of file diff --git a/src/NTwain/TwainSession.Callbacks.cs b/src/NTwain/TwainSession.Callbacks.cs index 9579514..38a3898 100644 --- a/src/NTwain/TwainSession.Callbacks.cs +++ b/src/NTwain/TwainSession.Callbacks.cs @@ -92,6 +92,11 @@ namespace NTwain case MSG.XFERREADY: break; case MSG.DEVICEEVENT: + // use diff thread to get it + //if (DGControl.DeviceEvent.Get(ref _appIdentity, ref _currentDS, out TW_DEVICEEVENT de) == STS.SUCCESS) + //{ + + //} break; case MSG.CLOSEDSOK: DisableSource(); @@ -101,10 +106,5 @@ namespace NTwain break; } } - - public void HandleWin32Message(uint msg) - { - - } } } diff --git a/src/NTwain/TwainSession.Windows.cs b/src/NTwain/TwainSession.Windows.cs new file mode 100644 index 0000000..15b164b --- /dev/null +++ b/src/NTwain/TwainSession.Windows.cs @@ -0,0 +1,69 @@ +#if WINDOWS || NETFRAMEWORK +using NTwain.Data; +using NTwain.Native; +using NTwain.Triplets; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows.Forms; + +namespace NTwain +{ + + // contains parts for winform/wpf message loop integration + + partial class TwainSession : IMessageFilter + { + // winform use with Application.AddMessageFilter() + bool System.Windows.Forms.IMessageFilter.PreFilterMessage(ref System.Windows.Forms.Message m) + { + return CheckIfTwainMessage(m.HWnd, m.Msg, m.WParam, m.LParam); + } + + // wpf use + IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + handled = CheckIfTwainMessage(hwnd, msg, wParam, lParam); + return IntPtr.Zero; + } + + private bool CheckIfTwainMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) + { + // this handles the message from a typical WndProc message loop and check if it's from the TWAIN source. + bool handled = false; + if (_state >= Data.STATE.S5) + { + TW_EVENT evt = default; + try + { + var winMsg = new WIN_MESSAGE + { + hwnd = hWnd, + message = (uint)msg, + wParam = wParam, + lParam = lParam + }; + // no need to do another lock call when using marshal alloc + evt.pEvent = Marshal.AllocHGlobal(Marshal.SizeOf(winMsg)); + Marshal.StructureToPtr(winMsg, evt.pEvent, false); + + var rc = DGControl.Event.ProcessEvent(ref _appIdentity, ref _currentDS, ref evt); + handled = rc == STS.DSEVENT; + if (evt.TWMessage != 0 && (handled || rc == STS.NOTDSEVENT)) + { + Debug.WriteLine("Thread {0}: CheckIfTwainMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, (MSG)evt.TWMessage); + HandleSourceMsg((MSG)evt.TWMessage); + } + } + finally + { + // do we need to free it + if (evt.pEvent != IntPtr.Zero) Marshal.FreeHGlobal(evt.pEvent); + } + } + return handled; + } + } +} +#endif \ No newline at end of file