C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

Win-10/Pro + C# + IPAmj明朝 /S.Kos (20/07/27(Mon) 08:23) #95373
Re[1]: Win-10/Pro + C# + IPAmj明朝 /Hongliang (20/07/27(Mon) 09:04) #95374
│└ Re[2]: Win-10/Pro + C# + IPAmj明朝 /Hongliang (20/07/27(Mon) 09:44) #95375
Re[1]: Win-10/Pro + C# + IPAmj明朝 /魔界の仮面弁士 (20/07/27(Mon) 09:49) #95377
  └ Re[2]: Win-10/Pro + C# + IPAmj明朝 /S.Kos (20/07/27(Mon) 10:18) #95380
    └ Re[3]: Win-10/Pro + C# + IPAmj明朝 /S.Kos (20/07/27(Mon) 14:31) #95385
      └ Re[4]: Win-10/Pro + C# + IPAmj明朝 /魔界の仮面弁士 (20/07/27(Mon) 15:46) #95386
        └ Re[5]: Win-10/Pro + C# + IPAmj明朝 /S.Kos (20/07/27(Mon) 19:50) #95387
          └ Re[6]: Win-10/Pro + C# + IPAmj明朝 /魔界の仮面弁士 (20/07/27(Mon) 20:41) #95388
            └ Re[7]: Win-10/Pro + C# + IPAmj明朝 /S.Kos (20/07/28(Tue) 10:00) #95389 解決済み
              └ Re[8]: Win-10/Pro + C# + IPAmj明朝 /魔界の仮面弁士 (20/07/28(Tue) 10:54) #95390 解決済み


親記事 / ▼[ 95374 ] ▼[ 95377 ]
■95373 / 親階層)  Win-10/Pro + C# + IPAmj明朝
□投稿者/ S.Kos (5回)-(2020/07/27(Mon) 08:23:39)

分類:[.NET 全般] 

こんにちは、みなさま
Win-10/Pro+C#で、表帳へプリンタ出力しようとしています。
System.Drawing.Printing.PrintPageEventArgs e の構成までは記しませんが、

System.Drawing.Font font = new System.Drawing.Font("MS 明朝", (float)cmS.fSize);
Brush brush = new SolidBrush(Color.Black);
e.Graphics.DrawString("なんちゃらかんちゃら", font, brush, new PointF(20, 30));

で巧く動いています。

人名に「ちょん切れた草冠」があり、これまではShift-JISの外字で対応していました。
今回これを、全てUnicodeとすべく、経産省「文字情報基盤整備事業」が配布する"IPAmj明朝フォント"を試しています。

ところが、上記コードを
System.Drawing.Font font = new System.Drawing.Font("IPAmj明朝", (float)cmS.fSize);
としただけでは、ダメみたいです。

書き出し文字に「ちょん切れた草冠」があると、ゴシック体の後にいわゆる豆腐が付与されます。
"IPAmj明朝"の活用について、ご教示いただければ幸いです。
[ □ Tree ] 返信 編集キー/

▲[ 95373 ] / ▼[ 95375 ]
■95374 / 1階層)  Re[1]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ Hongliang (1065回)-(2020/07/27(Mon) 09:04:59)
該当文字のUnicodeコードポイントを書いといていただけると追試が楽なので、次があればお願いします。

さて、表示結果から推察して多分IVSで字体を変えているものと思われます。
System.Drawing.Graphics::DrawStringメソッドは内部ではGDI+というWindowsの機能を使っているのですが、これはIVSに対応していません(emojiとかも対応してません)。
代わりに、System.Windows.Forms.TextRenderer.DrawTextメソッドを使用します。こちらはGDIというWindowsの機能を使っていて、IVS(やemoji……カラー絵文字は未対応だったかな)に対応しています。

