mirror of
https://github.com/cyanfish/naps2.git
synced 2024-08-16 18:50:45 +03:00
Now that ImageContext is stateless it can be created on demand, simplifying a lot of things.
177 lines
4.7 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
} |