DOBON.NETプログラミング道掲示板

■35185 / 親記事)  VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
  
□投稿者/ ゆりりん 一般人(1回)-(2022/10/21(Fri) 11:45:23)
  • アイコン環境/言語:[環境(Windows10 64bit)、使用言語(VB.net2017)、.NET Framework 4.6.1 ] 
    分類:[.NET] 

    いつも参照させていただいています。

    現在、VB6.0で書かれた印刷プログラムをVB.Netに移行しています。
    その中で、VB6.0と全く同じ座標とFont種類・サイズを指定しても、
    VB.Netで印刷すると、少し右にずれてしまうし、Fontのサイズが微妙に違ってしまいます。
    Fontの高さは同じようなのですが、文字と文字の隙間が微妙に違うようで、長い文字列を印刷すると、印刷された文字の長さがVB.Netの方が長くなってしまうのです。
    座標系はどちらも、ミリメートルを指定しています。
    VB.Netで印刷された文字列の前に空白が付くことは、下記のサイトを参照して分かったので、ずれる分を引いた座標を指定したら、右にずれる件は解決したのですが、同じFontを指定しても違ってしまう件が解決できません。
    同じプリンタとプリンタドライバを使用しているのに、どうしてVB6.0とVB.Netで違ってしまうのか、まったくわかりません。

    ・使用しているプリンタ ラベルプリンタ SATO CL4NX-J 609dpi
    ・プリンタ解像度 609dpi 24dot/mm

    ・参考にしたサイト
    VB.netで文字を正確な位置に描く。
    https://penguinlab.jp/blog/post/117

    ※VB6.0のサンプル

    Printer.ScaleMode = 6
    Printer.FontName = "MS ゴシック"
    Printer.FontSize = 9
    Printer.CurrentX = 12.5
    Printer.CurrentY = 30.7
    Printer.Print "IN-OUT<AB>CD EFG-HIJK-LMN A<10>"

    ※VB.Netのサンプル

    e.Graphics.PageUnit = GraphicsUnit.Millimeter
    Dim f As New Font("MS ゴシック", 9, FontStyle.Regular)
    e.Graphics.DrawString("IN-OUT<AB>CD EFG-HIJK-LMN A<10>", f, Brushes.Black, 12.5, 30.7)

    こんな感じです。


    どなたかわかる方、どうかアドバイスをお願いいたします。

マルチポストを報告
違反を報告
引用返信 削除キー/
■35189 / ResNo.1)  Re[1]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1465回)-(2022/10/21(Fri) 16:52:29)
  • アイコンNo35185に返信(ゆりりんさんの記事)
    > 少し右にずれてしまうし、Fontのサイズが微妙に違ってしまいます。
    もしかして、WinForms の Label コントロールで
    UseCompatibleTextRendering プロパティを
    True / False で切り替えた時と、同じようなズレ方ではないでしょうか。
    https://dobon.net/vb/dotnet/control/setcompatibletextrenderingdefault.html


    > どうしてVB6.0とVB.Netで違ってしまうのか、まったくわかりません。
    VB6 の方が「GDI」である印刷であるの対して
    Graphics.DrawString は「GDI+」という違いがありますね。
    TextRenderer.DrawText は「GDI」です。
    https://dobon.net/vb/dotnet/graphics/drawstring.html

    印刷結果を VB6 に合わせたいのであれば、TextOutW API を使って出力すれば
    同様の結果を得られるかと思います。
違反を報告
引用返信 削除キー/
■35193 / ResNo.2)  Re[2]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(2回)-(2022/10/22(Sat) 00:32:11)
  • アイコン魔界の仮面弁士さま、回答ありがとうございました。

    >>少し右にずれてしまうし、Fontのサイズが微妙に違ってしまいます。
    > もしかして、WinForms の Label コントロールで
    > UseCompatibleTextRendering プロパティを
    > True / False で切り替えた時と、同じようなズレ方ではないでしょうか。
    > https://dobon.net/vb/dotnet/control/setcompatibletextrenderingdefault.html

     はい、まさにこんな感じです。


    >>どうしてVB6.0とVB.Netで違ってしまうのか、まったくわかりません。
    > VB6 の方が「GDI」である印刷であるの対して
    > Graphics.DrawString は「GDI+」という違いがありますね。
    > TextRenderer.DrawText は「GDI」です。
    > https://dobon.net/vb/dotnet/graphics/drawstring.html

     VB6.0とVB.Netでこのような違いがあるとは知りませんでした。
     勉強になりました。

    > 印刷結果を VB6 に合わせたいのであれば、TextOutW API を使って出力すれば
    > 同様の結果を得られるかと思います。

     QRコードやBCDの印刷に、TextOutW API を使用しています。
     こちらは、きちんと指定した座標に印刷できています。
     文字の印刷にも、TextOutW API を使用して印刷してみます。

     VB.Netは初心者なのでわからないことばかりです。
     きちんとわかってよかったです。

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

