鏑矢の憂鬱2000年1月前半
透明1ドットイメージ
 
2000/01/01 (Sat)
・今日もお休みぴょん。明日はちゃんと更新するよん。
透明1ドットイメージ
 
2000/01/02 (Sun)
・今日はぷらとわを書いてました。ここで書くのは初めてなんでちゃんと書くと、#pragma twice は完全ないきあたりばったりで書いてます(爆)。わては基本的にどんなものもプロットや大まかな流れとかを書かないんで。んでもそれで4分の3年続けてきて、遅れたってこと以外はうまくいってるんでまー大丈夫でしょう(笑)。
 
・あと、実験レポートの期限が刻々と迫ってるんで、とりあえず解析は後回しにしてレポートだけ完成させてしまう予定(汗)。なんか時間かかりそうだし。ただ FFT のアルゴリズムくらい知っとかんとあかんかなと思うんで解析は必ず。できればこの辺をまとめて Codian に書きたいかな。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/03 (Mon)
・ありゃ、今日はプログラミングしてないからお休みぴょん。
透明1ドットイメージ
 
2000/01/04 (Tue)
・今日も引き続き、ぷらとわ書きと実験プログラミング。
 
・ぷらとわはやっとこさ1話完成。アイコンの話は1回で終わらせるつもりだったのに、もう1回必要に(汗)。こーやってくからどんどん伸びてくんだよなー。もしかしたらわてって商業誌には向いてないかも(笑)。ちなみに、1回目は、エクスプローラーで表示されるアイコンと、ダイアログに表示されるアイコンの話。デフォルトでもいいんだけど、やっぱダイアログに貼り付けるのは小さいアイコンがいーよねってことで。
 
・これから書く2回目は、アイコンの色の話。「透明色」とか「選択色」って結構分かりにくそうと思って。あと256色アイコンの作り方も。16色アイコンに作った色塗ってヒドイ目にあったこともあったなー。こーゆーのもまめに書いてきたいです。あと Exe ファイルの中を見て「ほーらアイコンが刷り込まれてるでしょう」って話もしたいんだが、時間的にきついかも。
 
・実験プログラミングはこつこつと。ホントはとっとと実験レポートだけでも仕上げちゃった方がいいんだけど、どーもプログラムの解析の方が楽しくて(笑)。えーっと、ちょっとややこしい話だけど、ベクトル A, B, C があって、その x, y 成分 Ax, Ay, Bx, By, Cx, Cy の計算式
 
Cx = Ax * Bx - Ay * By;
Cy = Ax * By + Ay * Bx;
 
・ってのはどんな行列計算なんでしょう。いや、これ、 std::complex の * 演算子のインプリメンテーションなんですけどね。内積や外積に似てて微妙に違う。うーむ、こーゆーのはやっぱ苦手だ。単に各要素ごとの掛け算をしないわけがあるんだろーけど……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/05 (Wed)
・今日はプログラミングしてなかったり。でもお便りが2通来てるからそれを紹介しましょう。まず1通目。
 
透明1ドットイメージ
透明1ドットイメージ
 よばれてとびでてじゃじゃじゃーん 尺八郎で〜す
>行列計算
 は〜い これは行列計算ではあ〜りません
 複素数のかけ算デース
 2つの複素数が
z1 = a1+ib1
z2 = a2+ib2
 で表現されますとしますね
z3 = a1*a2 - b1*b2 + i(a1*b2 + a2*b1)
 そうすると複素数のかけ算はこうですね。
 つまり
> ベクトル A, B, C があって、その x, y 成分 Ax, Ay, Bx, By, Cx, Cy
 実部がxで虚部がyで〜す
 
 良い子の皆さんはわかりま〜したか?
 ちなみに複素数は英語では
Complex Number
 言いマース
 
 と言うわけでsee you!
透明1ドットイメージ
透明1ドットイメージ
 
・あう、12月28日に書いてあるとーり、今回の実験は FFT するもんなんで std::complex が複素数ゆうことはもちろん分かってるんです(泣)。z3 を求める「複素数のかけ算」式を知らなかった&意味が分かんなくて、この式を「はっ、ベクトルを行列表示したときの演算なんとちゃう?」と勘違いしたのが不明瞭な発言の元だったとゆー(泣)。
 
・んでも尺八郎さんに「複素数のかけ算はこうですね」言われたことで「あ、複素数で考えればいいんだ」とやっと気が付きました<バカ。 Exp に変換するとかけ算は乗数の足し算になって、これを三角公式で表せば、実数部が cos( a + b ) の式に、虚数部が sin( a + b ) の式になって、それが z3 の式になるわけですね。おー、奥が深い(爆)。
 
