|
・今日もお休みぴょん。明日はちゃんと更新するよん。
|
・今日はぷらとわを書いてました。ここで書くのは初めてなんでちゃんと書くと、#pragma twice は完全ないきあたりばったりで書いてます(爆)。わては基本的にどんなものもプロットや大まかな流れとかを書かないんで。んでもそれで4分の3年続けてきて、遅れたってこと以外はうまくいってるんでまー大丈夫でしょう(笑)。
・あと、実験レポートの期限が刻々と迫ってるんで、とりあえず解析は後回しにしてレポートだけ完成させてしまう予定(汗)。なんか時間かかりそうだし。ただ FFT のアルゴリズムくらい知っとかんとあかんかなと思うんで解析は必ず。できればこの辺をまとめて Codian に書きたいかな。 ・でわまたっ! |
・ありゃ、今日はプログラミングしてないからお休みぴょん。
|
・今日も引き続き、ぷらとわ書きと実験プログラミング。
・ぷらとわはやっとこさ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 の * 演算子のインプリメンテーションなんですけどね。内積や外積に似てて微妙に違う。うーむ、こーゆーのはやっぱ苦手だ。単に各要素ごとの掛け算をしないわけがあるんだろーけど……。 ・でわまたっ! |
・今日はプログラミングしてなかったり。でもお便りが2通来てるからそれを紹介しましょう。まず1通目。
|
|
・あう、12月28日に書いてあるとーり、今回の実験は FFT するもんなんで std::complex が複素数ゆうことはもちろん分かってるんです(泣)。z3 を求める「複素数のかけ算」式を知らなかった&意味が分かんなくて、この式を「はっ、ベクトルを行列表示したときの演算なんとちゃう?」と勘違いしたのが不明瞭な発言の元だったとゆー(泣)。
・んでも尺八郎さんに「複素数のかけ算はこうですね」言われたことで「あ、複素数で考えればいいんだ」とやっと気が付きました<バカ。 Exp に変換するとかけ算は乗数の足し算になって、これを三角公式で表せば、実数部が cos( a + b ) の式に、虚数部が sin( a + b ) の式になって、それが z3 の式になるわけですね。おー、奥が深い(爆)。 ・……やっぱわてってバカ……なーんも考えず、まっさらなカンバスのように、素直な気持ちで、ごくごく普通に、 z1 * z2 を計算すれば、 z3 の式になるやん……ふぅ<タバコを一服<吸わんやろ。 ・おおっとここで質問だ! |
|
・いらっしゃいませー。これは 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 のあるヘッダーファイルは他のファイルからたいがいインクルードされてるし、レジストリとのアクセスも楽。お奨めです。ま、この方法の応用で、普通にグローバル変数を作って、こういった関数形式でアクセス、でもいいかも。 ・でわまたっ! |
・今日はコンパイラのバグ……みたいなものから。実験プログラムを組んでるときに見つかったものです。ま、とりあえず再現コードから。
|
// 純粋仮想関数を持っています。だからインスタンスは作れないはず。 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 使ってみるかなー。 ・あら、使ってみたら思った以上に簡単。これは明日にでも載っけますか。これでテンプレートとポリモーフィズムもあっさり同居っすね。 ・さて今日のお便り。 |
|
・ども〜。質問つねに大募集なんでどんどん送ってねー。
・でわまたっ! |
・やばいです。実験プログラミングが頓挫(泣)。フツーにコンパイルしてもエラーが発生することが判明。関数の引数が違ってて呼び出せない状態。ガッコの方では各関数が中間ファイルとして提供されていたから、問題なく通っちゃうんだよねー。しかもプログラムの意味とか分かんないし、謎な部分多いし、ちょっと修復不可能。とゆーわけで、火・水とガッコでなんとかするしかないかも。はひー、今までの苦労は?(泣)
・ま、STL の勉強になったんで結果オーライ(爆)。今回できなかった部分以外を家でできるだけやっといて、あと準備と計画をしっかりして、なんとか火曜だけで終わらせられるようにしよう。水曜はもともとお休みだし〜。さて、今日のツッコミ! |
|
・どうもですー。まずお知らせ。実は、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での使い方は不明。ま、インクルードリンクの優先度を上げれば大丈夫かなー。 ・メルマガの話に戻るけど、それまでに分かんないこと出てくると思うし、メルマガ自体、完全にフォローできるもんでもないんで、ここでどんどん質問してください。質問聞くと、どの辺が分かんないのかとかの傾向とかこっちも分かるしね。 ・でわまたっ! |
・うひゃー、昨日「頓挫した」と言ってたプログラムが完成しました(爆)。昨日書いたように、問題点は引数の違い。プログラムは double の2次元配列を double* へと渡してるんで、もちろん型が違うからコンパイルエラー。そこでふと「もしかして K&R じゃ、2次元配列へのポインタを渡しても double* と認識されるのかも」と思い、「最初の行へのポインタ」を渡したら……カコレポと同じ結果が出た(爆)。
・実装を見ると、どうやら「多次元配列の各列は隙間なく継ながってる」、つまりある関数で作った x[2][3] な配列を、他の関数では x[6] な配列として扱ってるみたいです。これってCの規則としてちゃんと定まってるのかなー。これじゃ std::vector に置き換えられないやん。ま、とりあえず実験終わらせられそうでひと安心(爆)。 ・昨日血迷って「ツッコミ」と言ってしまった、お便りです。今日は2通。まずひとつめ。 |
|
・あ、そいや CMap もハッシュテーブル使ってるみたいですね。完全に忘れてた(爆)。 MFC が使える環境ならこれを使うのもアリかも。Cマガ1月号のえぴすてーめーさんの記事にあるように、ラッピングすれば STL アルゴリズムにも噛ませられるんで、場合によっては結構使えるかもしんない。
・もひとつ! |
|
・どうもですー。んーと、望んでる結果がよく分かんないんで色々あげときましょう。まずVCだったら _getch() っつー関数を使うのが一番簡単。これは「文字を入力した直後に返ってくる」んでリターンキーを押してもらう必要がないという便利さ。ただーし、見ての通りVC拡張関数なんでVC専用。ってゆーかそーゆー機能はC言語に備わってないんですね。だからこれ以外の方法はナシ、たぶん。
・「リターンキーを押すのは許す」とゆーことであれば、std::cin と std::string を使えばいいと思うです。たとえばこんな感じ。 std::string cStr; std::cin >> cStr; ・っつーことではなかったのかなー。あ、もし std::cin がエラーになってて次に使えない、ってことなら、 std::cin::clear() を呼び出すことでエラー状態をリセットできるから、そのあとこの例のように呼び出せばOKです。ま、VCオンリー確定ってことなら _getch() がお奨めだけどねん。 ・でわまたっ! |
・今日はおやすみぴょん。
|
・実験レポートは無事完成しました。っつーても、逆にコード解析はほとんど放棄しちゃったも同然なんで、書くことがなかったり(汗)。初心に戻って、 DFT のプログラムから組み始めた方がいいかもしんない。
・おー、ぷらとわ質問箱、1通も来てない(爆)。こりゃぽしゃりそうですわ、はい。ま、これからは「ぷらとわの質問もかぶゆ〜で」とゆーふーにしてきますか。 ・あと、「プログラミング経歴」のページを書き換えたりしてました。ふと思ったんだが、5年前の冬、なぜわてはVC1.0を買おうと思ったんだろうか(汗)。ってゆーのも、今、わてはなんでプログラミングしてるんだろう、って考え始めてるから。明らかに「アプリを作るため」じゃないんだよねー。 ・ひとつあるはっきりした目的、それは「ライブラリを作ること」。KTLを見れば分かるように、わては今「 C++ に特化したライブラリ」を作るようになってます。継承とテンプレートをうまく使うと、「プログラムの元になるプログラム」を作ることができます。今のわては、そういうのを作ることが楽しいのかもしんない。 ・でもそれって、現在の流れと逆行してるんだよね。現在のプログラミングは「オブジェクト指向設計」を中心に回ってて、その域を出ないプログラミングが求められています。そうすれば C++ でも Java でも ObjectPascal でも似たようなコードが生成されて、可読性や再利用性が高まるからねー。そのメリットは理解してます。 ・でも好きくない(爆)。そういう考え方は「アプリを作る」ことが目的じゃない<って当たり前やん(汗)。わてはプログラムを組むこと自体に面白味を感じてるから、その辺でかなりずれが生じ始めてるのかも。ただ、STL推進派の人達がいる限り、わて的な C++ 特化コードを好む人間はまだまだやってけるかなとも思うんで……今年はSTLファンを増やしてみよう(爆)。 ・でわまたっ! |
・今日は 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 してもいいかも。 ・さて、今日のお便り。 |
|
・情報ありがとうですー。さっそくダウンロードしてみました。使用例も着いてるみたいなんでこれで FFT について調べてみたいと思います。でもコード解析は結構大変そう……。やっぱりこーゆーのは苦手なのかもしんない。んでも乗り越えないとねー。
・お便り、もうひとつ。 |
|
・どうもですー。 WH_GETMESSAGE のリファレンスを見ると、「メッセージを修正できる」って書いてあるんでとりあえずテストしてみたところ、 GetMsgProc() の戻り値を 0 にしても、メッセージが削除されないでウィンドウプロシージャに送られてる……リファレンスの書き間違い? と思ったら、こーやって削除するんだそうです(汗)。
// フックプロシージャの中。 if( ( (MSG *)lParam )->message == WM_MOUSEWHEEL ) { TRACE0( "Hit!(Hook)\n" ); ( (MSG *)lParam )->message = WM_NULL; //ここで書き換えちゃう。 } ・つまり送られてくるメッセージは読み取り専用じゃなくて、このまま直接ウィンドウプロシージャに送られるんですねー。わ、分かりにくい……。んでもこれは自由にメッセージを書き換えられるってことで結構便利かもしんない。まーこれで GetMsgProc() フックプロシージャで削除できると思うんで試してみてくださいです。 ・でわまたっ! |
・うき、今日はプログラミングしてないからお便りだけよん。
|
|
・そうそうそう。 MFC を筆頭に、多くのフレームワーク系ライブラリは文字列クラスやコンテナ(コレクション)クラスを持ってるんだけど、どーもそれを他で使えないってのが結構ネックなんだよね。ところが STL ならテンプレートライブラリだから、基本的に OS やコンパイラに左右されずどこででも使える! これも STL の立派なメリットです。
・ってゆーかなぜかこれがまず強調されるんだよね……なんとしても STL アルゴリズムを広めねば! ・でわまたっ! |
・今日はお休みっす。
|
・今日もプログラミングしてないけど、お便りが来てるんでそれを紹介しましょう。まずひとつめ。
|
|
・う、わかんないっす(汗)。なんせ「ブレゼンハム」とゆー単語を初めて聞いたくらいだし。んでもとりあえず思いつくことはあるかな。まず、どんなふうに汚いのかが問題かな。ギザギザが出ているとかなら、たとえば表示部分のサイズを縦横とも倍(つまり高解像度)にして、それをプリントアウトしたり縮小表示したりすればきれいになるかもしんないし、ただ単にぼかしたりアンチエイリアス掛けたりするだけできれいになるかも。出力したグラフをフォトレタッチ系にコピーして「きれいになる」んならこの関係かなー。
・直線を引いてるからガクガクするってことなら、 fDt をもっと小さい値にして、データをもっと細かく取って、その中から整数として得られる点を拾っていく、みたいな形にするとかがいいかも。実数>整数変換は必ず必要だと思います。たいがいの画像処理はやっぱし。そうでなきゃ「浮動小数点計算が高速」とかあんまウリになんないよーな(汗)。計算時間がかからないようなら、実数計算を細かくして、そこからきれいに整数値を拾っていくっていうのがいいんじゃないかなーと。 ・……想像の域を出ない(汗)。もひとつお便りです。 |
|
・一般的な 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 のメリット。しかーし、ポインタのコピーの仕方とか色々と大変なんだ、これが。ヘタするとバグの温床になりかねないのが怖いところ。んでも使わなくても温床になりそうな気もするし、ポインタ回りはいつの世も問題ばかりですねぇ(しみじみ)。
・でわまたっ! |
・最近お便りの紹介しかしてないねぇ。今日もそう(爆)。ではひとつめ。
|
|
・ちょちょちょちょいまちっ! Singularity2 には親クラスの Singularity が入ってるんだから、これじゃ Singularity がふたつできちゃうことになっちゃいますよ。なんか怖いです(汗)。 Singularity2 をアップキャストしたのと Singularity::getSingularity() で取得したのを混在させたらやばいことになるんでは? まー Singularity が特にメンバ変数を持たなきゃ問題ないだろうけど……。
・……ってことは、わての例もダメだわ。派生クラスごとに1個ずつ作れるってことは、その基底クラスはいーっぱい作れるってことやん、そりゃやばいよ(汗)。もちろん基底クラスが Singleton だけならいいけど、3世代以上継承したら始末に負えないです。ダメだこりゃ(汗)。 ・これはつまるところ「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. |