Click here to Skip to main content
15,887,371 members
Articles / Programming Languages / C#
Article

.NET TWAIN image scanner

Rate me:
Please Sign up or sign in to vote.
4.91/5 (227 votes)
12 May 2002Public Domain2 min read 7.2M   132.2K   421   996
Using TWAIN API to scan images

Sample Screenshot

Abstract

In Windows imaging applications, the most used API for scanning is TWAIN www.twain.org. Unfortunately, the new .NET Framework has no built-in support for TWAIN. So we have to work with the interop methods of .NET to access this API. This article doesn't explain this interop techniques, and good knowledge of the TWAIN 1.9 specifications is assumed! The sample code included doesn't present a finished library, only some essential steps for a minimal TWAIN adaption to .NET applications.

Details

First step was to port the most important parts of TWAIN.H, these are found in TwainDefs.cs. The real logic for calling TWAIN is coded in the class Twain, in file TwainLib.cs.. As the TWAIN API is exposed by the Windows DLL, twain_32.dll, we have to use the .NET DllImport mechanism for interop with legacy code. This DLL has the central DSM_Entry(), ordinal #1 function exported as the entry point to TWAIN. This call has numerous parameters, and the last one is of variable type! It was found to be best if we declare multiple variants of the call like:

C#
[DllImport("twain_32.dll", EntryPoint="#1")]
private static extern TwRC DSMparent(
    [In, Out] TwIdentity origin,
    IntPtr zeroptr,
    TwDG dg, TwDAT dat, TwMSG msg,
    ref IntPtr refptr );

The Twain class has a simple 5-step interface:

C#
class Twain
{
    Init();
    Select();
    Acquire();
    PassMessage();
    TransferPictures();
}

For some sort of 'callbacks', TWAIN uses special Windows messages, and these must be caught from the application-message-loop. In .NET, the only way found was IMessageFilter.PreFilterMessage(), and this filter has to be activated with a call like Application.AddMessageFilter(). Within the filter method, we have to forward each message to Twain.PassMessage(), and we get a hint (enum TwainCommand) back for how we have to react.

Sample App

The sample is a Windows Forms MDI-style application. It has the two TWAIN-related menu items Select Source... and Acquire... Once an image is scanned in, we can save it to a file in any of the GDI+ supported file formats (BMP, GIF, TIFF, JPEG...)

Limitations

All code was only tested on Windows 2000SP2, with an Epson Perfection USB scanner and an Olympus digital photo camera. The scanned picture is (by TWAIN spec) a Windows DIB, and the sample code has VERY little checking against error return codes and bitmap formats. Unfortunately, no direct method is available in .NET to convert a DIB to the managed Bitmap class... Some known problems may show up with color palettes and menus.

Note, TWAIN has it's root in 16-Bit Windows! For a more modern API supported on Windows ME/XP, have a look at Windows Image Acquisition (WIA).

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Web Developer
Switzerland Switzerland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSource Code for VB.NET 2005 Pin
phalcom21-Mar-07 12:20
phalcom21-Mar-07 12:20 
GeneralRe: Source Code for VB.NET 2005 Pin
gabegabe25-Apr-07 10:24
gabegabe25-Apr-07 10:24 
QuestionInit() method hangs up Pin
DiMann1-Mar-07 10:54
DiMann1-Mar-07 10:54 
AnswerRe: Init() method hangs up Pin
Ronsch4-Dec-08 22:06
Ronsch4-Dec-08 22:06 
GeneralSource Code para VB Pin
phalcom228-Feb-07 7:37
phalcom228-Feb-07 7:37 
GeneralRe: Source Code para VB Pin
rgf2128-Mar-07 0:45
rgf2128-Mar-07 0:45 
GeneralRe: Source Code para VB Pin
yalenap31-May-07 7:14
yalenap31-May-07 7:14 
AnswerRe: Source Code para VB Pin
cmchuan8-Jul-07 22:11
cmchuan8-Jul-07 22:11 
TwainLib.vb

Imports System
Imports System.Collections
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Namespace TwainLib

