プリンタ一覧、用紙サイズ一覧、用紙情報の取得 ~Delphiソースコード集
TPrinterクラスのインスタンスであるPrinterオブジェクトを使用するとプリンタに印刷することが出来ます。
プリンタに出力する前に出力先の情報(解像度、印刷可能領域の幅/高さ、印刷不可領域など)を取得する方法等も含めて解説します。
プリンタを扱うには Uses に Vcl.Printers, WinApi.WinSpool を追加してください。
uses Vcl.Printers, WinApi.WinSpool;
プリンタの一覧取得や使用するプリンタ設定
プリンタの一覧取得や使用するプリンタを設定するには以下を使います。
取得したい値 | 取得方法 |
---|---|
プリンタの数の取得 | Printer.Printers.Count |
プリンタ名一覧 |
Printer.Printers[ インデックス ] インデックスは 0 ~ Printer.Printers.Count-1 |
使用プリンタ設定 |
Printer.PrinterIndex := インデックス; インデックスは 0 ~ Printer.Printers.Count-1 |
用紙サイズ一覧と用紙サイズ設定
現在のプリンタの用紙サイズ一覧の取得や用紙サイズ設定は以下を使います。
取得したい値 | 取得方法 |
---|---|
用紙サイズ一覧 |
以下ソースコードで 動的配列 PaperNo[0 ~ PaperCount-1] に用紙サイズ番号、 動的配列 PaperName[0 ~ PaperCount-1)] に用紙サイズの文字列(A4、A3など) が取得できます。 現在設定されている出力先プリンタによって英語だったり日本語だったり表記が違います。 各プリンタドライバに依存しているのかもしれません。 type TPaperName = array[0..63] of Char; //静的配列はスタックメモリ var Device, Driver, Port: array[0..255] of char;//静的配列はスタックメモリ DeviceModeHandle: THandle; PMode : PDevMode; PaperCount, i:Integer; PaperNo:Array of WORD; //動的配列はヒープメモリ PaperName:Array of TPaperName; //動的配列はヒープメモリ begin //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try //第4引数が nil の場合は用紙の数が返る PaperCount := DeviceCapabilities(Device, Port, DC_PAPERS, nil, PMode); if PaperCount>0 then begin SetLength(PaperNo,PaperCount); SetLength(PaperName,PaperCount); //用紙サイズ番号を取得 DeviceCapabilities(Device, Port, DC_PAPERS, PChar(@PaperNo[0]), PMode); //用紙サイズ名を取得 DeviceCapabilities(Device, Port, DC_PAPERNAMES, PChar(@PaperName[0]), PMode); end; finally GlobalUnlock(DeviceModeHandle); end; end; |
用紙サイズ番号取得 |
var Device, Driver, Port: array[0..255] of char; DeviceModeHandle: THandle; PMode : PDevMode; begin //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try Showmessage('用紙サイズ番号:'+IntToStr(PMode.dmPaperSize)); finally GlobalUnlock(DeviceModeHandle); end; end; |
用紙サイズ設定 |
以下ソースコードで pMode.dmPaperSize := DMPAPER_B4; とすることで用紙を設定できます。 (参考)用紙サイズ番号は定数定義されています。 例えばDMPAPER_B4=13(用紙サイズ番号13)、DMPAPER_A4=9(用紙サイズ番号9) var Device, Driver, Port: array[0..255] of char;//静的配列はスタックメモリ DeviceModeHandle: THandle; PMode : PDevMode; begin //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try //用紙サイズ変更フラグを設定 PMode.dmFields := PMode.dmFields or DM_PAPERSIZE; //用紙サイズを変更 pMode.dmPaperSize := DMPAPER_A3; finally GlobalUnlock(DeviceModeHandle); end; //プリンタに用紙サイズを設定 Printer.SetPrinter(Device,Driver,Port,DeviceModeHandle); end; |
現在のプリンタの現在の用紙情報の取得
現在のプリンタの現在の用紙情報は以下のように取得することが出来ます。
取得したい値 | 取得方法 |
---|---|
用紙の物理幅(px) | GetDeviceCaps(Printer.Handle, PHYSICALWIDTH) |
用紙の物理高さ(px) | GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT) |
左上印刷不可X(px) | GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX) |
左上印刷不可Y(px) | GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY) |
解像度X(dpi) | GetDeviceCaps(Printer.Handle, LOGPIXELSX) |
解像度Y(dpi) | GetDeviceCaps(Printer.Handle, LOGPIXELSY) |
印刷可能幅(px) | GetDeviceCaps(Printer.Handle, HORZRES) 又は Printer.PageWidth |
印刷可能高さ(px) | GetDeviceCaps(Printer.Handle, VERTRES) 又は Printer.PageHeight |
用紙の方向 |
Printer.Orientation 以下のどちらかの値が入っている
として用紙の方向を設定することも可能。 |
上記の値と用紙との関係は以下です。
用紙の物理幅(px)
印刷可能高さ(px)
単位は全て px です。
例えば以下をミリメートル(mm)に変換する場合
- 用紙の物理幅 = 4960px
- 用紙の物理高さ = 7014px
- 左上印刷不可X = 120px
- 左上印刷不可Y = 120px
- 印刷可能幅 = 4720px
- 印刷可能高さ = 6774px
- 右下印刷不可X = 4960-120-4720 = 120px
- 右下印刷不可Y = 7014-120-6774 = 120px
- 解像度X = 600dpi
- 解像度Y = 600dpi
1インチ = 25.4ミリメートル(mm)、単位dpi = ドット(ピクセル)/インチ なので
ピクセル÷解像度×25.4 でミリメートルに変換できます。
- 用紙の物理幅 = 4960px ÷ 600dpi × 25.4 = 209.97mm
- 用紙の物理高さ = 7014px ÷ 600dpi × 25.4 = 296.93mm
- 左上印刷不可X = 120px ÷ 600dpi × 25.4 = 5.08mm
- 左上印刷不可Y = 120px ÷ 600dpi × 25.4 = 5.08mm
- 印刷可能幅 = 4720px ÷ 600dpi × 25.4 = 199.81mm
- 印刷可能高さ = 6774px ÷ 600dpi × 25.4 = 286.77mm
- 右下印刷不可X = 120px ÷ 600dpi × 25.4 = 5.08mm
- 右下印刷不可Y = 120px ÷ 600dpi × 25.4 = 5.08mm
用紙左上から(x=20mm, y=40mm)の位置を印刷不可範囲を考慮してピクセルに換算するには
(20mm÷25.4×600dpi-120px, 40mm÷25.4×600dpi-120px) = (352px, 825px)
となります。
プリンタ・用紙サイズ一覧取得と設定、用紙情報取得アプリケーションを作成
プロジェクトの作成と画面設計
Delphiを起動し、メニューから「ファイル」⇒「新規作成」⇒
「Windows VCLアプリケーション -Delphi(W)」をクリックしてプロジェクトを作成します。
「TListBox」×2個、「TRadioGroup」×1個、「TMemo」×1個をフォームにドラッグ&ドロップします。

