予定は未定

記事中のプログラムコードについて、常識的な範囲で引用・プログラムへの利用ができます。利用に当たって許諾の必要はありません。

Viewport3Dの画像をコピー・印刷するには

TViewport3Dの画像をコピーしたり印刷したい場合はどうするか。
その方法と注意点について示す。
まず、今回のコードはAndroidでは動かない(プリンターサービスとかがない)コードが含まれるので注意。

画像をコピー

TViewport3Dの画像をクリップボードにコピーするには、以下のようにする。

// あらかじめインクルード
#include <FMX.Platform.hpp>
#include <FMX.Clipboard.hpp>

void __fastcall OnCopy( TObject* Sender )
{
  TBitmap* pBmp = Viewport3D1->MakeScreenshot();
  TBitmapSurface* pBmpSurface = new TBitmapSurface;
  pBmpSurface->Assign( pBmp );

  _di_IFMXExtendedClipboardService pCs =    TPlatformServices::Current->GetPlatformService(__uuidof(IFMXExtendedClipboardService));

  pCs->SetImage( pBmpSurface );

  delete pBmp;
  delete pBmpSurface;
}

VCLとは異なり、TBitmapそのままでクリップボードに渡せないので、一回TBitmapSurfaceを介さなければならない。

印刷

TViewport3Dの画像を印刷するには、以下のようにする。

// あらかじめインクルード
#include <FMX.Printer.hpp>

void __fastcall OnPrint( TObject* Sender )
{
  TPrinter* pPrn = Printer::Printer();

  pPrn->BeginDoc();
    pPrn->Canvas->BeginScene();
      TRectF ARect(  dLeft, dTop, dRight, dBottom );
      Viewport3D1->PaintTo( pPrn->Canvas, ARect, nullptr );
    pPrn->Canvas->EndScene();
  pPrn->EndDoc();
}

プリンターへのポインターは上記のようにネームスペースつきにする必要がある。
VCLとは異なり、印刷中に描画コードはBegeinScene()とEndScene()で挟む必要がある。

注意事項

MakeScreenshot()で得たビットマップは不要になり次第削除する。

TViewport3D::MakeScreenshot()で得たビットマップは、利用者側で削除する必要がある。
削除しない場合はメモリー領域が徐々に圧迫されることと、Windowsリソースが消費されるのでGDIエラーが出る可能性がある。

TViewport3Dで生成される画像のサイズは、TViewport3Dのサイズ

TViewport3D::MakeScreenshot()はもちろん、TViewport3D::PaintTo()で得られる画像も基のサイズはTViewport3Dのサイズである。TViewport3D::PaintTo()では与えるTRectFのサイズに引き延ばしして描画される。

任意のサイズにしたい場合は、以下のようなテクニックを用いる。

#include <FMX.Printer.hpp>

void __fastcall OnPrint( TObject* Sender )
{
  int nOldWidth  = Viewport3D1->Width;
  int nOldHeight = Viewport3D1->Height;

  // サイズを指定
  Viewport3D1->Visible = false; 
  Viewport3D1->Width   = dW; 
  Viewport3D1->Height  = dH;
  
  TPrinter* pPrn = Printer::Printer();

  pPrn->BeginDoc();
    pPrn->Canvas->BeginScene();
      TRectF ARect(  dLeft, dTop, dRight, dBottom );
      Viewport3D1->PaintTo( pPrn->Canvas, ARect, nullptr );
    pPrn->Canvas->EndScene();
  pPrn->EndDoc();

  // サイズを元に戻す
  Viewport3D1->Width   = nOldWidth;
  Viewport3D1->Height  = nOldHeight;
  Viewport3D1->Visible = true;

}

但し、Viewport3Dで作成できる画像のサイズは限りがある(10000x10000と言った画像は作れない)ので、プラットフォームによるが概ね縦横5000ピクセル以上になる場合は、作成に失敗することを念頭に設計する必要がある。