DXライブラリでの自動改行

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
赤鬼

DXライブラリでの自動改行

#1

投稿記事 by 赤鬼 » 8年前

DXライブラリを用いて、テキストファイルの読み込んで、ある一定の長さまできたら自動改行するプログラムを作りたいのです。
(例
”あいうえおかきくけこさしすせそたちつてと”

”あいうえおかきくけこ”
”さしすせそたちつてと”

テキストの読み込みは問題なく出来るのですが、問題は改行の為の文字列を分割する為に必要な、適切な要素数を返すプログラムです。

コード:

//与えられた文字列と幅を元にして適切な要素数を返す関数
//widthは幅
int str_size(const int width,const std::string& buf,int font=0){
	int i=0,str_len;
	if(font==0){
		str_len=GetDrawStringWidth(buf.c_str(),buf.size());
		for(i=0;width<str_len;++i){
			str_len=GetDrawStringWidth(buf.c_str(),buf.size()-i);
		}
	}
	else{
		str_len=GetDrawStringWidthToHandle(buf.c_str(),buf.size(),font);
		for(i=0;width<str_len;++i){
			str_len=GetDrawStringWidthToHandle(buf.c_str(),buf.size()-i,font);
		}
	}
	return buf.size()-i;
}
//テキストを分割し表示するプログラム フォント有り
//bufはstring型を持つvector配列 コンテナだから普通はイテレータ使うべきなのかな?(要素削除したりするわけでは無いので要らないかなと思いました)
//x2-x1-40はボックスか何かに合わせた時にぴったりだと困るので両端の分(各20ずつ)の間を空けるための値
//実際はクラス関数なので引数は全部省略されます
void txt_graph(int x1,int y1,int x2,int font,std::vector<std::string> &buf){
	int n=0,str_len=0,size=0;
	std::string str[2];
	for(unsigned int i=0;i<buf.size();i++){
		str_len=GetDrawStringWidthToHandle(buf[i].c_str(),buf[i].size(),font);
		if(str_len>x2-x1-40){
			str[0]=buf[i];
			size=0;

			//設定された幅になるまで繰り返す。
			while(str_len>(x2-x1-40)){
				str_len=GetDrawStringWidthToHandle(str[0].c_str(),str[0].size(),font);
				size=nov_size(x2-x1-40,str[0],font);
				str[1]=str[0].substr(0,size);				//分割した文字の代入
				str[0]=str[0].substr(size);					//文字の切り詰め
				
				//テキストの描画
				DrawStringToHandle(x1+20,y1+20*(i+n+1),str[1].c_str(),WHITE,font);

				if(str_len>(x2-x1-40))
					n++;									//一つ進める
			}
		}else
			DrawStringToHandle(x1+20,y1+20*(i+n+1),buf[i].c_str(),WHITE,font);
	}
}

が、しかし、これだとサイズの単位が1バイト、つまりchar型1つ分単位になってしまいます。
1バイトだけの記号やアルファベットなら構わないのでしょうが、
2バイト使う漢字やその他の文字がchar一つ分ずつ分割されて、文字化けしてしまいます。
ワイド文字であれば2バイトずつで良いのですが、DXライブラリはマルチバイト文字を採用しています
(もしかしたらUNICODEの方もあるのでしょうか?でも、これまで書いたほかのは全部マルチバイトだったので直す作業が大変に・・・)。
API関数を用いてワイド文字変換するしか無いのでしょうか?
他に何か良い方法があればお願い致します。

同じ文字列を、長さごとに改行したいので読み込みの際の分割は無しでお願い致します。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: DXライブラリでの自動改行

#2

投稿記事 by h2so5 » 8年前

1byte文字の場合と2byte文字の場合で分岐して分割する位置を調整すればいいと思います。

参考までに、自分が使っているコード(SJIS版)↓

コード:

for (auto it = self_ptr->text_.begin(); it != self_ptr->text_.end(); ++it) {
      unsigned char c = *it;
      TCHAR string[2] = {0, 0};

      int width;
      if (((c>=0x81 && c<=0x9f) || (c>=0xe0 && c<=0xfc)) && (it + 1) != self_ptr->text_.end()) {
          // 2byte文字
          string[0] = c;
          string[1] = *(it + 1);
          ++it;
          width = GetDrawStringWidthToHandle(string, 2, self_ptr->font_handle_);
      } else {
          // 1byte文字
          string[0] = c;
          width = GetDrawStringWidthToHandle(string, 1, self_ptr->font_handle_);
      }
      // self_ptr->char_width_list_.push_back(width);
  }

赤鬼

Re: DXライブラリでの自動改行

#3

投稿記事 by 赤鬼 » 8年前

h2so5 さんが書きました:1byte文字の場合と2byte文字の場合で分岐して分割する位置を調整すればいいと思います。
なるほど、すっかり頭から抜けてました。
上位1バイトが0x81~0x9f,0xe0~0xef だから、文字コードごとに分けてやれば良いんですね。
有難うございました。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: DXライブラリでの自動改行

#4

投稿記事 by ISLe » 8年前

ウチのブログに禁則処理がオマケに付いたサンプルコードを公開してますので良かったら参考にしてください。

広告貼ってあってフォーラムルールに抵触するため直リンはしませんので、投稿者名の横の[URL]から辿ってDXライブラリのカテゴリを探してください。
ShiftJIS文字列を読み込むマルチバイト版と、UTF-8文字列を読み込むワイド文字版があります。

閉鎖

“C言語何でも質問掲示板” へ戻る