ただし、TextRenderer.DrawTextは余白の扱い等でGraphics::DrawStringと多少異なる部分があるのにはご注意ください。
[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95374 ] / 返信無し
■95375 / 2階層)  Re[2]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ Hongliang (1066回)-(2020/07/27(Mon) 09:44:50)
すいません、先の投稿は取り消します。
ドキュメントによると
> TextRenderer クラスによって提供されるテキストレンダリングは、GDI テキストレンダリングに基づいており、Windows フォームからの印刷ではサポートされていません。 代わりに、Graphics クラスの DrawString メソッドを使用します。
とのことなので、印刷用途では使えないようでした。

// うーん、こうなるともうSystem.Printing使う方向になるかなぁ…。
[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95373 ] / ▼[ 95380 ]
■95377 / 1階層)  Re[1]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ 魔界の仮面弁士 (2786回)-(2020/07/27(Mon) 09:49:06)
2020/07/27(Mon) 10:36:49 編集(投稿者)

No95373 (S.Kos さん) に返信
> 人名に「ちょん切れた草冠」があり、これまではShift-JISの外字で対応していました。

[U+8279] 3画の草冠(┼┼)
[U+5EFF] 3画の草冠(廿)
[U+FA5D] 4画の草冠(┤├)
[U+FA5E] 4画の草冠(┼ ┼)


> 書き出し文字に「ちょん切れた草冠」があると、ゴシック体の後にいわゆる豆腐が付与されます。

異体字セレクタ(IVS)ですよね。

人名利用ということで、Hanyo-Denshi コレクションの字形を挙げてみますが、たとえば [U+82E5]「若」の異体字の場合、

[U+82E5][U+E0101] で ┼┼ な草冠 (Hanyo-Denshi, JA2867)
[U+82E5][U+E0102] で ┤├ な草冠 (Hanyo-Denshi, JTB949)
[U+82E5][U+E0103] で ┼ ┼な草冠 (Hanyo-Denshi, JTB948)

が定義されています。この掲示板では Unicode 非対応なので、
実際の字形は下記の「登録済の異体字を検索」で確認してみてください。
https://747.github.io/vsselector/

※追記:その後の No95380 で「花」の異体字だと分かったので、
 下記を見た方が直接的かも知れません。草冠以外の差異、
 たとえば E0103 と E0106 の違い(七とヒ)も視認しやすい。
http://tool.mau2.com/ivs/ja/u/%E8%8A%B1


private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
  // GDI+ な Graphics.DrawString は、印刷にも使えるが異体字が文字化けする
  using (var f = new Font("IPAmj明朝", 24f))
  {
    e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
    e.Graphics.DrawString("\u82E5\U000E0101", f, Brushes.Red, 10f, 10f);
    e.Graphics.DrawString("\u82E5\U000E0102", f, Brushes.Green, 10f, 70f);
    e.Graphics.DrawString("\u82E5\U000E0103", f, Brushes.Blue, 10f, 130f);
  }
}

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
  // GDI な TextRenderer.DrawText は異体字に対応しているが、印刷には使えない
  using (var f = new Font("IPAmj明朝", 24f))
  {
    e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
    TextRenderer.DrawText(e.Graphics, "\u82E5\U000E0101", f, new Point(10, 10), Color.Red);
    TextRenderer.DrawText(e.Graphics, "\u82E5\U000E0102", f, new Point(10, 70), Color.Green);
    TextRenderer.DrawText(e.Graphics, "\u82E5\U000E0103", f, new Point(10, 130), Color.Blue);
  }
}

