Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2004年08月19日] [更新 2019年10月12日] Delphi サンプルプログラム集
014_プリンタ情報の保存と読出し
動作確認等 Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32
014_Save_PrinterProperty.zip [996 KB] 2019年10月12日版 (EXE 同梱)



  • 2019年10月12日 (これより前の履歴は省略)
  • Unicode 対応のため TMemoryStream を使用するコードに変更
    この変更により,以前のサンプルで保存したファイルを読み込んでも正常に取得できない




01_プリンタ情報の保存と読出し


プリンタのプロパティ設定のサンプルでは,プリンタのプロパティの設定方法を掲載していますが,これらの値はアプリケーションを終了すると元に戻ってしまいます.同じアプリケーションを起動しても,また設定し直さなければなりません.設定したプロパティを保存しておき,次回にも自動的に設定することができれば便利なこともあります.

次のサンプルはその 1 つの方法です.プリンタの設定ダイアログで設定した後,保存ボタンで適当に名前を付けて保存します.ここでは,拡張子を dev にしてあります.
保存したらプログラムを終了し,再度実行し,読出しボタンクリックします.プリンタ設定ダイアログで内容を確認すると,設定内容が再現されていることが確認できます.

もちろん,コードで用紙サイズ等を設定すれば,このような手間は必要ありません.このプロパティを全て保存する方法は,コードでは設定できない,プリンタドライバ固有の値も保存して再現できる利点があります.


図1
設計時画面
図2
実行画面
  • このダイアログで設定した内容を全て保存

リスト1
プリンタのプロパティの保存と読出し
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.Printers,
  Winapi.WinSpool;

type
  TForm1 = class(TForm)
    PrinterSetupDialog1: TPrinterSetupDialog;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    procedure DevModeSaveToFile(AFilePath: TFilename);
    procedure DevModeLoadFromFile(AFilePath: TFilename);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//-----------------------------------------------------------------------------
//  DevModeのサイズや他の情報を同時にファイルに読書きするため
//  プリンタ情報関係のレコード型定義
//-----------------------------------------------------------------------------
type
  TPrtInfo = record
    ADevice : array[0..MAX_PATH-1] of Char;  // プリンタ名の文字列
    ADriver : array[0..MAX_PATH-1] of Char;  // ドライバ名の文字列
    APort   : array[0..MAX_PATH-1] of Char;  // ポート名の文字列
    DevSize : DWORD;                         // DevMode構造体のサイズ
  end;
  PPrtInfo = ^TPrtInfo;

//=============================================================================
//  フォーム作成時にダイアログの各プロパティを設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  SaveDialog1.Filter     := 'プリンタ情報|*.dev';
  SaveDialog1.InitialDir := ExtractFileDir(Application.ExeName);

  OpenDialog1.DefaultExt := SaveDialog1.DefaultExt;
  OpenDialog1.Filter     := SaveDialog1.Filter;
  OpenDialog1.InitialDir := SaveDialog1.InitialDir;
end;

//=============================================================================
//  プリンタの設定ダイアログを表示
//  ここで設定した内容をファイルに保存する
//  また読み出した内容の確認用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  PrinterSetupDialog1.Execute;
end;

//=============================================================================
//  現在のプリンタの設定をディスクに保存
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  if SaveDialog1.Execute then begin
    DevModeSaveToFile(SaveDialog1.Filename);
  end;
end;

//=============================================================================
//  ディスクから保存したプリンタの設定を読出す
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  if OpenDialog1.Execute then begin
    DevModeLoadFromFile(OpenDialog1.Filename);
  end;
end;