・……やっぱわてってバカ……なーんも考えず、まっさらなカンバスのように、素直な気持ちで、ごくごく普通に、 z1 * z2 を計算すれば、 z3 の式になるやん……ふぅ<タバコを一服<吸わんやろ。
 
・おおっとここで質問だ!
 
透明1ドットイメージ
透明1ドットイメージ
 はじめまして。
 いつもプログラミングする際、参考にしています。
 質問ですが、VC++でアプリケーションの中で、グローバルに使用する変数は、どこ(どのクラス)に定義すれば、良いのでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・いらっしゃいませー。これは View クラスや Document クラス問わずどのクラスからもアクセスできる変数の作り方ってことかな。MFC AppWizard 使うといっぺんにいろんなファイルができて、相互通信の仕方とかちょっと難しいかもしんないね。……そーゆー話でなかったらもいちど送ってください(汗)。
 
・とりあえず一例。まず CXxxApp クラスにその「グローバルに使いたい変数」を public メンバ変数として持たせます。ここでは仮に int m_iData とします。次に CXxxApp クラスのあるヘッダーファイル(拡張子 h のファイル)に次のような関数宣言を追加します。
 
CXxxApp &GetAppInstance();
	
 
・メンバ関数でなくてよ、普通の関数のね。あと、必ず CXxxApp クラスの宣言のあとに追加してください。そしたら、CXxxApp クラスのあるソースファイル(拡張子 cpp のファイル)に……
 
//////////////////////////////////////////////
// 唯一の CXxxApp オブジェクト

CXxxApp theApp;
	
 
・てな部分があると思うから、このすぐ下に次の関数定義を追加してください。
 
CXxxApp &GetAppInstance()
{
	return theApp;
}
	
 
・こうすれば、あとは GetAppInstance() を呼び出すことで CXxxApp のメンバ変数にアクセスできるようになります。使用例はこんな感じ。
 
 
void Test()
{
	GetAppInstance().m_iData = 100;	//参照を通してアクセス。
}
	
 
・あ、もちろん理想を言えば、こんなふうに直接メンバ変数にアクセスするんじゃなくて、Get なんたらとか Set なんたらみたいなメンバ関数を CXxxApp に持たせてこのメンバ関数を使ってアクセスするようにした方がいいと思うです。メンバ変数は private にしてね。
 
・こーゆー実装方法は一例だけど、これが比較的簡単でいいんじゃないかなー。 CXxxApp のあるヘッダーファイルは他のファイルからたいがいインクルードされてるし、レジストリとのアクセスも楽。お奨めです。ま、この方法の応用で、普通にグローバル変数を作って、こういった関数形式でアクセス、でもいいかも。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/06 (Thu)
・今日はコンパイラのバグ……みたいなものから。実験プログラムを組んでるときに見つかったものです。ま、とりあえず再現コードから。
 


//	純粋仮想関数を持っています。だからインスタンスは作れないはず。
class CParent
{
	virtual void VFunc() = 0;
public:
	void Func()
	{
		VFunc();	//これが呼べるかどうか……。
	}
};

//	子クラス。オーバーライドしているのでインスタンスを作れます。
class CChild
	: public CParent
{
	virtual void VFunc()
	{
		TRACE0( "Called\n" );
	}
};

//	関数テンプレート。 type_CParent は CParent にはなれないはず。だが!
template< class type_CParent >
void Error( type_CParent p_cParent )
{
	p_cParent.Func();
}

//	お試し。
void Test()
{
	CChild cChild;
	CParent &rcParent 
		= cChild;
	Error( rcParent );
	//	こうすると CParent のインスタンスが作れてしまうのです。
}

	
 
・これを実行するとランタイムエラーが発生すると思います。 CParent は抽象クラスだから、インスタンス( CParent 型の変数)を作ろうとするとコンパイルエラーが発生するはず、ってゆーかしてくれないと困ります。ところがこのコードのようにすると、関数テンプレートの引数が CParent のインスタンスを作成してしまうんです。もちろん仮想関数ポインタは初期化されてないんでランタイムエラー。
 
・関数テンプレートの引数は、値渡し用の型を優先的に割り当てるんでこうなっちゃうんですね。実はこれ、VCだけじゃなく gcc でも通っちゃいました。関数テンプレートのインスタンス化ってまーコンパイラにとって難しいから、こーゆーセキュリティリークが発生しちゃうんだろうけど……。
 
・これは「関数テンプレートのテンプレート引数を、参照やポインタにすればいい」って問題じゃないんだよねー。今回の問題は STL アルゴリズムを使ってて発生したもの。 STL アルゴリズムに渡す関数オブジェクトは「値渡し」をする仕様になってます。だからこの部分は変えられないんですね。ってゆーか、基本的にテンプレートとポリモーフィズムって相性悪いのかもしんない。 std::mem_fun1 使ってみるかなー。
 
