c++ で独自のストリームを作ったときのiwordの使いかた

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

c++ で独自のストリームを作ったときのiwordの使いかた

#1

投稿記事 by hukuzawa » 3年前

今現在、qiitaで
https://qiita.com/gis/items/496ad51cbce15fd75abc
というサイトを見つけ、コメント欄に書かれていたのを参考に実装に挑戦しています。
とりあえず、元サイトとは違いますが、dxlibのDrawStringで表示するのに成功しました。
なので次はどうしようかと思ったときに、マニピュレータで色を指定できたら便利じゃないかと思いました。
(文字列の途中で色を変えられるようになりますし。)
そこで引数があるマニピュレータの作り方を調べて実装に挑戦しました。
で、ここで問題になったのはどうやって引数で指定した色を描画するところに伝えるかです。
色々調べた結果、ostreamはiwordというところに数字を保存できることが分かったのでそこに色を入れて
描画するときに参照しようとしたのですが、実行した途端に強制終了してしまいました。
原因は保存されているかどうかのチェックをしてないので、まずはそれが一つ。
他にはiwordの使いかたが間違っているかが考えられます。
また、落ち着いてプログラムを見直した結果多分無事動いても一番左で指定された色になるだけになりそうです。
(overflow関数内でx変更して描画に反映してるってことは多分CDstreambufは一回作成されてoverflowが複数回呼ばれてるということですし。)
なので代替案があれば教えてくれると嬉しいです。
環境はvisualstudioでc++を使っています。
ライブラリはdxlibを使っています。
c++に関してはどのくらいできるかというのは説明しづらいので割愛します。
現在のプログラムが

コード:

#include <iostream>
#include "Dxlib.h"

using namespace std;

const int name_index = std::ios::xalloc();

class CDstreambuf : public streambuf {
	char m_acBuffer[2]; // 出力用の一時バッファ
	int x = 0;
	int y = 0;
	int color = 0;
	int type = 0;
public:
	CDstreambuf() { ZeroMemory(m_acBuffer, sizeof m_acBuffer); }    // バッファをクリアしておく。
	CDstreambuf(int x,int y,int color) {
		ZeroMemory(m_acBuffer, sizeof m_acBuffer);
		this->x = x;
		this->y = y;
		this->color = color;
		type = 1;

	}    // バッファをクリアしておく。
	virtual int_type overflow(int_type iChar = EOF) {
		if (iChar != EOF) {
			m_acBuffer[0] = iChar;          // 文字をバッファに書き込んで、
			if(type==0) printfDx(m_acBuffer);
			if (type == 1) {
				DrawString(x, y, m_acBuffer,color);
				x += GetDrawStringWidth(m_acBuffer,2);
			}
		}
		return iChar;   // 出力が成功したときには EOF 以外を返す。
	}
};

class coutDx : public ostream {
	CDstreambuf* m_pdstreambuf;
public:
	//~coutDx() { delete m_pdstreambuf; }
	coutDx() : ostream(m_pdstreambuf = new CDstreambuf()) {}
	coutDx(int x, int y) :ostream(m_pdstreambuf = new CDstreambuf(x, y, static_cast<int>(this->iword(name_index)))) {}
	coutDx(int x,int y,int color) : ostream(m_pdstreambuf = new CDstreambuf(x,y,color)) {}
};

ostream& flushDx(ostream& ros) {
	clsDx();
	return ros;
}

class SetColor {
	int color;
	friend ostream& operator <<(ostream& ros, SetColor sc) {
		return sc(ros);
	}
	ostream& operator()(ostream& ros) {
		ros.iword(name_index) = color;
		return ros;
	}
public:
	SetColor(int c) {
		color = c;
	}
};

int WINAPI WinMain(HINSTANCE h1,HINSTANCE hp,LPSTR lpC,int nC) {
	ChangeWindowMode(true);

	if (DxLib_Init() == -1) return -1;

	coutDx(0,20,GetColor(255,0,0)) << "test" <<endl;
	coutDx() << "test" << endl;
	coutDx(0, 30) << SetColor(GetColor(255, 0, 0)) << "test" << endl;

	WaitKey();
	DxLib_End();
	return 0;
}
となっています。
この掲示板を使うのは記憶が確かなら初めてなので、
足らない情報があれば言ってください。

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