Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2012年01月08日] [更新 2015年06月05日] Delphi サンプルプログラム集
017_通常使うプリンタを変更
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
017_ChangeDefaultPrinter.zip [2,224 KB] 2015年06月05日版 (EXE 同梱)



  • 2013年10月01日
  • WMI を使用したサンプルを追加




01_通常使うプリンタを変更


システムの「通常使うプリンタ」(デフォルトのプリンタ) をコードで変更するサンプルです。
プリンタの変更部分は関数にしてあります。使用している関数や構造体は、他のプリンタ関係のサンプルプログラムの記事の説明や MSDN オンラインの記事を参考にしてください。
この、通常使うプリンタを変更する関数は、管理者でログインしていないと設定に失敗します。

プリンタのプロパティも同時に変更するテストがありますが、注意が必要です。
プロパティを変更してしまうと、そのプロパティの値が、そのプリンタのデフォルトのプロパティとなってしまいます。他のアプリケーションでそのプリンタで使用している場合に設定の変更が必要となるような状況が発生します。

これを避けるには、通常使うプリンタだけを変更した後、[013_プリンタのプロパティ設定] [03_コードでプロパティを設定] のようなコードでプロパティを設定します。
そうすれば、そのプロパティの設定は、現在のアプリだけで有効な設定となります。

現在はどうなっているか分かりませんが、一部の帳票作成用コンポーネントでは、内部で通常使うプリンタを変更しているものがあります。ワードやエクセルもそうです。用紙等のプロパティが希望通りに設定できないことがあります。そのような場合、この関数であらかじめ通常使うプリンタのプロパティを設定して印刷するようにしておけば、希望通りの印刷が可能なことがあります。



図1
設計時画面
  • コンボボックスはプリンタ選択用
図2
実行時画面例
  • コンボボックスに表示されているプリンタを通常使うプリンタにする