・あら、使ってみたら思った以上に簡単。これは明日にでも載っけますか。これでテンプレートとポリモーフィズムもあっさり同居っすね。
 
・さて今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 VC++でのグローバル変数の定義について質問したものです。
 丁寧に説明していただき、ありがとうございました。
 これからも質問することがあるかと思いますが、よろしくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・ども〜。質問つねに大募集なんでどんどん送ってねー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/07 (Fri)
・やばいです。実験プログラミングが頓挫(泣)。フツーにコンパイルしてもエラーが発生することが判明。関数の引数が違ってて呼び出せない状態。ガッコの方では各関数が中間ファイルとして提供されていたから、問題なく通っちゃうんだよねー。しかもプログラムの意味とか分かんないし、謎な部分多いし、ちょっと修復不可能。とゆーわけで、火・水とガッコでなんとかするしかないかも。はひー、今までの苦労は?(泣)
 
・ま、STL の勉強になったんで結果オーライ(爆)。今回できなかった部分以外を家でできるだけやっといて、あと準備と計画をしっかりして、なんとか火曜だけで終わらせられるようにしよう。水曜はもともとお休みだし〜。さて、今日のツッコミ!
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは、べりあるんです。お世話になってます。
 
 質問ではないんですが、お願いです。僕は今、STLを使っているんですが、ファイル処理がすっごく大変で困ってます。ファイル処理は結構みんな引っかかる場所だと思うので、集中的に解説してもらえたらなぁ、と。例えば一行読み込み、string型に読み込む方法、書式付読み込みの特長と使い方などです。
 
 あと、STLのあり方についてご意見を聞きたいです。STLを使えばだいたいはCライブラリを使わずに済むことが多いですよね。そうなってくると、Cライブラリは極力使わないでSTLに移行した方が良いのでしょうか?それとも両方を混在させてつまみ食いみたいに使って良いものなのでしょうか?ご意見をお願いします。
 
 ハッシュマップに付いてもお聞きしたいです。2000/1月号のCマガジンに、「公式ではないがハッシュマップがだいたいのSTLには付属している」というような文章が載っていたのですが、VCにもあるのでしょうか?サーチしてみた限りでは無いようなのですが…。ハッシュマップは結構早くて好きなので、有れば使いたいです。
 
 それでは宜しくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。まずお知らせ。実は、4月から「 STL & iostream 入門」とゆーメールマガジンを始めようと思ってます。こんなかでは STL と iostream の使い方をわかりやすーく解説するつもり。……でもまだちょっと先なんで、とりあえずここでも簡単に解説。1行読み込みには std::istream::getline() がお奨め。
 
std::stringstream cStrm( "あい うえお" );	//テスト用ストリーム。
std::string cStr( MAX_PATH, '\0' );	//格納するための std::string。
cStrm.getline( cStr.begin(), cStr.size() );	//こーやって1行読み込めます。
TRACE( "%s\n", cStr.data() );	
// あい うえお

	
 
・上の例じゃ std::string をただの領域としてしか使ってないけど、それでいーんじゃないかな。>> とかを使った書式付読込だと、この例だとスペースで区切られちゃいます。だから使い分けが肝心かな。あ、あとストリームは std::stringstream 以外でももちろんOK。だからファイル処理するときにはこれを std::ifstream にすればいいってことですね。
 
・標準 C++ ライブラリと標準 C ライブラリの使い分け、それは難しい問題。っつーのも、なんだかんだ言って strlen() とかって便利。わざわざ std::copy() とか char_traits::length() 使うのもなんかなと思います。実際のところ、 iostream は標準 C ライブラリの関数をべたべたに使ってるんで、なくなることはないと思うし。だからわては今のところ混在派。
 
・ハッシュマップはVCのには付いてないみたいですね。シリコングラフィックスからダウンロードできる SGI 版 STL には入ってるみたいです。結構多くの人が「 hash_map があるんで SGI 版の方が好き」って言ってるみたい。ただVCでの使い方は不明。ま、インクルードリンクの優先度を上げれば大丈夫かなー。
 
・メルマガの話に戻るけど、それまでに分かんないこと出てくると思うし、メルマガ自体、完全にフォローできるもんでもないんで、ここでどんどん質問してください。質問聞くと、どの辺が分かんないのかとかの傾向とかこっちも分かるしね。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/08 (Sat)
・うひゃー、昨日「頓挫した」と言ってたプログラムが完成しました(爆)。昨日書いたように、問題点は引数の違い。プログラムは double の2次元配列を double* へと渡してるんで、もちろん型が違うからコンパイルエラー。そこでふと「もしかして K&R じゃ、2次元配列へのポインタを渡しても double* と認識されるのかも」と思い、「最初の行へのポインタ」を渡したら……カコレポと同じ結果が出た(爆)。
 
