• ベストアンサー

GetTextExtentPoint32での高さ

こんにちは。 数字が入った文字列をGetTextExtentPoint32関数で幅と高さを取得しようとすると、幅は正しく取得できるのですが、高さが倍近い値で返ってきてしまいます。どうやら高さはフォント全体の高さで取得しているようです。"0123"と"0123j"をセットしても同じ高さが返ってきます。 これを実際の描画範囲で取得するにはどうすればよろしいのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

幅については描画する範囲がプロポーショナルピッチによる幅の変動する為、取得する必要がありますが、 高さについては文字(といか行)毎に上下することはない(上下するようでは見にくい)ということから、指定したフォントで設定されている値がそのまま返却されるのでしょう。 それでも「描画される最小矩形」が必要なのでしょうか? 画面更新時はなるべく最小矩形の方が処理量は減るかと思われますが、現在のPCならドライバ任せでも問題になるような差は出ないと思われますが……。 それでも取得したい。 ということであれば文字列を分解してGetGlyphOutline()で取得することで1文字のフォントでの矩形サイズが取得できるでしょう。 ただし、文字描画の際にはベースラインなどを考慮しますので、ベースラインをそろえた上で算出する必要がありますが…… http://marupeke296.com/WINT_GetGlyphOutline.html 辺りが図になっているのでわかりやすい…でしょうかね。 各文字のグリフを取得した後、「ベースラインより上」と「ベースラインより下」のサイズをそれぞれ算出し、必要な文字フォント分の処理を終えた後で加算すればよいでしょう。 # uCharの設定がいろいろと手間…でしょうかね。(UNICODEならそれほどでもないかも知れませんが…SJISだと面倒) # uFormatも…かな。アンチエイリアス有りと無しでは取得できるサイズが変わるでしょうし。 # cbBufferは0、lpvBufferはNULLでもかまわない…かも知れません。 使用する文字によっては… (gmBlackBoxY - gmGlyphOrign.y)がマイナスになってしまう場合もあるのでご注意を。 # "-"等、ベースラインより上だけで済んでしまうものの場合とか。

TeijigoTeatime
質問者

お礼

詳細なご返答ありがとうございます。 いろいろ考慮しなくてはならないことが多いですね。 片手間ではできそうもありません。 今はGetTextExtentPoint32を利用して、余裕ができたらWr5さんの提示していただいた方法を確認してみます。 ありがとうございました。

