如何在delphi中从dll获取图片并将其发送到应用程序

如何在delphi中从dll获取图片并将其发送到应用程序,delphi,Delphi,我无法从DLL文件中获取图像,调用图像的函数是: SNAPI_快照主机到扫描仪命令 如果扫描仪支持成像,则会向扫描仪发送命令以进入图像捕获模式。扫描仪将保持图像捕获模式,直到触发(物理触发或调用 SNAPI_PullTrigger)并捕获图像,或者直到触发触发超时过期。然后扫描仪返回到解码模式 如果触发,图像数据将发送到DLL。WM_XFERSTATUS被发送到主机应用程序,其中包含有关图像大小的信息 收到第一条传输状态消息时,主机应用程序应通过调用SNAPI_SetImageBuffer为映像

我无法从DLL文件中获取图像,调用图像的函数是:

SNAPI_快照主机到扫描仪命令

如果扫描仪支持成像,则会向扫描仪发送命令以进入图像捕获模式。扫描仪将保持图像捕获模式,直到触发(物理触发或调用 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__
再仔细一点。您引用的部分准确地告诉您如何获取图像数据

当您收到
WM_XFERSTATUS
窗口消息时,它会告诉您图像大小。分配一个足以容纳该大小的数据缓冲区,然后将该缓冲区传递给
SNAPI\u SetImageBuffer()
。DLL随后将用图像数据填充该缓冲区。完成后,您将收到一条
WM_IMAGE
消息,告诉您缓冲区已准备就绪

在第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;
类型
TScanner=类
公众的
装置:THandle;
连通:布尔;
ImageData:字节数组;
待定:布尔型;
程序连接;
程序断开;
程序快照;
过程SetImageBuffer(大小:整数);
结束;
常数
SNAPI_DLL='SNAPI.DLL';
函数SNAPI_Init(wnd:HWND;var DeviceHandles:THandle,var NumDevices:Integer):Integer;stdcall;外部SNAPI_动态链接库;
函数SNAPI_Connect(DeviceHandle:THandle):整数;stdcall;外部SNAPI_动态链接库;
函数SNAPI_Disconnect(DeviceHandle:THandle):整数;stdcall;外部SNAPI_动态链接库;
函数SNAPI_SetImageBuffer(DeviceHandle:THandle;数据:指针;MaxLength:Longint):整数;stdcall;外部SNAPI_动态链接库;
函数SNAPI_SnapShot(DeviceHandle:THandle):整数;stdcall;外部SNAPI_动态链接库;
常数
最大扫描器=…;//你得查一下这个
BUFFERSIZE_错误=$0000;
NOBUFFER_错误=$0001;
BUFFERSIZE_GOOD=$0003;
BUFFERSIZE_MASK=$0003;
WM_IMAGE=WM_APP+2;
WM_误差=WM_应用程序+4;
WM_超时=WM_应用程序+5;
WM_XFERSTATUS=WM_APP+7;
WM_设备化:=WM_应用程序+12;
图像\数据\超时=$B1;
类型
PDWPARAM=^DWPARAM;
DWPARAM=记录
dwHigh:DWORD;
dwLow:DWORD;
结束;
函数HIDWORD(wParam:PDWPARAM):DWORD;
开始
结果:=wParam^.dwHigh;
结束;
函数LODWORD(wParam:PDWPARAM):DWORD;
开始
结果:=wParam^.dwLow;
结束;
类型
ESNAPIError=类(异常)
公众的
状态:整数;
构造函数createrr(AStatus:Integer);
结束;
构造函数ESNAPIError.CreateErr(AStatus:Integer);
开始
继承的CreateFmt('SNAPI错误%d',[AStatus]);
状态:=静止状态;
结束;
过程检查SnapStatus(AStatus:整数);
开始
如果AStatus为0,则
提高ESNAPIError.CreateErr(AStatus);
结束;
程序TScanner.Connect;
开始
如果没有连接,那么
开始
检查SnapIstatus(SNAPI_Connect(设备));
已连接:=真;
结束;
结束;
程序TScanner.断开;
开始
如果连接,则
开始
SNAPI_断开(设备);
连接:=假;
结束;
结束;
程序TScanner.RequestSnapshot;
开始
连接
如果待决,则
引发异常。创建('扫描仪正忙,请稍后重试');
设置长度(ImageData,0);
检查SnapIstatus(SNAPI_快照(设备));
待定:=真;
结束;
程序TScanner.SetImageBuffer(大小:整数);
开始
设置长度(图像数据、大小);
检查SnapIstatus(SNAPI_SetImageBuffer(设备、指针(ImageData)、大小));
结束;

类型
TMyForm=类(TForm)
过程表单创建(发送方:ToObject);
销毁程序表(发送方:TObject);
私有的
扫描者编号:HWND;
扫描仪:TObjectList;
功能查找扫描仪(设备:THandle):TScanner;
程序扫描程序(int索引);
程序断开扫描仪(int索引);
程序请求快照(int索引);
程序扫描程序WNDPROC(var消息:TMessage);
结束;
程序TMyForm.FormCreate(发送方:TObject);
变量
设备:THandle的阵列[0..MAX_SCANNER-1];
NumScanners,I:整数;
扫描仪:TScanner;
开始
扫描器:=TObjectList.Create(True);
ScannerWnd:=AllocateHWnd(ScannerWndProc);
检查snapistatus(SNAPI_Init(扫描设备[0],NumScanners));
对于I:=0到NumScanners-1 do
开始
扫描仪:=TScanner.Create;
Scanner.Device:=设备[I];
扫描器。添加(扫描器);
//将其添加到UI的某个位置。。。
结束;
结束;
程序TMyForm.FormDestroy(发送方:ToObject);
开始
解除分配HWND(扫描程序WND);
扫描仪。免费;
结束;
功能TMyForm.FindScanner(设备:THandle):TScanner;
变量
I:整数;
开始
对于I:=0到0.Count-1 do
开始
结果:=TScanner(扫描器[I]);
如果Scanner.Device=Device,则
出口
结束;
结果:=无;
结束;
程序TMyForm.ConnectScanner(int索引);
开始
t扫描仪(扫描仪[索引])连接;
结束;
程序TMyForm.DisconnectScanner(int索引);
开始
t扫描仪(扫描仪[索引])。断开连接;
结束;
程序TMyForm.RequestSnapshot(int索引);
开始
TScanner(扫描器[索引])请求快照;
结束;
程序TMyForm.ScannerWndProc(变量消息:TMessage);
变量
扫描仪:TScanner;
参数:PDWPARAM;
开始
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;