none
Win7(32bit)上のVB2008(Pro)で作成したアプリをWin7(64bit)のPCで印刷させると位置がずれる RRS feed

  • 質問

  • Win7(32bitSP1)のPC上のVB2008(Pro)で作成したアプリをWin7(64bit)のPCで動作させるとPrintDocumentで印刷設定した内容が大幅にずれてしまいます。(罫線も含めて縦横ともに縮んでしまうのです)

    PrintDocumentの中では使用フォントの高さ( Hi = myFont.Height)を基準に罫線の長さや縦、横の位置を決めて文字を印刷させています。32bitのPCではきちんと印刷できますが64bitのPCでは印刷がずれてしまいます。(どのプリンターに印刷させても同じです。)何が原因なのか教えていただけないでしょうか。Printdocumentの内容は以下のようなものです。

            myFont = New Drawing.Font(PrintFont, Val(PrintPoint))   '印刷用フォントとポイントを指定
            Hi = myFont.Height
            offX = Hi * 3
            offY = Hi * 3
            'これより順位表の印刷
            For i = StartBan To EndBan
                '日付の印刷
                ss = String.Format("{0:G}", MyDay)
                e.Graphics.DrawString(ss, myFont, Brushes.Black, 20 * Hi, offY)
                'テストタイトルの印刷
                e.Graphics.DrawString(TestTitle, myFont, Brushes.Black, offX, offY)
                '学年・組番号の印刷
                ss = CStr(TargetGakunen) & " 年 " & CStr(ClBangou(i)) & "組  (  )内は全体での順位"
                e.Graphics.DrawString(ss, myFont, Brushes.Black, offX, offY + Hi * 1)
                ss = "組 番    氏   名      国語     社会     数学     理科     英語    合計  性順 総合順"
                e.Graphics.DrawString(ss, myFont, Brushes.Black, offX, offY + Hi * 3)
                  .....
                  .....

    2013年7月31日 2:46

回答

  • 外池と申します。

    「かも」とか「かな?」ではなく、ドキュメントをしっかり読んで、かつ、実働の確認をして、確実な方法を理解・会得されることをお勧めします。

    Fontというクラスはプリンタの印刷解像度の情報を持ち合わせていないので、Heightプロパティーのピクセル数で表現された高さを紙面上の物理的な寸法に正しく換算することはできないはずです。

    同じパソコン、同じプリンターを対象に動作させる場合でも、ユーザーのプリンタードライバの印刷品質設定次第で解像度が変わってしまい、1.25倍というような決め打ちの数字が役に立たなくなる可能性も考慮すべきです。また、プリンターの場合、縦方向、横方向の解像度が異なることもあります。まして、プリンターが異なれば、あるいは、OSのバージョンとともにプリンター・ドライバーが異なれば、解像度は異なることを前提にすべきです。

    印刷描画面を表すGraphicsクラスには、解像度や位置・寸法を指定する際の単位の情報が含まれていますので、これと、Fontを結び付けて、初めて、具体的な活字の寸法や、配置の位置を決めることができます。プロポーショナルフォントの場合ですと、横方向は、文字の内容そのものにも依存します。

    Font.GetHeight(Graphics)や、Graphics.MeasureString(.....)などで、描画面情報(Graphics)、フォント(Font)、及び文字列(String)を常に関連づけて寸法・位置を把握し、最後に、Graphics.DrawStringになります。

    参考になれば幸いです。

    • 回答としてマーク UPR 2013年8月5日 11:40
    2013年8月5日 9:08
  • 印刷周りは扱ったことがないので見当はずれかもしれませんが、

    Font.Heightの説明には画面表示の垂直解像度に依存する旨が記載されています。64bit OSかどうかは関係なくて、開発に使用したPC(もしくは64bitのPC)が画面上のテキストを大きくまたは小さくするの設定により解像度が変更されていたりしませんか?

    その場合、Font.GetHeightメソッドのオーバーロードにより、適切なGraphicsを渡したり、dpiを指定した上で値を取得すべきではないでしょうか。

    まずは、各PCで得られるFont.Heightの値が意図した高さを表しているかを確認した方がいいかもしれません。

    • 回答としてマーク UPR 2013年8月5日 7:45
    2013年8月5日 0:42
  • 確かに開発用PC(32bit)では画面上のテキストを大きめに設定していました。そこで元に戻して(100%)にして実行させても印刷は改善されませんでした。

    何をどう試行して「改善され」なかったと結論付けたのでしょうか。この値はコンパイル時に取得されるものではなく、実行時に取得されます。ここの値を変化させた時に印刷レイアウトが崩れるのではありませんか?

    私の勝手な想像ですが

    提示したドキュメントをよく読んでください。フォントは確かに画面にもプリンタにも依存しませんが、同時に32bit / 64bitにも依存しません。その上で、Font.Heightプロパティの値については「画面表示の垂直解像度を使用して計算されます」。あくまでHeightプロパティは利便性を考慮して画面向けの値が返されます。

    * 1.25 という値が、質問者さんのテキストの拡大倍率 125% に一致するのになぜそれを否定する方向に進めようとするのですか?

    • 回答としてマーク UPR 2013年8月7日 11:35
    2013年8月5日 10:09

