WindowsXP VC++6.0SP6 SDK(アップデート版)
プロジェクトの設定は C/C++タブに _UNICODE リンクのアウトプットに
wWinMainCRTStartupです
スケルトンは SDIです
CString s1,s2;
int x1,x2,y1,y2,len;
void CTestView::OnDraw(CDC* pDC){
なにがしかの処理の後
pDC->TextOut(x1,y1,s1);
なにがしかの処理の後 同じ行の異なる位置に
pDC->TextOut(x2,y1,s2);
その後なにがしかの処理
}
pDC->TextOut(x1,y1,s1);によりs1を印字(画面上に表示するのも便宜上印字ということ
ばを
使わせていただきます)
したあとそのすぐ右の位置から
pDC->TextOut(x2,y1,s2);によりs2を印字するのが目的です
MBCSの場合ですと len = s1.GetLength()でながさを取得してそれに
半角1文字の印字幅( ここではhabaとします )かけて すなわち
len * haba で計算できるのですが
UNICODEだとどのようにすればよろしいのでしょうか
すぐ右でいいなら発想を逆にして s1+s2 を TextOut すれば簡単
> MBCSの場合ですと len = s1.GetLength()でながさを取得してそれに
> 半角1文字の印字幅( ここではhabaとします )かけて すなわち
> len * haba で計算できるのですが
等幅フォント決めうちならそれでいいかもしれんけど、
そうじゃなかったら iiiii と MMMMM の幅はふつー異なりますけども…
説明不足だったようです
たとえば一例として s1 = _T(abc東京); だったとしますと
印字長 は haba * 7 になりますが
この 7 に相当する数値を得たいわけです
これを len となづけて
x2 = x1 + len; と計算して
pDC->TextOut(x2,y1,s2);
とすればよいと考えているわけです
それから一回きりだったら tetrapodさんがおっしゃるようにできますが
ひとつ上の目的としては
int Next_X_Position,Next_Y_Position;
void CTestView::DisplayString(CString InputString){
}
Next_X_Position,Next_Y_Position はすでに表示してある文字列の
すぐ右の位置を示します InputStringには表示したい文字列をいれます
int Next_X_Position,Next_Y_PositionはInputStringをもとに
この関数が更新します
DisplayStringのなかをコーディングするのに
質問したことが必要になると考え質問したわけです
>この 7 に相当する数値を得たいわけです
単にバイト数がほしいならば、Shift_JISコードに変換して算出するんですかね。
ただ、Unicodeなんで対応していない文字があると思います。
(1文字ずつ見て、Shift_JISコードでの半角に当たるかどうかチェックするのが妥当か
な。)
別解:
byteを要求されるCDC::TextOutでなく、
文字数を渡す::TextOut (UNICODE版)を使う。
最終的に表示幅が欲しいなら、GetTextExtent でよいのでは。
または、位置更新モードで TextOut して、
GetCurrentPosition で次の表示位置を得るとか。
出力位置を計算するのに,不確かな方法を使うのではなく,
出力幅を得るCDC::GetTextExtentのような関数を使って計算するようにすればよいので
は?
# そもそも記号はFIXED_PITCHでも幅が異なるものですし。
むっちゃ御意。GetTextExtent32 のほうが良いらしいけど。
それとは別に
DisplayString(const CString& InputString) のほうが良いかもしれない。
個人的には DisplayString(const TCHAR* s) も欲しい気がする。
# っていうか後者があれば前者はイラン
> 等幅フォント決めうちならそれでいいかもしれんけど、
> そうじゃなかったら iiiii と MMMMM の幅はふつー異なりますけども…
そうですね プロポーショナルの場合など幅は一定ではないですね
> 単にバイト数がほしいならば、Shift_JISコードに変換して算出するんですかね。
そうですね MBCSに変換したと仮定したときのバイト数がわかれば
問題解決と思っていました
調べてみましたら それは WideCharToMultiByte や wcstombs など使えば解決するよ
うです
ところが上記に指摘されたように幅が一定でない場合もありますので
この方法は使えないようです
> GetTextExtent
> または、位置更新モードで TextOut して、GetCurrentPosition で次の表示位置を得る
とか。
あとでも述べますがこの二つはいまのところ必要不可欠のようです
> 出力位置を計算するのに,不確かな方法を使うのではなく,
> 出力幅を得るCDC::GetTextExtentのような関数を使って計算するようにすればよいので
は?
> # そもそも記号はFIXED_PITCHでも幅が異なるものですし。
上記と同様 おっしゃるとおりです
> むっちゃ御意。GetTextExtent32 のほうが良いらしいけど。
GetTextExtentと使いくらべてみます
> それとは別に
> DisplayString(const CString& InputString) のほうが良いかもしれない。
関数(const CString& InputString)
関数(CString InputString)
のちがい(どこにどういう影響のちがいがでるのか)が私にはまだよく
わからないので勉強します(値渡しと参照渡しのちがいかな)
> 個人的には DisplayString(const TCHAR* s) も欲しい気がする。
> # っていうか後者があれば前者はイラン
わたくしには CString型のほうが扱いやすいようです
-----------------------------------------------------------------------------
ご指摘をふまえ その後調べた結果をご報告します
(1)pDC->SetTextAlign(TA_UPDATECP);
で自動更新を設定すれば文字幅は気にせずに
pDC->TextOut(0,0,s);
でどんどん文字列を追加表示して良いようです
(2)ただし 右端で折り返してくれないので
GetCurrentPositionやGetTextExtentを使って
情報を取得して
必要とあらば行を改めることをします
(3)改行または任意の位置から始めたいときには
MoveToなどを使います
個々にご芳名は挙げませんが皆様大変ありがとうございました