・実装を見ると、どうやら「多次元配列の各列は隙間なく継ながってる」、つまりある関数で作った x[2][3] な配列を、他の関数では x[6] な配列として扱ってるみたいです。これってCの規則としてちゃんと定まってるのかなー。これじゃ std::vector に置き換えられないやん。ま、とりあえず実験終わらせられそうでひと安心(爆)。
 
・昨日血迷って「ツッコミ」と言ってしまった、お便りです。今日は2通。まずひとつめ。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
>ハッシュマップはVCのには付いてないみたいですね。
 
 え〜と、使ったことないので良く分かりませんが CMap っていうのは違うんでしょうか?
# 違ってたらスイマセン。
透明1ドットイメージ
透明1ドットイメージ
 
・あ、そいや CMap もハッシュテーブル使ってるみたいですね。完全に忘れてた(爆)。 MFC が使える環境ならこれを使うのもアリかも。Cマガ1月号のえぴすてーめーさんの記事にあるように、ラッピングすれば STL アルゴリズムにも噛ませられるんで、場合によっては結構使えるかもしんない。
 
・もひとつ!
 
透明1ドットイメージ
透明1ドットイメージ
 iostreamの話題が出たので、質問します(in VC)。
 
 コンソールアプリで、入力をcinで受け取るプログラムがあります。エラーが起きたときに、その詳細を表示します。
 で、ここから質問。
 エラーが起きたらプログラムを終了するのですが、「何かキーを押してください。終了します。」とメッセージを出して、画面を止めます。これをiostreamを使って実現するにはどうすれば良いのでしょうか?
 
 ちなみに、僕は分からなかったので、getchar()で逃げました(ぶざま)。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。んーと、望んでる結果がよく分かんないんで色々あげときましょう。まずVCだったら _getch() っつー関数を使うのが一番簡単。これは「文字を入力した直後に返ってくる」んでリターンキーを押してもらう必要がないという便利さ。ただーし、見ての通りVC拡張関数なんでVC専用。ってゆーかそーゆー機能はC言語に備わってないんですね。だからこれ以外の方法はナシ、たぶん。
 
・「リターンキーを押すのは許す」とゆーことであれば、std::cin と std::string を使えばいいと思うです。たとえばこんな感じ。
 
	std::string cStr;
	std::cin
		>> cStr;
	
 
・っつーことではなかったのかなー。あ、もし std::cin がエラーになってて次に使えない、ってことなら、 std::cin::clear() を呼び出すことでエラー状態をリセットできるから、そのあとこの例のように呼び出せばOKです。ま、VCオンリー確定ってことなら _getch() がお奨めだけどねん。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/09 (Sun)
・今日はおやすみぴょん。
透明1ドットイメージ
 
2000/01/10 (Mon)
・実験レポートは無事完成しました。っつーても、逆にコード解析はほとんど放棄しちゃったも同然なんで、書くことがなかったり(汗)。初心に戻って、 DFT のプログラムから組み始めた方がいいかもしんない。
 
・おー、ぷらとわ質問箱、1通も来てない(爆)。こりゃぽしゃりそうですわ、はい。ま、これからは「ぷらとわの質問もかぶゆ〜で」とゆーふーにしてきますか。
 
・あと、「プログラミング経歴」のページを書き換えたりしてました。ふと思ったんだが、5年前の冬、なぜわてはVC1.0を買おうと思ったんだろうか(汗)。ってゆーのも、今、わてはなんでプログラミングしてるんだろう、って考え始めてるから。明らかに「アプリを作るため」じゃないんだよねー。
 
・ひとつあるはっきりした目的、それは「ライブラリを作ること」。KTLを見れば分かるように、わては今「 C++ に特化したライブラリ」を作るようになってます。継承とテンプレートをうまく使うと、「プログラムの元になるプログラム」を作ることができます。今のわては、そういうのを作ることが楽しいのかもしんない。
 
・でもそれって、現在の流れと逆行してるんだよね。現在のプログラミングは「オブジェクト指向設計」を中心に回ってて、その域を出ないプログラミングが求められています。そうすれば C++ でも Java でも ObjectPascal でも似たようなコードが生成されて、可読性や再利用性が高まるからねー。そのメリットは理解してます。
 
・でも好きくない(爆)。そういう考え方は「アプリを作る」ことが目的じゃない<って当たり前やん(汗)。わてはプログラムを組むこと自体に面白味を感じてるから、その辺でかなりずれが生じ始めてるのかも。ただ、STL推進派の人達がいる限り、わて的な C++ 特化コードを好む人間はまだまだやってけるかなとも思うんで……今年はSTLファンを増やしてみよう(爆)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/11 (Tue)
・今日は STL の推進も兼ねて、尺八郎さんのところにあった STL コードの「ごっつさ」を取り除いてみましょう。尺八郎さんも読んでくださってると思うので。ってゆーか呼ばれたような気がした(汗)。とゆーわけでサンプルコード。
 