//-----------------------------------------------------------------------------
//  現在のプリンタの情報をディスクに保存
//  このメソッドの前にプリンタの設定ダイアログで設定を変更している場合は,その
//  変更後の内容
//
//  Delphi7用のコードでは DEVMODE のサイズ取得に DocumentProperties を使用した
//  Delphi2009 Pro(UP3)では正常に取得できないので GlobalSize を使用
//-----------------------------------------------------------------------------
procedure TForm1.DevModeSaveToFile(AFilePath: TFilename);
var
  LPrtInfo   : TPrtInfo;
  LDevHandle : THandle;
  LPrtHandle : THandle;
  LpDevMode  : PDeviceMode;
  LStream    : TMemoryStream;
begin
  //プリンタの情報取得...
  Printer.GetPrinter(LPrtInfo.ADevice,
                     LPrtInfo.ADriver,
                     LPrtInfo.APort,
                     LDevHandle);
  OpenPrinter(LPrtInfo.ADevice, LPrtHandle, nil);

  // DEVMODE 構造体のデータの必要バイト数を取得
  LPrtInfo.DevSize := GlobalSize(LDevHandle);

  LStream := TMemoryStream.Create;
  try
    // ハンドル LDevHandleをロック.DevMode のポインタを取得
    LpDevMode := GlobalLock(LDevHandle);
    try
      // メモリストリームにプリンタ情報を書き込む
      LStream.Write(@LPrtInfo, SizeOf(LPrtInfo));
      // DEVMODE 構造体のデータをメモリストリームに書き込む

      // メモリストリームをファイルに保存
      LStream.Write(TDeviceMode(LpDevMode^), LPrtInfo.DevSize);
      LStream.SaveToFile(AFilePath);
    finally
      // ハンドル LDevHandle のロック解除
      GlobalUnLock(LDevHandle);
    end;
  finally
    FreeAndNil(LStream);
  end;

  ClosePrinter(LPrtHandle);
end;

//-----------------------------------------------------------------------------
//  ディスクに保存してあるプリンタの情報を読み出す
//  プリンタ情報とDevMode 構造体のデータは以下の様に取得する
//  ADevice   プリンタ名の文字列
//  ADriver   ドライバ名の文字列
//  APort     ポート名の文字列
//  LpDevMode  DEVMODE構造体
//
//  例  プリンタ名 : String(LPrtInfo.ADevice)
//  例  用紙サイズ番号 : LpDevMode.dmPaperSize 数値は Windows.pas 内の定数を参照
//
//  GMEM_MOVEABLE
//  移動可能メモリを割り当てる.戻り値はメモリオブジェクトのハンドル
//  ハンドルをポインタに変換するには GlobalLock関数を使用する
//  GMEM_ZEROINIT
//  メモリ内容を 0 に初期化する
//-----------------------------------------------------------------------------
procedure TForm1.DevModeLoadFromFile(AFilePath: TFilename);
var
  LPrtInfo   : TPrtInfo;
  LDevHandle : THandle;
  LpDevMode  : PDeviceMode;
  LStream    : TMemoryStream;
begin
  if not FileExists(AFilePath) then Exit;

  LStream := TMemoryStream.Create;
  try
    LStream.LoadFromFile(AFilePath);
    // メモリストリームからプリンタ情報レコード型のデータを読み出す
    LStream.Read(LPrtInfo, SizeOf(LPrtInfo));

    // 続いて DEVMOE 構造体のデータを読出す
    // メモリを初期化して移動可能で DevSize 分確保
    // LDevHandleは DevMode 構造体の分
    LDevHandle := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, LPrtInfo.DevSize);

    //メモリ領域ロックしてpDevModeのポインタを取得
    LpDevMode := GlobalLock(LDevHandle);
    try
      LStream.Read(LpDevMode^, LPrtInfo.DevSize);
    finally
      // ハンドル LDevHandle のロックを解除
      GlobalUnLock(LDevHandle);
    end;
  finally
    FreeAndNil(LStream);
  end;

  // 読出した ADevice,ADirver,APort でプリンタをセットする
  Printer.SetPrinter(LPrtInfo.ADevice,
                     LPrtInfo.ADriver,
                     LPrtInfo.APort,
                     LDevHandle);
end;

end.