-3

我有一个用于扫描向我的应用程序发送消息的图像的 DLL。文档是这样描述的:

如果扳机被拉动,图像数据将被发送到 DLL。WM_XFERSTATUS 与有关图像大小的信息一起发送到主机应用程序。当接收到第一个传输状态消息时,主机应用程序应通过调用 SNAPI_SetImageBuffer 为图像提供目标缓冲区。将整个图像从扫描仪传输到 DLL 后,应用程序会收到一条 Windows 消息,指示图像数据已存储。

第一条消息记录如下:

消息 WM_XFERSTATUS
描述 图像数据正在从扫描仪传输。
表 1-1 Windows 消息(续)
属性 描述
DLL 数据、错误报告、消息和哔声代码 1 - 5
值 WM_APP+7

参数

  • wParam – 指向 DWPARAM 结构的指针(转换为 DWPARAM *)。
  • LODWORD (wparam) – 到目前为止接收的字节总数。
  • HIDWORD (wparam) – 预期的总字节数。
  • lParam – 发布消息的设备的句柄。

第二条消息,当图像完成传输时,是这样的:

消息 WM_IMAGE
描述 图像数据可从扫描仪获得,并存储在先前调用 SNAPI_SetImageBuffer 提供的缓冲区中。
值 WM_APP+2

参数

  • wParam – 指向 DWPARAM 结构的指针(转换为 DWPARAM *)
  • LODWORD (wparam) – 存储数据的缓冲区状态
  • HIDWORD (wparam) – 数据的长度(以字节为单位)
  • lParam – 发布消息的设备句柄

数据格式 实际图像数据。

我使用这段代码来获取消息,但是当我设置数据的长度时,会引发异常:

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;
procedure TMyform.FormCreate(Sender: TObject);
var
  Devices: array[0..MAX_SCANNER-1] of THandle;
  NumScanners, I: Integer;
  Scanner: TScanner;
begin
  Scanners := TObjectList.Create;
  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;

procedure TScanner.SetImageBuffer(Size: Integer);
begin
  SetLength(ImageData, Size);   //Hear I get the error
  SNAPI_SetImageBuffer(Device, Pointer(ImageData), Length(ImageData));
end;

procedure TMyform.ScannerWndProc(var Message: TMessage);
var
  Scanner: TScanner;
begin
  case Message.Msg of

    WM_XFERSTATUS:
    begin
        Scanner.SetImageBuffer(HiDWord(Message.WParam));
    end;

    WM_IMAGE:
    begin
      if (LO(Message.WParam) and BUFFERSIZE_MASK) <> BUFFERSIZE_GOOD then
        raise Exception.Create('Image buffer error');

      // use Scanner.ImageData up to HIDWORD(Message.WParam) bytes as needed...

      SetLength(Scanner.ImageData, 0);
    end;

注意:我使用了该HIDWORD功能,但它在 Delphi 中不起作用。我用HIWORD函数替换了它。

请问如何获取图像数据

4

1 回答 1

4

很难弄清楚你的问题到底是什么。至少其中一些似乎围绕着如何破译这些信息。

您需要强制wParam转换为指向结构的指针DWPARAM。我不知道那是什么,因为您的问题没有提及。但是您没有将wParam其视为指针,这似乎是不正确的。

我的猜测是这DWPARAM是一个包含两个DWORD值的结构。像这样:

type
  PDWPARAM = ^DWPARAM;
  DWPARAM = record
    Lo, Hi: DWORD;
  end;

因此,您可以像这样提取两个值:

PDWPARAM(Message.wParam).Lo

PDWPARAM(Message.wParam).Hi

话虽如此,我能找到的文档与问题中出现的完全矛盾。例如:

消息:WM_XFERSTATUS
值:WM_APP+7
说明:正在从扫描仪传输图像数据。
参数: wParam:到目前为止接收到的总字节数(转换为 uint)
             lParam:预期的总字节数(转换为 uint)

……

消息:WM_IMAGE
值:WM_APP+2
说明:图像数据可从扫描仪获得并存储在缓冲区中
             由先前调用 SetImageBuffer 提供。
参数: wParam:存储数据的缓冲区状态
             lParam:以字节为单位的数据长度(转换为长)

那么,谁知道这个库的接口到底是什么?


您报告的问题是这行代码

SetLength(ImageData, Size);   

导致错误。你没有说错误是什么,所以我们必须猜测。

错误最可能的原因是ImageData无法访问。如果您没有实例化该类的实例,就会出现这种情况TScanner。代码确实证实了这一点。您在其中声明了一个局部变量ScannerTMyform.ScannerWndProc但从不初始化它。如果您启用警告,编译器会警告您。或者,警告可能已启用,而您只是忽略了它们。

无论如何,在您使用它的地方有两个变量Scanner在范围内命名。一个是类的成员,另一个是局部变量。局部变量是使用的变量,它还没有被初始化。您需要删除那个虚假的局部变量。


但是,到目前为止,您犯的最大错误是您没有报告使用您观察到的信息。您遇到了一个错误,并且未能告诉我们该错误是什么,这是不可原谅的疏忽之罪。

而且,您还没有给我们任何诊断信息。您的程序中有各种变量。您还没有告诉我们它们在运行时持有什么值。也许你需要退后一步,学习一些调试技巧。

解决问题的真正方法是学习如何收集和报告诊断信息。

于 2013-09-11T18:33:22.167 回答