Edit.Widthの算出方法


GSXR750  2008-06-10 11:04:18  No: 30953  IP: 192.*.*.*

開発環境Delphi7
表題の件ですが文字数に対するEdit.Widthの値を算出したいですが
なにかよい方法はないでしょうか、
VBの場合はLableにBorderを設定して算出していたのですが
Delphi7では無理みたいです。
文字数に対するEdit.Widthの算出式を導く方法はないのでしょうか

尚,Font:MSゴシック,Size:9,Pitch:Default,BorderStyle:single,Ctl3d:true
です。

編集 削除
めじな  2008-06-10 14:02:02  No: 30954  IP: 192.*.*.*

Canvasのフォントを指定してTextHeight,TextWidthで判定出来ませんか。

編集 削除
GSXR750  2008-06-11 13:17:43  No: 30955  IP: 192.*.*.*

めじなさんご回答ありがとうございます。
>Canvasのフォントを指定してTextHeight,TextWidthで判定出来ませんか
方法がわかりません
Canvasてなんですか、プロパティorオブジェクトなんでしょうか

編集 削除
それは  2008-06-11 17:32:50  No: 30956  IP: 192.*.*.*

フォームのプロパティ
Helpに書いてない?

編集 削除
仮のモノ  2008-06-11 17:56:16  No: 30957  IP: 192.*.*.*

真琴:「Canvas知らないナンて、ホントに初心者なんだね、このヒト」
春子:「Delphiは初心者、でもVBはケッコウ出来るみたいじゃない?」
真琴:「だけどハルコさん、TextWidthを使うにもぉ、EditにはCanvasないでしょ?」
春子:「Canvasならナンでもイイんだから仮に自分で作るのよ、マコト」
真琴:「え?そうなの?でもEditのFont変えてもそれで大丈夫?」
春子:「作ったCanvasのFontと、EditのFontを同じにしとけばOKよ」
真琴:「そっか、じゃぁ、これでイイかな?」

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Font.Size := 12;
  Edit1.Font.Name := 'MS ゴシック';
  with TCanvas.Create do try
   Font.Assign(Edit1.Font);
   Edit1.Width := TextWidth(Edit1.Text)+7;
  finally
   Free;
  end;
end;

真琴:「あれ? 実行したら'Canvasに対する描画ができません'てエラー、ナンで?」
春子:「HDCがナイんだもん、仮のHDCでもCanvasのHandleに入れとかなきゃ」
真琴:「また、仮のモノ入れるの?」
広海:「マコトも仮のモノ入れてオッパイ膨らませばもっとモテルんじゃないの〜?」
真琴:「バァ〜ッカ」
春子:「それは、ホンモノで勝負しなきゃネェ〜」

procedure TForm1.Button1Click(Sender: TObject);
var
  Dummy: HWND;     // 追加
begin
  Edit1.Font.Size := 12;
  Edit1.Font.Name := 'MS ゴシック';
  with TCanvas.Create do try
   Handle := GetDeviceContext(Dummy);     // 追加
   Font.Assign(Edit1.Font);
   Edit1.Width := TextWidth(Edit1.Text)+7;
  finally
   Free;
  end;
end;

真琴:「カイトさんは、もう病院に着いたかなぁ…」
広海:「クルマの調子が悪くなけりゃ、オレが病院まで送ってやれたんだけどね」
真琴:「サクラさん大丈夫だよね…、きっと病気軽いよね」
春子:「次の日曜に皆でサクラさんのお見舞いに行こ…ね? マコト」
真琴:「うん」

編集 削除
GSXR750  2008-06-11 19:16:22  No: 30958  IP: 192.*.*.*

理論的に算出式はないのでしょうか

編集 削除
そうなの?  2008-06-11 22:50:17  No: 30959  IP: 192.*.*.*

上の回答の方法が理論的でなくて、「LableにBorderを設定して算出」する方法が理論的であると言う理屈が分からないけど、等幅の"MS ゴシック"FONTに限って言うならば、
文字幅は ((Round(Font.Size * Font.PixelsPerInch / 72) + 1) and $FFFE) div 2
これはDelphiもVBも関係ない。もちろん、この計算式は等幅でないプロポーショナルFONTでは無意味。