すべての返信

  •  Graphics クラスのメソッドは、PageUnit に指定してある単位で処理します。よって、これが違っていると、異なる結果が出てきます。

     また、フォントの縦の長さを元に計算しているのですから、指定するフォントが違えば、異なる結果となります。

     あと、気になるのは、どのようなフォントを指定しているか、です。日本語フォントでも、「MS Pゴシック」など、「P」の付いたフォントや、メイリオは、文字毎に幅の異なるプロポーショナル フォントです。「"組 番 氏 名 国語..."」のところが、期待通りになるかどうか、ここにはどのようなフォントを指定しているか書かれていないため判断できません。


    Jitta@わんくま同盟

    2013年7月31日 14:22
  • jitta さん ありがとうございます。

    ご指摘の通りフォントはプロポーショナルフォントは使用しないということになっていますので、フォントの違いによる印刷のずれではありません。ご指摘のGraphics クラスの、PageUnit については勉強不足のためまだ何もわかっていません。しかしながら先のコードの

    Hi = myFont.Heightのところで

    Hi = myFont.Height*1.2

    というようにフォントの幅を広げてやると64bitのOSでもきちんと32bitと同じように印刷できました。32bitOSでいうフォントの高さと64bitのOSでのフォントの高さに違いがあるのでしょうか。もしそうだとすればソフトのほうで64bitと32bitなのかを見分けて処理するコードを書かなければいけなくなるのではないかと心配しています。

    2013年8月3日 0:51
  • UPR さま よろしく。

    後続のスレッドでの OS が x86 で AnyCPU で開発し、「64bitのPCにインストール(program Files(X86))すると」 とありますが、
    私のVB2008SP1 は EE 版なので x86 Build を選べないため確認できないのですが、
    確か、AnyCPU は x64 では 64bit モードで実行される つまり program Files(X86)でなく program Files に配置される筈だと思ったのですが。

    気になりましたので。

    2013年8月5日 0:29
  • 印刷周りは扱ったことがないので見当はずれかもしれませんが、

    Font.Heightの説明には画面表示の垂直解像度に依存する旨が記載されています。64bit OSかどうかは関係なくて、開発に使用したPC(もしくは64bitのPC)が画面上のテキストを大きくまたは小さくするの設定により解像度が変更されていたりしませんか?

    その場合、Font.GetHeightメソッドのオーバーロードにより、適切なGraphicsを渡したり、dpiを指定した上で値を取得すべきではないでしょうか。

    まずは、各PCで得られるFont.Heightの値が意図した高さを表しているかを確認した方がいいかもしれません。

    • 回答としてマーク UPR 2013年8月5日 7:45
    2013年8月5日 0:42
  • ShiroYuki_Mot 様

    お返事ありがとうございます。

    すべて AnyCPU (X64にはなっていません)で開発(当然32bitアプリとなると思いますが)して64bitのPCにインストールすると自動的にprogram Files(X86)にインストールされます。

    なにかとんちんかんなお返事かもしれませんが・・・・・・・

    2013年8月5日 1:41
  • UPR さま 認識違いでした。 申し訳ありません。
    以下を参照下さい。 最終行の出典よりの転記です。

    アプリケーションをインストールする際に指定されるデフォルトのインストールパスは次のようになる
    Windows   アプリケーション  デフォルトのインストールパス 
    32 bit      32 bit     C:\Program Files     
           64 bit     - (インストール不可) 
    64 bit      32 bit     C:\Program Files (x86)
           64 bit     C:\Program Files 


    ※インストーラーは基本的にはファイルのコピーやレジストリへの登録などを処理するだけなので、32 bit インストーラーでも 64 bit アプリケーションをインストールすることができる。ただしインストール先が​ファイルシステムリダイレクタによって 32 bit 用のフォルダにリダイレクトされるため、64 bit 用のフォルダにはインストールすることができない。64 bit アプリケーションを 64 bit 用のフォルダにインストールするには別途 64 bit インストーラーが必要となる。なお 64 bit アプリケーションが 32 bit 用のフォルダにある状態でもアプリケーションの動作に問題は生じない。

    ※ 64 bit Windows に用意されている 32/64 bit 用の フォルダは、アプリケーションを 32/64 bit のどちらで起動するかの判定には影響しない。32 bit 用のフォルダにある 64 bit アプリケーションは 64 bit で起動し、64 bit 用のフォルダにある 32 bit アプリケーションは 32 bit で起動する。アプリケーションを 32/64 bit のどちらで起動するかは PE ヘッダー内の 32BIT フラグによって決定される。

    以上、出典 http://www.attosoft.info/trac/ticket/15 中ほど 「64 bit アプリケーション」 の項

                    私は EE 版の利用なので、インストローラーの挙動を知りませんでした。 申し訳ありません。
    • 編集済み ShiroYuki_Mot 2013年8月5日 4:47 桁ズレ修正
    2013年8月5日 3:06
  • 佐祐理 様

    開発に使用したPC(もしくは64bitのPC)が画面上のテキストを大きくまたは小さくするの設定により解像度が変更されていたりしませんか?

    とのことですが、確かに開発用PC(32bit)では画面上のテキストを大きめに設定していました。そこで元に戻して(100%)にして実行させても印刷は改善されませんでした。考えてみれば印刷はフォントを指定してそのFont.Heightを取得し、それを基準に罫線や文字を印刷させているので、画面上のテキストの大きさには関係ないものと思われます。

    私の勝手な想像ですがFont.Heightで得られる値(高さの上下の余白部分も含んでいる)が64bitと32bitで違うものと思われます。 実際に複数行(文字のみ)を印刷させると(Font.heightでの改行の場合)行間隔が詰まってしまい大変読みづらくなってしまいます。32bitPCの場合は適切な行間隔で印刷されます。

    開発用PCでのフォントのポイントが実行用PCのポイントで微妙にポイント数が違うためかもしれません(小数点以下)

    同じ11ポイントを指定してもPCにインストールされているフォントによっては10.8であったり11.2だったりするからかな?なんて思ったりします。でも実行用PCでフォントポイントが違っていても実行時にはそのフォントの高さを取得して処理をしているので関係ないのかも・・・?

    先に書きましたFont.height*1.25に設定しておくと、どの大きさのフォントでもきちんと印刷されるわけで、この辺がよくわかりません。Win8(64bit)のPCにインストールしても全く同じで*1.25できちんと印刷できました。

    何かくどきのような返信になってしまいました。ご容赦ください。

    2013年8月5日 8:17
  • Shiroyuki_Mot さま

    返信ありがとうございました。よくわかりました。

    2013年8月5日 8:22
  • 外池と申します。

    「かも」とか「かな?」ではなく、ドキュメントをしっかり読んで、かつ、実働の確認をして、確実な方法を理解・会得されることをお勧めします。

    Fontというクラスはプリンタの印刷解像度の情報を持ち合わせていないので、Heightプロパティーのピクセル数で表現された高さを紙面上の物理的な寸法に正しく換算することはできないはずです。

    同じパソコン、同じプリンターを対象に動作させる場合でも、ユーザーのプリンタードライバの印刷品質設定次第で解像度が変わってしまい、1.25倍というような決め打ちの数字が役に立たなくなる可能性も考慮すべきです。また、プリンターの場合、縦方向、横方向の解像度が異なることもあります。まして、プリンターが異なれば、あるいは、OSのバージョンとともにプリンター・ドライバーが異なれば、解像度は異なることを前提にすべきです。

    印刷描画面を表すGraphicsクラスには、解像度や位置・寸法を指定する際の単位の情報が含まれていますので、これと、Fontを結び付けて、初めて、具体的な活字の寸法や、配置の位置を決めることができます。プロポーショナルフォントの場合ですと、横方向は、文字の内容そのものにも依存します。

    Font.GetHeight(Graphics)や、Graphics.MeasureString(.....)などで、描画面情報(Graphics)、フォント(Font)、及び文字列(String)を常に関連づけて寸法・位置を把握し、最後に、Graphics.DrawStringになります。

    参考になれば幸いです。

    • 回答としてマーク UPR 2013年8月5日 11:40
    2013年8月5日 9:08
  • 確かに開発用PC(32bit)では画面上のテキストを大きめに設定していました。そこで元に戻して(100%)にして実行させても印刷は改善されませんでした。

    何をどう試行して「改善され」なかったと結論付けたのでしょうか。この値はコンパイル時に取得されるものではなく、実行時に取得されます。ここの値を変化させた時に印刷レイアウトが崩れるのではありませんか?

    私の勝手な想像ですが

    提示したドキュメントをよく読んでください。フォントは確かに画面にもプリンタにも依存しませんが、同時に32bit / 64bitにも依存しません。その上で、Font.Heightプロパティの値については「画面表示の垂直解像度を使用して計算されます」。あくまでHeightプロパティは利便性を考慮して画面向けの値が返されます。

    * 1.25 という値が、質問者さんのテキストの拡大倍率 125% に一致するのになぜそれを否定する方向に進めようとするのですか?

    • 回答としてマーク UPR 2013年8月7日 11:35
    2013年8月5日 10:09
  • 佐祐理 さま

    たびたびのご回答ありがとうございました。私の思い違いでした。

    >Font.Heightプロパティの値については「画面表示の垂直解像度を使用して計算されます」。あくまでHeightプロパティは利便性を考慮して画面向けの値が返されます。

    ご指摘の通りでした。確かに画面解像度が異なると印刷位置がずれてしまうことが確認できました。私はFont.heightの値はフォント固有の不変のものと勘違いしていたようで、これがすべての原因であったようです。改めて印刷関係のの見直しをしたいと思います。

    大変ご迷惑をおかけしました。

    2013年8月5日 11:35
  • 外池 様

    アドバイスありがとうございました。 佐祐理様のご指摘で原因がわかり、納得しました。印刷基準に画面解像度に依存するFont.heightを使用したのが間違いの元でした。貴兄のアドバイスに従い勉強し直してもう一度印刷の見直しを図りたいと思います。

    あらためていろいろご意見やアドバイスをいただいた各諸兄に感謝申し上げます。

    これに懲りずに今後ともよろしくお願いいたします。

    2013年8月5日 11:49
  • 外池様

    ユーザーが指定したフォントのポイント数を基準に印刷させることにしました。こうすることで画面解像度には関係なく指定されたフォントで印刷できるようになりました。

    どうもありがとうございました。とりあえず報告ということで・・

    2013年8月7日 0:01
  •  時間が経っていますが、気になったので。

     「21インチのディスプレイ」と、「1600×1080ドットのディスプレイ」があります。どちらのディスプレイの方が大きいでしょうか。
     そんなのわかりませんよね。「インチ」という単位と「ドット」という単位は、直接比較できませんから。でも、この質問は、直接比較したために発生したものです。

     Font コンストラクタでは、フォントの大きさを「ポイント」で指定します。この「ポイント」という単位は1/72インチです。画面そのものはドット数、「ピクセル」という単位を使いますが、インチとピクセルは、解像度「1インチ毎のドット数」で関係づけられています。

     文字を描画する Graphics で使用する単位は、デフォルトでは GraphicsUnit.Display で、ディスプレイとプリンタで異なります。ディスプレイの場合はピクセル、プリンタの場合は1/100インチです。

     Font クラスにも Unit プロパティがあるので、Font と Graphics で使用する単位を合わせてから参照、描画していれば、最初からうまくいったかもしれませんね。


    Jitta@わんくま同盟

    2013年8月21日 12:58
  • jitta 様

    アドバイスありがとうございます。

    今回の問題はディスプレイに表示されたものをそのまま印刷するわけではなく,用紙の問題もあるため,決まった大きさの文字(指定ポイント)で印刷させたかったわけです。にも関わらずFont.Heightを使ってしまったということで不具合が起きてしまいました。

    アドバイスに従いいろいろ試してみようと思います。

    ありがとうございました。

    2013年8月23日 0:42