//	ダミーの casVesselLink クラス。
class casVesselLink
{
public:
	int points[2];

	casVesselLink()
	{
		points[0] = 1;
		points[1] = 1;
	}
};

//	ダミーの変数。これがフラグ。
const int id1_ = 1;
const int id2_ = 2;

//	関数オブジェクト。これを作れば OK 。
class PredFor_casVesselLink
{
public:
	//	() 演算子のオーバーロード。
	bool operator()( casVesselLink &p_rcLink )
	{
		//	この if も STL アルゴリズムでできるかも。
		if( ( (p_rcLink.points[0] == id1_)
			&& (p_rcLink.points[1] == id2_ ) )
			|| ( ( p_rcLink.points[0] == id2_)
			&& ( p_rcLink.points[1] == id1_ ) ) )
		{
			return true;	//一致するなら true を、
		}
		return false;	//しないなら false を返します。
	}
};

//	お試し。
void Test()
{
	typedef std::list< casVesselLink > CLinkList;
	CLinkList cList( 3 );
	( *( ++( cList.begin() ) ) ).points[0] = 2;	//うぎゃー汚い。
	
	CLinkList::iterator cEndIter
		= cList.end();

	CLinkList::iterator cHitIter
		= std::find_if( cList.begin(), cEndIter, PredFor_casVesselLink() );
	if( cHitIter != cEndIter )
		TRACE( "%d, %d\n", cHitIter->points[0], cHitIter->points[1] );
}

	
 
・コツは STL アルゴリズムを積極的に使うことです。ってゆーかそうしないともったいないです(汗)。やっぱ STL の魅力はアルゴリズムにあるんで。 STL を使う場合、for や while を見たらまず「 STL アルゴリズムに掛けられないかな?」と考えます。ここでは検索を行ってるんで std::find() 系がよさそう、でも検索条件が複雑やね。
 
・そういうときは「関数オブジェクト」を作って std::find_if() に噛ませます。関数オブジェクトは「() 演算子をオーバーロードしたクラス」のことで、ここでは PredFor_casVesselLink ってクラスがそうです。この中に「検索条件」を入れて、 std::find_if() に渡します。そうすると PredFor_casVesselLink::operator()() が呼ばれてこの中で条件判断ができるというわけ。
 
・ STL アルゴリズムの魅力は「ループを関数に置き換えられる」こと。コードがすっきりするし、「検索してる」ってことが一目瞭然だし。この魅力に取り憑かれるとやばいです(汗)。デメリットは、ループ部分と検索条件部分が分かれちゃう事かな。でも、 PredFor_casVesselLink はテンプレート化とかすることで汎用性を高めることができるんで、その点を加味するとやっぱ…… STL って魅力的(爆)。
 
・イテレーター関係は、 begin() は直接渡して、 end() はフラグ用に必要なので変数として作ります。んでも「2度必要」ってだけなんで作る必要もないかも(汗)。あとこの例みたく関数内で typedef すれば、ローカルスコープでしか効かないんで他のコードを邪魔したりしなくていい感じです。イテレーターも typedef してもいいかも。
 
・さて、今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちわ、BLUEといいます。質問ではないのですが、KABさん、最近信号処理やってますよね?
 それでしたら、このページが役に立つと思いますよ。
 信号処理の中のFFTやDFTをCのプログラムで提供していて、その概要や設計方法を説明しています。
 どうでしょうか?
 あ、必要なければ捨てちゃってください。
透明1ドットイメージ
透明1ドットイメージ
 
・情報ありがとうですー。さっそくダウンロードしてみました。使用例も着いてるみたいなんでこれで FFT について調べてみたいと思います。でもコード解析は結構大変そう……。やっぱりこーゆーのは苦手なのかもしんない。んでも乗り越えないとねー。
 
・お便り、もうひとつ。
 
透明1ドットイメージ
透明1ドットイメージ
  はじめまして、こんにちは。
 VCというよりWindowsプログラミングそのものについての質問です。
  システムフックを使ってWM_MOUSEWHEELメッセージをウィンドが取得することのないように破棄したいのですが、WH_MOUSEではWM_MOUSEWHEELメッセージについてはフックできないので破棄できません。WH_GETMESSAGEではWM_MOUSEWHEELをフックできるものの、メッセージの変更を許可してないので、破棄できません。
 サブクラス化を使うことなく、システムフックでWM_MOUSEWHEELメッセージを破棄する方法はありませんか?
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。 WH_GETMESSAGE のリファレンスを見ると、「メッセージを修正できる」って書いてあるんでとりあえずテストしてみたところ、 GetMsgProc() の戻り値を 0 にしても、メッセージが削除されないでウィンドウプロシージャに送られてる……リファレンスの書き間違い? と思ったら、こーやって削除するんだそうです(汗)。
 