リスト1
通常使うプリンタを変更する関数と、そのテストプログラム
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Select(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
    ADevice     : array[0..MAX_PATH - 1] of Char;
    ADriver     : array[0..MAX_PATH - 1] of Char;
    APort       : array[0..MAX_PATH - 1] of Char;
    ADeviceMode : THandle;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Printers, WinSpool;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  通常使うプリンタ(デフォルトのプリンタ)を変更する関数
//  ただし、管理者でログインしていないと設定できない
//  この関数を使用するには、usesにPrintersとWinSpoolが必要
//
//  PrinterName : プリンタ名の文字列
//  DevMode     : プリンタのプロパティも変更する場合のDEVMODE構造体
//                プロパティを変更しない場合はnilとする
//
//  この関数は、プロパティの設定にDocumentProperties関数ではなくPRINTER_INFO_2
//  構造体を使用している
//
//  この関数では、指定プリンタドライバのデータの取得にGetPrinterDriver関数を使
//  用しているが、DriverNameには
//  Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
//  で取得したADriverも使用可能(DelphiのPrinter.pas内の関数はプリンタ名も同時に
//  取得できる等、この意味で便利)
//  このplChangeDefaultPrinterでは、変更するプリンタ名とプロパティを引数にして
//  動作を独立するためにWindows APIのGetPrinterDriver関数を使用
//  また、ポート名もPRINTER_INFO_2でpPInfo2^.pPortNameで取得しているが、これも
//  Printer.GetPrinterの3番目の引数の値が使用可能
//-----------------------------------------------------------------------------
function plChangeDefaultPrinter(PrinterName: String; DevMode: PDeviceMode): Boolean;
var
  hPrinter       : THandle;
  PDefaults      : TPrinterDefaults;
  dwNeeded       : DWORD;
  pPInfo2        : PPrinterInfo2;
  pDrvInfo       : PDriverInfo2;
  DefaultPrinter : String;
  DriverName     : String;
begin
  //Windows APIでプリンタを操作するにはOpenPrinter関数をまず実行
  //アクセス権をPRINTER_ALL_ACCESSにして変更可能とする
  FillChar(PDefaults, SizeOf(PDefaults), 0);
  PDefaults.DesiredAccess := PRINTER_ALL_ACCESS;
  //プリンタの変更権限がない場合(一般ユーザ等)はOpenPrinterの実行に失敗する
  if not WinSpool.OpenPrinter(PChar(PrinterName), hPrinter, @PDefaults) then begin
    Result := False;
    exit;
  end;

  try
    //PRINTER_INFO_2構造体の配列に必要なバイト数を取得して確保
    WinSpool.GetPrinter(hPrinter, 2, nil, 0, @dwNeeded);
    GetMem(pPinfo2, dwNeeded);

    try
      //PRINTER_INFO_2構造体の値を取得して設定
      WinSpool.GetPrinter(hPrinter, 2, pPInfo2, dwNeeded, @dwNeeded);
      pPInfo2^.Attributes := pPInfo2^.Attributes or PRINTER_ATTRIBUTE_DEFAULT;

      //引数のDEVMODE構造体がnilでなければ、その値でプリンタを設定
      if DevMode <> nil then pPInfo2^.pDevMode := DevMode;
      WinSpool.SetPrinter(hPrinter, 2, pPInfo2, 0);


      //プリンタドライバのデータ構造体の配列に必要なバイト数を取得して確保
      GetPrinterDriver(hPrinter, nil, 2, nil, 0, dwNeeded);
      GetMem(pDrvInfo, dwNeeded);
      try
        //指定プリンタドライバのデータを取得
        GetPrinterDriver(hPrinter, nil, 2, pDrvInfo, dwNeeded, dwNeeded);
        //WriteProfileString関数の引数に渡す値を作成
        DriverName     := ExtractFileName(String(pDrvInfo^.pDriverPath));
        DriverName     := ChangeFileExt(DriverName, '');
        DefaultPrinter := String(pPInfo2^.pPrinterName) + ',' +
                          DriverName                    + ',' +
                          String(pPInfo2^.pPortName);
        //レジストリへ情報を書き込む
        //この関数は16bitとの互換性のためにあるが現在も使用可能なようだ
        Result := WriteProfileString('windows', 'device', PChar(DefaultPrinter));
      finally
        FreeMem(pDrvInfo);
      end;


      //変更をシステムに通知
      //WM_WININICHANGEも互換性のために残されているとあるが使用可能
      Result := not PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
    finally
      FreeMem(pPInfo2);
    end;
  finally
    ClosePrinter(hPrinter);
  end;
end;

//=============================================================================
//  プリンタのリストをコンボボックスにセット
//  PRINTER_INFO_4構造体から取得した方が正確
//  Printerオブジェクトから取得したプリンタ名と順番や内容が異なる場合がある
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.Clear;

  ComboBox1.Items.Assign(Printer.Printers);
  ComboBox1.ItemIndex := Printer.PrinterIndex;

  //選択したプリンタを初期化
  //ここでは通常使うプリンタとなっている
  ComboBox1Select(nil);
end;

//=============================================================================
//  TComboBoxのOnSelectイベント
//  プリンタを変更したらそのプリンタのデフォルト値で初期化
//  前のプリンタの設定値を引き継ぐことは原則的にできない
//=============================================================================
procedure TForm1.ComboBox1Select(Sender: TObject);
begin
  //選択したプリンタを現在のプリンタとする
  Printer.PrinterIndex := ComboBox1.ItemIndex;

  //ここで取得するADeviceMode1には、変更前のプリンタの情報が格納されている
  //その他の値は現在(変更後)のプリンタの情報となっている
  Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
  //ADeviceMode初期化
  Printer.SetPrinter(ADevice, ADriver, APort, 0);
  //現在のプリンタのデフォルト値情報を取得
  //ADeviceModeが新しいプリンタドライバの値となる
  Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
end;

//=============================================================================
//  plChangeDefaultPrinterの使用例
//  通常使うプリンタを変更するだけ
//  そのプリンタのプロパティは変更しない
//
//  ADevice, ADriver, APort, ADeviceModeはPrinter.GetPrinterで取得したもの
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  //ADeviceModeのメモリをロック
  GlobalLock(ADeviceMode);
  try
    //ADeviceがプリンタ名
    if not plChangeDefaultPrinter(ADevice, nil) then begin
      Application.MessageBox('設定には管理者権限が必要です。', 'プリンタの変更');
    end;
  finally
    GlobalUnlock(ADeviceMode);
  end;
end;

//=============================================================================
//  plChangeDefaultPrinterの使用例
//  通常使うプリンタを変更し、そのプリンタのプロパティも変更する場合
//
//  【重要な注意】
//  ここでプロパティの変更をすると、そのプリンタのデフォルトの設定がこの値にな
//  ってしまう。他のアプリからこのプリンタを使用する際には注意が必要
//  テストが終了したら、元に戻しておいた方が無難
//  日本の多くのプリンタのデフォルト値は
//    ADevMode^.dmPaperSize   := DMPAPER_A4;
//    ADevMode^.dmOrientation := DMORIENT_PORTRAIT;
//  となっている
//
//  ADevice, ADriver, APort, ADeviceModeはPrinter.GetPrinterで取得したもの
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  ADevMode : PDeviceMode;
begin
  //ADeviceModeのメモリをロックしDEVMODE構造体のポインタを取得
  ADevMode := GlobalLock(ADeviceMode);
  try
    //用紙サイズをB5に、印刷方向を横に設定
    //実際には、該当するプロパティをサポートしているかを確認してから設定する
    ADevMode^.dmPaperSize   := DMPAPER_B5;
    ADevMode^.dmOrientation := DMORIENT_LANDSCAPE;

    //ADeviceがプリンタ名
    if not plChangeDefaultPrinter(ADevice, ADevMode) then begin
      Application.MessageBox('設定には管理者権限が必要です。', 'プリンタの変更');
    end;
  finally
    GlobalUnlock(ADeviceMode);
  end;
end;

//=============================================================================
//  AdvancedDocumentProperties関数でプロパティダイアログを表示
//  設定の確認用
//  ADevice, ADriver, APort, ADeviceModeはPrinter.GetPrinterで取得したもの
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  ADevMode : PDeviceMode;
  hPrinter : THandle;
begin
  //ADeviceModeのメモリをロックしDEVMODE構造体のポインタを取得
  ADevMode := GlobalLock(ADeviceMode);

  try
    //対象のプリンタのハンドルを取得
    if WinSpool.OpenPrinter(ADevice, hPrinter, nil) then begin
      try
        AdvancedDocumentProperties(Handle, hPrinter, ADevice, ADevMode, ADevMode);
      finally
        //Openしたら閉じる
        ClosePrinter(hPrinter);
      end;
    end;
  finally
    //ロック解除
    GlobalUnlock(ADeviceMode);
  end;
  //なくても設定は行われるが、次回のGetPrinter実行時に反映されない場合がある
  Printer.SetPrinter(ADevice, ADriver, APort, ADeviceMode);
end;

end.




02_通常使うプリンタの変更  -  WMI を使用した方法


WMI の Win32_Printer クラスを使用すると、通常使用するプリンタを変更できます。
次のサンプルでは、タイプライブラリの取り込みでインポートした WbemScripting_TL.pas ファイルを使用して、通常使用するプリンタ名の取得と設定を行います。印刷ジョブのクリアのサンプルも追加しておきました。

本サンプルでは、ボタンクリックごとに WMI オブジェクトを生成し、WMI サービスに接続していますが、実際にはアプリの開始時に実行しておけば済みます。サンプルとして、グローパル変数を使用しないようにしているだけです。

プリンタの DEVMODE 構造体の値を操作するには、上のサンプルの TComboBox.OnSelect イベントと同じような処理が必要です。



図3
設計時画面
  • コンボボックスはプリンタ選択用
  • EXE を起動すると、コンボボックスには、通常使用するプリンタ名が表示される
図4
[通常使用するプリンタを取得]
  • コンボボックスの表示プリンタ名と同じ
図5
[通常使用するプリンタを変更]
  • コンボボックスで選択したプリンタ名を、通常使うプリンタにする
図6
[印刷ジョブを全てクリア]
  • インストールされている全てのプリンタの印刷ジョブをクリア
  • 各プリンタに印刷ジョブがあるかのチェックはしていない


リスト2
WMI を使用して通常使うプリンタを変更するサンプル
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Printers, WbemScripting_TLB, ActiveX;

{$R *.dfm}

//=============================================================================
//  プリンタのリストをコンボボックスにセット
//  PRINTER_INFO_4構造体から取得した方が正確
//  Printerオブジェクトから取得したプリンタ名と順番や内容が異なる場合がある
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.Clear;

  ComboBox1.Items.Assign(Printer.Printers);
  ComboBox1.ItemIndex := Printer.PrinterIndex;
end;

//=============================================================================
//  通常使用するプリンタ名を取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  objWMILocator  : ISWbemLocator;
  objWMIService  : ISWbemServices;
  objPropSet     : ISWbemObjectSet;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  strText        : String;
begin
  //Wbemのオブジェクトを生成
  objWMILocator := CoSWbemLocator.Create;

  //WMIサービスに接続。引数は必要に応じて設定
  objWMIService := objWMILocator.ConnectServer(
                     'Localhost',    //コンピュータ名。ローカルの場合は空白でも可
                     'root\cimv2',   //名前空間
                     '',             //ユーザ名。ローカルの場合は空文字にする
                     '',             //パスワード。ローカルの場合は空文字にする
                     '',             //ロケール識別子
                     '',             //ドメイン名
                     0,              //応答フラグ
                     nil);

  //クエリーを実行して、プロパティのセットのオブジェクトを取得
  objPropSet := objWMIService.ExecQuery(
                     'SELECT * FROM Win32_Printer Where Default = True',
                     'WQL',
                     wbemFlagForwardOnly,
                     nil);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := objPropSet._NewEnum as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    strText := '通常使用するプリンタは' + sLineBreak + String(ObjTemp.Name);
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);

    objTemp := Unassigned;
  end;
