テキストボックスの文字列を、そのままピクチャボックスに描画するには?

解決


夏の朝も天玉うどん  2005-05-21 16:59:08  No: 121836  IP: [192.*.*.*]

はじめまして。使用言語はVB.NETです。
簡単なエディタもどきを作成しようと考えています。
以下のようなコード
Dim drawbrush As Brush = New SolidBrush(Color.DarkBlue)
canvas.Font = InputBox.Font  ’入力用ボックスのフォントに合わせる。
・・・.DrawString(InputBox.Text, canvas.Font, drawbrush, 0, 0)
で、このcanvasと言う名のピクチャボックスに描かれる文字列の全体の
幅が入力用テキストボックスの文字列の幅と変わってしまいます。
これを同じに(DrawImageなどは使わずに)する方法は、
ありませんか?
よろしく、おねがいいたします。

編集 削除
夏の朝も天玉うどん  2005-05-22 10:20:13  No: 121837  IP: [192.*.*.*]

追記します。どうやらこの現象は日本語のテキストのところに限って
起こっているようです。
よろしく、おねがいいたします。

編集 削除
マグ  2005-05-22 13:07:10  No: 121838  IP: [192.*.*.*]

>このcanvasと言う名のピクチャボックスに描かれる文字列の全体の
>幅が入力用テキストボックスの文字列の幅と変わってしまいます。

読んだのですが、理解できませんでした。

PictureBoxに描画するときにTextBoxのフォントと
同じ大きさで描画したいということでしょうか?

それをしたいならば、
TextBoxのコントロール名はInputBoxにしています。
PictureBoxのコントロール名は貼り付けたときの名前です。
あと、Buttonも追加してください。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim g As Graphics = Nothing

        g = PictureBox1.CreateGraphics
        g.Clear(SystemColors.Control)

        Dim drawbrush As Brush = New SolidBrush(Color.DarkBlue)
        g.DrawString(InputBox.Text, InputBox.Font, drawbrush, 0, 0)

        If Not g Is Nothing Then
            g.Dispose()
            g = Nothing
        End If
        If Not drawbrush Is Nothing Then
            drawbrush.Dispose()
            drawbrush = Nothing
        End If

    End Sub

編集 削除
夏の朝も天玉うどん  2005-05-22 14:41:32  No: 121839  IP: [192.*.*.*]

レスありがとうございます。
説明の仕方が下手で申し訳ありません。例えばテキストボックスに以下の文
  "ABCDEFGあいうえおHIJKL" などと入力し、それをピクチャボックスに
DrawStringで表示したときに文字"A"から文字"L"までの長さがピクセル単位
で示したときに変わってしまうということです。これでもまだ解りづらいと
思いますが、もう少し具体的に説明します。

ピクチャボックスの上に入力用テキストボックスを置き、その下にテキスト
ボックスの内容を表示し、テキストボックスを消す。そうしたときにその
テキストボックスが消えたことが解らない、ピクセル単位で同等のものが
描画されているといったイメージなのですが。

編集 削除
マグ  2005-05-22 16:48:36  No: 121840  IP: [192.*.*.*]

>ピクチャボックスの上に入力用テキストボックスを置き、その下にテキスト
>ボックスの内容を表示し、テキストボックスを消す。そうしたときにその
>テキストボックスが消えたことが解らない

TextBoxとPictureBoxを連動させたいということですよね。
TextBoxのTextChangedで出来ませんでしたか?

あるいは、KeyUpイベントでBackSpaceが押されたかを確認させて、再描画
する方法でも、出来ませんでしたか?

>ピクセル単位で同等のものが
>描画されているといったイメージなのですが。

フォントのサイズはpt(ポイント)です。
もしかして、ピクセルなんて思ってないですよね。
それとも、ポイントをピクセルに単位を変換したいということでしょうか?

編集 削除
夏の朝も天玉うどん  2005-05-23 20:08:22  No: 121841  IP: [192.*.*.*]

やはり私の説明が下手なようです。"ABCDEFGあいうえおHJKL"を
テキストボックスに入力し、それを同一フォントでピクチャボックスに
DrawStringで描画します。それを文字"A"の位置を合わせて表示した場合に
終わりの文字位置"L"が揃わないということなんです。極端に記述すると
"ABCDEFGあいうえおHJKL"(テキストボックス)が
"ABCDEFGあ い う え おHJKL"(ピクチャボックス)となるような感じです。
これは半角スペースを入れて表現していますがここまで極端では
ありませんが日本語(全角)をいれると終端が揃わないのです。
そのために入力用テキストボックスを消したときその下に同じ文字列を描画
していても同一の画像(見た目)が表示されていないということなのです。
何かこれでもまだ上手に説明できていないのがわかるのですが、
何とかよろしくお願いいたします。

編集 削除
葉月α  2005-05-24 12:47:09  No: 121842  IP: [192.*.*.*]

.Netは無知ですが
テキストボックスにも、ピクチャーボックスにもフォントの設定はできませんでしたか?
この際に、等幅フォントを12ポイントで選択すれば
全角半角の問題は解決できるんじゃないでしょうか?
一般的にMS明朝やMSゴシックが等幅フォントにあたります

