2

ネットで検索しているときに、EMF ファイルから画像を抽出するための VB のコードを数行取得しました。

それをDelphiに変換しようとしましたが、うまくいきません。

このコードをデルファイに変換するのを手伝ってください。

Public Function CallBack_ENumMetafile(ByVal hdc As Long, _
                                      ByVal lpHtable As Long, _
                                      ByVal lpMFR As Long, _
                                      ByVal nObj As Long, _
                                      ByVal lpClientData As Long) As Long
  Dim PEnhEMR As EMR
  Dim PEnhStrecthDiBits As EMRSTRETCHDIBITS
  Dim tmpDc As Long
  Dim hBitmap  As Long
  Dim lRet As Long
  Dim BITMAPINFO As BITMAPINFO
  Dim pBitsMem As Long
  Dim pBitmapInfo As Long
  Static RecordCount As Long

  lRet = PlayEnhMetaFileRecord(hdc, ByVal lpHtable, ByVal lpMFR, ByVal nObj)


  RecordCount = RecordCount + 1
  CopyMemory PEnhEMR, ByVal lpMFR, Len(PEnhEMR)
  Select Case PEnhEMR.iType
  Case 1  'header
    RecordCount = 1
  Case EMR_STRETCHDIBITS
    CopyMemory PEnhStrecthDiBits, ByVal lpMFR, Len(PEnhStrecthDiBits)
    pBitmapInfo = lpMFR + PEnhStrecthDiBits.offBmiSrc
    CopyMemory BITMAPINFO, ByVal pBitmapInfo, Len(BITMAPINFO)
    pBitsMem = lpMFR + PEnhStrecthDiBits.offBitsSrc

    tmpDc = CreateDC("DISPLAY", vbNullString, vbNullString, ByVal 0&)
    hBitmap = CreateDIBitmap(tmpDc, _
                            BITMAPINFO.bmiHeader, _
                            CBM_INIT, _
                            ByVal pBitsMem, _
                            BITMAPINFO, _
                            DIB_RGB_COLORS)
    lRet = DeleteDC(tmpDc)

  End Select
  CallBack_ENumMetafile = True

End Function
4

1 に答える 1

4

あなたが投稿したものはEnumMetaFileProcコールバック関数のインスタンスであるため、署名から始めます。

function Callback_EnumMetafile(
  hdc: HDC;
  lpHTable: PHandleTable;
  lpMFR: PMetaRecord;
  nObj: Integer;
  lpClientData: LParam
): Integer; stdcall;

一連の変数を宣言することから始めますが、どの変数が本当に必要になるかわからないため、ここではスキップします。また、VB の型システムは Delphi よりも制限されています。必要に応じて宣言します。それらをすべて自分で関数の先頭に移動できます。

次は、PlayEnhMetaFileRecordコールバック関数に渡されたのとほとんど同じパラメーターを使用する呼び出しです。関数は Bool を返しますが、コードはそれを無視するので、気にしないでlRetください。

PlayEnhMetaFileRecord(hdc, lpHtable, lpMFR, nObj);

次に初期化しますRecordCount。これは静的であると宣言されています。つまり、ある呼び出しから次の呼び出しまで値が保持されます。それは少し疑わしく見えます。おそらくパラメーターのポインターとして渡されるはずlpClientDataですが、今のところ元のコードから離れすぎないようにしましょう。Delphi は型付き定数を使用して静的変数を処理し、変更可能にする必要があるため、$J ディレクティブを使用します。

{$J+}
const
  RecordCount: Integer = 0;
{$J}

Inc(RecordCount);

次に、メタ レコードの一部を別の変数に mcopy します。

var
  PEnhEMR: TEMR;

CopyMemory(@PEnhEMR, lpMFR, SizeOf(PEnhEMR));

TMetaRecord 構造体を TEMR 構造体にコピーするのは少し奇妙に見えますが、これらはあまり似ていないためです。

iType次は、フィールドでの case ステートメントです。最初のケースは、1 の場合です。

case PEnhEMR.iType of
  1: RecordCount := 1;

次のケースは、emr_StretchDIBits です。メタ レコードをさらにコピーし、メイン データ構造のサブセクションを参照するために他のポインタを割り当てます。

var
  PEnhStretchDIBits: TEMRStretchDIBits;
  BitmapInfo: TBitmapInfo;
  pBitmapInfo: Pointer;
  pBitsMem: Pointer;

  emr_StretchDIBits: begin
    CopyMemory(@PEnhStrecthDIBits, lpMFR, SizeOf(PEnhStrecthDIBits));
    pBitmapInfo := Pointer(Cardinal(lpMFR) + PEnhStrecthDiBits.offBmiSrc);
    CopyMemory(@BitmapInfo, pBitmapInfo, SizeOf(BitmapInfo));
    pBitsMem := Pointer(Cardinal(lpMFR) + PEnhStrecthDiBits.offBitsSrc);

次に、関数の真骨頂と思われるものが続きます。ここでは、前のコードを使用して抽出された DIBits を使用して、表示コンテキストとビットマップを作成します。

var
  tmpDc: HDC;
  hBitmap: HBitmap;

    tmpDc := CreateDC('DISPLAY', nil, nil, nil);
    hBitmap := CreateDIBitmap(tmpDc, @BitmapInfo.bmiHeader, cbm_Init,
      pBitsMem, @BitmapInfo, dib_RGB_Colors);
    DeleteDC(tmpDc);
  end; // emr_StretchDIBits
end; // case

最後に、戻り値をコールバック関数に割り当てます。

Result := 1;

それで、あなたの翻訳があります。それをbegin-endブロックで囲み、コメントを削除して、すべての変数宣言を一番上に移動すると、VB コードと同等の Delphi コードが得られます。ただし、このコードが最終的に行うことは、メモリ リークを生成することだけです。hBitmap変数は関数に対してローカルであるため、この関数が戻るとすぐに変数が保持するビットマップ ハンドルがリークされます。ただし、VB コードは機能すると思いますので、それをどうするかについて他の計画があると思います。

メタファイルを扱っている場合、 GraphicsユニットTMetafileでクラスを使用することを検討しましたか? それはあなたの人生を楽にするかもしれません。

于 2010-06-17T15:14:51.680 に答える