//	フックプロシージャの中。
if( ( (MSG *)lParam )->message == WM_MOUSEWHEEL )
{
	TRACE0( "Hit!(Hook)\n" );
	( (MSG *)lParam )->message = WM_NULL;	//ここで書き換えちゃう。
}
	
 
・つまり送られてくるメッセージは読み取り専用じゃなくて、このまま直接ウィンドウプロシージャに送られるんですねー。わ、分かりにくい……。んでもこれは自由にメッセージを書き換えられるってことで結構便利かもしんない。まーこれで GetMsgProc() フックプロシージャで削除できると思うんで試してみてくださいです。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/12 (Wed)
・うき、今日はプログラミングしてないからお便りだけよん。
 
透明1ドットイメージ
透明1ドットイメージ
  こんにちは。べりあるんです。
>今年はSTLファンを増やしてみよう(爆)。
 STLイイですよね〜。文字列を扱うクラスがあるだけでもう最高!これさえあればCStringに振り回されずに済みますしね。 でも僕がSTLに惹かれているのって、移植性の点についてだけかもしれない…。 いやっ!それを抜いてもSTLは良い!CArrayとか使わなくて良いですしね。
透明1ドットイメージ
透明1ドットイメージ
 
・そうそうそう。 MFC を筆頭に、多くのフレームワーク系ライブラリは文字列クラスやコンテナ(コレクション)クラスを持ってるんだけど、どーもそれを他で使えないってのが結構ネックなんだよね。ところが STL ならテンプレートライブラリだから、基本的に OS やコンパイラに左右されずどこででも使える! これも STL の立派なメリットです。
 
・ってゆーかなぜかこれがまず強調されるんだよね……なんとしても STL アルゴリズムを広めねば!
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/13 (Thu)
・今日はお休みっす。
透明1ドットイメージ
 
2000/01/14 (Fri)
・今日もプログラミングしてないけど、お便りが来てるんでそれを紹介しましょう。まずひとつめ。
 
透明1ドットイメージ
透明1ドットイメージ
 メモリを確保し(DIB)、直接メモリを操作することで、滑らかな曲線を表示しようと思い、以下のようにしたのですが、この方法では、滑らかに表示できませんでした。また、無駄な計算が多いです。(計算は 実数で行うが、画面は整数のドットだから)
 
 どのようにすれば、滑らかな曲線を表示できますか? 直線におけるブレゼンハムのようなものは、あるのでしょうか? お願いします。
 
 環境 win98 + Visual C++6
 
////////////////////
 
B-Spline
 
位数 k 4
次数 n 3
ノットベクトル 0 0 0 0 1 1 1 1
 
P(t)= (1-t)^3*P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3
 
( Bezier Curve と同じになる)
 
Line は、ブレゼンハムによる直線絵画
 
/////////////////////
int	iX;
int	iY;
int	iOx;
int	iOy;
float	fT;
unsigned char byRed;
unsigned char byGreen;
unsigned char byBlue;

for(fT=0;fT<=1;fT+=fDt)
{
	fX=(1-fT)*(1-fT)*(1-fT)*iX0+
		3*fT*(1-fT)*(1-fT)*iX1+
		3*fT*fT*(1-fT)*iX2+
		fT*fT*fT*iX3;

	fY=(1-fT)*(1-fT)*(1-fT)*iY0+
		3*fT*(1-fT)*(1-fT)*iY1+
		3*fT*fT*(1-fT)*iY2+
		fT*fT*fT*iY3;

	iX=(int)fX;
	iY=(int)fY;

	Line(iOx,iOy,iX,iY,byRed,byGreen,byBlue);

	iOx=iX;
	iOy=iY;
}
	
透明1ドットイメージ
透明1ドットイメージ
 
・う、わかんないっす(汗)。なんせ「ブレゼンハム」とゆー単語を初めて聞いたくらいだし。んでもとりあえず思いつくことはあるかな。まず、どんなふうに汚いのかが問題かな。ギザギザが出ているとかなら、たとえば表示部分のサイズを縦横とも倍(つまり高解像度)にして、それをプリントアウトしたり縮小表示したりすればきれいになるかもしんないし、ただ単にぼかしたりアンチエイリアス掛けたりするだけできれいになるかも。出力したグラフをフォトレタッチ系にコピーして「きれいになる」んならこの関係かなー。
 
