マウスイベントを任意の場所で取得する方法

[戻る]
やっぴ 2015/01/12(月) 12:04:20
マウスイベントを取得する方法についての確認です。

マウスイベントは、WM_LBUTTONDOWNなどのウィンドウメッセージで取得できますが、
これは、イベントを受信するウィンドウがアクティブの場合にのみ取得できます。
これを、ウィンドウが非アクティブであっても取得する方法はありますでしょうか?
任意のウィンドウ上でマウスホイールのイベントを受信し、そのウィンドウ上でのホイール操作を
カスタマイズしたいと考えております。
フリーツールでいうと、igmouseというツールのようなイメージになります。

非アクティブウィンドウのマウスイベントを取得する方法をご教授ください。

環境:
Windows7
Visual Studio 2010 Express

ITO 2015/01/12(月) 15:46:54
う--ん、
 >非アクティブウィンドウのマウスイベントを取得する方法をご教授ください。

igmouseというツールのコメントを見ると、
  マウスカーソルの下のウインドウをアクティブにして。。。。
とあります。
非アクティブ状態でばないですね。

>非アクティブウィンドウのマウスイベントを取得する方法
これは難しいと思います。
通常、マウスのドライバーはマイクロソフト製なので何らかの裏ワザは
あるかも知れません。

やっぴ 2015/01/12(月) 20:11:27
ITOさん、回答ありがとうございました。

言葉足らずで申し訳ありません。
非アクティブのウィンドウという表現が不適切でした。

やりたいこととしては、エクセルやワードといったあらゆるウィンドウ上で、
マウス操作をしたときにそのイベントを受けとりたいということです。
例えば、ウィンドウベースのアプリを実装した場合、
そのウィンドウ上でのマウス操作は受けとることができますが、
そのウィンドウが非アクティブだとマウス操作を受けとることができません。
こういった場合もマウス操作を受け付けるようにしたいです。

そもそもウィンドウベースのアプリを実装している時点で的外れなのかもしれませんが、
ウィンドウを持ったアプリを実装したいわけではなく、
単純に任意の場所でのマウス操作を受け付けたいだけですので、
もし、取っ掛かりが間違っていればその点も含めてご教授いただきたいです。

ITO 2015/01/13(火) 13:01:46
うーーん、
ウインドウを検索する関数の一部で、ウインドウハンドルを得ることが
できるみたいですね。
 ただ、オペレータがたまたまそのウインドウを非アクティブにしているときに、
イベントを受け取ろうとするとウインドウハンドル = NULLの例外でアプリが異常終了
します。
 NULLをチェックしていても違うタイミングで非アクティブになる可能性もあります。

結構難しそうですね。

仲澤@失業者 2015/01/13(火) 18:59:31
メッセージフックを使うのが本筋的内容ですが、

http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+201008/10080005.txt

のような方法でも、簡易的にホイールメッセージを変更できます。

これは、最上位ウインドウに届いたWM_MOUSEWHEELを、
直接子ウインドウに、リダイレクトして、
アクティブでないウインドウでも、ホイールでスクロールできるようにしたものです。
手前味噌ですみません(笑)。

ITO 2015/01/13(火) 21:30:10
仲澤さん、
フォロー助かります。
なるほど、専用のメッセージ関数があるのですね。
マイクロソフトマウスの対応のためでしょうかね。

やっぴ 2015/01/15(木) 10:48:54
仲澤さん、回答ありがとうございました。

http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+201008/10080005.txt

の実装を試してみましたが、期待通りの動作となりませんでした。
本ソースコードを埋め込んだMDIウィンドウ上でのマウスホイール動作は受け取ることが
できますが、全然別の、例えばExcel上でマウスホイール動作を行っても、本ソースコー
ドを埋め込んだMDIウィンドウにはイベントは通知されませんでした。
別のアプリケーション上のマウスホイール動作も、今自分が作成しているアプリケーシ
ョン上で受けるにはどのようにしたらよろしいでしょうか。

AR 2015/01/15(木) 11:54:02
仲澤さんが述べられたフックは試されましたか?
昔書いたコードの抜粋ですが、以下のような低レベルフックでマウスイベントを横取りで
きます。
あとは、マウス座標位置のアプリケーションを特定し、メッセージをリダイレクトしてや
れば良いでしょう。

void CMainFrame::SetMouseHook()
{//Windows7以降はスリープなどでフックが外れることがあるので注意
    m_hhkLowLevelMouse = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc,
theApp.m_hInstance, 0);
}
void CMainFrame::FreeMouseHook()
{
    if (m_hhkLowLevelMouse)
    {
        if (UnhookWindowsHookEx(m_hhkLowLevelMouse))
            m_hhkLowLevelMouse = NULL;
    }
}

LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        MSLLHOOKSTRUCT* pllhook = (MSLLHOOKSTRUCT *)lParam;
        if (wParam == WM_MOUSEMOVE)//マウス移動
        {
(中略)
    return CallNextHookEx(m_hhkLowLevelMouse, nCode, wParam,  lParam);
}

ITO 2015/01/15(木) 12:15:21
>MDIウィンドウにはイベントは通知されませんでした。
メインのウインドウの「CMDIFrameWnd」上ではどうですか?
試してみてはどうでしょうか。

古いスレッドには追加発言できません。