違反を報告
引用返信 削除キー/
■35195 / ResNo.3)  Re[3]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1466回)-(2022/10/24(Mon) 12:03:00)
  • アイコンNo35193に返信(ゆりりんさんの記事)
    >>VB6 の方が「GDI」である印刷であるの対して
    >>Graphics.DrawString は「GDI+」という違いがありますね。
    >>TextRenderer.DrawText は「GDI」です。
    ただし TextRenderer.DrawText は画面描画を目的としたものであり、
    印刷に適したものではありません。

    > QRコードやBCDの印刷に、TextOutW API を使用しています。
    > こちらは、きちんと指定した座標に印刷できています。
    逆に VB6 や VBA 側で GDI+ を使いたい場合は、Declare ステートメントで
    GdiPlus.dll のもつ API 群を呼び出す形になりますね。
    GdipDrawImageRectI API とか、GdipDrawString API とか。

    今回は VB6 開発をするわけでも無いので、蛇足だとは思いますが。
    http://tanlab.blog.fc2.com/blog-entry-34.html

    https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-graphics-flat
    https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-text-flat
    https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-flatapi-flat
違反を報告
引用返信 削除キー/
■35200 / ResNo.4)  Re[4]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(3回)-(2022/10/26(Wed) 13:45:04)
  • アイコン> 逆に VB6 や VBA 側で GDI+ を使いたい場合は、Declare ステートメントで
    > GdiPlus.dll のもつ API 群を呼び出す形になりますね。
    > GdipDrawImageRectI API とか、GdipDrawString API とか。
    >
    > 今回は VB6 開発をするわけでも無いので、蛇足だとは思いますが。

    ありがとうございます。

    アドバイスをいただき、TextOutを使用して、印刷のプログラムを作成し、印刷してみたのですが、
    座標は合っているようなのですが、想定していたよりかなり小さく印刷されてしまい、ほとんど解読できないような大きさでした。
    単純に大きな値にしたら、見えるようにはなったのですが、Fontサイズの指定の仕方がわかりません。
    色々調べてみたのですが、わからなかったので、また、ここに質問させていただきます。

    ※以前のVB.Netのサンプル

    e.Graphics.PageUnit = GraphicsUnit.Millimeter
    Dim f As New Font("MS ゴシック", 9, FontStyle.Regular)
    e.Graphics.DrawString("IN-OUT<AB>CD EFG-HIJK-LMN A<10>", f, Brushes.Black, 12.5, 30.7)

    だったので、同様に、同じFontとFontSizeを指定して以下のようにやってみました。
    少し長いですが、すみません。

     ' 印刷データを指定の位置に出力します
    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")> _
    Friend Shared Function TextOut(ByVal hdc As IntPtr, _
    ByVal nXStart As Integer, ByVal nYStart As Integer, _
    ByVal lpString As String, ByVal cbString As Integer) As Integer
    End Function

    ' 論理フォントを作成します
    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")> _
    Friend Shared Function CreateFont(ByVal nHeight As Integer, ByVal nWidth As Integer, ByVal nEscapement As Integer, _
    ByVal nOrientation As Integer, ByVal fnWeight As Integer, ByVal fdwItalic As Boolean, _
    ByVal fdwUnderline As Boolean, ByVal fdwStrikeOut As Boolean, ByVal fdwCharSet As Integer, _
    ByVal fdwOutputPrecision As Integer, ByVal fdwClipPrecision As Integer, ByVal fdwQuality As Integer, _
    ByVal fdwPitchAndFamily As Integer, ByVal lpszFace As String) As IntPtr
    End Function

    --------- 省略 ---------

    Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)

    Dim mFont As IntPtr
    Dim mFontOld As IntPtr

    ' Graphicsの設定をします
    e.Graphics.PageUnit = GraphicsUnit.Millimeter

    Dim intX As Integer = 0 ' X座標
    Dim intY As Integer = 0 ' Y座標
    Dim intFont As Integer = 0 ' フォントサイズ
    Dim Dt As String ' 印刷データ

    Dim hdc As IntPtr

    ' 印刷データを設定します
    Dt = "IN-OUT<AB>CD EFG-HIJK-LMN A<10>"

    ' --- QRコードを印刷 ---

    ' デバイスコンテキストを識別するハンドルを取得します
    hdc = e.Graphics.GetHdc()
    ' 座標とFontSize設定
    intX = 3
    intY = 5
    intFont = 1
    Call SetFont(hdc, "QR-01", intFont) 'QR-01:プリンタに登録したQRコードのFont
    Call PrintTextOut(hdc, intX, intY, Dt, Dt.Length) ← このQRコードはきちんと印刷されます

    ' グラフィックオブジェクトを削除し、システムリソースの解放をします
    DeleteObject(mFont)
    ' デバイスコンテキストにオブジェクトの選択をします
    SelectObject(hdc, mFontOld)
    ' デバイスコンテキストハンドルを解放します
    e.Graphics.ReleaseHdc(hdc)

    ' --- 文字列を印刷 ---

    ' デバイスコンテキストを識別するハンドルを取得します
    hdc = e.Graphics.GetHdc()
    ' 座標とFontSize設定
    intX = 12
    intY = 30
    intFont = 9
    Call SetFont(hdc, "MS ゴシック", intFont)
    Call PrintTextOut(hdc, intX, intY, Dt, Dt.Length) ← これが読み取れないくらい小さく印刷されます

    ' グラフィックオブジェクトを削除し、システムリソースの解放をします
    DeleteObject(mFont)
    ' デバイスコンテキストにオブジェクトの選択をします
    SelectObject(hdc, mFontOld)
    ' デバイスコンテキストハンドルを解放します
    e.Graphics.ReleaseHdc(hdc)


    End Sub

    ' 論理フォント作成

    Private Sub SetFont(ByVal control As IntPtr, ByVal fontFamily As String, ByVal fontSize As Integer)

    mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    mFontOld = SelectObject(control, mFont)

    End Sub

    ' 文字列描写

    Private Sub PrintTextOut(ByVal hdc As IntPtr, ByVal intX As Integer, ByVal intY As Integer, ByVal strPrint As String, ByVal intCount As Integer)

    ' SATO CL4NX-J 609dpi(24dot/mm)より1dot辺りのMillimeterを指定しています
    Dim dbldotmm As Double = 0.04166
    Dim intPixelX As Integer = Convert.ToInt16(intX / dbldotmm)
    Dim intPixelY As Integer = Convert.ToInt16(intY / dbldotmm)

    Call TextOut(hdc, intPixelX, intPixelY, strPrint, intCount)

    End Sub

    e.Graphics.DrawStringの時と、同じFontとFontSizeなのですが、印刷される大きさが違ってしまいます。
    FontSizeはどのように設定すればよいのでしょうか。

    どうぞよろしくお願いいたします。

