Msg loop filter tweaks.

This commit is contained in:
Eugene Wang
2023-04-03 06:35:03 -04:00
parent eee811df14
commit 0f0f613ced
4 changed files with 42 additions and 38 deletions

View File

@@ -31,8 +31,4 @@
<LastGenOutput>DSMGenerator.dummy</LastGenOutput> <LastGenOutput>DSMGenerator.dummy</LastGenOutput>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project> </Project>

View File

@@ -88,20 +88,24 @@ namespace NTwain
/// <returns></returns> /// <returns></returns>
public STS EnableSource(bool showUI, bool uiOnly) public STS EnableSource(bool showUI, bool uiOnly)
{ {
var ui = new TW_USERINTERFACE if (State != STATE.S4) return STS.SEQERROR; // shouldn't check it ourselves but whatev
_userInterface = new TW_USERINTERFACE
{ {
ShowUI = (ushort)((showUI || uiOnly) ? 1 : 0), ShowUI = (ushort)((showUI || uiOnly) ? 1 : 0),
hParent = _hwnd, hParent = _hwnd,
}; };
var rc = uiOnly ? var rc = uiOnly ?
DGControl.UserInterface.EnableDSUIOnly(ref _appIdentity, ref _currentDS, ref ui) : DGControl.UserInterface.EnableDSUIOnly(ref _appIdentity, ref _currentDS, ref _userInterface) :
DGControl.UserInterface.EnableDS(ref _appIdentity, ref _currentDS, ref ui); DGControl.UserInterface.EnableDS(ref _appIdentity, ref _currentDS, ref _userInterface);
if (rc == STS.SUCCESS || (!uiOnly && !showUI && rc == STS.CHECKSTATUS)) if (rc == STS.SUCCESS || (!uiOnly && !showUI && rc == STS.CHECKSTATUS))
{ {
// keep it around for disable use
_userInterface = ui;
State = STATE.S5; State = STATE.S5;
}; }
else
{
_userInterface = default;
}
return rc; return rc;
} }

View File

@@ -17,7 +17,7 @@ namespace NTwain
partial class TwainSession : IMessageFilter partial class TwainSession : IMessageFilter
{ {
private HwndSource? _wpfhook; HwndSource? _wpfhook;
/// <summary> /// <summary>
/// Registers this session for use in a Winform UI thread. /// Registers this session for use in a Winform UI thread.
@@ -75,32 +75,24 @@ namespace NTwain
bool handled = false; bool handled = false;
if (_state >= STATE.S5) if (_state >= STATE.S5)
{ {
TW_EVENT evt = default; var winMsg = new WIN_MESSAGE
try
{ {
var winMsg = new WIN_MESSAGE hwnd = hWnd,
{ message = (uint)msg,
hwnd = hWnd, wParam = wParam,
message = (uint)msg, lParam = lParam
wParam = wParam, };
lParam = lParam // no need to do another lock call when using marshal alloc
}; if (_procEvent.pEvent == IntPtr.Zero)
// no need to do another lock call when using marshal alloc _procEvent.pEvent = Marshal.AllocHGlobal(Marshal.SizeOf(winMsg));
evt.pEvent = Marshal.AllocHGlobal(Marshal.SizeOf(winMsg)); Marshal.StructureToPtr(winMsg, _procEvent.pEvent, true);
Marshal.StructureToPtr(winMsg, evt.pEvent, false);
var rc = DGControl.Event.ProcessEvent(ref _appIdentity, ref _currentDS, ref evt); var rc = DGControl.Event.ProcessEvent(ref _appIdentity, ref _currentDS, ref _procEvent);
handled = rc == STS.DSEVENT; handled = rc == STS.DSEVENT;
if (evt.TWMessage != 0 && (handled || rc == STS.NOTDSEVENT)) if (_procEvent.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 Debug.WriteLine("Thread {0}: CheckIfTwainMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, (MSG)_procEvent.TWMessage);
if (evt.pEvent != IntPtr.Zero) Marshal.FreeHGlobal(evt.pEvent); HandleSourceMsg((MSG)_procEvent.TWMessage);
} }
} }
return handled; return handled;

View File

@@ -3,6 +3,7 @@ using NTwain.Triplets;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -96,8 +97,9 @@ namespace NTwain
} }
internal IntPtr _hwnd; internal IntPtr _hwnd;
internal TW_USERINTERFACE _userInterface; internal TW_USERINTERFACE _userInterface; // kept around for disable use
// test this a bit TW_EVENT _procEvent = default; // kept here so the alloc/free only happens once
// test threads a bit
readonly BlockingCollection<MSG> _bgPendingMsgs = new(); readonly BlockingCollection<MSG> _bgPendingMsgs = new();
private readonly IThreadMarshaller _uiThreadMarshaller; private readonly IThreadMarshaller _uiThreadMarshaller;
private bool disposedValue; private bool disposedValue;
@@ -152,6 +154,7 @@ namespace NTwain
// this will end the bg thread // this will end the bg thread
_bgPendingMsgs.CompleteAdding(); _bgPendingMsgs.CompleteAdding();
} }
if (_procEvent.pEvent != IntPtr.Zero) Marshal.FreeHGlobal(_procEvent.pEvent);
disposedValue = true; disposedValue = true;
} }
} }
@@ -263,10 +266,14 @@ namespace NTwain
int tries = 0; int tries = 0;
while (State > targetState) while (State > targetState)
{ {
if (tries++ > 5) break; var oldState = State;
switch (State) switch (oldState)
{ {
// todo: finish
case STATE.S7:
case STATE.S6:
break;
case STATE.S5: case STATE.S5:
DisableSource(); DisableSource();
break; break;
@@ -277,6 +284,11 @@ namespace NTwain
CloseDSM(); CloseDSM();
break; break;
} }
if (oldState == State)
{
// didn't work
if (tries++ > 5) break;
}
} }
return State; return State;
} }