関連するQ&A

  • 文字を削除して合計 Excel2007

    Excelで数字を含む文字列から数字のみを取り出し、合計する方法を考えているのですが、わかりません。  |..A..|..B..|..C.|..D.| .2|50%|30%|20%|10%| という風にセルに記入している場合、E2に全体としての割合を表す関数を作りたいと思っています。 とりあえず各セルから%を除いて数字のみを表示する関数を作りました。 =LEFT(A2,LEN(A2)-1) 例はデータが少ないのですが、実際は多数のデータを使うつもりなので、全ての値を足すのでなく、 指定した範囲内の値を合計するようにしたいと思っています。 作業列を使えばできるかもしれませんが、使わない方向でやりたいので、宜しくお願いします。 ちなみに、各割合は、別のシートから=で値を入力しています。

  • PHPのGD系の関数で描画した文字列の下に下線を引きたい

    PHPのGD系の関数で描画した文字列の下に下線を引きたい PHPのGD系の文字列関数がありますよね? (例:日本語が扱えるやつだとImageTTFTextとか) これで文字列の長さに揃えてリンクっぽく見せるために 下線を引きたいのですが、良い手法が思いつきません。 文字数をstrlenでカウントしてフォントのサイズ/2を掛けたら 文字列の長さになるかなーと思って試しましたが、 これだとaとあの文字の横幅が違うようにずれが出ます。 あるフォントである文字列描画関数を使ったときに文字列の横幅が 調べられるような手法があれば、その長さに応じた下線が引けるのですが、 そうした手法はないでしょうか?

    • ベストアンサー
    • PHP
  • GetTextExtentの動きが違う

    VC++2008でmfcによるグラフィックス系のアプリを開発しています。 ビューに文字列を描画する前にその幅を取得したく、 文字列入力用のエディットボックスに文字列を入力中にメモリデバイスコンテキストを作成し、 GetTextExtent関数を用いて取得しています。 しかし、Releaseビルドして実行したところ、Debug版で取得したサイズと違うため困っています。 例えばDebug版で1文字の幅が18、2文字で35となっているものが、 Release版だと28, 57になっていました。 幅を同じにするための解決案はございますでしょうか。

  • エクセルの関数の質問です。

    エクセルの関数の質問をさせていただきます。 例えばセルA列に1,2,5,6,4,5,7,9,10,13というランダムな値があったら、1は1の儘で、それ以外の奇数を偶数にしてB列に呼び出すような関数がありましたら教えてください。 このA列の値は1-15-1、2-3-2、5-2-3、というような文字列の左側の値をMID関数を使って呼び出した値です。 よろしくお願いします。 前回の質問と同じプログラムなのですが、全体の値を半分にして求めた数を2倍にしてみたのですが、値を半分にすると精度が少し狂いますので、再度、良い方法があったら教えていただきたくお願いいたします。

  • Excel LookUP関数のタイプ設定

    お世話になります。 エクセルで別シートにデータベースを作り、メインのシートで入力したらLookUp関数で名前を取得するように組んでいます。 このとき、入力するコードが数字4桁固定で、しかも0から始まるので文字列にし、データベースも文字列指定しているのに、正しい値を持ってきません。 どうやら、関数では数字で認識していたり、文字列になっていたり、正しい名称をもってきたり来なかったりと不安定です。 どのように設定したら良いのでしょうか、教えてください。

  • rand関数の割合変更

    C言語プログラムでrand関数を使用して乱数を取得しているのですが、 取得できる値の範囲の割合を変更することは出来ないでしょうか? 例えば、0~10の範囲の乱数を取得するようにしている場合、 0~3の範囲の値が全体の10%、 3~8の範囲の値が全体の50%、 8~10の範囲の値が全体の40% といった割合で取得するようにはできないでしょうか? よろしくおねがいします

  • Excelの関数で、範囲内で条件と一致したセルの位置を取得するには

    Excelの関数で、範囲内で条件と一致したセルの位置を取得するには どうすればよろしいでしょうか? (例)  5行×5列にA~Yまでの25文字がランダムで配置されている場合、  「K」と「R」の位置(相対位置等)を取得したい。  ※範囲内に配置されている値は重複しません。 実際は20行程度×20列程度の範囲です。 ほとほと困り果てています。 よろしくお願いします。

  • エクセルで一致する値のタイトルを取得

    初歩的な質問ですみません。探しましたが見つかりませんでした。 B3の値を用いて 範囲D3:F6の値で比較。 一致する数値がある列の一番上の文字列を取得したいのですが この場合は,D3に値があるので,D2の「松」という値をどこか任意のセル(B2)に返します (実際はもっと大きなデータでB3に対応する値も複数,でもこれは一つ関数をつくってちょっといじればいいのかと思っています(^_^;) エクセル得意な方お願いします!

  • EXCELで範囲内にある値を検索してA列の値を返す

    タイトル通りなのですが、OSはXPでEXCEL2000を使用しています。 シート内ですが 1.A列には文字列が入っています。200行まで空白は無いです。 1.B列からL列の200行までに数字がランダムに入っています。 2.数字は1~500までです。 3.行によってはL列まですべてのセルに値が入ってません。  数字の入っていないセルは空白です。 4.数字の重複はありません。 やりたいことは 別のシートのA列に1~500までの数字を入れ、B列に上記範囲の中からその数字を検索して、その行のA列の値を返したいのですが、出来ません。 どの関数を組み合わせれば出来るのでしょうか? vlookupの検索範囲は1列だけなのでダメでした。 よろしくお願いします。

  • JavaのString、StringBuffer、Charの中でメモリ

    JavaのString、StringBuffer、Charの中でメモリの使用が一番良いものは? Java初心者です。 現在JavaMEのMIDP(2.0)で辞書アプリケーションを作成しています。 携帯電話のメモリが小さいことから不向きではあると思っていますが、できるだけ多くの単語と説明を登録していようとしています。 基本的な文法は通常のJavaと同じだと思います。 大まかな構造は不要部分を省きますと、 ----- class Dictionary extend Canvas(){  int i,j,start=0,end=0,x=1;  private static Font fontL=Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_LARGE);  void paint(Graphics g){   //getsetsumei(x)で単語の意味・説明をString型で受け取っています。   //substringで一文字ずつ増やしながら文字の横幅をgetWidthで受け取り、   //描画画面横幅の最大値240を越えないように部分文字列で表示しています。   //文字の続きは文字サイズの縦幅をfontL.getHeight()で取得し、   //改行のような形で続けて表示します。   //また描画画面縦幅の最大領域getHeight()を越えて表示しないために   //i行目までに描画した文字列の縦幅の総和がこれを越えないようにすることで、   //無駄な描画をしないようにしています。   for(i=1;i!=0 && i*fontL.getHeight()<getHeight()-130;i++){//画面縦幅の描画範囲の判定    while(fontL.stringWidth(getsetsumei(x).substring(start,end+1))<240){//画面横幅の描画範囲の判定     end++;//横幅に達するまで文字数を増やす     if(end==getsetsumei(x).length()){//表示すべき文字列の取得が終わった      g.drawSubstring(getsetsumei(x),start,end-start,0,130+x,Graphics.TOP|Graphics.LEFT);      i=-1;//終了条件のi!=0を満たさなくするため      break;     }    }    //描画すべき文字列の一部をSubstringで描画    g.drawSubstring(getsetsumei(x),start,end-start,0,130+y,Graphics.TOP|Graphics.LEFT);    start=end;//次の行の描画すべき部分文字列の開始位置を指定    y+=fontL.getHeight()+1;//改行のためのy座標の移動   }  }  String getsetsumei(int DicNum){   switch(DicNum){   case 0:return " ";//説明無し   case 1:return "辞典,辞書,字引";//Dictionaryの意味、説明   }  } } ----- となっています。 実際は単語の意味をString型で返すgetsetsumeiの引数xの値を変化させて単語に合わせて意味を取得しようとしています。 改行するプログラムのためにgetsetsumei関数は何度も呼ばれることになるので、できるだけメモリを使用せず、高速にしたいと思っています。 色々調べたところStringは非可変文字列であるとのことでした。 これは説明内容が変更されるたびに別のメモリを確保するということでしょうか? それとも同じメモリに新しい説明が上書きされるのでしょうか?その場合、StringではなくStringBufferを使用すべき、もしくはchar配列を使用すべきでしょうか? どなたかご教授願います。

    • ベストアンサー
    • Java

専門家に質問してみよう