Hello,

 

     I am working on an application to scan in VB.NET using TWAIN.  but I am having problems with the structures and am getting incorrect data.  I created a class in C++ and found that one of the VB structures (twsIdentity) is 156 bytes using Marshal.SizeOf.  i even tried eliminating the new method and declaring Version as new but it didn't matter.

   <StructLayout(LayoutKind.Sequential, Pack:=2, CharSet:=CharSet.Ansi)> Friend Class twsIdentity '***MAR
        Public Id As IntPtr                     '4
        Public Version As twsVersion            '42
        Public ProtocolMajor As Short           '2
        Public ProtocolMinor As Short           '2
        Public SupportedGroups As Integer       '4
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=34)> Public Manufacturer As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=34)> Public ProductFamily As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=34)> Public ProductName As String

        Public Sub New()
            MyBase.New()
            Version = New twsVersion
        End Sub
    End Class

    <StructLayout(LayoutKind.Sequential, Pack:=2, CharSet:=CharSet.Ansi)> Friend Class twsVersion '***MAR
        Public MajorNum As Short
        Public MinorNum As Short
        Public Language As Short
        Public Country As Short
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=34)> Public Info As String
    End Class

 

I can't pass the structure between C++ and VB.  I assume because the structure in C is 160 bytes using sizeof.

 typedef unsigned short TW_UINT16;
 typedef unsigned long  TW_UINT32;
 typedef char    TW_STR32[34];

 struct TW_VERSION{
   TW_UINT16  MajorNum;  /* Major revision number of the software. */
   TW_UINT16  MinorNum;  /* Incremental revision number of the software. */
   TW_UINT16  Language;  /* e.g. TWLG_SWISSFRENCH */
   TW_UINT16  Country;   /* e.g. TWCY_SWITZERLAND */
   TW_STR32   Info;      /* e.g. "1.0b3 Beta release" */
 };

 struct TW_IDENTITY{
    TW_UINT32  Id;              /* Unique number.  In Windows, application hWnd      */
    TW_VERSION Version;         /* Identifies the piece of code              */
    TW_UINT16  ProtocolMajor;   /* Application and DS must set to TWON_PROTOCOLMAJOR */
    TW_UINT16  ProtocolMinor;   /* Application and DS must set to TWON_PROTOCOLMINOR */
    TW_UINT32  SupportedGroups; /* Bit field OR combination of DG_ constants */
    TW_STR32   Manufacturer;    /* Manufacturer name, e.g. "Hewlett-Packard" */
    TW_STR32   ProductFamily;   /* Product family name, e.g. "ScanJet"       */
    TW_STR32   ProductName;     /* Product name, e.g. "ScanJet Plus"         */
 };

 

Although when I use this structure (twsIdentity) in VB (calling twain_32.dll) and pass it to the dll, I get it back OK.  I get problems from another structure () when I try to set the capabilities of the scanner.  I was going to set the capabilities in a C dll to see if that fixes if, but then I can't pass the twsIdentity structure between C and VB.  I could try moving all the functionality to a C DLL, but the boss wants the app done in VB.  I just want to know what I am doing wrong.  Any ideas?

 

Here is the VB structure that I can't get any good data from:

    <StructLayout(LayoutKind.Sequential, Pack:=2)> Private Structure twsCapability '***MAR
        Public Cap As twCap                   'short
        Public ConType As twContainerTyoe   'short
        Public Handle As IntPtr     'Pointer to a container
    End Structure

copied from this structure:

typedef struct {
   TW_UINT16  Cap; /* id of capability to set or get, e.g. CAP_BRIGHTNESS */
   TW_UINT16  ConType; /* TWON_ONEVALUE, _RANGE, _ENUMERATION or _ARRAY   */
   TW_HANDLE  hContainer; /* Handle to container of type Dat              */
} TW_CAPABILITY, FAR * pTW_CAPABILITY;

And here is the code that tries to get the data from the dll (which allocates the space for it)

           ...other code comes before

            twCapability = New twsCapability
            With twCapability
                .Cap = twCap.IPhysicalWidth
                '.ConType = 7 'TWON_DONTCARE16
                '.Handle = Nothing
            End With
            strWidth = GetOneValue(twCapability)

            ...other code follows



Private Function GetOneValue(ByVal twCapability As twsCapability) As String

        Dim rc As twRC
        Dim strTemp As String
        Dim twOneValue As TW_ONEVALUE


        rc = DS_Capability(mtwApp, mtwSource, twDG.Control, twDAT.Capability, twMSG.Get, twCapability)
        If rc = twRC.Success Then
            strTemp = vbNullString
            Select Case twCapability.ConType
                Case twContainerTyoe.One
                    twOneValue = New TW_ONEVALUE
                    Marshal.PtrToStructure(twCapability.Handle, twOneValue)
                    strTemp = CType(twOneValue.Item, String)
                Case Else
                    MsgBox("Error, one value expected; " & twCapability.ConType & " returned.")
            End Select
            Marshal.FreeHGlobal(twCapability.Handle)
            Return strTemp
        Else
            ErrorStatus()
            Return vbNullString
        End If

    End Function

 

 

Any help is appreciated, if anyone can direct me to any dull reading that may help me I will read it!!

 

Thanks for looking