1

純粋なAPIを使用してクリップボードから画像を保存するのに問題があります。

これが私のコードです。20個の空のbmpファイルを作成します。dwSizeを確認しましたが、データが正しく取得されているように見えますが、ファイルへの書き込みが正しくありません。

  program WebcamTest;
  //cswi

  uses
    Windows;

  const
    WM_CAP_DRIVER_CONNECT = 1034;
    WM_CAP_GRAB_FRAME = 1084;
    //WM_CAP_SAVEDIB = 1049;
    WM_CAP_EDIT_COPY = 1054;
    WM_CAP_DRIVER_DISCONNECT = 1035;

  function SendMessageA(hWnd: Integer;
                        Msg: Integer;
                        wParam: Integer;
                        lParam: Integer): Integer;
                        stdcall;
                        external 'user32.dll' name 'SendMessageA';

  function capGetDriverDescriptionA(DrvIndex: Cardinal;
                                    Name: PAnsiChar;
                                    NameLen: Integer;
                                    Description: PAnsiChar;
                                    DescLen: Integer) : Boolean;
                                    stdcall;
                                    external 'avicap32.dll' name 'capGetDriverDescriptionA';

  function capCreateCaptureWindowA(lpszWindowName: PAnsiChar;
                                   dwStyle: Integer;
                                   x : Integer;
                                   y : Integer;
                                   nWidth : Integer;
                                   nHeight : Integer;
                                   ParentWin: Integer;
                                   nId: Integer): Integer;
                                   stdcall;
                                   external 'avicap32.dll' name 'capCreateCaptureWindowA';

  function IntToStr(i: Integer): String;
  begin
    Str(i, Result);
  end;

  var
    WebCamId : Integer;
    CaptureWindow : Integer;
    x : Integer;
    FileName : PAnsiChar;
    hData:  DWORD;
    pData:  Pointer;
    dwSize: DWORD;
    szText : AnsiString;
    FileHandle, BytesWritten : LongWord;
  begin
    WebcamId := 0;
    CaptureWindow := capCreateCaptureWindowA('CaptureWindow', 0, 0, 0, 0, 0, 0, 0);
    if CaptureWindow <> 0 then
    begin
      if SendMessageA(CaptureWindow, WM_CAP_DRIVER_CONNECT, WebCamId, 0) <> 1 then
      begin
        SendMessageA(CaptureWindow, WM_CAP_DRIVER_DISCONNECT, 0, 0);
      end
      else
      begin
        for x := 1 to 20 do // Take 20 photos.
        begin
          SendMessageA(CaptureWindow, WM_CAP_GRAB_FRAME, 0, 0);
          FileName := PAnsiChar('C:\Test' + IntToStr(x) + '.bmp');
          //SendMessageA(CaptureWindow, WM_CAP_SAVEDIB, 0, LongInt(FileName));
          SendMessageA(CaptureWindow, WM_CAP_EDIT_COPY, 0, LongInt(FileName));
          if OpenClipBoard(0) then
          begin
            hData := GetClipBoardData(CF_DIB);
            if hData <> 0 then
            begin
              pData := GlobalLock(hData);
              if pData <> nil then
              begin
                dwSize := GlobalSize(hData);
                if dwSize <> 0 then
                begin
                  FileHandle := CreateFileA(FileName, GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, 0);
                  WriteFile(FileHandle, pData, dwSize, BytesWritten, nil);
                  CloseHandle(FileHandle);
                end;
                GlobalUnlock(DWORD(pData));
              end;
            end;
            CloseClipBoard;
          end;
        end;
      end;
      SendMessageA(CaptureWindow, WM_CAP_DRIVER_DISCONNECT, 0, 0);
    end;
  end.
4

2 に答える 2

4

とにかくファイルに書き込んでいるので、メモリ内のデータにアクセスしたいという理由だけで、クリップボードを使用してキャプチャウィンドウから画像データを転送することは非常に(非常に!)悪い考えです。オプションに固執することをお勧めしWM_CAP_SAVEDIBます。(2つの非常に良い理由を挙げてください:クリップボードでは他のプロセスにアクセスできます:セキュリティ!;クリップボードにあったものはすべてドロップします:不便です!)

しかし、あなたの質問に答えるために:WriteFileは型なし引数としてBufferを受け取るので、ポインターを渡すと、このように指定しない限り、ポインターが指すデータではなく、ポインターのを取ります(注意サフィックス):

WriteFile(FileHandle, pData^, dwSize, BytesWritten, nil);
于 2012-08-28T08:42:08.657 に答える
1

ユーザーの操作に反応しないものにクリップボードを使用するのは非常に悪い(非常に悪い)ので、取得したフレームのデータにアクセスするための別の方法を提供します。capCreateCaptureWindowフォームのコントロールにハンドルを渡すと、WM_CAP_GRAB_FRAMEメッセージを送信した後、フォーム上BitBltのonとビットマップを使用してこのデータをビットマップにコピーするために使用できますCanvas.Handle。この方法の重要な欠点は、フォームが画面に表示される必要があることです。

于 2012-09-04T10:09:28.350 に答える