Public Enum TwainCommand
[Not] = -1
Null = 0
TransferReady = 1
CloseRequest = 2
CloseOk = 3
DeviceEvent = 4
Failure = 5
End Enum

Public Class Twain

Private hwnd As IntPtr
Private appid As TwIdentity
Private srcds As TwIdentity
Private evtmsg As TwEvent
Private winmsg_m As WINMSG_S

<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSMparent(<[In](), Out()> ByVal origin As TwIdentity, ByVal zeroptr As IntPtr, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, ByRef refptr As IntPtr) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSMident(<[In](), Out()> ByVal origin As TwIdentity, ByVal zeroptr As IntPtr, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal idds As TwIdentity) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSMstatus(<[In](), Out()> ByVal origin As TwIdentity, ByVal zeroptr As IntPtr, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal dsmstat As TwStatus) As TwRC
End Function

<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSuserif(<[In](), Out()> ByVal origin As TwIdentity, <[In](), Out()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, ByVal guif As TwUserInterface) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSevent(<[In](), Out()> ByVal origin As TwIdentity, <[In](), Out()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, ByRef evt As TwEvent) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSstatus(<[In](), Out()> ByVal origin As TwIdentity, <[In]()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal dsmstat As TwStatus) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DScap(<[In](), Out()> ByVal origin As TwIdentity, <[In]()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal capa As TwCapability) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSiinf(<[In](), Out()> ByVal origin As TwIdentity, <[In]()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal imginf As TwImageInfo) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSixfer(<[In](), Out()> ByVal origin As TwIdentity, <[In]()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, ByRef hbitmap As IntPtr) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSpxfer(<[In](), Out()> ByVal origin As TwIdentity, <[In]()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal pxfr As TwPendingXfers) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSilayout(<[In](), Out()> ByVal origin As TwIdentity, <[In](), Out()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal imglo As TwImageLayout) As TwRC
End Function
<DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DSMlayout(<[In](), Out()> ByVal origin As TwIdentity, <[In](), Out()> ByVal dest As TwIdentity, ByVal dg As TwDG, ByVal dat As TwDAT, ByVal msg As TwMSG, <[In](), Out()> ByVal imglo As IntPtr) As TwRC
End Function


<DllImport("kernel32.dll", ExactSpelling:=True)> Friend Shared Function GlobalAlloc(ByVal flags As Integer, ByVal size As Integer) As IntPtr
End Function
<DllImport("kernel32.dll", ExactSpelling:=True)> Friend Shared Function GlobalLock(ByVal handle As IntPtr) As IntPtr
End Function
<DllImport("kernel32.dll", ExactSpelling:=True)> Friend Shared Function GlobalUnlock(ByVal handle As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", ExactSpelling:=True)> Friend Shared Function GlobalFree(ByVal handle As IntPtr) As IntPtr
End Function

<DllImport("user32.dll", ExactSpelling:=True)> Private Shared Function GetMessagePos() As Integer
End Function
<DllImport("user32.dll", ExactSpelling:=True)> Private Shared Function GetMessageTime() As Integer
End Function

<DllImport("gdi32.dll", ExactSpelling:=True)> Private Shared Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("gdi32.dll", CharSet:=CharSet.Auto)> Private Shared Function CreateDC(ByVal szdriver As String, ByVal szdevice As String, ByVal szoutput As String, ByVal devmode As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll", ExactSpelling:=True)> Private Shared Function DeleteDC(ByVal hdc As IntPtr) As Boolean
End Function

Private Const CountryUSA As Short = 1
Private Const LanguageUSA As Short = 13

Public Sub New()
appid = New TwIdentity
appid.Id = IntPtr.Zero
appid.Version.MajorNum = 1
appid.Version.MinorNum = 1
appid.Version.Language = LanguageUSA
appid.Version.Country = CountryUSA
appid.Version.Info = "TWAIN Scanner"
appid.ProtocolMajor = TwProtocol.Major
appid.ProtocolMinor = TwProtocol.Minor
appid.SupportedGroups = CType(TwDG.Image Or TwDG.Control, Integer)
appid.Manufacturer = "Kod Efisien Sdn Bhd"
appid.ProductFamily = "TWAIN 32 Scanner"
appid.ProductName = "ScanSoft"

srcds = New TwIdentity
srcds.Id = IntPtr.Zero

evtmsg.EventPtr = Marshal.AllocHGlobal(Marshal.SizeOf(winmsg_m))
End Sub

Public Sub Dispose()
Marshal.FreeHGlobal(evtmsg.EventPtr)
End Sub

Protected Overrides Sub Finalize()
Marshal.FreeHGlobal(evtmsg.EventPtr)
End Sub

Public Sub Init(ByVal hwndp As IntPtr)
Finish()
Dim rc As TwRC = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.OpenDSM, hwndp)
If (rc = TwRC.Success) Then
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetDefault, srcds)
If (rc = TwRC.Success) Then
hwnd = hwndp
Else
rc = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, hwndp)
End If
End If
End Sub