end;

//=============================================================================
//  通常使用するプリンタを変更
//  コンボボックスで選択中のプリンタにする
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  objWMILocator  : ISWbemLocator;
  objWMIService  : ISWbemServices;
  objPropSet     : ISWbemObjectSet;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  NewPrinterName : String;
  strText        : String;
begin
  //Wbemのオブジェクトを生成
  objWMILocator := CoSWbemLocator.Create;

  //WMIサービスに接続。引数は必要に応じて設定
  objWMIService := objWMILocator.ConnectServer(
                     'Localhost',    //コンピュータ名。ローカルの場合は空白でも可
                     'root\cimv2',   //名前空間
                     '',             //ユーザ名。ローカルの場合は空文字にする
                     '',             //パスワード。ローカルの場合は空文字にする
                     '',             //ロケール識別子
                     '',             //ドメイン名
                     0,              //応答フラグ
                     nil);

  //クエリーを実行して、プロパティのセットのオブジェクトを取得
  //クエリー文の中の変数は、" (ダブルクォーテーション)で囲む
  NewPrinterName := AnsiQuotedStr(ComboBox1.Items[ComboBox1.ItemIndex], '"');
  objPropSet := objWMIService.ExecQuery(
                     'SELECT * FROM Win32_Printer Where Name = ' + NewPrinterName,
                     'WQL',
                     wbemFlagForwardOnly,
                     nil);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := objPropSet._NewEnum as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //クエリーの結果のオブジェクトを取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    objTemp.SetDefaultPrinter;
    objTemp := Unassigned;

    strText := '通常使用するプリンタを変更';
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);
  end;