デフォルトはMS Pゴシックになっていると思われます

フォントについて、プロポーショナルフォントと等幅フォント
フォントサイズについて調べてみてください

編集 削除
マグ  2005-05-24 16:50:00  No: 121843  IP: [192.*.*.*]

基本的に半角文字と全角文字は文字の長さが違います。
そのことは、注意してますよね。
見れば、長さが違うことぐらいは分かるのですが・・・・
半角文字と全角文字を同じ長さで並べると夏の朝も天玉うどんさん
が記述したような現象が起こります。
回避方法としては、葉月αさんの言うとおり、フォントで描画してしまうのが
速いです。
それが出来なかった場合、半角文字の長さと全角文字の長さを別々に取得し、
キーボードが押されたのを確認し、入力されたのが、半角か全角かを判断
させて、描画するという方法もあります。
でも、これ、面倒だけど・・・・

あと、できれば、原因を再現できるソースも記述して欲しいです。

編集 削除
さるべーじ  2005-05-24 17:54:38  No: 121844  IP: [192.*.*.*]

> マグさん 2005/05/22(日) 13:07:10

のコードで検証してみました。
FormのFontはMS UI Gothic 9pt.、使用した文字列は「abcdeあいうえお」で、
表示結果をキャプチャしてグラフィックエディタでピクセル単位で比較。

「e」と「あ」の間の空白が、PictureBoxへDrawStringすると2ピクセル、
TextBoxの表示は1ピクセルといぅ結果になりました。

プロポーショナルフォントの問題ではなく、カーニングの違いを質問されているのではないかと思います。

編集 削除
夏の朝も天玉うどん  2005-05-24 19:50:45  No: 121845  IP: [192.*.*.*]

マグ様・葉月a様・さるべーじ様  レスありがとうございます。
ソースについてはマグ様が先に示していただいたものと同等と思っていただいて結構です。実際に現在は、そのコードで検証(行き当たりばったり)
しているところです。
当初からサルベージ様が示していただいたような説明ができていればと
反省しきりです。(特にマグ様には、申し訳なく思っております)

この書き込みの前に「カーニング」で調べてみたのですが「文字詰め」
くらいの言葉の意味くらいしか解りませんでした。
この問題を回避する手段はないものでしょうか?
改めてお願いいたします。

編集 削除
通ってみた  2005-05-24 23:14:08  No: 121846  IP: [192.*.*.*]

いっそテキストボックスをキャプチャしてピクチャに貼っちゃえば?

編集 削除
さるべーじ  2005-05-25 02:06:35  No: 121847  IP: [192.*.*.*]

日本ではあまり「カーニング」についての意識がないようですので、
「kerning」でワールドワイドに探すのがいいと思ういます。

で、ちょっとフォントの構造の知識が必要になると思いますが。

文字ひとつが占有する横幅をB寸法、その左右の他の文字と隣接させないための
空白幅をA寸法(左)、C寸法(右)と言います。
普通はA・C寸法は正数値ですが、左右に飛び出ている形の字体は、
これを負数値とし、わざと隣の文字の領域に食い込ませることで
字間が不自然に空かないようにデザインされている場合があります。

また、上記ABC寸法の例外として、特定の文字のペアの場合にのみ
特に字間を別に狭める組合せの値があり、これをカーニングペア
(kerning pair)と呼びます。

どうも DrawString 等のテキスト出力系のメソッドでは、この
カーニングペアを無視した動作になっているのではないか?
逆に TextBox はカーニングペアまで含めた文字配置となっているために
DrawString との配置差異が発生しているのではないか?

というのが私の推測です。

これは現時点の .Net Framework ではそもそも機能仕様に含まれていないらしく、
アンマネージド API を使用して自力で配置座標を算出する機能を自作するしか
手がないようです。

かなりめんどうな処理になりますのでなんらかの代替手段を
考えた方がいいように思いますが、どうしても実装したいのであれば、

C++6による出力制御サンプル
    http://www.codeguru.com/Cpp/W-P/printing/article.php/c5897/

VB.NETにおける GetKerningPairs API の  Declare 文
    http://custom.programming-in.net/articles/art9-1.asp?f=GetKerningPairs
  (ここは他のアンマネージドAPIの宣言記述も豊富)

あたりでがんばってみていただくしかないかもしれません。

なお、このへんのフォント属性に関する機能は、
.NET Framework2.0 ではラッパされた関数としてクラスライブラリに
なる予定のようです。

編集 削除
夏の朝も天玉うどん  2005-05-26 06:52:29  No: 121848  IP: [192.*.*.*]

さるべーじ様ありがとうございます。
VB5で作成していたソースを生かしたかったことと、
特定の単語を色を変えて表示する等を容易にしたいためDrawStringを使用
したかったのですが、このあたりの仕様変更も含め検討し直したいと思います。
まず最初にカーニングがされないフォントを探してみることになるでしょう。
その結果更なる代替手段を考えてみます。
それで解らないことが出てきましたら改めてお世話になることと思います。
皆様、お手数おかけしました。ありがとうございます。

編集 削除