Public Sub [Select](Optional ByRef Model As String = "")
Dim rc As TwRC
CloseSrc()
If Equals(appid.Id, IntPtr.Zero) = True Then
Init(hwnd)
If Equals(appid.Id, IntPtr.Zero) = True Then
Return
End If
End If
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.UserSelect, srcds)
Model = srcds.ProductName.ToString
End Sub

Public Sub [SelectDefault](Optional ByRef Model As String = "")
Dim rc As TwRC
CloseSrc()
If Equals(appid.Id, IntPtr.Zero) = True Then
Init(hwnd)
If Equals(appid.Id, IntPtr.Zero) = True Then
Return
End If
End If
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetDefault, srcds)
Model = srcds.ProductName.ToString
End Sub

Public Sub Acquire(Optional ByVal PaperSize As TwSS = TwSS.TwSS_A4, Optional ByVal XScale As Single = 1, _
Optional ByVal YScale As Single = 1, Optional ByVal SColor As TwColourType = TwColourType.twRGB, _
Optional ByVal TopMargin As Single = 0.0, Optional ByVal LeftMargin As Single = 0.0, _
Optional ByVal RightMargin As Single = 0.0, Optional ByVal BottomMargin As Single = 0.0, _
Optional ByVal FrameNumber As Integer = 1, Optional ByVal PageNumber As Integer = 1, _
Optional ByVal DocumentNumber As Integer = 1)

Dim rc As TwRC
CloseSrc()
If Equals(appid.Id, IntPtr.Zero) = True Then
Init(hwnd)
If Equals(appid.Id, IntPtr.Zero) = True Then
Return
End If
End If

rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.OpenDS, srcds)
If (rc <> TwRC.Success) Then
Return
End If

'Set Unit to Pixels
Dim Pixels As TwUnit = TwUnit.twPIXELS
Dim capUnit As TwCapability = New TwCapability(TwCap.IUnits, Pixels, TwType.Int16)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, capUnit)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If

''Set X Resolution
'Dim XResolution As Single = 1
'Dim capX As TwCapability = New TwCapability(TwCap.XResolution, XResolution, TwType.Fix32)

'rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, capX)
'If rc <> TwRC.Success Then
' CloseSrc()
' Return
'End If

''Set Y Resolution
'Dim capY As TwCapability = New TwCapability(TwCap.YResolution, YResolution, TwType.Fix32)

'rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, capY)
'If rc <> TwRC.Success Then
' CloseSrc()
' Return
'End If

Dim xcap As TwCapability = New TwCapability(TwCap.XScaling, XScale, TwType.Fix32)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, xcap)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If

xcap = New TwCapability(TwCap.YScaling, YScale, TwType.Fix32)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, xcap)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If


Dim ps As TwCapability = New TwCapability(TwCap.SupportedSizes, PaperSize, TwType.Int16)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, ps)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If

'Set Layout
Dim Layout As TwImageLayout = New TwImageLayout
rc = DSilayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Get, Layout)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If
If TopMargin > 0 Then
Layout.Frame.Top.FromFloat(CSng(TopMargin))
End If
If LeftMargin > 0 Then
Layout.Frame.Left.FromFloat(CSng(LeftMargin))
End If
If RightMargin > 0 Then
Layout.Frame.Right.FromFloat(CSng(RightMargin))
End If
If BottomMargin > 0 Then
Layout.Frame.Bottom.FromFloat(CSng(BottomMargin))
End If
Layout.FrameNumber = 1
Layout.PageNumber = 1
Layout.DocumentNumber = 1
rc = Me.DSilayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Set, Layout)
If rc <> TwRC.Success Then
CloseSrc()
Return
End If