end;

//=============================================================================
//  全てのプリンタの印刷ジョブをクリア
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  objWMILocator  : ISWbemLocator;
  objWMIService  : ISWbemServices;
  objPropSet     : ISWbemObjectSet;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  strText        : String;
begin
  //Wbemのオブジェクトを生成
  objWMILocator := CoSWbemLocator.Create;

  //WMIサービスに接続。引数は必要に応じて設定
  objWMIService := objWMILocator.ConnectServer(
                     'Localhost',    //コンピュータ名。ローカルの場合は空白でも可
                     'root\cimv2',   //名前空間
                     '',             //ユーザ名。ローカルの場合は空文字にする
                     '',             //パスワード。ローカルの場合は空文字にする
                     '',             //ロケール識別子
                     '',             //ドメイン名
                     0,              //応答フラグ
                     nil);

  //クエリーを実行して、プロパティのセットのオブジェクトを取得
  objPropSet := objWMIService.ExecQuery(
                     'SELECT * FROM Win32_Printer',
                     'WQL',
                     wbemFlagForwardOnly,
                     nil);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := objPropSet._NewEnum as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //クエリーの結果のオブジェクトを取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    objTemp.CancelAllJobs;

    strText := String(objTemp.Name) + sLineBreak + ' の印刷ジョブをクリア';
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);

    objTemp := Unassigned;
  end;
