質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.83%

  • C#

    6318questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C# マウスのグローバルフック マウスの左をクリックしてもマウスの移動で判定される

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 828

konan1234

score 1

c#でマウスのグローバルフックを使って、マウスのイベントを監査するシステムを作っています。
何とか動くようになったのですが、マウスのイベントを拾う処理が上手く行きません。

現象ですが、マウスを左クリックしても、マウスの移動として判定されてしまいます。
詳細

定義
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_LBUTTONDBLCLK = 0x0203,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208
}

マウスをクリックしたら動くメソッド
private IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
{
// parse system messages
if (nCode >= 0)
{
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
if (LeftButtonDown != null)
LeftButtonDown((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
if (LeftButtonUp != null)
LeftButtonUp((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
if (RightButtonDown != null)
RightButtonDown((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_RBUTTONUP == (MouseMessages)wParam)
if (RightButtonUp != null)
RightButtonUp((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
if (MouseMove != null)
MouseMove((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam)
if (MouseWheel != null)
MouseWheel((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_LBUTTONDBLCLK == (MouseMessages)wParam)
if (DoubleClick != null)
DoubleClick((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_MBUTTONDOWN == (MouseMessages)wParam)
if (MiddleButtonDown != null)
MiddleButtonDown((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
if (MouseMessages.WM_MBUTTONUP == (MouseMessages)wParam)
if (MiddleButtonUp != null)
MiddleButtonUp((MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)));
}
return CallNextHookEx(hookID, nCode, wParam, lParam);
}

マウスを左クリックしたら  WM_LBUTTONDOWNの判定をされるはずが、WM_MOUSEMOVEに判定されます。
ちなみにマウスのホイールをクリックしたらWM_MOUSEWHEELで判定されるのでプログラムに問題はないと思います。
この原因が分かりません。OSや環境、使用しているマウスによって変わってしまうのでしょうか。 

アドバイスの方、よろしくお願いいたします

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2017/12/15 16:01

    読みにくいです。ソースをコードブロックに入れてください。プログラミングをする人に言うのは初歩的過ぎて失礼に当たりますが、例えばコードブロックという言葉の意味がわからない場合は質問するのではなくググってください。

    キャンセル

回答 2

+2

フック用プロシージャ内で参照している引数と値が間違っているのでは。

WM_LBUTTONDOWNはWindowメッセージを示す値なのでフック用プロシージャのnCodeに入るはずです。
WM_LBUTTONDOWNメッセージの場合、wParam は仮想キーコード、lParamはマウスのX,Y座標です。
※※追記していますが、これは私の間違いです。※※

詳細はMSDNをご覧ください。
WM_LBUTTONDOWN message


追記(2017/12/20)
+評価をいただいていましたが、コメントでご指摘のようにマウスフック用のプロシージャのnCodeにはWM_LBUTTONDOWNは入りません。質問者様のコードで正しいです。この点、私の間違いでしたのでお詫びいたします。機会があれば回答の評価を下げてください。すみません。


追記#2(2017/12/20) 動作を確認しました。

私の先の回答、フック用プロシージャのwParamにWM_LBUTTONDOWNが入る件については間違った指摘を載せてしまいすみません。申し訳なかったので、こちらでも動作確認してみました。質問者様がご提示のコードは全部ではないと思いましたので、以下のマイクロソフトのサンプルコードを流用して試しました。
Visual C# .NET では、ウィンドウ フックを設定する方法

結果、マウスを動かさなくても(マウスカーソルを動かさない)、WM_MOUSEMOVE時にプロシージャが呼ばれました。

ただ、左クリックではWM_LBUTTONDOWN、右クリックではWM_RBUTTONDOWNの時に期待するように呼ばれています。WM_MOUSEMOVEはマウスの操作にもよりますが、左クリックでは
WM_LBUTTONDOWN --> WM_MOUSEMOVE --> WM_MOUSEMOVE とのように複数回呼ばれました。これはWindows 7(64ビット) と Windows 10(64ビット)のどちらでも同じでした。
(プログラムは Visual Studio 2017, .NET Framework 4.6.1で作成)

質問者様のケースでも、WM_MOUSEMOVEもあるものの、WM_LBUTTONDOWNも受信できているのではないでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 12:51

    nCodeにはWM_LBUTTONDOWNは設定されません。https://msdn.microsoft.com/en-us/library/windows/desktop/ms644988.aspx

    キャンセル

  • 2017/12/20 15:48

    ご指摘ありがとうございます。仰る通りですね。

    キャンセル

0

回答とは言えませんが、気になった部分があったのでコメントさせていただきます。

if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)


上記のコードではIntPtr型のwParamを列挙型MouseMessagesに変換されています。
IntPtr型はint型と互換性がありますがIntPtrのコンストラクタを見ての通り、内部の変数を64bitの整数値と解釈することもできます。

if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam.ToInt32())


最低でも上記程度の型指定はしたほうが厳密な型指定という意味で安心かもしれません。

読む限りはグローバルフックでイベント取得後の振り分け処理には問題なさそうなので、行き詰っているようであれば、グローバルフックのソースコードのほうをあげてもらえると言えることが増えるかもです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/16 06:28 編集

    ToInt32() の必要はありません。わずかに速度が低下するだけで何のメリットもありません。型こそ IntPtr 型ですが、マウスメッセージであるかぎり取りうる範囲は 32 ビットに収まります。

    キャンセル

  • 2017/12/16 08:10

    IntPtrとintの扱うビット数が同じなのは知っていたのですが、取りうる値の範囲はまた別だと思っていました。ToInt32()は速度の低下を招くだけでメリットないのですね。勉強になりました。教えて下さりありがとうございます。

    キャンセル

  • 2017/12/16 11:05

    みなさん回答して頂きありがとうございます。少々調べたのですが、
    デバックでマウスを移動、左クリックしても押してるボタンはxbutton2となってました。ただ、マウスを移動、左クリックしても、移動で判定されるのは解決出来ない状態です…

    キャンセル

  • 2017/12/19 18:17

    tsubaki961さんのコードしか見てませんが
    ```if (MouseMessages.WM_LBUTTONDOWN == MouseMessages.WM_LBUTTONDOWN & wParam)```
    では?

    キャンセル

  • 2017/12/19 18:23

    演算の優先順位を間違えてました
    if ((MouseMessages.WM_LBUTTONDOWN & wParam) == MouseMessages.WM_LBUTTONDOWN)

    キャンセル

  • 2017/12/20 11:27

    教えていただいた条件式にすると以下のエラーが発生しました…
    演算子 '&' を 'bool' と 'System.IntPtr' 型のオペランドに適用することはできません

    キャンセル

  • 2017/12/22 12:03

    型を合わせて下され。
    要は wParam には複数の状態が一緒に入ってくるので、== 演算子で単純には比較できません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    6318questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • トップ
  • C#に関する質問
  • C# マウスのグローバルフック マウスの左をクリックしてもマウスの移動で判定される