編集 削除
もにゃ  2008-06-12 00:03:52  No: 30960  IP: 192.*.*.*

ちゃんとやろうとすると面倒です。
しかもTCanvas使わないとなるとWin32APIの直叩きですよ。
やってることは同じですがこんな感じになります。

procedure TForm1.Button1Click(Sender: TObject);
var
  wRect,cRect:TRect;
  wmgn,hmgn:Integer;
  aSize:TSize;
  fString:String;
  fhBuffer,fhdc:HWND;
  apos:TPoint;
begin
  fString:=Edit1.Text;
  Windows.GetWindowRect(Edit1.Handle,wRect);
  Windows.GetClientRect(Edit1.Handle,cRect);
  wmgn:= (wRect.Right-wRect.Left)-(cRect.Right-cRect.Left);
  hmgn:= (wRect.Bottom-wRect.Top)-(cRect.Bottom-cRect.Top);
  fhdc:= GetDC(Handle);
  fhBuffer := CreateCompatibleDC(fhdc);
  SelectObject(fhBuffer, Edit1.Font.Handle);
  Windows.GetTextExtentPoint32(fhBuffer, PChar(fString), Length(fString), aSize);
  DeleteDC(fhdc);
  DeleteDC(fhBuffer);
  apos:=Point(wRect.Left,wRect.Top);
  apos:=ScreenToClient(apos);
  SetWindowPos(Edit1.Handle,0,apos.X,apos.Y,aSize.cx+wmgn,aSize.cy+hmgn,
               SWP_NOMOVE or SWP_NOACTIVATE or SWP_NOZORDER);
  Caption:=IntToStr(aSize.cx+wmgn);
end;

編集 削除
Mr.XRAY  2008-06-12 00:31:40  No: 30961  IP: 192.*.*.*

GSXR750さんの質問内容は,等倍フォントで,
「文字数に対する」とあります.したがって,2008/06/11(水) 22:50:17のレスの
方法で可能でしょう.これが理論といえば理論です.

「ビーチボーイズ」の仲間と他の方のレスでTCanvasを使用した例は,
通常,「文字の数」から文字列全体の幅を求めるということはしないからでしょう.
それよりも,文字列全体の長さ(幅)の情報を何かに利用することが考えられるからです.
この方法なら,プロポーショナルフォントにも適用可能です.
つまり,文字の数(が必要なときもありますが)よりも,文字列の幅が重要ということです.

釈迦に説法となりますが,プロポーショナルフォントでこの文字列の幅を,
1つ1つの文字幅から算出するのは,非常に困難です.
TCanavsを使用した手順なら,自動的にやってくれます.利用しない手はありません.

フォントの幅の算出が面倒な理由の参考
http://www.winapi-database.com/Graphics/Font/

これはDelphiに限ったことではありません.他の言語でも同じです.
そんなことはない!!  
VBならと言いたいですか〜! (アントニオ猪木の「元気ですか〜」調で)

編集 削除
KHE00221  2008-06-12 01:19:24  No: 30962  IP: 192.*.*.*

>VBの場合はLableにBorderを設定して算出していたのですが
>Delphi7では無理みたいです。

Borderが設定できるって事は TLabel じゃなくて 
TStaticText じゃないのかな?(自前で描画してるかもしれんけど)

編集 削除
ttt  2008-06-12 02:23:22  No: 30963  IP: 192.*.*.*

そうなの?さんの式だと出てくるのは文字の幅じゃなくて高さじゃないでしょうか。

質問者さんがやりたいことは、N文字入力した時に文字がはみ出さない
最小のEditの幅を求めること、だと思われます。
だとすると「理論的に」求めるとしたら、TEXTMETRICを取得して
MaxCharWidthを使うという手もありそうですね。

編集 削除
CANDY  2008-06-12 11:32:19  No: 30964  IP: 192.*.*.*

単純に・・・・
TStaticText(AutoSize)を非表示で持たせて、editと同じフォントにして
値をTStaticTextにセットした後でWidthを取ればいいのでは?

編集 削除