・直線を引いてるからガクガクするってことなら、 fDt をもっと小さい値にして、データをもっと細かく取って、その中から整数として得られる点を拾っていく、みたいな形にするとかがいいかも。実数>整数変換は必ず必要だと思います。たいがいの画像処理はやっぱし。そうでなきゃ「浮動小数点計算が高速」とかあんまウリになんないよーな(汗)。計算時間がかからないようなら、実数計算を細かくして、そこからきれいに整数値を拾っていくっていうのがいいんじゃないかなーと。
 
・……想像の域を出ない(汗)。もひとつお便りです。
 
透明1ドットイメージ
透明1ドットイメージ
 はじめまして、Valiosです。
 
 デザインパターンのSingletonについてなんですが、継承した場合(Singletonをサブクラス化)した場合にどのような実装をすればよいのか教えてください。
 うーーーん…なんかどうやっても泥臭くなってしまうような気がしてます。(エレガントな実装って無理なんでしょうか?)
 
 それとホントに情けない話なんですが(笑)、auto_ptrってどのヘッダファイルをインクルードすればよいのか分かりません。使ってみようと思って適当にテストプログラムを作ったのですが、未定義だと言われました…。(簡単な使い方を教えてください)
 
 どうか宜しくお願いします。
 
 環境はVC++6.0です。
透明1ドットイメージ
透明1ドットイメージ
 
・一般的な Singleton パターン(ガンマ本のやCマガ1999年5月のとか)だと、基本的に Singleton クラスは継承できないと思います。 new を継承先クラスで作らなきゃいけないけどそれを指定できないからねぇ。 static メンバ関数は仮想化できないし、仮想関数を呼ぶこともできないしね。基本的にテンプレートで解決するのがフツーかな。たとえばこんなクラス。
 


//	Singleton クラス。
template< class type_Child >
class SingletonParent
{
protected:
	SingletonParent< type_Child >()
	{}
public:
	static type_Child *Instance()
	{
		static type_Child *s_pInstance = new type_Child;
		return s_pInstance;
	}
};

//	その派生クラス。
class SingletonChild
: public SingletonParent< SingletonChild >
{
	friend SingletonParent< SingletonChild >;
protected:
	SingletonChild()
	{}
public:
	void Test()
	{
		TRACE0( "Test()\n" );
	}
};

//	使ってみましょう。
void Test2()
{
	SingletonChild *pcSChild
		= SingletonChild::Instance();
	pcSChild->Test();
}

	
 
・この例で static 変数を使ってないのは、 static 変数をテンプレートで表すのは難しいから。こーゆークラステンプレート形式の Singleton を作れば、派生クラスを作ることができます。つっても、これだと派生クラスひとつずつ作れちゃいますけど(汗)。あと削除するタイミングとか、複数作る場合とかも問題かも。あ、1個だけでいいんならなにも new する必要はないや……。
 
・ std::auto_ptr は memory をインクルードすれば使えると思います。標準C++ライブラリからヘッダーは拡張子なしになったんで grep が使いにくくなっちゃったのがね。わてはVC付属のを別フォルダにコピーして拡張子加えてこれで grep するようにしてます。 SGI 版だと全然問題ないんだけどねー。んで使い方はこんな感じ。
 


void Use_auto_ptr()
{
	std::auto_ptr< int > pi( new int );
	*pi = 100;	//こんなふうにポインタ同様に使えます。
	TRACE( "%d\n", *pi );
}

	
 
・こんなふうに delete を呼ばずに済みます。これが std::auto_ptr のメリット。しかーし、ポインタのコピーの仕方とか色々と大変なんだ、これが。ヘタするとバグの温床になりかねないのが怖いところ。んでも使わなくても温床になりそうな気もするし、ポインタ回りはいつの世も問題ばかりですねぇ(しみじみ)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/15 (Sat)
・最近お便りの紹介しかしてないねぇ。今日もそう(爆)。ではひとつめ。
 
透明1ドットイメージ
透明1ドットイメージ
 拙者、尺八郎
 召還された模様ですのでちょっと話します
 
 曲線、概ねKABさんの言うとおりで計算自体は普通浮動小数点で行います。最近のCPUは浮動小数点演算が十分に速いのでその点は気にしなくて結構です。
 で、肝心のアルゴリズムですが・・・。学校に本を置いてきてしまいましたので少々お待ち下さい。
 
singleton
 これはこれで泥臭い方法ですが
 
class Singularity {
public:
	static Singularity * getSingularity();
protected:
	// 通常の方法で作成できないようにする
	Singularity();
};

Singularity * Singularity::getSingularity()
{
	static Singularity theObj;
	return &theObj;
}

class Singularity2 : public Singularity{
public:
	static Singularity2 * getSingularity2();
protected:
	//ここからSingularityのコンストラクタはコールできる
	Singularity2();
};

