naps2/NAPS2.Lib.WinForms/Scan/Twain/Legacy/TwainApi.cs
Ben Olden-Cooligan e547d35be1 Remove ImageContext from IMemoryImage constructors
Now that ImageContext is stateless it can be created on demand, simplifying a lot of things.
2024-04-01 00:25:25 -07:00

177 lines
4.7 KiB
C#

using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using NAPS2.Images.Gdi;
using NAPS2.Platform.Windows;
using NAPS2.Scan.Exceptions;
using NAPS2.WinForms;
namespace NAPS2.Scan.Twain.Legacy;
internal static class TwainApi
{
public static ScanDevice? SelectDeviceUI()
{
var tw = new Twain();
if (!tw.Init(Application.OpenForms[0]!.Handle))
{
throw new NoDevicesFoundException();
}
if (!tw.Select())
{
return null;
}
string? name = tw.GetCurrentName();
if (name == null)
{
return null;
}
return new ScanDevice(Driver.Twain, name, name);
}
public static List<ScanDevice> GetDeviceList(ScanOptions options)
{
var tw = new Twain();
if (!tw.Init(options.DialogParent))
{
throw new NoDevicesFoundException();
}
var result = new List<ScanDevice>();
if (!tw.GetFirst())
{
return result;
}
do
{
string? name = tw.GetCurrentName();
if (name != null)
{
result.Add(new ScanDevice(Driver.Twain, name, name));
}
} while (tw.GetNext());
return result;
}
public static void Scan(ScanOptions options, Action<IMemoryImage> produceImage)
{
var tw = new Twain();
if (!tw.Init(options.DialogParent))
{
throw new DeviceNotFoundException();
}
if (!tw.SelectByName(options.Device!.ID))
{
throw new DeviceNotFoundException();
}
var form = new FTwainGui();
var mf = new TwainMessageFilter(options, tw, form);
form.ShowDialog(new Win32Window(options.DialogParent));
foreach (var b in mf.Bitmaps)
{
produceImage(b);
}
}
private class TwainMessageFilter : IMessageFilter
{
private readonly ScanOptions _settings;
private readonly Twain _tw;
private readonly FTwainGui _form;
private bool _activated;
private bool _msgfilter;
public TwainMessageFilter(ScanOptions settings, Twain tw, FTwainGui form)
{
_settings = settings;
_tw = tw;
_form = form;
Bitmaps = [];
form.Activated += FTwainGui_Activated;
}
public List<IMemoryImage> Bitmaps { get; }
public bool PreFilterMessage(ref Message m)
{
TwainCommand cmd = _tw.PassMessage(ref m);
if (cmd == TwainCommand.Not)
return false;
switch (cmd)
{
case TwainCommand.CloseRequest:
{
EndingScan();
_tw.CloseSrc();
_form.Close();
break;
}
case TwainCommand.CloseOk:
{
EndingScan();
_tw.CloseSrc();
break;
}
case TwainCommand.DeviceEvent:
{
break;
}
case TwainCommand.TransferReady:
{
ArrayList pics = _tw.TransferPictures();
EndingScan();
_tw.CloseSrc();
foreach (IntPtr img in pics)
{
int bitcount = 0;
Bitmap bmp = DibUtils.BitmapFromDib(img, out bitcount);
Bitmaps.Add(new GdiImage(bmp));
}
_form.Close();
break;
}
}
return true;
}
private void EndingScan()
{
if (_msgfilter)
{
Application.RemoveMessageFilter(this);
_msgfilter = false;
_form.Enabled = true;
_form.Activate();
}
}
private void FTwainGui_Activated(object? sender, EventArgs e)
{
if (_activated)
return;
_activated = true;
if (!_msgfilter)
{
_form.Enabled = false;
_msgfilter = true;
Application.AddMessageFilter(this);
}
try
{
if (!_tw.Acquire())
{
EndingScan();
_form.Close();
}
}
catch (Exception ex)
{
Log.ErrorException("An error occurred while interacting with TWAIN.", ex);
EndingScan();
_form.Close();
}
}
}
}