This tutorial shows how to acquire an image from a TWAIN source in a Windows C DLL application using the LEADTOOLS SDK.
Overview | |
---|---|
Summary | This tutorial covers how to acquire an image from a TWAIN source in a Windows C DLL application. |
Completion Time | 30 minutes |
Visual Studio Project | Download tutorial project (19 KB) |
Platform | Windows C DLL Application |
IDE | Visual Studio 2017, 2019, 2022 |
Development License | Download LEADTOOLS |
Try it in another language |
|
Get familiar with the basic steps of creating a project and loading/displaying images by reviewing the Add References and Set a License and Load, Display, and Save Images tutorials, before working on the Acquire an Image From a TWAIN Source - Windows C DLL tutorial.
Start with a copy of the project created in the Load, Display, and Save Images tutorial. If the project is not available, create it by following the steps in that tutorial.
To implement TWAIN scanning using LEADTOOLS, add the required header and library files. Open the pre-compiled header file (either pch.h
or stdafx.h
, depending on the version of Visual Studio used) and add the following lines:
#include "C:\LEADTOOLS23\Include\Lttwn.h"
#pragma comment (lib, "C:\\LEADTOOLS23\\Lib\\CDLL\\x64\\Lttwn_x.lib") // TWAIN support
Note
For a complete list of DLLs that are required for your application, refer to Files to be Included with your Application - C API.
The License unlocks the features needed for the project. It must be set before any toolkit functionality is called. For details, including tutorials for different platforms, refer to Setting a Runtime License.
There are two types of runtime licenses:
Note
Adding LEADTOOLS references and setting a license are covered in more detail in the Add References and Set a License tutorial.
With the project created, the references added, the license set, and the load image code added, coding can begin.
Using the Solution Explorer, navigate to the main CPP file of the project and add the following global variable near the BITMAPHANDLE
declaration at the top:
HTWAINSESSION twainSession = NULL;
Add a new case to the switch (message)
statement in the WndProc()
function named WM_CREATE
. Add the code below to the new case to initialize the TWAIN session:
case WM_CREATE:
if (!L_IsTwainAvailable(hWnd))
{
MessageBox(hWnd, TEXT("Could not initialize Twain features.\nTwain Not Available"), TEXT("Twain Tutorial"), MB_ICONERROR);
}
else
{
APPLICATIONDATA appData = { sizeof(APPLICATIONDATA), hWnd, TEXT("My Company"), TEXT("My Product"), TEXT("1.0"), TEXT("My App"), TWLG_ENGLISH_USA, TWCY_USA };
L_TwainInitSession(&twainSession, &appData);
}
break;
Modify the case that handles WM_DESTROY
, in the WndProc()
function, to terminate the TWAIN session at the end of the program.
case WM_DESTROY:
if(twainSession)
{
L_TwainEndSession(&twainSession);
twainSession = NULL;
}
// Keep the rest of the code in the case unchanged
In the Solution Explorer double-click the resources file (.rc) to open the Resource View. Then double-click the menu in the resources tree.
Add a new &Twain drop down menu next to the File menu. Add two menu items in the the table below to the newly-added &Twain menu.
Menu Item Text | Item ID |
---|---|
&Select Source | ID_TWAIN_SELECTSOURCE |
&Acquire | ID_TWAIN_ACQUIRE |
Navigate back to the WndProc
function, and under the switch (wmId)
statement that is below the WM_COMMAND
case, add the below two new cases.
switch (wmId)
{
case ID_TWAIN_SELECTSOURCE:
L_TwainSelectSource(twainSession, NULL);
break;
case ID_TWAIN_ACQUIRE:
if (TwainScan(hWnd) == SUCCESS)
InvalidateRect(hWnd, NULL, TRUE);
else
MessageBox(hWnd, TEXT("Did not scan from Twain source. Either the user canceled or an error occurred."), TEXT("Twain Tutorial"), MB_ICONERROR);
break;
// Keep rest of the code as is
Add a new TwainScan
function, which can be placed above the WndProc
function, and add the code below.
L_INT TwainScan(HWND hwnd)
{
BITMAPHANDLE bmp = { 0 };
L_INT nRet = L_TwainAcquire(twainSession, &bmp, sizeof(bmp), NULL, LTWAIN_SHOW_USER_INTERFACE, NULL, NULL);
if (nRet != SUCCESS)
return nRet;
if (LEADBmp.Flags.Allocated)
L_FreeBitmap(&LEADBmp);
L_CopyBitmapHandle(&LEADBmp, &bmp, sizeof BITMAPHANDLE); // The data now belongs to the global bitmap
return SUCCESS;
}
Open the Resource View and double-click the menu in the resources tree.
Add a new &Options drop down menu next to the &Twain menu. Add the three menu items in the table below to the newly-added &Options menu.
Menu Item Text | Item ID |
---|---|
&Native | ID_OPTIONS_NATIVE |
&Memory | ID_OPTIONS_MEMORY |
&File | ID_OPTIONS_FILE |
Go to the WndProc
function, and under the switch (wmId)
statement that is below the WM_COMMAND
case, add the new cases below for the new menu items.
switch (wmId)
{
case ID_OPTIONS_NATIVE:
SetTransferMech(hWnd, TWSX_NATIVE);
break;
case ID_OPTIONS_MEMORY:
SetTransferMech(hWnd, TWSX_MEMORY);
break;
case ID_OPTIONS_FILE:
SetTransferMech(hWnd, TWSX_FILE);
break;
// Keep rest of the code as is
Add a new SetTransferMode
function, placed above the WndProc
function. This function shows how to set TWAIN capability by changing the value of the Image Transfer Mechanism capability.
void SetTransferMech(HWND hWnd, L_UINT transferMech)
{
// Instruct the Twain source to change transfer mode
TW_CAPABILITY twSetCap;
twSetCap.Cap = ICAP_XFERMECH;
twSetCap.ConType = TWON_ONEVALUE;
L_TwainStartCapsNeg(twainSession);
L_TwainCreateNumericContainerOneValue(&twSetCap, TWAINNUMERICTYPE_TW_UINT16, transferMech);
L_TwainSetCapability(twainSession, &twSetCap, LTWAIN_CAPABILITY_SET);
L_TwainFreeContainer(&twSetCap);
L_TwainEndCapsNeg(twainSession);
CheckOptionsMenu(hWnd);
}
Add a new CheckOptionsMenu
function above the SetTransferMode
function. This new function shows how to retrieve the value of the Image Transfer Mechanism TWAIN capability and add a check mark next to the corresponding menu item.
void CheckOptionsMenu(HWND hWnd)
{
// Ask the Twain source about current transfer mode
TW_CAPABILITY twGetCap = { 0 };
twGetCap.Cap = ICAP_XFERMECH;
twGetCap.ConType = TWON_ONEVALUE;
L_TwainStartCapsNeg(twainSession);
L_TwainGetCapability(twainSession, &twGetCap, LTWAIN_CAPABILITY_GETCURRENT);
L_UINT transferMech = -1;
L_TwainGetNumericContainerUINTValue(&twGetCap, 0, &transferMech);
L_TwainEndCapsNeg(twainSession);
UINT item = 0;
switch (transferMech)
{
case TWSX_NATIVE:
item = ID_OPTIONS_NATIVE;
break;
case TWSX_MEMORY:
item = ID_OPTIONS_MEMORY;
break;
case TWSX_FILE:
item = ID_OPTIONS_FILE;
}
HMENU menu = GetMenu(hWnd);
CheckMenuItem(menu, ID_OPTIONS_NATIVE, MF_UNCHECKED);
CheckMenuItem(menu, ID_OPTIONS_MEMORY, MF_UNCHECKED);
CheckMenuItem(menu, ID_OPTIONS_FILE, MF_UNCHECKED);
CheckMenuItem(menu, item, MF_CHECKED);
}
Run the project by pressing F5, or by selecting Debug -> Start Debugging.
If the steps were followed correctly, the application should run. For testing, follow the below instructions:
Note
Ensure that required TWAIN drivers for the scanner are installed on the machine, which is usually installed with the scanning device.
This tutorial showed how to list the available TWAIN devices and acquire a scanned image from those devices. It also covered how to use the TwainSession
and TwainCapability
classes.