喫茶XRAYトップページ

[▲前のスレッド]

[9521] プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/8 (金) 15:38:29 taki
マスター お世話になります。
サンプルプログラム集
「011_プリンタドライバの情報をDEVMODE構造体から取得」での質問です。

やりたい事はPrinterSetupDialogを表示して「用紙サイズ」(種類)を変更したり
「印刷の向き」を変更することで変更された用紙の大きさ(縦・横の長さ)を
得て印刷データの行数を決めたいのです。

dmOrientation,dmPaperSize,dmPaperLength,dmPaperWidthの情報がそれらに
該当するのですが、
サンプルに同梱されている「DEVMODE_Structure.exe」で試したところ

A4縦 → portrait,A4,2970,2100(初期値)
A4横 → landscape,A4,2970,2100
再度 A4横 → landscape,A4,2970,2100
A4縦 → portrait,A4,2970,2100
となります。縦と横の長さが入れ替わるかなと予想したのですが、
そうではないようです。

次に用紙のサイズ(種類)を変更したところ
B5縦 → portrait,B5,2970,2100 (A4用紙の長さが残る?)
再度 B5縦 → portrait,B5,2570,1820 (B5に直った)
となりました。

A4縦 → portrait,A4,2570,1820 (B5用紙の長さが残る?)
再度 A4縦 → portrait,A4,2970,2100 (A4に直った)

どうやらdmPaperLength,dmPaperWidthの情報は直ちには反映されない
ようなのですが、これは仕様?なのでしょうか。
それとも私のPCもしくはプリンタードライバーだけの現象なのでしょうか。

環境 Windows7 Pro,Delphi XE4 Starter,Canon MG5430


[9522] Re:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/8 (金) 18:39:42 Mr.XRAY
▼ takiさん,どうもです.

> どうやらdmPaperLength,dmPaperWidthの情報は直ちには反映されない
> ようなのですが、これは仕様?なのでしょうか。
> それとも私のPCもしくはプリンタードライバーだけの現象なのでしょうか。


