プリンタのデバイスコンテキストを取得するには

解決


ぞる  2002-03-19 01:18:50  No: 684  IP: [192.*.*.*]

プリンタのデバイスコンテキストを得るにはどうすればよいのでしょうか?
プリンタDCを参照DCとしてメタファイルを作成したいのです。

Delphiマガジンのバックナンバーには、
Printer.HandleでDCが得られるというようなことを書いていたと記憶しています
(立ち読みしただけなのではっきりとは覚えていません)。

しかしながら、Printer.Handleはプリンタのハンドルであって、
DCではないと思うのです。

自分では Printer.Canvas.Handle かなと思ったのですが、
どうしてもエラーになります。
もしかして、Printer.BeginDocを実行しないとDCが作成されないのでしょうか?

Delphiを始めて1週間程度の若輩者ですがどうぞ宜しくお願いします。

編集 削除
ruu  2002-03-19 07:51:26  No: 685  IP: [192.*.*.*]

HDCは 0でも構わないようです。
もしCanvasのHDCを使うなら、HDCを作成すればいいのでは?

------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  MyMetafile  : TMetafile;
  MyMetaCanvas: TMetafileCanvas;
  MyCanvas    : TCanvas;
  MyHDC       : HDC;
begin
  MyCanvas := Form1.Canvas;         // 描画対象のキャンバス
  MyMetafile := TMetafile.Create;   // MyMetafileを作成
  MyHDC := GetDC(MyCanvas.Handle);  // MyHDCを作成
  MyMetaCanvas := TMetafileCanvas.Create(MyMetafile, MyHDC); // MyMetaCanvasを作成
  with MyMetaCanvas do begin
    try
      Brush.Color := clFuchsia;
      Ellipse(0, 0, 100, 100);
    finally
      Free;                               // MyMetaCanvasを破棄
      ReleaseDC(MyCanvas.Handle, MyHDC);  // MyHDCを破棄
    end;
  end;
  MyCanvas.Draw(0, 0, MyMetafile);        // MyMetafileをMyCanvasに描画

  // MyMetafileに追加描画するには、MetafileCanvasを再作成する
  MyMetaCanvas := TMetafileCanvas.Create(MyMetafile, 0);  // HDCは0でも構わない
  with MyMetaCanvas do begin
    try
      Draw(0, 0, MyMetafile);      // 以前の描画実行
      Brush.Color := clAqua;
      FillRect(Rect(100, 100, 200, 200));
      Brush.Color := clBlue;
      Ellipse(100, 100, 200, 200);
    finally
      Free;
    end;
  end;
  MyCanvas.Draw(0, 0, MyMetafile);       // MyMetafileをMyCanvasに描画
end;
------------------------------------------------

編集 削除
にしの  2002-03-19 10:40:35  No: 686  IP: [192.*.*.*]

> しかしながら、Printer.Handleはプリンタのハンドルであって、
> DCではないと思うのです。

ヘルプで、TPriner.Handleを調べると、Handle: HDC;と書いてあります。ということは、DCだと思うのですが。
そこの例にもあるように、Printer.Handleに描くことで、印刷できます。

> もしかして、Printer.BeginDocを実行しないとDCが作成されないのでしょうか?
TPrinter.Canvasのヘルプには、
「グラフィック機能のないプリンタもあります。
そのようなプリンタでは Draw,StretchDraw,および CopyRect メソッドは無効です。」
とあります。
グラフィック機能が無い場合には使えません。
BeginDocに関しては、想像どおりだと思います。BeginDocしてから描画して、印刷するならEndDoc, キャンセルするならAbortになると思います。

編集 削除
ドック  2002-03-20 01:19:47  No: 687  IP: [192.*.*.*]

Printer.Handle プロパティは、Printer.Canvas の Handle プロパティと同じコンテキストハンドルですが…全く同じではありません。

Printer.Canvas.Handle … 常にプリンタDCを表わす。
Printer.Handle … 状況によって異なる。

Printer.Canvas へのアクセスは、BeginDoc 〜 EndDoc 間でのみ有効。
BeginDoc 〜 EndDoc 間で参照されると Printer.Handle は、Printer.Canvas.Handle と同じ働き。その他の所で使用すると、その値は情報コンテキストのハンドルを返す。

編集 削除
ぞる  2002-03-20 23:34:15  No: 688  IP: [192.*.*.*]

ruuさん、にしのさん、ドックさん、貴重なご意見ありがとうございます。

まずruuさんから
> HDCは 0でも構わないようです
はっきりと書かなかったのですが、印刷プレビューをやりたかったので
プリンタDCをメタファイルキャンバスのコンストラクタの引数として
渡したいのです。
> HDCを作成すればいいのでは?
確かにそうですね。昔VBでプリンタDCを作成した記憶があるので、
Delphiの練習のつもりでやってみます。

にしのさん
> ヘルプで、TPriner.Handleを調べると、Handle: HDC;と書いてあります
ヘルプはもちろん見たのですが、どうもよくわからなかったんです。
確かに、TPriner.Handleを参照DCとして渡してもエラーは出ませんでした。
Delphiのヘルプがどうもわかりづらいのは私だけでしょうか?

ドックさん
> Printer.Canvas.Handle … 常にプリンタDCを表わす。
> Printer.Handle … 状況によって異なる。
ここのところ(両者の違い)もお聞きしたかったんです。

総合的に考えると、
Printer.BeginDocは実行したくないので、
プリンタDCをAPIで作成したほうがいいかな。
もうちょっと簡単にできるかなと思っていたんですが、
すこし手間取りそうなかんじです。
いずれにせよ、ご意見をくださった方々ありがとうございました。

編集 削除
ぞる  2002-03-21 20:10:52  No: 689  IP: [192.*.*.*]

自己レスです。
メタファイルキャンバスの参照DCにプリンタDCを指定したい場合、
やはりPrinter.Handleで良いみたいです。

ドックさんが発言されたとおり、Printer.Handleは
Printer.BeginDocを実行する前は「情報コンテキスト」ハンドルなるものを
返すわけですが、この「情報コンテキスト」とは、DCとは異なり、描画(印刷)は
できませんが、デバイスドライバから情報を取得することができるようです。
つまり、read only なDCのようなものらしいです。

以上のことは、「Delphi Grahic Secrets」(中村拓男  著、ソフトバンク
パブリッシング)と言う本に書いてありました。この本はなかなかよさそうな
本でした。

編集 削除