ソースコードの記述とプロパティ設定
F12を押して「コード」モードに切り替えて、以下ソースコードをコピー&ペースとします。
F12を押して「デザイン」モードに切り替えて、左下ペイン「オブジェクト インスペクタ」を「イベント」タブに切り替えて
Form1.OnCreate イベントプロパティ に FormCreate を設定します。
ListBox1.OnClick イベントプロパティ に ListBox1Click を設定します。
ListBox2.OnClick イベントプロパティ に ListBox2Click を設定します。
RadioGroup1Click イベントプロパティ に RadioGroup1Click を設定します。
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; type TForm1 = class(TForm) ListBox1: TListBox; ListBox2: TListBox; RadioGroup1: TRadioGroup; Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure ListBox1Click(Sender: TObject); procedure ListBox2Click(Sender: TObject); procedure RadioGroup1Click(Sender: TObject); private { Private 宣言 } //現在のプリンタの現在の用紙情報を取得 procedure GetPaperInfo(); //現在のプリンタの用紙サイズ一覧を取得 procedure GetPapersList(); public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} uses Vcl.Printers, WinApi.WinSpool; procedure TForm1.FormCreate(Sender: TObject); var i:Integer; begin //プリンターの一覧を取得 for i := 0 to Printer.Printers.Count-1 do ListBox1.AddItem(Printer.Printers[i],nil); ListBox1.ItemIndex:=Printer.PrinterIndex; //用紙方向 RadioGroup1.Caption:='用紙方向'; RadioGroup1.Items.Add('縦(Portrait)'); RadioGroup1.Items.Add('横(Landscape)'); RadioGroup1.ItemIndex:=0; //現在のプリンタの用紙サイズ一覧を取得 GetPapersList(); //現在のプリンタの現在の用紙情報を取得 GetPaperInfo(); end; //現在のプリンタの現在の用紙情報を取得 procedure TForm1.GetPaperInfo; var Device, Driver, Port: array[0..255] of char; DeviceModeHandle: THandle; PMode : PDevMode; begin Memo1.Clear; Memo1.Lines.Add('用紙の物理幅:' + IntToStr(GetDeviceCaps(Printer.Handle, PHYSICALWIDTH))+'px'); Memo1.Lines.Add('用紙の物理高さ:' + IntToStr(GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT))+'px'); Memo1.Lines.Add('左上印刷不可X:' + IntToStr(GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX))+'px'); Memo1.Lines.Add('左上印刷不可Y:' + IntToStr(GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY))+'px'); Memo1.Lines.Add('解像度X:' + IntToStr(GetDeviceCaps(Printer.Handle, LOGPIXELSX))+'dpi'); Memo1.Lines.Add('解像度Y:' + IntToStr(GetDeviceCaps(Printer.Handle, LOGPIXELSY))+'dpi'); Memo1.Lines.Add('印刷可能幅:' + IntToStr(GetDeviceCaps(Printer.Handle, HORZRES))+'px'); Memo1.Lines.Add('印刷可能高さ:' + IntToStr(GetDeviceCaps(Printer.Handle, VERTRES))+'px'); Memo1.Lines.Add('印刷可能幅:' + IntToStr(Printer.PageWidth) +'px'); Memo1.Lines.Add('印刷可能高さ:' + IntToStr(Printer.PageHeight)+'px'); if Printer.Orientation=TPrinterOrientation.poPortrait then Memo1.Lines.Add('用紙方向:縦') else Memo1.Lines.Add('用紙方向:横'); //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try Memo1.Lines.Add('用紙サイズ番号:'+IntToStr(PMode.dmPaperSize)); finally GlobalUnlock(DeviceModeHandle); end; end; //現在のプリンタの用紙サイズ一覧を取得 procedure TForm1.GetPapersList; type TPaperName = array[0..63] of Char; //静的配列はスタックメモリ var Device, Driver, Port: array[0..255] of char;//静的配列はスタックメモリ DeviceModeHandle: THandle; PMode : PDevMode; PaperCount, i:Integer; PaperNo:Array of WORD; //動的配列はヒープメモリ PaperName:Array of TPaperName; //動的配列はヒープメモリ begin ListBox2.Clear; //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try //第4引数が nil の場合は用紙サイズの数が返る PaperCount := DeviceCapabilities(Device, Port, DC_PAPERS, nil, PMode); if PaperCount>0 then begin SetLength(PaperNo,PaperCount); SetLength(PaperName,PaperCount); //用紙サイズ番号を取得 DeviceCapabilities(Device, Port, DC_PAPERS, PChar(@PaperNo[0]), PMode); //用紙サイズ名を取得 DeviceCapabilities(Device, Port, DC_PAPERNAMES, PChar(@PaperName[0]), PMode); for i := 0 to PaperCount-1 do ListBox2.AddItem(IntToStr(PaperNo[i])+'='+ PaperName[i], nil); end; finally GlobalUnlock(DeviceModeHandle); end; if ListBox2.Items.Count>0 then begin ListBox2.ItemIndex:= ListBox2.Items.IndexOfName( IntToStr(PMode.dmPaperSize) ); end; end; //ListBox1(プリンタ)クリック時 procedure TForm1.ListBox1Click(Sender: TObject); begin Printer.PrinterIndex:=ListBox1.ItemIndex; //現在のプリンタの用紙サイズ一覧を取得 GetPapersList; //現在のプリンタの現在の用紙情報を取得 GetPaperInfo(); end; //ListBox2(用紙サイズ)クリック時 procedure TForm1.ListBox2Click(Sender: TObject); var Device, Driver, Port: array[0..255] of char; DeviceModeHandle: THandle; PMode : PDevMode; begin //現在のプリンタのDeviceModeハンドルを取得 Printer.GetPrinter(Device, Driver, Port, DeviceModeHandle); if DeviceModeHandle = 0 then exit; //DeviceModeハンドルからDevMode構造体のポインタを取得 PMode := GlobalLock(DeviceModeHandle); try //用紙サイズ変更フラグを設定 pMode.dmFields := pMode.dmFields or DM_PAPERSIZE; //用紙サイズを変更 pMode.dmPaperSize := StrToInt( ListBox2.Items.Names[ListBox2.ItemIndex] ); finally GlobalUnlock(DeviceModeHandle); end; //プリンタに用紙を設定 Printer.SetPrinter(Device,Driver,Port,DeviceModeHandle); //現在のプリンタの現在の用紙情報を取得 GetPaperInfo(); end; //RadioGroup1(用紙方向)クリック時 procedure TForm1.RadioGroup1Click(Sender: TObject); begin if RadioGroup1.ItemIndex=0 then Printer.Orientation:=TPrinterOrientation.poPortrait else Printer.Orientation:=TPrinterOrientation.poLandscape; //現在のプリンタの現在の用紙情報を取得 GetPaperInfo(); end; end.
実行する
メニューから「実行」⇒「実行」をクリックするとコンパイルと実行が行われます。
ListBox1にプリンタの一覧が表示され、現在のプリンタが選択されます。
ListBox1に現在のプリンタの用紙サイズの一覧が表示され、現在の用紙サイズが選択されます。
Memo1に現在のプリンタの現在の用紙の情報が表示されます。