[01_プリンタドライバの情報を DEVMODE 構造体から取得 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/011_DEVMODE_Structure.htm#01

これですね.ちょっと時間ください.


[9523] Re2:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/8 (金) 22:44:35 taki
▼ Mr.XRAYさん
 
> [01_プリンタドライバの情報を DEVMODE 構造体から取得 ]
> http://mrxray.on.coocan.jp/Delphi/plSamples/011_DEVMODE_Structure.htm#01
>
> これですね.ちょっと時間ください.


マスター ご迷惑をおかけしてすみません。<m(__)m>

私のPCの環境のせいではないのですね。

それなら、用紙のサイズ(種類)と向きはリアルタイムに取得できるので、
それらの情報から用紙の縦と横の長さを得ることにします。

つまり、A4なら2970,2100、B5なら2570,1820といった感じで。
その他の用紙は印刷不可ということで回避します。

おさがわせしました。



[9525] Re3:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/9 (土) 11:01:34 taki
理由はわかりませんが、PrinterSetupDialogの後にPrintDialogを
呼び出すと用紙の長さが変わります。(正常になります。)

procedure TForm1.Button3Click(Sender: TObject);
var
  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;
  ADevMode    : PDeviceMode;

begin
  if PrinterSetupDialog1.Execute then begin
    // 縦の長さを得る
    Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
    ADevMode := GlobalLock(ADeviceMode);
    try
      label1.Caption := inttostr(ADevMode^.dmPaperLength);
    finally
      GlobalUnlock(ADeviceMode);
    end;

    // 必要ないけどPrintDialogを開く
    PrintDialog1.Execute;

    // もう一度縦の長さを得る
    Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
    ADevMode := GlobalLock(ADeviceMode);
    try
      label4.Caption := inttostr(ADevMode^.dmPaperLength);
    finally
      GlobalUnlock(ADeviceMode);
    end;
  end;
end;

まあ、これでもいいかな?


[9526] Re4:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/9 (土) 14:50:34 Mr.XRAY
▼ takiさん,どうもです.

> 理由はわかりませんが、PrinterSetupDialogの後にPrintDialogを
> 呼び出すと用紙の長さが変わります。(正常になります。)
>
> まあ、これでもいいかな?


taki さんの書き込みがあったので,今,ちょっと考えています.
[011] のサンプルにはちょっと問題があるんです.
これは,前から分かっていることなんですが,
私は,誤字脱字の名人なので... 慎重にと思っています.


[9532] Re5:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/11 (月) 07:31:51 Mr.XRAY
> これは,前から分かっていることなんですが,
> 私は,誤字脱字の名人なので... 慎重にと思っています.


第一段階終了しました.
実際に DEVMODE の値を取得して表示する部分を別ルーチンにしました.
もうちょっとお待ちくださいませ.
taki さん用というわけではなく,利用される方皆さん用ですので (^^;


[9533] Re6:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/11 (月) 08:44:48 taki
▼ Mr.XRAYさん
 
> 第一段階終了しました.
> 実際に DEVMODE の値を取得して表示する部分を別ルーチンにしました.
> もうちょっとお待ちくださいませ.
> taki さん用というわけではなく,利用される方皆さん用ですので (^^;


ありがとうございます。(T_T)/


[9534] Re:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/11 (月) 09:29:48 Mr.XRAY
> やりたい事はPrinterSetupDialogを表示して「用紙サイズ」(種類)を変更したり
> 「印刷の向き」を変更することで変更された用紙の大きさ(縦・横の長さ)を
> 得て印刷データの行数を決めたいのです。


今読み直してみたんですが,
実は [011] のサンプルは,DEVMODE 構造体から取得可能な値をリストするものです.

dmPaperLength, dmPaperWidth はユーザ定義サイズの値です.
dmPaperLength は,縦向きの時の用紙の長さ,
dmPaperWidth は,縦向きの時の用紙の幅です.

で,印刷の時の用紙のサイズの取得は,

[012_プリンタの解像度と用紙サイズ等の取得]
http://mrxray.on.coocan.jp/Delphi/plSamples/012_PrintResolution.htm

を参考にしてくださいませ.
意味が違っていたらゴメンなさいです.


[9535] Re2:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/11 (月) 19:19:50 taki
▼ Mr.XRAYさん
 
> 今読み直してみたんですが,
> 実は [011] のサンプルは,DEVMODE 構造体から取得可能な値をリストするものです.
>


> で,印刷の時の用紙のサイズの取得は,
>
> [012_プリンタの解像度と用紙サイズ等の取得]
> http://mrxray.on.coocan.jp/Delphi/plSamples/012_PrintResolution.htm
>
> を参考にしてくださいませ.
> 意味が違っていたらゴメンなさいです.


マスター 誠にすみません。
マスターのご指摘のように
GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);で
常に正しい情報を得ることができました。

それと、私がしくじった原因も報告します。

以下のコードで試しました。

uses Printers;

procedure TForm1.GetNagasa;
var
  TempInt,YDPI: Integer;
  TempDouble  : Double;
begin
  YDPI  := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
  TempInt    := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);
  TempDouble := TempInt * 25.4 / YDPI;
  label2.Caption := Format('%8.1f [mm]', [TempDouble]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//  Printer.PrinterIndex := -1;  // ←間違った使い方1
  if PrinterSetupDialog1.Execute then begin
  // OKで閉じるまでに用紙の種類を変更する
    GetNagasa;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
//  Printer.PrinterIndex := -1;  // ←間違った使い方2
  GetNagasa;
end;

確実にデフォルトのプリンターを使おうとしてPrinterIndex := -1;を
コーディングしたのが間違いでした。

色々試した結果、PrinterIndex := -1;とすると、デフォルトの
プリンターが選ばれるだけでなく、デフォルトの状態も設定されるようです。
つまり私の環境の場合、
プリンター名 「Canon MG5400 series Printer」
用紙サイズ 「A4」
印刷の向き 「縦」
に戻ってしまうようです。

それぞれの間違った使い方のコードが有効な状態で試すと
Button1をClickすると、PrinterSetupDialogを開くたびにA4・縦になる。
しかし、用紙の縦の長さは変化する。(変更した正しい長さになる。)
Button2をClickすると、常にA4用紙の縦の長さ297mmに戻ってしまう。

それぞれのコードをコメントアウトすると
Button1をClickすると、PrinterSetupDialogは以前の状態が保持されている。
変更した用紙の紙の長さも正常に表示される。
Button2をClickしても、用紙の紙の長さは変わらない。

出入り禁止にはしないでください。m(__)m


[9536] Re3:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/11 (月) 20:50:28 Mr.XRAY
▼ takiさん

> 色々試した結果、PrinterIndex := -1;とすると、デフォルトの
> プリンターが選ばれるだけでなく、デフォルトの状態も設定されるようです。


今後使用する状況があるかどうか分かりせんが,以下のようになっています.
これは,実は,問題になることがあるんです.
今回のこととは直接関係ありませんが,プリンタ関係を扱う場合の参考として.

  //現在のプリンタを指定したプリンタにする
  //-1 を代入した場合は,-1 になるのではなく,デフォルトのプリンタの番号
  //が代入される
  Printer.PrinterIndex := プリンタ番号(整数値);

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

プリンタを変更して,DEVMODE 構造体で設定する場合は,上のコードの後に書きます.
上の 3 行を実行しないと,正常に設定されないことがあります.
(昔は,この手の質問がいっぱいあったんですよね --- 遠い目)
 

> 出入り禁止にはしないでください。m(__)m

え ? 何か悪いことしました ??


[9537] Re4:プリンタドライバの情報をDEVMODE構造体から取得返信 削除
2016/1/12 (火) 10:56:59 taki
▼ Mr.XRAYさん
 
> (昔は,この手の質問がいっぱいあったんですよね --- 遠い目)

マスター もう少しお付き合いください。

プリンタ関係のサンプルプログラムの記事を読み直してみて、分かったことも
多くあるのですが、色々と混乱して分からなくなってしまいました。

具体的な例にしての質問です。

パソコンに2台のプリンタが接続されています。
インクジェットと連続帳票専用プリンタです。

「通常使うプリンタ」(デフォルトのプリンタ) は、OSに登録(定義)されている
プリンタで、色々なアプリ(メモ帳、Word、Execl等)で印刷する時に自動で
選択されているプリンタですね。
インクジェットプリンタでプリンタ番号を2としてください。
プロパティはA4用紙・縦です。

連続帳票印刷アプリは連続帳票専用のプリンタを使います。
専用プリンタのプリンタ番号を3としてください。プロパティは連続用紙(かな?)
連続帳票印刷アプリを起動直後は、OSの「通常使うプリンタ」のままではダメ
(無駄紙大量発生)なので、帳票印刷する前に使用するプリンタの変更が
必要になります。

そのプリンタの変更を人間ができる場合は、「PrinterSetupDialog」でプリンタを
連続帳票専用プリンタに変更すれば、プロパティも連続用紙に変わってくれる?
(多分)ので、後は印刷すれば良い事になります。

でも、通常は「無駄紙大量発生」を防ぐため、使用するプリンタの変更をアプリの
コードで行いますよね。

そのコードが

Printer.PrinterIndex := 3;
// または
//Printer.PrinterIndex := Printer.Printers.indexof('OKI XXXX');
// OKI XXXX は帳票プリンタの名前(仮称)

Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
Printer.SetPrinter(ADevice, ADriver, APort, 0);
Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
// これで連続帳票専用プリンタ(仮称 OKI XXXX)に変更できたのでしょうか?
この時に、プロパティも連続用紙に変わっているのでしょうか?

無事に連続帳票の印刷が済んでアプリを終了したら、「通常使うプリンタ」は
インクジェットに戻っているのでしょうか?(上記コードはアプリ内だけ有効?)

自分で試せばいいのですが、プリンタが1台しかないもので…。


[9538] 通常使用するプリンタ返信 削除
2016/1/12 (火) 11:55:14 Mr.XRAY
▼ takiさん

> マスター もう少しお付き合いください。

やだ !! ハハハッ
 
> // これで連続帳票専用プリンタ(仮称 OKI XXXX)に変更できたのでしょうか?
> この時に、プロパティも連続用紙に変わっているのでしょうか?


なりません.プリンタの設定ダイアログで設定した場合はなります.
上のコードのように,DEVMODE 構造で設定する場合は,設定のコードが必要です.

> 無事に連続帳票の印刷が済んでアプリを終了したら、「通常使うプリンタ」は
> インクジェットに戻っているのでしょうか?(上記コードはアプリ内だけ有効?)


戻っています.
Delphi の Printer オブジェクトで操作した内容は,そのアプリだけで
有効です.ただし,Windows 10 では様子がかわったようです.

[ Windows10 通常使うプリンターが・・・]
http://mrxray.on.coocan.jp/bbs/DelphiBBS/mrxray_delphifan_coffe.cgi?tree=s9486#9486
 
> 自分で試せばいいのですが、プリンタが1台しかないもので…。

プリンタドライバをインストールすればテストできます.
しかし,物理的にプリンタが接続されていません.そこで「一時停止」にして
テストします.
結果は,印刷スプールにあります.
これは,DEKO さんとこにあるやつを利用すると確認できます.
ん ? 何というやつだったかな ? 調べてみます.

# 当サイトにもサンプルを掲載していたのですが,
# 削除しました.わざわざ自分で作成する必要はないと思って... (^^;

また,富士ゼロックス社の DocuWorks(ドキュワークス)も便利です.
DocuWorks はここのお客さんに教わったものです.



[9539] 印刷スプールを表示するツール返信 削除
2016/1/12 (火) 11:59:13 Mr.XRAY
> ん ? 何というやつだったかな ? 調べてみます.

こいつですね.
[スプールファイル変換ツール]
http://ht-deko.com/junkbox.html#SPLCONV

これの [ファイル][プレビュー] で印刷結果を確認することができます.
細い罫線は,拡大しないと確認が難しいです.


[9540] プリンタ,印刷の設定返信 削除
2016/1/12 (火) 12:10:25 Mr.XRAY
> なりません.プリンタの設定ダイアログで設定した場合はなります.
> 上のコードのように,DEVMODE 構造で設定する場合は,設定のコードが必要です.


プリンタの設定ダイアログ,あるいは印刷ダイアログを表示して設定させない,
コードで,自動で設定したい場合に,DEVMODE 構造体で設定する,
ということになります.

どちらの方法にするかは,開発するアプリによります.
ダイアログを表示すると,使用者によっては,余計な操作をしてしまう
可能性があります.DEVMODE 構造体で設定すれば確実ということになります.
ただし,コーディングは面倒ということになります.


[9543] Re:プリンタ,印刷の設定返信 削除
2016/1/12 (火) 14:15:03 taki
▼ Mr.XRAYさん
> > なりません.プリンタの設定ダイアログで設定した場合はなります.
> > 上のコードのように,DEVMODE 構造で設定する場合は,設定のコードが必要です.
>
> プリンタの設定ダイアログ,あるいは印刷ダイアログを表示して設定させない,
> コードで,自動で設定したい場合に,DEVMODE 構造体で設定する,
> ということになります.
>
> どちらの方法にするかは,開発するアプリによります.
> ダイアログを表示すると,使用者によっては,余計な操作をしてしまう
> 可能性があります.DEVMODE 構造体で設定すれば確実ということになります.
> ただし,コーディングは面倒ということになります.


なるほど。
この3行は呪文みたいなものですか。このコードに続いてプロパティを変更する
コードを書く必要があるのですね。
「013_プリンタのプロパティ設定」の「03_コードでプロパティを設定」のように。

Printer.SetPrinter(ADevice, ADriver, APort, 0);でプロパティの内容を初期化しないと
プリンターのプロパティの内容は個々のプリンターで違うので、DocumentProperties関数で
うまく書き込めないのでしょうね。
確かに面倒です。
そういう意味ではPrinterSetupDialogはすごいですね。プリンターの一覧作成からプロパティの
獲得、変更までやってくれるのだから。


スプールファイル変換ツール「splconv」は面白そうですね。早速ダウンロードしました。
readme.txtにメタファイルで出力とあるのでその辺は…。

富士ゼロックス社の DocuWorks(ドキュワークス)は以前インストールしていたかもしれません。
認知症が進んでるみたいで、物忘れが激しい。


[9545] Re:通常使用するプリンタ返信 削除
2016/1/16 (土) 00:07:10 Sara
▼ Mr.XRAYさん こんばんわ

> 有効です.ただし,Windows 10 では様子がかわったようです.
>
> [ Windows10 通常使うプリンターが・・・]
> http://mrxray.on.coocan.jp/bbs/DelphiBBS/mrxray_delphifan_coffe.cgi?tree=s9486#9486


Windows10 10240までは上記のLinkで言っている設定がありません・・・
Windows10 10586からのようです。

ちなみに、アップグレード後に注意事項等は表示されません。
自分で気づけと・・・(設定値はやはりONでした)
もちろん、すぐにOFFにしましたが・・・

[9546] Re2:通常使用するプリンタ返信 削除
2016/1/16 (土) 14:58:00 Mr.XRAY
▼ Saraさん

> Windows10 10240までは上記のLinkで言っている設定がありません・・・
> Windows10 10586からのようです。


おおっ,これは貴重な情報です.
Windows10 10586 もまだまだという感じがします.

教訓 : 慌てて新しい Windows は導入しないこと.


[9541] お付き合い返信 削除
2016/1/12 (火) 12:28:06 Mr.XRAY
> マスター もう少しお付き合いください。

これは結婚を前提にしてのことでしょうか ? なんてね.
ほら,昔,付き合っている女性に言われたことないですか ?
「私は貴方のなんなの ?」

で,彼女にこんなことを書いたメモを渡したでしょう ?

以下の希望するどれかに○を付けてください.
  1. 単なる女友達
  2. 女友達以上,恋人未満
  3. 婚約者
  4. 妻
  5. 今から別れる彼女


[9542] Re:お付き合い返信 削除
2016/1/12 (火) 14:13:44 taki
▼ Mr.XRAYさん
> > マスター もう少しお付き合いください。
>
> これは結婚を前提にしてのことでしょうか ? なんてね.
> ほら,昔,付き合っている女性に言われたことないですか ?
> 「私は貴方のなんなの ?」
>
> で,彼女にこんなことを書いたメモを渡したでしょう ?
>
> 以下の希望するどれかに○を付けてください.
>   1. 単なる女友達
>   2. 女友達以上,恋人未満
>   3. 婚約者
>   4. 妻
>   5. 今から別れる彼女


残念ながら、おじさんはそんなことを言われたことがありません。

マスターはモテモテだったんでしょうね。


[9544] Re2:お付き合い返信 削除
2016/1/12 (火) 15:56:45 Mr.XRAY
▼ takiさん

> マスターはモテモテだったんでしょうね。

んなわけありません !

で,このメモの話は本当らしいです.実際の内容は記憶です.
違っていると思います.
山岳会の同期の友人で,そういう方がいたそうです.
で,5. に○を付けられて,あわてて追いかけたそうです.

結果的に,その女性と結婚したそうです.めでたし,めでたし.


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82