Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
282 views
in Technique[技术] by (71.8m points)

How To Get Picture from the dll sending it to application in delphi

I have problem to get the image from the DLL file, the function to call the image is:

SNAPI_SnapShot Host to Scanner Command

If the scanner supports imaging, this sends a command to the scanner to enter Image Capture Mode. The scanner remains in Image Capture Mode until the trigger is pulled (physically or with a call to SNAPI_PullTrigger) and an image is captured, or until the timeout for a trigger pull expires. The scanner then returns to Decode Mode.

If the trigger is pulled, the image data is sent to the DLL. WM_XFERSTATUS is sent to the host application with information about the size of the image.

When the first transfer status message is received, the host application should provide a destination buffer for the image by calling SNAPI_SetImageBuffer. After the entire image is transferred from the scanner to the DLL, the application receives a Windows message indicating that the image data was stored.

The Image data is sent to the DLL. I need to know how to get the image in 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 D

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Read the documentation again more carefully. The portion you quoted tells you EXACTLY how to get the image data.

When you receive the WM_XFERSTATUS window message, it will tell you the image size. Allocate a data buffer that is large enough to accomodate that size, and then pass the buffer to SNAPI_SetImageBuffer(). The DLL will then fill that buffer with image data. When it is finished, you will receive a WM_IMAGE message telling you the buffer is ready.

The documentation explains this in more detail in the Data Returned by DLL and Windows Messages Sent to Calling Process sections of Chapter 1.

Update: For example:

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...