'Dim ptr1 As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Layout))
'Marshal.StructureToPtr(Layout, ptr1, False)

'rc = Me.DSMlayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Get, ptr1)
'If rc <> TwRC.Success Then
' CloseSrc()
' Return
'End If
''Dim ptr2 As IntPtr = ptr1
'Marshal.PtrToStructure(ptr1, Layout)
'If TopMargin > 0 Then
' Layout.Frame.Top.FromFloat(CSng(TopMargin))
'End If
'If LeftMargin > 0 Then
' Layout.Frame.Left.FromFloat(CSng(LeftMargin))
'End If
'If RightMargin > 0 Then
' Layout.Frame.Right.FromFloat(CSng(RightMargin))
'End If
'If BottomMargin > 0 Then
' Layout.Frame.Bottom.FromFloat(CSng(BottomMargin))
'End If
'Layout.FrameNumber = 1
'Layout.PageNumber = 1
'Layout.DocumentNumber = 1
'Marshal.StructureToPtr(Layout, ptr1, True)

'rc = Me.DSMlayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Set, ptr1)

'If rc <> TwRC.Success Then
' CloseSrc()
' Return
'End If

'Scan Colour
Dim Ccap As TwCapability = New TwCapability(TwCap.IPixelType, SColor, TwType.UInt16)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, Ccap)
If (rc <> TwRC.Success) Then
CloseSrc()
Return
End If

Dim cap As TwCapability = New TwCapability(TwCap.XferCount, 1, TwType.Int16)
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, cap)
If (rc <> TwRC.Success) Then
CloseSrc()
Return
End If

Dim guif As TwUserInterface = New TwUserInterface
guif.ShowUI = 1
guif.ModalUI = 1
guif.ParentHand = hwnd
rc = DSuserif(appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.EnableDS, guif)
If (rc <> TwRC.Success) Then
CloseSrc()
Return
End If

End Sub

Public Function TransferPictures() As ArrayList
Dim pics As ArrayList = New ArrayList
If Equals(srcds.Id, IntPtr.Zero) Then
Return pics
End If

Dim rc As TwRC
Dim hbitmap As IntPtr = IntPtr.Zero
Dim pxfr As TwPendingXfers = New TwPendingXfers

Do
pxfr.Count = 0
hbitmap = IntPtr.Zero

Dim iinf As TwImageInfo = New TwImageInfo
rc = DSiinf(appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf)
If (rc <> TwRC.Success) Then
CloseSrc()
Return pics
End If

'StartScan
rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, hbitmap)
If (rc <> TwRC.XferDone) Then
CloseSrc()
Return pics
End If

rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr)
If (rc <> TwRC.Success) Then
CloseSrc()
Return pics
End If

pics.Add(hbitmap)
Loop While (pxfr.Count <> 0)

rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr)
Return pics
End Function

Public Function PassMessage(ByVal m As Message) As TwainCommand
If Equals(srcds.Id, IntPtr.Zero) Then
Return TwainCommand.Not
End If

Dim pos As Integer = GetMessagePos()

winmsg_m.hwnd = m.HWnd
winmsg_m.message = m.Msg
winmsg_m.wParam = m.WParam
winmsg_m.lParam = m.LParam
winmsg_m.time = GetMessageTime()
winmsg_m.x = pos 'CType(pos, Short)
winmsg_m.y = Int(pos / 2 ^ 16) 'CType(Int(pos / 2 ^ 16), Short)

Marshal.StructureToPtr(winmsg_m, evtmsg.EventPtr, False)
evtmsg.Message = 0

Dim rc As TwRC = DSevent(appid, srcds, TwDG.Control, TwDAT.Event, TwMSG.ProcessEvent, evtmsg)
If (rc = TwRC.NotDSEvent) Then
Return TwainCommand.Not
End If

