我从DLL文件中获取图像有问题,调用图像的函数是:
SNAPI_SnapShot主机到扫描程序命令
如果扫描仪支持成像,则会向扫描仪发送命令以进入图像捕获模式。扫描仪保持在图像捕捉模式,直到拉动扳机(物理上或通过呼叫) SNAPI_PullTrigger)并捕获图像,或者直到触发器拉出超时。然后扫描仪返回解码模式。
如果触发了触发器,则图像数据将被发送到DLL。 WM_XFERSTATUS将发送到主机应用程序,其中包含有关图像大小的信息。
当收到第一个传输状态消息时,主机应用程序应通过调用SNAPI_SetImageBuffer为映像提供目标缓冲区。将整个图像从扫描仪传输到DLL后,应用程序会收到一条Windows消息,指示已存储图像数据。
图像数据被发送到DLL。我需要知道如何在Delphi中获取图像。
SnapiDll.h:
/*****************************************************************************
* FILENAME: SNAPIdll.h
* COPYRIGHT(c) 2002-2007 Motorola, Inc. All rights reserved
*
* DESCRIPTION : SNAPI.dll API Functions - Entry points into the dll and error codes
*
* File Version : 3.0.0.4
*****************************************************************************/
#ifndef __SNAPIDLL_API_H__
#define __SNAPIDLL_API_H__
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the SNAPIDLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// SNAPIDLL_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef SNAPIDLL_EXPORTS
#define SNAPIDLL_API extern "C" __declspec(dllexport)
#else
#ifdef __cplusplus
#define SNAPIDLL_API extern "C" __declspec(dllimport)
#else
#define SNAPIDLL_API __declspec(dllimport)
#endif
#endif
/****************************************************************************/
/* Defines, typedefs, etc. *************************************************/
#define MAX_COM_PORTS 16
///////////////////////////////////////////////////////////////////////////////
//
// Library Error reporting
//
// ALL library function calls return 0 if successful, o/w an error code is returned.
// If the error code is a fatal error, SNAPIDisconnect() should be called.
// The list of error codes below describes the errors that can be reported.
//
// In addition to the failure status returned by library function and error codes
// the library can also send or post a WM_ERROR message to the application.
// The application should handle that message and respond appropriately
// The list of Windows messages includes a description of the WM_ERROR message.
//
///////////////////////////////////////////////////////////////////////////////
// Error codes - return values for API CALLS
#define SSICOMM_NOERROR 0 // No error code is set - this will be the value when an API call returns success
#define ERR_SSI_NOOBJECT -1 // Not a valid device object(handle)
#define ERR_SSI_HWND -2 // The hwnd parameter to the SNAPI_Init function was NULL
#define SSICOMM_BAD_SETSTATE -3 // The library was unable to set the state of the com port - no connection established
#define SSICOMM_BAD_SETTIMEOUTS -4 // The library was unable to set the com timeouts - no connection established
#define SSICOMM_BAD_GETTIMEOUTS -5 // The library was unable to get the curent com timeouts - no connection established
#define SSICOMM_BAD_GETCOMSTATE -6 // The library was unable to get the curent com state - no connection established
#define SSICOMM_ALREADY_CLOSED -7 // Call to close com port was made when the com port is not open. There is no connection.
#define SSICOMM_UNABLE_PURGE -8 // Call to purge the com port before closing it was not successful.
#define SSICOMM_THREADS_BADEXIT -9 // fatal error - the threads didn't exit properly
#define SSICOMM_ERROR_CLRDTR -10 // unable to lower DTR when closing com port
#define SSICOMM_BAD_CREATEFILE -11 // unable to open the com port
#define SSICOMM_BAD_READTHREAD -12 // unable to create the read/status thread - no connection
#define SSICOMM_BAD_WRITETHREAD -13 // unable to create the writer thread - no connection
#define SSICOMM_BAD_CREATEEVENT -14 // call to CreateEvent failed - fatal error
#define SSICOMM_BUSY -15 // not fatal - try your request again later
#define SSICMD_UNIMPLEMENTED -16 // not fatal - this command is not implemented in the library
#define SSICOMM_ALREADYCONNECTED -17 // if already connected, can't connect without a call to disconnect
#define ERR_SSI_MISMATCHHWND -18 // the hwnd paramter for the function does not match the stored hwnd for the connection
#define SSICOMM_TOOMUCHDATA -19 //the maximum allowable input data length was exceeded
#define SSICOMM_ERRVERSION -20 // Can't run on this version of windows
#define SSI_INPUTQ_FULL -21 // unable to add new user request to input queue for transmitting to scanner
// user should re-try request
#define SSICOMM_BADDATA -22 // param data is in incorrect format
// these generate WM_ERROR messages to the app - all are either fatal/nonfatal errors occurring during program execution,
// ... or are the return value of an api function indicating a fatal error
#define SSICOMM_WAITMOWRITER -23 // Wait for Multiple Objects gave WAIT_FAILED in writer proc - if not fatal, protocol retry may recover
#define SSITHREAD_CREATEWEVENT -24 // Failure to create write event - fatal error
#define SSITHREAD_OLRESW -25 // Get overlapped result failed - fatal error
#define SSITHREAD_WRITEERR -26 // Number of bytes written is not the number requested to be written -if not fatal, retry may recover
#define SSITHREAD_WMOW -27 // Wait multiple objects failure in overlapped write - fatal error
#define SSITHREAD_WRITEFILEFAIL -28 // Call to Write failed, but isn't just delayed - fatal error
#define SSITHREAD_BADSETEV -29 // write thread returned error on set event
#define SSIRTHREAD_ORESULT -30 // read thread bad overlapped result - fatal error
#define SSIRTHREAD_SETMASK -31 // read thread bad set mask return - fatal error
#define SSIRTHREAD_BADREAD -32 // read thread bad read - fatal error
#define SSIRTHREAD_CREATEREVENT -33 // read thread bad create read event - error code set, AIP call will return false
#define SSIRTHREAD_CREATESEVENT -34 // read thread bad create status event- error code set, AIP call will return false
#define SSIRTHREAD_WAITCEVENT -35 // read thread wait com event bad return - fatal error
// One of these error codes is place in the WPARAM of a WM_ERROR messges during SNAPI protocol handling of scanner msgs
#define COMMAND_NOTHANDLED -36 // command was not processed successfully by decoder
#define ERR_UNSUPPORTED_COMMAND -37 // command was not processed successfully by decoder
#define SSI_DATAFORMAT_ERR -38 // scanner data packet was not of correct format from decoder
#define ERR_UNEXPECTEDDATA -39 // state machine has received data that was unexpected for the current state
//USB error messages
#define ERR_USB_DEV_NOTFOUND -40 // No USB device found with mentioned GUID
#define ERR_USB_OUT_OF_MEMORY -41 //No memory
#define ERR_INVALID_DEVICE_HANDLE -42 //Inavlid Device Handle
#define IMAGE_FRAME_CRC_ERROR -43 // CRC Error
#define SSITHREAD_WMOW_TIMEDOUT -44 // // Wait multiple objects timed out in overlapped write - fatal error
//Firmware update process messages and error codes
#define SSICOMM_FWUPDATE_ABORTED -45 // Firmware update process aborted
// One of these OPCODES are placed in the WPARAM of a WM_TIMEOUT msg
#define DECODE_DATA_TIMEOUT 0xF3
#define IMAGE_DATA_TIMEOUT 0xB1
#define VIDEO_DATA_TIMEOUT 0xB4
// Response Codes
#define COMMAND_SUCCESS 0x01
#define COMMAND_FAIL 0x02
#define COMMAND_NOT_SUPPORTED 0x03
#define COMMAND_SUPPORTED_NOT_COMPLETED 0x04
//Extended Response Codes
#define ALL_PARAMETERS_STORED 0x01
#define NO_PARAMETERS_STORED 0x02
#define SOME_PARAMETERS_STORED 0x03
//Event Codes
#define EVENT_POWER_UP 0x01
#define EVENT_DECODE 0x02
#define EVENT_PARAM_DFLTS 0x03
#define EVENT_PARAM_ENTRY_ERR 0x04
#define EVENT_PARAM_NUM_EXPECTED 0x05
#define EVENT_PARAM_STORED 0x06
#define EVENT_DECODE_MODE 0x10
#define EVENT_IMAGE_MODE 0x11
#define EVENT_VIDEO_MODE 0x12
// These are the beep codes for the beep functions
#define ONESHORTHI 0x00
#define TWOSHORTHI 0x01
#define THREESHORTHI 0x02
#define FOURSHORTHI 0x03
#define FIVESHORTHI 0x04
#define ONESHORTLO 0x05
#define TWOSHORTLO 0x06
#define THREESHORTLO 0x07
#define FOURSHORTLO 0x08
#define FIVESHORTLO 0x09
#define ONELONGHI 0x0A
#define TWOLONGHI 0x0B
#define THREELONGHI 0x0C
#define FOURLONGHI 0x0D
#define FIVELONGHI 0x0E
#define ONELONGLO 0x0F
#define TWOLONGLO 0x10
#define THREELONGLO 0x11
#define FOURLONGLO 0x12
#define FIVELONGLO 0x13
#define FASTHILOHILO 0x14
#define SLOWHILOHILO 0x15
#define HILO 0x16
#define LOHI 0x17
#define HILOHI 0x18
#define LOHILO 0x19
//for windows message handling
typedef struct
{
DWORD high;
DWORD low;
} DWPARAM;
#define HIDWORD(wParam) (wParam->high)
#define LODWORD(wParam) (wParam->low)
/****************************************************************************/
/* Extern Function Prototypes **********************************************/
SNAPIDLL_API int __stdcall SNAPI_Connect(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_Init(HWND hwnd, HANDLE * DeviceHandles, int * NumDevices);
SNAPIDLL_API int __stdcall SNAPI_Disconnect(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_SnapShot(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_TransmitVersion(HANDLE DeviceHandle);
/*SNAPIDLL_API int __stdcall AbortImageXfer(HANDLE DeviceHandle);*/
SNAPIDLL_API int __stdcall SNAPI_PullTrigger(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_ReleaseTrigger(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_SetParameters(WORD *Params, int ParamWords, HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_TransmitVideo(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_RequestParameters(WORD *Params, int ParamWords, HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_AimOn(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_AimOff(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_LedOn(HANDLE DeviceHandle, unsigned char nLEDselection);
SNAPIDLL_API int __stdcall SNAPI_LedOff(HANDLE DeviceHandle, unsigned char nLEDselection);
SNAPIDLL_API int __stdcall SNAPI_ScanEnable(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_ScanDisable(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_SoundBeeper(HANDLE DeviceHandle, unsigned char nBeepCode);
SNAPIDLL_API int __stdcall SNAPI_RequestScannerCapabilities(HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_SetParamPersistance(HANDLE DeviceHandle, int bPersist);
SNAPIDLL_API int __stdcall SNAPI_AbortMacroPdf(HANDLE DeviceHandle); // aborts macro session and throws out any data
SNAPIDLL_API int __stdcall SNAPI_FlushMacroPdf(HANDLE DeviceHandle); // aborts macro session and sends any data
SNAPIDLL_API int __stdcall SNAPI_SetParameterDefaults(HANDLE DeviceHandle);
SNAPIDLL_API unsigned int __stdcall SNAPI_ReturnDLLVersion(void);
SNAPIDLL_API int __stdcall SNAPI_GetSerialNumber(HANDLE DeviceHandle,unsigned char * SerialNo);
SNAPIDLL_API int __stdcall SNAPI_UpdateFirmware(char* frmFilePath, HANDLE DeviceHandle);
SNAPIDLL_API int __stdcall SNAPI_AbortFirmwareUpdate(HANDLE DeviceHandle);
/* Once filled by the DLL, the app is sent a WM_XXX messagge with the number of bytes of data that were (or should have
** been stored) in lParam and if the buffer wasn't big enough to hold all the data, wparam will have it's last 2 bits set
** to zero. If no buffer was given to the DLL for the data to be stored into, the last 2 bits of wparam will be 01.
* If the data was stored correctly, the last 2 bits of wparam will be 11.
**
** After the message is sent, the buffer is marked by the dll as
** NULL indicating no user buffer available for storage - the buffer should be reset as soon as possible
* after a WM_xxx message is processed. A second call to set the data buffer will cause the new buffer to be used for any incoming data.
**
**
** An ample video buffer size would be 5000 bytes
*
** Decode data depends on the type of barcode. If MacroPDF is buffered, large amounts of data are possible.
* The first byte is the SNAPI codetype id, followed by the decode data sent from the scanner.
**
** The image data buffer can be set when the first image transfer status message is sent to the application which holds
** the length information for the entire image.
**
** The parameter data buffer can be set immediately before the call to RequestParameters is made. A size of 4000 bytes
** should be ample to hold all the parameter number/value pairs. A call for a single parameter only requires a small
** buffer - 10 bytes is more than enough.
**
** The version data buffer can be set immediately before the call to TransmitVersion. The amount of data returned is
** variable but a buffer of length 256 should be ample.
**
** Capabilities data buffer can be set immediately before the call to RequestScannerCapabilities. The amount of data returned is
** variable but a buffer of length 256 should be ample.
**
*/
#define BUFFERSIZE_MASK 0x0003
#define BUFFERSIZE_GOOD 0x0003
#define BUFFERSIZE_ERROR 0x0000
#define NOBUFFER_ERROR 0x0001
SNAPIDLL_API int __stdcall SNAPI_SetVideoBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
SNAPIDLL_API int __stdcall SNAPI_SetImageBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
SNAPIDLL_API int __stdcall SNAPI_SetDecodeBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
SNAPIDLL_API int __stdcall SNAPI_SetParameterBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
SNAPIDLL_API int __stdcall SNAPI_SetVersionBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
SNAPIDLL_API int __stdcall SNAPI_SetCapabilitiesBuffer(HANDLE DeviceHandle, unsigned char *pData, long max_length);
/**********************************************************************************************/
/** Windows Messages sent to calling process ************************************************/
#define WM_DECODE WM_APP+1 // Sent if there is decode data available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
//LODWORD (wparam ) is the buffer status of the data stored
//HIDWORD(wparam) is the length of the data in bytes
//lparam is the handle to the device for which the message was posted
#define WM_IMAGE WM_APP+2 // Sent if there is image data available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
//LODWORD (wparam ) is the buffer status of the data stored
//HIDWORD(wparam) is the length of the data in bytes
//lparam is the handle to the device for which the message was posted
#define WM_VIDEOIMAGE WM_APP+3 // Sent if there is a video frame available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the buffer status of the data stored
// HIDWORD(wparam) is the length of the data in bytes
//lparam is the handle to the device for which the message was posted
#define WM_ERROR WM_APP+4 // Sent if an error occurred.
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the error code (cast to signed short) (see WM_ERROR codes list )
//lparam is the handle to the device for which the message was posted
#define WM_TIMEOUT WM_APP+5 // Sent if the scanner does not respond to a request from the library within
// ...the timeout for the request.
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is set to zero (reserved for future use)
// HIDWORD (wparam ) is the request code (int) that did not receive the response
// ...(see WM_TIMEOUT codes list)
//lparam is the handle to the device for which the message was posted
#define WM_CMDCOMPLETEMSG WM_APP+6 // Sent when an ACK is received from the scanner in response to a handled
// user command.
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
//LODWORD (wparam ) is the command status.
//HIDWORD (wparam ) is extended command status.
//lparam is the handle to the device for which the message was posted
#define WM_XFERSTATUS WM_APP+7 // Sent during the transfer of image data from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *).
// LODWORD (wparam ) is the total number of bytes received so far (cast to uint)
// HIDWORD (wparam ) is the total number of bytes expected (cast to uint)
//lparam is the handle to the device for which the message was posted
#define WM_SWVERSION WM_APP+8 // Sent when the software version information is available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the buffer status code
// HIDWORD (wparam ) is the length of the data in bytes (cast to int).
// version data is device dependent
//lparam is the handle to the device for which the message was posted
#define WM_PARAMS WM_APP+9 // Sent when parameter information is available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the buffer status,
// HIDWORD (wparam ) is the length of the parameter data as number of words(cast to int).
//lparam is the handle to the device for which the message was posted
#define WM_CAPABILITIES WM_APP+10 // Sent when capabilities data is available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the buffer status
// HIDWORD (wparam ) is the length of the data in bytes (cast to int).
//lparam is the handle to the device for which the message was posted
#define WM_EVENT WM_APP+11 // Sent when event data is available from the scanner
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the event data
// HIDWORD (wparam ) is the length of the data in bytes (always 1 byte).
//lparam is the handle to the device for which the message was posted
#define WM_DEVICE_NOTIFICATION WM_APP+12 // Sent when a SNAPI compatible device is detected or
// removed from the system.
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is either of
// - DEVICE_ARRIVE or DEVICE_REMOVE
//lparam is the handle to the device for which the message was posted
#define WM_MGMT_CMD_RESP WM_APP+13 // Sent when a response is available from the scanner to a management command
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the buffer status
// HIDWORD (wparam ) is the length of the data in bytes (cast to int).
//lparam is the handle to the device for which the message was posted
#define WM_FU_STARTED WM_APP+14 //Sent when firmware update process starts
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the number steps in firmware update process
//lparam is the handle to the device for which the message was posted
#define WM_FU_PROGRESS WM_APP+15 //Sent when each firmware update step finished
//wparam is a pointer to DWPARAM structure (cast to DWPARAM *)
// LODWORD (wparam ) is the current step number
//lparam is the handle to the device for which the message was posted
// for WM_DEVICE_NOTIFICATION event
#define DEVICE_ARRIVE 0 // The system has detected a new device
#define DEVICE_REMOVE 1 // The device has been removed from the system.
#endif // ifdef __SNAPIDLL_API_H__
答案 0 :(得分:5)
Read the documentation再次更加谨慎。您引用的部分会告诉您完全如何获取图像数据。
当您收到WM_XFERSTATUS
窗口消息时,它会告诉您图像大小。分配足够大的数据缓冲区以容纳该大小,然后将缓冲区传递给SNAPI_SetImageBuffer()
。然后,DLL将使用图像数据填充该缓冲区。完成后,您将收到一条WM_IMAGE
消息,告诉您缓冲区已准备就绪。
documentation在第1章的由DLL返回的数据和发送给调用过程的Windows消息部分中更详细地解释了这一点。
更新:例如:
type
TScanner = class
public
Device: THandle;
Connected: Boolean;
ImageData: array of Byte;
Pending: Boolean;
procedure Connect;
procedure Disconnect;
procedure RequestSnapshot;
procedure SetImageBuffer(Size: Integer);
end;
const
SNAPI_DLL = 'snapi.dll';
function SNAPI_Init(wnd: HWND; var DeviceHandles: THandle, var NumDevices: Integer): Integer; stdcall; external SNAPI_DLL;
function SNAPI_Connect(DeviceHandle: THandle): Integer; stdcall; external SNAPI_DLL;
function SNAPI_Disconnect(DeviceHandle: THandle): Integer; stdcall; external SNAPI_DLL;
function SNAPI_SetImageBuffer(DeviceHandle: THandle; Data: Pointer; MaxLength: Longint): Integer; stdcall; external SNAPI_DLL;
function SNAPI_SnapShot(DeviceHandle: THandle): Integer; stdcall; external SNAPI_DLL;
const
MAX_SCANNER = ...; // you will have to look this up
BUFFERSIZE_ERROR = $0000;
NOBUFFER_ERROR = $0001;
BUFFERSIZE_GOOD = $0003;
BUFFERSIZE_MASK = $0003;
WM_IMAGE = WM_APP+2;
WM_ERROR = WM_APP+4;
WM_TIMEOUT = WM_APP+5;
WM_XFERSTATUS = WM_APP+7;
WM_DEVICENOTIFICATION := WM_APP+12;
IMAGE_DATA_TIMEOUT = $B1;
type
PDWPARAM = ^DWPARAM;
DWPARAM = record
dwHigh: DWORD;
dwLow: DWORD;
end;
function HIDWORD(wParam: PDWPARAM): DWORD;
begin
Result := wParam^.dwHigh;
end;
function LODWORD(wParam: PDWPARAM): DWORD;
begin
Result := wParam^.dwLow;
end;
type
ESNAPIError = class(Exception)
public
Status: Integer;
constructor CreateErr(AStatus: Integer);
end;
constructor ESNAPIError.CreateErr(AStatus: Integer);
begin
inherited CreateFmt('SNAPI Error %d', [AStatus]);
Status := AStatus;
end;
procedure CheckSNAPIStatus(AStatus: Integer);
begin
if AStatus <> 0 then
raise ESNAPIError.CreateErr(AStatus);
end;
procedure TScanner.Connect;
begin
if not Connected then
begin
CheckSNAPIStatus(SNAPI_Connect(Device));
Connected := True;
end;
end;
procedure TScanner.Disconnect;
begin
if Connected then
begin
SNAPI_Disconnect(Device);
Connected := False;
end;
end;
procedure TScanner.RequestSnapshot;
begin
Connect;
if Pending then
raise Exception.Create('Scanner is busy, try again later');
SetLength(ImageData, 0);
CheckSNAPIStatus(SNAPI_SnapShot(Device));
Pending := True;
end;
procedure TScanner.SetImageBuffer(Size: Integer);
begin
SetLength(ImageData, Size);
CheckSNAPIStatus(SNAPI_SetImageBuffer(Device, Pointer(ImageData), Size));
end;
type
TMyForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
ScannerWnd: HWND;
Scanners: TObjectList;
function FindScanner(Device: THandle): TScanner;
procedure ConnectScanner(int Index);
procedure DisconnectScanner(int Index);
procedure RequestSnapshot(int Index);
procedure ScannerWndProc(var Message: TMessage);
end;
procedure TMyForm.FormCreate(Sender: TObject);
var
Devices: array[0..MAX_SCANNER-1] of THandle;
NumScanners, I: Integer;
Scanner: TScanner;
begin
Scanners := TObjectList.Create(True);
ScannerWnd := AllocateHWnd(ScannerWndProc);
CheckSNAPIStatus(SNAPI_Init(ScannerWnd, Devices[0], NumScanners));
for I := 0 to NumScanners-1 do
begin
Scanner := TScanner.Create;
Scanner.Device := Devices[I];
Scanners.Add(Scanner);
// add it to the UI somewhere...
end;
end;
procedure TMyForm.FormDestroy(Sender: TObject);
begin
DeallocateHWnd(ScannerWnd);
Scanners.Free;
end;
function TMyForm.FindScanner(Device: THandle): TScanner;
var
I: Integer;
begin
for I := 0 to Scanners.Count-1 do
begin
Result := TScanner(Scanners[I]);
if Scanner.Device = Device then
Exit;
end;
Result := nil;
end;
procedure TMyForm.ConnectScanner(int Index);
begin
TScanner(Scanners[Index]).Connect;
end;
procedure TMyForm.DisconnectScanner(int Index);
begin
TScanner(Scanners[Index]).Disconnect;
end;
procedure TMyForm.RequestSnapshot(int Index);
begin
TScanner(Scanners[Index]).RequestSnapshot;
end;
procedure TMyForm.ScannerWndProc(var Message: TMessage);
var
Scanner: TScanner;
Param: PDWPARAM;
begin
case Message.Msg of
WM_XFERSTATUS:
begin
Scanner := FindScanner(THandle(Message.LParam));
if Scanner = nil then Exit;
Param := PDWPARAM(Message.WParam);
//BytesRecv := LODWORD(Param)
//BytesTotal := HIDWORD(Param)
if Scanner.ImageData = nil then
Scanner.SetImageBuffer(Integer(HIDWORD(Param)));
end;
WM_IMAGE:
begin
Scanner := FindScanner(THandle(Message.LParam));
if Scanner = nil then Exit;
Scanner.Pending := False;
Param := PDWPARAM(Message.WParam);
// Status := LODWORD(Param)
// BytesTotal := HIDWORD(Param)
if (LODWORD(Param) and BUFFERSIZE_MASK) <> BUFFERSIZE_GOOD then
raise Exception.Create('Image buffer error');
// use Scanner.ImageData as needed...
SetLength(Scanner.ImageData, 0);
end;
WM_DEVICENOTIFICATION:
begin
Param := PDWPARAM(Message.WParam);
// NotifyCode := LODWORD(Param)
case LODWORD(Param) of
DEVICE_ARRIVE:
begin
Scanner := TScanner.Create;
Scanner.Device := THandle(Message.LParam);
Scanners.Add(Scanner);
// add it to the UI somewhere...
end;
DEVICE_REMOVE:
begin
Scanner := FindScanner(THandle(Message.LParam));
if Scanner <> nil then
begin
Scanners.Remove(Scanner);
// remove it from the UI...
end;
end;
end;
end;
WM_TIMEOUT:
begin
Scanner := FindScanner(THandle(Message.LParam));
if Scanner = nil then Exit;
Scanner.Pending := False;
// NotifyCode := HIDWORD(Param)
case HIDWORD(Param) of
IMAGE_DATA_TIMEOUT:
begin
raise Exception.Create('Image timeout');
end;
end;
end;
WM_ERROR:
begin
Scanner := FindScanner(THandle(Message.LParam));
if Scanner = nil then Exit;
Scanner.Pending := False;
Param := PDWPARAM(Message.WParam);
// Status := LODWORD(Param)
CheckSNAPIStatus(Integer(LODWORD(Param)));
end;
else
Message.Result := DefWindowProc(ScannerWnd, Message.Msg, Message.WParam, Message.LParam);
end;