Singularity2 * Singularity2::getSingularity2()
{
	static Singularity2 theObj;
	return &theObj;
}
	
 
 と言う方法もあります。こうすればSingularityとSingularity2が一個ずつ手に入ります。この場合はgetSingularityX()がきちんと書かれていないと破綻しますのでカプセル化に問題がありますが私は最近はこうしています。
 
 では、
透明1ドットイメージ
透明1ドットイメージ
 
・ちょちょちょちょいまちっ! Singularity2 には親クラスの Singularity が入ってるんだから、これじゃ Singularity がふたつできちゃうことになっちゃいますよ。なんか怖いです(汗)。 Singularity2 をアップキャストしたのと Singularity::getSingularity() で取得したのを混在させたらやばいことになるんでは? まー Singularity が特にメンバ変数を持たなきゃ問題ないだろうけど……。
 
・……ってことは、わての例もダメだわ。派生クラスごとに1個ずつ作れるってことは、その基底クラスはいーっぱい作れるってことやん、そりゃやばいよ(汗)。もちろん基底クラスが Singleton だけならいいけど、3世代以上継承したら始末に負えないです。ダメだこりゃ(汗)。
 
・これはつまるところ「1個だけ派生クラスの作成を許したい」っつークラスを作るにはどうすればいいんかとゆー問題になるんかな。それをコンパイルタイムで処理するのは難しいだろうなー。あー、なんかクラスからの視点とプログラマーからの視点がごっちゃになっちゃったわ。この辺の方向性をしっかり決めないと先進めないかも。むぅ。
 
・画像処理の方は呼びました(爆)。あいっかわらずこーゆーのは苦手なんですよねーわて。なんで苦手か? しないからだな(爆)。すりゃ憶えるだろうけど、今のとこする必要がないってのが。あと「ソースデータ」と「出力結果」が揃ってないと、プログラムが正しいのか分かんないし(爆)。研究室決まったらやっぱせんとあかんかな。
 
・もひとつお便りよん。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。
 前にシステムフックのことで、質問させてもらったK-taです。
 返答、ありがとうございました。
 すみませんが、もう一度、質問ですm(_ _)m
 
 教えてもらったように、messageにWM_NULLを代入したのですが、ローカルフックで試したときは、きちんとWM_MOUSEWHEELメッセージが送られなくなったのですが、システムフックで同様に試したら、WM_MOUSEWHEELメッセージが送られてしまいました。
 システムフックでは、メッセージの修正はできないものなんでしょうか?
 
#それとも、私の使ってる言語がC++Builderのためなんでしょうか・・・
#って、WinApi周りだから使用言語にはよらないですよねぇ?
透明1ドットイメージ
透明1ドットイメージ
 
・こちらでもシステムフックとして試してみました。んでもちゃんと WM_MOUSEWHEEL を無効化できました。VCや秀丸でも効かなくなったんでちゃんとシステムフックとして効いてるみたいです。なんでだろう、 API 使ってるんだから C++Builder だからってこたぁないだろうし……。一応フックプロシージャ全体を載せておきますね。あ、これちょっと無駄ある……。
 


LRESULT GetMsgProc( int p_iCode, WPARAM p_wParam, LPARAM p_lParam )
{
	if( p_iCode < 0 || p_iCode == HC_NOREMOVE )
		return ::CallNextHookEx( g_hHook, p_iCode, p_wParam, p_lParam );

	//	WM_MOUSEWHEEL を無効化します。
	if( ( (MSG *)p_lParam )->message == WM_MOUSEWHEEL )
	{
		//	来てるかチェック。
		MessageBox( 0, "WM_MOUSEWHEEL", "WM_MOUSEWHEEL", MB_OK );
		//	無効化。
		( (MSG *)p_lParam )->message = WM_NULL;
	}

	return  ::CallNextHookEx( g_hHook, p_iCode, p_wParam, p_lParam );
}

	
 
・とりあえずすることは、 GetMsgProc() 自体が呼ばれてるかどうか MessageBox() でチェックすることかな。呼ばれてなかったらどっかでフックのセットが失敗してるってことになるんで、エラーチェックを綿密にしてみるとか。っつーてもローカルが通ってるんだから場所は限定されるかも。 DLL をちゃんとロードできてるかとか、ロードした DLL はホントに最新のものかとか。
 
・もしちゃんと呼ばれてたら……やだなぁ(汗)。それだと解決方法思いつかないです。とりあえず他のメッセージが無効化できるかとか試してみるとかかなぁ。あ、そうそう、他のユーティリティーアプリが CallNextHookEx() を呼ばないんでフックされないとかゆー場合もあるんで、常駐してるユーティリティーアプリがあったら終了させておきましょう。
 
・でわまたっ!
 
 
(C)KAB-studio 2000 ALL RIGHTS RESERVED.