If (rc = TwRC.Failure) Then
Return TwainCommand.Failure
End If

If (evtmsg.Message = CType(TwMSG.XFerReady, Short)) Then
Return TwainCommand.TransferReady
End If

If (evtmsg.Message = CType(TwMSG.CloseDSReq, Short)) Then
Return TwainCommand.CloseRequest
End If
If (evtmsg.Message = CType(TwMSG.CloseDSOK, Short)) Then
Return TwainCommand.CloseOk
End If
If (evtmsg.Message = CType(TwMSG.DeviceEvent, Short)) Then
Return TwainCommand.DeviceEvent
End If

Return TwainCommand.Null
End Function

Public Sub CloseSrc()
Dim rc As TwRC
If Not Equals(srcds.Id, IntPtr.Zero) Then
Dim guif As TwUserInterface = New TwUserInterface
rc = DSuserif(appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.DisableDS, guif)
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.CloseDS, srcds)
End If
End Sub

Public Sub Finish()
Dim rc As TwRC
CloseSrc()
If Not Equals(appid.Id, IntPtr.Zero) Then
rc = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, hwnd)
End If
appid.Id = IntPtr.Zero
End Sub

Public Shared ReadOnly Property ScreenBitDepth() As Integer
Get
Dim screenDC As IntPtr = CreateDC("DISPLAY", Nothing, Nothing, IntPtr.Zero)
Dim bitDepth As Integer = GetDeviceCaps(screenDC, 12)
bitDepth *= GetDeviceCaps(screenDC, 14)
DeleteDC(screenDC)
Return bitDepth
End Get
End Property

<StructLayout(LayoutKind.Sequential, Pack:=4)> Friend Structure WINMSG_S
Public hwnd As IntPtr
Public message As Integer
Public wParam As IntPtr
Public lParam As IntPtr
Public time As Integer
Public x As Integer
Public y As Integer
End Structure
End Class
End Namespace
AnswerRe: Source Code para VB Pin
cmchuan8-Jul-07 22:12
cmchuan8-Jul-07 22:12 
AnswerRe: Source Code para VB Pin
cmchuan8-Jul-07 22:14
cmchuan8-Jul-07 22:14 
GeneralRe: Source Code para VB Pin
svincetic13-Nov-09 0:46
svincetic13-Nov-09 0:46 
GeneralRe: Source Code para VB Pin
djdrew17-Dec-09 6:39
djdrew17-Dec-09 6:39 
QuestionRe: Source Code para VB Pin
VBdotnetSara19-Oct-10 18:38
VBdotnetSara19-Oct-10 18:38 
QuestionHow to put this in a HTML page Pin
memovera26-Feb-07 9:40
memovera26-Feb-07 9:40 
Questionproblem with scan area Pin
koncuch20-Feb-07 11:06
koncuch20-Feb-07 11:06 
AnswerRe: problem with scan area Pin
cmchuan8-Jul-07 22:23
cmchuan8-Jul-07 22:23 
GeneralRe: problem with scan area Pin
alien2501-Aug-07 4:32
alien2501-Aug-07 4:32 
GeneralGiving something back Pin
alanmac15-Feb-07 13:17
alanmac15-Feb-07 13:17 
GeneralRe: Giving something back Pin
adnanmn19-Nov-07 21:20
adnanmn19-Nov-07 21:20 
QuestionDirect Scanning Pin
realblue15-Feb-07 7:24
realblue15-Feb-07 7:24 
AnswerRe: Direct Scanning Pin
josepaulino22-Mar-07 18:40
josepaulino22-Mar-07 18:40 
GeneralRe: Direct Scanning Pin
NitinMakwana17-Feb-10 19:34
NitinMakwana17-Feb-10 19:34 
Questionhow to change the source manage user interface Pin
jiuheng4-Feb-07 20:21
jiuheng4-Feb-07 20:21 
GeneralDetecting Scanner event Pin
Armanirani17-Jan-07 19:22
Armanirani17-Jan-07 19:22 
QuestionHow can I suppress the error UI and scanning progress UI? Pin
bgunes10-Jan-07 7:26
bgunes10-Jan-07 7:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.