違反を報告
引用返信 削除キー/
■35202 / ResNo.5)  Re[5]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1467回)-(2022/10/26(Wed) 18:29:47)
  • アイコンNo35200に返信(ゆりりんさんの記事)
    > 想定していたよりかなり小さく印刷されてしまい、
    物理単位と論理単位の違いでは無いでしょうか。

    恐らく、最初の回答で述べた「TextRenderer.DrawText」を使った場合と
    同じぐらいのサイズで描画されていませんか?

    GDI+ 側の PageUnit プロパティを操作しても、
    GDI 側のデバイスコンテキストには影響を与えないと思います。


    > 座標は合っているようなのですが、想定していたよりかなり小さく印刷されてしまい
    単位系が未設定の場合、初期値として
    GDI+ 側(PageUnit プロパティ)は Display(1) を返し、
    GDI 側(GetMapMode API)は MM_TEXT(1) を返すようです。

    Sub SetFont でフォントを生成する際に、
    MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    生成するようにしてみては如何でしょうか。


    > Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
    >  Dim mFont As IntPtr
    ここで宣言されたローカル変数の mFont と

    > Private Sub SetFont(ByVal control As IntPtr, ByVal fontFamily As String, ByVal fontSize As Integer)
    >  mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    ここで利用されているフィールド変数の mFont は
    それぞれ別の変数ですが、大丈夫ですか?
違反を報告
引用返信 削除キー/
■35207 / ResNo.6)  Re[6]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(4回)-(2022/10/28(Fri) 10:38:17)
  • アイコンいつもありがとうございます。

    > 物理単位と論理単位の違いでは無いでしょうか。
    >
    > GDI+ 側の PageUnit プロパティを操作しても、
    > GDI 側のデバイスコンテキストには影響を与えないと思います。

     そういうことだったのですね。

    > Sub SetFont でフォントを生成する際に、
    > MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    > 生成するようにしてみては如何でしょうか。

     早速、やってみようと思います。
     
    >> Dim mFont As IntPtr
    > ここで宣言されたローカル変数の mFont と
    >
    >> mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    > ここで利用されているフィールド変数の mFont は
    > それぞれ別の変数ですが、大丈夫ですか?

     すみません。
     ここに載せる時に、間違えました。
     実際には、論理フォントの作成の後に入っています。
     お気づきいただき、ありがとうございました。