private void button1_Click(object sender, RoutedEventArgs e)
{
  var printDialog = new PrintDialog();
  if (!printDialog.ShowDialog() ?? false)
  {
    return;
  }

  // WPF なら異体字の印刷も可能
  var textBlock = new TextBlock();
  textBlock.FontFamily = new FontFamily("IPAmj明朝");
  textBlock.FontSize = 24d;
  // textBlock.Text = "\u82E5\U000E0101\r\n\u82E5\U000E0102\r\n\u82E5\U000E0103";
  Run r = new Run("\u82E5\U000E0101\r\n") { Foreground = new SolidColorBrush(Colors.Red) };
  Run g = new Run("\u82E5\U000E0102\r\n") { Foreground = new SolidColorBrush(Colors.Green) };
  Run b = new Run("\u82E5\U000E0103\r\n") { Foreground = new SolidColorBrush(Colors.Blue) };
  textBlock.Inlines.AddRange(new Inline[] { r, g, b });

  var canvas = new Canvas();
  Canvas.SetTop(textBlock, 100);
  Canvas.SetLeft(textBlock, 100);
  canvas.Children.Add(textBlock);

  var page = new FixedPage();
  page.Children.Add(canvas);

  var queue = printDialog.PrintQueue;
  var writer = PrintQueue.CreateXpsDocumentWriter(queue);
  writer.Write(page);
}
[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95377 ] / ▼[ 95385 ]
■95380 / 2階層)  Re[2]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ S.Kos (1回)-(2020/07/27(Mon) 10:18:43)
Hongliangさん、ご教示のほど感謝です。

"該当文字のUnicodeコードポイント"とは「U+82B1, 82B1_E0106」で宜しいしょうか?
草冠がちょん切れた「花」です。

さて、No95374の"DrawStringメソッドは内部ではGDI+という・・"を拝読し、内部が判らないクラスに、改めてウンザリしています。
遥か昔(?)の、P・J・プラウガーだったか、「関数とはトイレである、そのココロは、覗こうとは思わないが、中でのありさまは誰もが知っている」との言を懐かしく思い出しました。

ご教示に沿って"TextRenderer.DrawTextメソッド"を探り、MSのドキュメント
>TextRenderer クラスによって提供されるテキストレンダリングは、GDI テキストレンダリングに基づいており、Windows フォームからの印刷ではサポートされていません。 代わりに、Graphics クラスの DrawString メソッドを使用します。
>
に辿り着いたところでした。

この"Windows フォームからの印刷ではサポートされていません"に戸惑い、改めてお尋ねしようと開いたらNo68375に次のご教示がありました。

> // うーん、こうなるともうSystem.Printing使う方向になるかなぁ…。
>
VC6の時代、ゴリゴリのCでプリンタアプリケーションを作っていたので、Win/APIを直接呼ぶことにも抵抗はありません。

詰まるところは、C#で"IPAmj明朝"をプリンタ出力したい、だけです。
重ねてご教示いただけれは幸いです。

と思ってたところ、魔界の仮面弁士さんに、コードを示していただきました。
取り急ぎ、ここまで投稿します。


[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95380 ] / ▼[ 95386 ]
■95385 / 3階層)  Re[3]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ S.Kos (3回)-(2020/07/27(Mon) 14:31:49)
魔界の仮面弁士さん、ご教示のほどありがとうございます。

示していただいたコード、
>var canvas = new Canvas();
>Canvas.SetTop(textBlock, 100);
>Canvas.SetLeft(textBlock, 100);
>canvas.Children.Add(textBlock);
>
が判らなかったので、WPFなるシカケを探ってみました・・・なにやら(?)厄介そうですねぇ・・・
キャンバス(印刷用紙?)を用意して、
印刷データを載せ・・書き込む、ではない?
プリンタキューへ、キャンバスごと、引き渡す。

こんなイメージかと理解しました。
やってみましょう。

[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95385 ] / ▼[ 95387 ]
■95386 / 4階層)  Re[4]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ 魔界の仮面弁士 (2789回)-(2020/07/27(Mon) 15:46:22)
No95385 (S.Kos さん) に返信
> WPFなるシカケを探ってみました・・・なにやら(?)厄介そうですねぇ・・・

"PrintQueue.CreateXpsDocumentWriter" などで検索すると、印刷系のサンプルが見つかるかも。
WinForms との連携ではなく、WPF Application 向けの情報が殆どだとは思いますが。