end;

end.




03_通常使うプリンタの変更  -  WMI を OleVariant 型で扱う


WMI のインスタンスを CreateOleObject で生成して、通常使用するプリンタを変更します。
COM オブジェクトのインスタンスを CreateOleObject で生成して、OleVariant 型で扱うと、タイプライブラリの取り込みで作成したファイルが必要ありません。ただし、WbemScripting_TL.pas を使用しない場合は、定数名が使えません。自分で定義して使用することになります。

定数名の実際の値は、WbemScripting_TL.pas 内に定義があります。これを参考にします。
WbemScripting_TL.pas の使用の有無にかかわらず、WbemScripting_TL.pas を作成しておくと、開発には便利です。

実行結果は上のサンプルと全く同じです。
本サンプルでも、ボタンクリックごとに WMI オブジェクトを生成し、WMI サービスに接続していますが、実際にはアプリの開始時に実行しておけば済みます。サンプルとして、グローパル変数を使用しないようにしているだけです。


リスト3
WMI を CreateOleObject で生成して、通常使うプリンタを変更する例
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Printers, ComObj, ActiveX;

{$R *.dfm}

//=============================================================================
//  プリンタのリストをコンボボックスにセット
//  PRINTER_INFO_4構造体から取得した方が正確
//  Printerオブジェクトから取得したプリンタ名と順番や内容が異なる場合がある
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.Clear;

  ComboBox1.Items.Assign(Printer.Printers);
  ComboBox1.ItemIndex := Printer.PrinterIndex;
end;

//=============================================================================
//  通常使用するプリンタ名を取得
//
//  WbemScripting_TLBを使用しないので、定数名は定義して使用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
const
  wbemFlagForwardOnly = $00000020;
var
  objWMILocator  : OleVariant;
  objWMIService  : OleVariant;
  objPropSet     : OleVariant;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  strText        : String;
begin
  //WMIオブジェクトを生成
  ObjWMILocator := CreateOleObject('WbemScripting.SWbemLocator');

  //WMIサービスに接続
  //第1引数はコンピュータ名(Localhostまたは空白なら自分のマシン)
  ObjWMIService := ObjWMILocator.ConnectServer('Localhost', 'root\CIMV2');

  //クエリーの実行
  objPropSet := objWMIService.ExecQuery(
    'SELECT * FROM Win32_Printer Where Default = True', 'WQL', wbemFlagForwardOnly);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := IUnknown(objPropSet._NewEnum) as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    strText := '通常使用するプリンタは' + sLineBreak + String(ObjTemp.Name);
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);

    objTemp := Unassigned;
  end;
end;

//=============================================================================
//  通常使用するプリンタを変更
//  コンボボックスで選択中のプリンタにする
//
//  WbemScripting_TLBを使用しないので、定数名は定義して使用
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
const
  wbemFlagForwardOnly = $00000020;
var
  objWMILocator  : OleVariant;
  objWMIService  : OleVariant;
  objPropSet     : OleVariant;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  NewPrinterName : String;
  strText        : String;
begin
  //WMIオブジェクトを生成
  ObjWMILocator := CreateOleObject('WbemScripting.SWbemLocator');

  //WMIサービスに接続
  //第1引数はコンピュータ名(Localhostまたは空白なら自分のマシン)
  ObjWMIService := ObjWMILocator.ConnectServer('Localhost', 'root\CIMV2');

  //クエリーの実行
  //クエリー文の中の変数は、" (ダブルクォーテーション)で囲む
  NewPrinterName := AnsiQuotedStr(ComboBox1.Items[ComboBox1.ItemIndex], '"');
  objPropSet := objWMIService.ExecQuery(
                  'SELECT * FROM Win32_Printer Where Name = ' + NewPrinterName,
                  'WQL',
                  wbemFlagForwardOnly);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := IUnknown(objPropSet._NewEnum) as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //クエリーの結果のオブジェクトを取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    objTemp.SetDefaultPrinter;
    objTemp := Unassigned;

    strText := '通常使用するプリンタを変更';
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);
  end;