違反を報告
引用返信 削除キー/
■35212 / ResNo.7)  Re[6]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(5回)-(2022/10/28(Fri) 16:49:02)
  • アイコン> Sub SetFont でフォントを生成する際に、
    > MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    > 生成するようにしてみては如何でしょうか。


    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")>
    Friend Shared Function SetMapMode(ByVal hdc As Integer, ByVal fnMapMode As Integer) As Integer
    End Function

     を追加しまして、

    Private Sub SetFont(ByVal control As IntPtr, ByVal fontFamily As String, ByVal fontSize As Integer)

    Call SetMapMode(control, 2) 'MM_LOMETRIC
    mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    mFontOld = SelectObject(control, mFont)

    End Sub

     このように書いてみたのですが、
     何も印刷されなくなってしまいました。
     SetMapMode の使い方が、間違っているのでしょうか。

     度々申し訳ございません。
     ご教授いただければと思います。
     どうぞよろしくお願いいたします。


違反を報告
引用返信 削除キー/
■35214 / ResNo.8)  Re[7]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1473回)-(2022/10/28(Fri) 21:29:20)
  • アイコン
    No35212に返信(ゆりりんさんの記事)
    > 何も印刷されなくなってしまいました。
    
    『フォントサイズ』の指定、および、『描画位置の座標』は正しいですか?
    
    MM_TEXT から MM_LOMETRIC に変更したのであれば、フォントサイズだけでは無く
    描画座標も MM_LOMETRIC 単位系で計算しなおす必要があります。
    
    
    描画位置を変更したくない場合は、GetMapMode と SetMapMode をペアで使うようにして、
    フォント作成後、描画時に座標系を元に戻してみてください。先の私の回答では、フォントを
    「MM_LOMETRIC あるいは MM_HIMETRIC で生成する」とは書きましたが、
    「MM_LOMETRIC あるいは MM_HIMETRIC で描画する」とは書いていません。
    
    
    MapMode は 1〜8 の 8 種類あります。指定するモードによっては、
    単位だけでなく軸の向きも変化していることに注意してください。
    
     (A) X 座標が右に、Y 座標が上に向かって増加していくもの
     (B) X 座標が右に、Y 座標が下に向かって増加していくもの
     (C) SetWindowExtEx() / SetViewportExtEx() で単位、向き、スケーリングを指定するもの
     http://www.kumei.ne.jp/c_lang/sdk/sdk_55.htm
     http://yamatyuu.net/computer/program/sdk/gdi/mapmode/index.html
    
    ---
    
    (A) 右向き、上向きな MapMode
     1 … MM_TEXT。1 デバイスピクセル単位の物理座標系。
     6 … MM_TWIPS。0.05ポイント単位(1/1440インチ単位)の論理座標系。
    
    (B) 右向き、下向きな MapMode
     2 … MM_LOMETRIC。0.1 ミリ単位の論理座標系。
     3 … MM_HIMETRIC。0.01 ミリ単位の論理座標系。
     4 … MM_LOENGLISH。0.01 インチ単位の論理座標系。
     5 … MM_HIENGLISH。0.001 インチ単位の論理座標系。
    
    (C) 単位、向き、スケーリングを任意に指定できる MapMode
     7 … MM_ISOTROPIC。異方性ユーザー定義単位系。任意の単位、向き、スケーリングを持つ。
     8 … MM_ANISOTROPIC。等方性ユーザー定義単位系。X 軸と Y 軸の 1 単位が等しい。

違反を報告
引用返信 削除キー/
■35215 / ResNo.9)  Re[8]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(6回)-(2022/11/02(Wed) 11:23:32)
  • アイコン> 描画位置を変更したくない場合は、GetMapMode と SetMapMode をペアで使うようにして、
    > フォント作成後、描画時に座標系を元に戻してみてください。先の私の回答では、フォントを
    > 「MM_LOMETRIC あるいは MM_HIMETRIC で生成する」とは書きましたが、
    > 「MM_LOMETRIC あるいは MM_HIMETRIC で描画する」とは書いていません。
    >
    そういうことだったのですね。
    よくわかっていませんでした。

    『描画位置の座標』はピクセルで計算していたので、
    MM_TEXTの指定にしたら、きちんと印刷されるようになりました。

    今までどうもありがとうございました。


解決み!
違反を報告
引用返信 削除キー/



スレッド内ページ移動 / << 0 >>

このスレッドに書きこむ

Mode/  Pass/


- Child Tree -