もしも先のコードを Windows Forms アプリケーションから呼び出す場合は、下記が必要です。

 // 追加するべき参照設定
 PresentationFramework.dll
 PresentationCore.dll
 WindowsBase.dll
 System.Printing.dll


 // 必要な名前空間
 using System.Printing;
 using System.Windows.Controls;
 using System.Windows.Documents;
 using System.Windows.Media;


ただし、下記で示した名前空間の競合がありますので、
実際のコードでは名前空間を含めて指定するようにするか、
あるいは using で別名を付与しておくことが求められます。


> var printDialog = new PrintDialog();
System.Windows.Forms.PrintDialog クラスではなく
System.Windows.Controls.PrintDialog クラスの方です。


> textBlock.FontFamily = new FontFamily("IPAmj明朝");
System.Drawing.FontFamily クラスではなく
System.Windows.Media.FontFamily クラスの方です。
[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95386 ] / ▼[ 95388 ]
■95387 / 5階層)  Re[5]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ S.Kos (4回)-(2020/07/27(Mon) 19:50:47)
魔界の仮面弁士さんのご教示に沿って、なんとか一行だけのテスト印字成功まで、辿り着きました。
MSのサイトを覗きながらusing設定する過程で、

Windows フォームアプリケーションから印刷する場合は、System.Drawing.Printing 名前空間を参照してください。

とのコメントを数多く目にしました。
いま、私がやろうとしていることは正にソレです。

レガシーなフォームアプリケーションの一部を、"IPAmj明朝"を使いたいが為だけに、WPFで書き換えようとしています。
たった一行とは言え、まともに動いているように思えるのですが・・・

このあたりの事情をご教示いただければ幸いです。


と、エディタで書き、サイトを開いたらNo95386がありました・・!
ざっと眺めた限りでは、これが回答になっているかと・・

[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95387 ] / ▼[ 95389 ]
■95388 / 6階層)  Re[6]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ 魔界の仮面弁士 (2790回)-(2020/07/27(Mon) 20:41:33)
2020/07/27(Mon) 20:43:58 編集(投稿者)

No95387 (S.Kos さん) に返信
> Windows フォームアプリケーションから印刷する場合は、System.Drawing.Printing 名前空間を参照してください。

それは、WPF で使う System.Printing 名前空間とは別物です。


System.Drawing.Printing 名前空間は、主に Windows Forms 用であり、
PrintDocument クラスや PrinterSettings クラスなどを有しています。
(GDI+ 系の印刷処理で使われるものです)


[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95388 ] / ▼[ 95390 ]
■95389 / 7階層)  Re[7]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ S.Kos (5回)-(2020/07/28(Tue) 10:00:42)
魔界の仮面弁士さん、ご教示のほど感謝しかありません。

"IPAmj明朝"を用いて「ちょん切れた草冠」を、WPF経由でプリンタ出力できました。
加えて、直線や楕円の描画などSystem.Drawing.Printingによる実装も、全てをWPFで書き換えられました。

改めて御礼申し述べます。ありがとうございました。

解決済み
[ 親 95373 / □ Tree ] 返信 編集キー/

▲[ 95389 ] / 返信無し
■95390 / 8階層)  Re[8]: Win-10/Pro + C# + IPAmj明朝
□投稿者/ 魔界の仮面弁士 (2791回)-(2020/07/28(Tue) 10:54:21)
No95389 (S.Kos さん) に返信
> "IPAmj明朝"を用いて「ちょん切れた草冠」を、WPF経由でプリンタ出力できました。
> 加えて、直線や楕円の描画などSystem.Drawing.Printingによる実装も、全てをWPFで書き換えられました。

それは良かった!


追記として…WPF による印刷 では、.NET Framework + Win10 の場合、
明示的に Dispose しないと、メモリ解放が遅れることがあるようです。
https://qiita.com/fala/items/b28d4dbd2d0a8c189b55

解放にあたり、印刷完了まで待ち合わせる必要があるかもしれません。
https://ktts.hatenablog.com/entry/2019/02/27/235205


# 当方未検証です。
解決済み
[ 親 95373 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -