- PR -

C# グローバルフックでメッセージを編集して送り返す。

投稿者投稿内容
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-28 09:39
うーん質問を変えさせていただきます。

この質問にいたった理由が以下のような流れです。

マウスジェスチャーをしたい

ガジェット形式なのでところどころにあるサンプルのようにウィンドウ内やウィンドウでクリックされた場合のみに動作するマウスジェスチャーでは意味がない

マウスフックを使おう

低レベルマウスフックならC#でも使えた!

マウスフックする場合右クリックや真ん中クリックしてるときにだけマウスジェスチャーをするのが標準らしい

でも右クリックでマウスジェスチャーをすると、右クリックを離したときにメニューが表示されてしまうことがある(デスクトップとかブラウザじょうでやった場合) 真ん中クリックだとブラウザでは自動スクロールが働くことがある。

うざい

右クリックで行えば右クリックを離した時のメッセージを消してしまえばメニューが表示されないのでは?真ん中クリックはクリックしたときに動作するから無理だろう…

ジェスチャーが成功した場合は右クリックを話したときのメッセージを消してしまおう

どうする?

フックでメッセージの編集ができるらしい

低レベルフックでできないらしい

どうしよう・・・


って感じです。 ようはこの問題を解決する方法であればどのような方法でもかまわないわけです。

現状では [Ctrl]キーを押してるときにマウスジェスチャーを行う等が良い方法に思われますが、できればマウスのボタンで動作を行いたい(で、メニューとか表示されてほしくない)

なにか良いアイディアありますか?
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-29 17:09
引用:

なにか良いアイディアありますか?



グローバルフックくらいしかないです。
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-29 17:43
やっぱりorz

まずはUnmanaged C++とManaged C++とC#の相互間の動作の勉強とグローバルフックについてももっと詳しい知識の収集ですねorz

いや、でもいろいろ参考になりました。ありがとうございました *^^
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-29 21:03
どうもいろいろ試してみたんですが上手に行きません。

危険性を考慮しても試して見たかったのでC++でDLLを書いてC#で呼び出してみました(C++はほとんどわからないので先のものを参考に書きました。)

下記がC++のコードです。

コード:
#include "stdafx.h"
#include <windows.h>
#include "SystemHookCore.h"

HookProc userHookProc;
HHOOK hook = NULL;
static LRESULT CALLBACK InternalHookCallback(int code, WPARAM wparam, LPARAM lparam);

//
// Store the application instance of this module to pass to
// hook initialization. This is set in DLLMain().
//
HINSTANCE g_appInstance = NULL;

HHOOK SetWindowsHookExWrapper(int idHook,
    HookProc lpfn,
    /*HINSTANCE hMod,*/
    DWORD dwThreadId
)
{
	userHookProc = lpfn;
	hook = SetWindowsHookEx(idHook,(HOOKPROC)InternalHookCallback,::GetModuleHandle("SystemHookCore.dll"),dwThreadId);
	return hook;
}

BOOL UnhookWindowsHookExWrapper(          HHOOK hhk
)
{
	return UnhookWindowsHookEx(hook /*hhk*/);
}

LRESULT CallNextHookExWrapper(      

    HHOOK hhk,
    int nCode,
    WPARAM wParam,
    LPARAM lParam
)
{
	return CallNextHookEx(hook /*hhk*/,nCode,wParam,lParam);
}

static LRESULT CALLBACK InternalHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
	if (code < 0)
	{
		return CallNextHookEx(hook, code, wparam, lparam);
	}

	userHookProc(code, wparam, lparam);

	return CallNextHookEx(hook, code, wparam, lparam);
}



でC#

コード:
const string DLL_FILENAME = "SystemHookCore.dll";
[DllImport(DLL_FILENAME, CharSet = CharSet.Auto,
   CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(
    int idHook,
    HookProc lpfn,
    /*IntPtr hMod,*/
    int dwThreadId);


[DllImport(DLL_FILENAME, CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);


[DllImport(DLL_FILENAME, CharSet = CharSet.Auto,
     CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(
    int idHook,
    int nCode,
    int wParam,
    IntPtr lParam);

private delegate int HookProc(int nCode, int wParam, IntPtr lParam);



このようにしてC#からC++の関数を呼び出してます。

WH_MOUSE_LLならグローバルフックできるんですが(こんなことしなくてもできるんだからできるか) WH_MOUSEだとローカルフックしかできません(ウィンドウ外にマウスが出るとフックが止まる)

DLLはネイティブでコンパイルされたDLLなはずなんでグローバルフックも動くものだと思っていたのですが…なにかコードに問題点等ありますか?
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-29 22:00
解決。

userHookProc(code, wparam, lparam);

で.NET呼び出してるのがだめらしいですねorz

こんなんドウでしょうか?

1 作成時にWindow Handleを渡しておく

2 フック時にそこにメッセージを送信。

3 メッセージをゲットしたウィンドウがDLLに対してメッセージを送信

4 それを見てDLLで処理を行う。

3がちょっとまだわからないんですがorz GetMessageとかですか?それともウィンドウをメッセージ取得用に作成する必要がありますか?

ほかSocket通信とかでもいけそうですね*^^
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-30 00:00
引用:

こんなんドウでしょうか?



出来なくはないです。が、

引用:

2 フック時にそこにメッセージを送信。



もフックされることをお忘れなく。

引用:

3がちょっとまだわからないんですがorz GetMessageとかですか?それともウィンドウをメッセージ取得用に作成する必要がありますか?



ウィンドウメッセージを受け取るならウィンドウは必要です。

それと、PostMessage() されたメッセージを受け取るにはメッセージループが必須です。
SendMessage() されたメッセージだけを受け取るなら、メッセージループは無くてもなんとかなります。

スキルアップ/キャリアアップ(JOB@IT)