第九回・そのバグフィクス


 さて、前回のプログラムにはバグがありました。
それは『Windows98だと右クリックしてもクリックが止まらない』
という致命的なものでした。
いやー、NT4.0で作ってるもので全然気づかなかった。

 では気を取り直してバグフィクスをしましょう。
プログラミングとはバグとの闘いなのさ…。

 さて、まずバグの原因を調査しましょう。
どうやらタイマー処理中のキーチェックがうまく行っていないようです。
さて困りました。どうすればこれを回避できるでしょうか?
おそらく最もまっとうな回避手段はDLLを作ってマウスにフックを
かけることでしょう。
…が!今回は姑息な手段で回避してしまいましょう。(いい加減だなぁ…)

 具体的な方法はタイマー処理中にたえずマウスの位置を調べ、
(0, 0)だった場合(画面左上になります)タイマーを止めます。
つまり、クリックの終了法が右クリックではなくカーソルが左上隅に
移動した場合になります。

ソースコード(新しいウィンドウで開きます)

前回からの変更点は二点だけです。

        static DWORD dwCount = 0;
        POINT point;

ダイアログプロシージャの最初の部分です。
short sKeyCheck;
を削除して代わりに
POINT point;
が追加されています。POINTは点を表す構造体で、内部にxとyの二つの
変数を持っています。これらがそれぞれx座標とy座標を表し、画面上の
点の位置を表現しています。

                ::GetCursorPos(&point);
                if(point.x==0 && point.y==0)
                {
                        KillTimer(hWnd, ID_TIMER);
                        return 0;
                }

WM_TIMERの部分です。
GetKeyStateでのチェックをやめてGetCursorPosでマウスカーソルの
位置をチェックしています。ここで、先ほど宣言したPOINT構造体の
pointが渡されているわけですが、&マークがついています。
これは何かというと『pointのアドレスを渡す』ということです。

つまり、
「この場所にその変数作っといたからそこに結果を書き込んでね」
という意味です。
わかりにくい?わかりにくいですね。
ですが引数に渡した変数で結果を受け取る場合にはこの様な方法を
使います。よくわからない人はC/C++の解説書で『ポインタ』
または『参照渡し』などの項目を読んでみてください。

そしてpointのxとpointのyが共に0だった場合はタイマーをストップ
させます。
さて、このxとyが画面の位置を表すと説明しましたが、画面の左上が
(0,0)になります。そして右に移動するほどxの値が増えて、下に移動
するほどyの値が増えることになります。注意してくださいね。

あと戻り値を0に修正しました。MSDNライブラリによるとWM_TIMER
メッセージを処理したときの戻り値は

『もしそれがこのメッセージを処理すればっていうかー、アプリケーションはゼロを返すべきですみたいなー。』
(IBM インターネット翻訳の王様 《語尾…みたいなー》で翻訳)

らしいので。

さて、今回はこれで終了です。
けど左上に持ってきたときに終了ってもしかしてマイコンピュータ連打
しちゃうんじゃないかなー?
その場合はただ画面の上端に来たときに終了するように変更するといいかも。
それと他にもバグがあった場合はメール等で報告してくださいね。
では、お疲れさまでした。

戻る