end;

//=============================================================================
//  全てのプリンタの印刷ジョブをクリア
//
//  WbemScripting_TLBを使用しないので、定数名は定義して使用
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
const
  wbemFlagForwardOnly = $00000020;
var
  objWMILocator  : OleVariant;
  objWMIService  : OleVariant;
  objPropSet     : OleVariant;
  objPropSetEnum : IEnumVariant;
  objTemp        : OleVariant;
  iValue         : LongWord;
  strText        : String;
begin
  //WMIオブジェクトを生成
  ObjWMILocator := CreateOleObject('WbemScripting.SWbemLocator');

  //WMIサービスに接続
  //第1引数はコンピュータ名(Localhostまたは空白なら自分のマシン)
  ObjWMIService := ObjWMILocator.ConnectServer('Localhost', 'root\CIMV2');

  //クエリーの実行
  objPropSet := objWMIService.ExecQuery(
          'SELECT * FROM Win32_Printer', 'WQL', wbemFlagForwardOnly);


  //プロパティのセットのコレクションを取得
  objPropSetEnum := IUnknown(objPropSet._NewEnum) as IEnumVariant;

  //-------------------------------------------------------------------------
  //  以下がプロパティの取得または操作コード
  //-------------------------------------------------------------------------

  //クエリーの結果のオブジェクトを取り出す
  while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
    objTemp.CancelAllJobs;

    strText := String(objTemp.Name) + sLineBreak + ' の印刷ジョブをクリア';
    MessageBox(Handle, PChar(strText), '結果', MB_ICONINFORMATION);

    objTemp := Unassigned;
  end;
end;

end.




04_実行時に使用するプリンタの指定


Delphi のアプリケーションで使用するプリンタは、Printer.PrinterIndex の値にプリンタの番号を指定すると設定できます。
「通常使用するプリンタ」を使用したい場合は、通常使用するプリンタの番号が不明でも、次のサンプルコードのように、Printer.PrinterIndex := -1; を実行すると設定できます。
この時、Printer.PrinterIndex プロパティには、-1 という値ではなく、実際の「通常使用するプリンタ」の番号が代入されます。


図7
実行時に使用するプリンタの指定とその結果

リスト4
実行時に使用するプリンタの指定とその設定結果を確認
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    ADevice     : array[0..MAX_PATH - 1] of Char;
    ADriver     : array[0..MAX_PATH - 1] of Char;
    APort       : array[0..MAX_PATH - 1] of Char;
    ADeviceMode : THandle;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  Printers;

{$R *.dfm}

//=============================================================================
//  使用するプリンタを設定・取得
//  usesにPrintersが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LPrtIndex    : Integer;
  LPrinterName : String;
  LTheText     : String;
begin
  //-1にすると通常使用するブリンタのインデックスになる
  Printer.PrinterIndex := -1;
  //改めて通常使用するプリンタ(デフォルトのプリンタ)のインデックスを取得
  LPrtIndex := Printer.PrinterIndex;

  //そのインデックスのプリンタ名を取得
  LPrinterName := Printer.Printers[LPrtIndex];
  //実際のインデックスの値とプリンタ名を表示
  LTheText := IntToStr(LPrtIndex) + sLineBreak + LPrinterName;
  MessageBox(Handle, PChar(LTheText), '結果', MB_ICONINFORMATION);

  //実際のプリンタの切り換えには以下のコードが必要
  //コードの動作については他のサンプルのコメントを参照
  Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
  Printer.SetPrinter(ADevice, ADriver, APort, 0);
  //以下はDEVMODEを操作する必要がなければ不要(慣習的に実行した方がいいかも知れない)
  Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
end;

end.