自分のアプリにメッセージ送信するには?

返信する


答えを正確に入力してください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 自分のアプリにメッセージ送信するには?

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月24日(水) 23:14

NoWest様、ありがとう御座います。

だいたい基本的な事は、解りました。(チョッと不安ですが)
連日、懇切丁寧に教えて頂きまして、ありがとう御座いました。

関連サイトを、参考に読んでも解り辛い事が有り、この掲示板が
頼りです。

これからも、宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月24日(水) 19:45

> PostMessage(pData[1],WM_MusKeyMOVE,0,0)を
> SendMessage(pData[1],WM_MusKeyMOVE,0,0)に、したら問題は無くなりましたが
> PostMessage()でないと、マズイですか?
>
> 宜しくお願いします。
特にそういうマズイという訳ではありません。
SendMessageで動作しているならSendMessageで十分です。

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月23日(火) 17:41

PostMessage(pData[1],WM_MusKeyMOVE,0,0)を
SendMessage(pData[1],WM_MusKeyMOVE,0,0)に、したら問題は無くなりましたが
PostMessage()でないと、マズイですか?

宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月23日(火) 15:35

NoWest様、ありがとう御座います。
> 確かにポップアップメニューの時に変になりますね。
ポップアップメニューの動作確認までして頂いて、ありがとう御座います。

Exit Functionを外しましたが、変化ありませんでした。


宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月23日(火) 14:31

確かにポップアップメニューの時に変になりますね。

それの原因が分かりましたので説明しますね。



そもそもフックというのはその名の通り、
ウィンドウに送信されるべきメッセージを釣り上げるという意味があるのですが
今回のサンプルの場合、釣り上げたメッセージをリリースするのを忘れていたんですね。

ですので

コード: 全て選択

Function GetMouseMsgProc(code As Long, wParam As DWord, lParam As DWord) As DWord
    Dim pmh As *MOUSEHOOKSTRUCT
    pmh=lParam
    If code<0 Then
        GetMouseMsgProc=CallNextHookEx(pData[0],code,wParam,lParam)
        Exit Function
    End If
    Select Case wParam
        Case WM_LBUTTONDOWN
            PostMessage(pData[1],WM_MusKeyMOVE,0,0)
    End Select
    '次のフックを呼び出す
    GetMouseMsgProc = CallNextHookEx(pData[0],code,wParam,lParam)
End Function
前回のものと比較して頂くと分かると思いますが
Exit Functionを使っていません。

要するに、WM_LBUTTONDWONを釣り上げた後、CallNextHookExを使って本来
メッセージが通知されるべきウィンドウにメッセージを通知させるわけです。

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月23日(火) 11:35

NoWest様、ありがとう御座います。
> 終了時に、Beep(デバッグ用)が鳴り続け終了出来ません。

>> こちらではそのような問題は起きていないので何ともいえませんが
>> どうせなのでメッセージの受信側のソースも見せていただけると
>> 何が問題なのか分かるかも知れません。
NoWest様の方では、問題無く動いているとの事でしたので、テスト用としてボタン1つだけのウィンドウを作って試した結果、問題は起こりませんでした。

コード: 全て選択


'-----------------------------------------------------------------------------
'  イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd

' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。

	Declare Function StartHook Lib "GetStatusMK" (hWnd As DWord) As Long

	Declare Function EndHook Lib "GetStatusMK" () As Long


	Const WM_MusKeyMOVE	= (WM_APP+1)'システムフック用(GetStatusMK.dll)メッセージコード

'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数

Function MainWndProc(hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord) As DWord
	' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
	Select Case dwMsg
		Case WM_MusKeyMOVE
				Beep(5000,10)
	End Select

	' イベントプロシージャの呼び出しを行います。
	MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。

Sub MainWnd_Destroy()
	'System Hookのアンインストール
	EndHook()
	TestHook_DestroyObjects()
	PostQuitMessage(0)
End Sub

Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
	'System Hookのインストール
	If StartHook(hMainWnd)<0 Then
		SendMessage(hMainWnd,WM_CLOSE, 0, 0): ExitProcess(0)
	End If
End Sub

Sub MainWnd_CommandButton1_Click()
	SendMessage(hMainWnd,WM_CLOSE,0,0): ExitProcess(0)
End Sub

Sub MainWnd_QueryClose(ByRef cancel As Integer)
	Beep(8000,100)
End Sub
問題が起こる方では、システムメニューを外してあるので、
ポップアップメニューから終了しています。(但し、メニューの選択項目を終了にし
Enterキー押下の場合は、大丈夫です。)

ポップアップメニューに、問題が有るのでしょうか?
他にも、タブコントロールシートの格タブが表示され無いとか、部分的に不安定です。


宜しくお願いします]。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月22日(月) 21:14

> NoWest様、ありがとう御座います。
>
> ウィンドウ外も、修正コードで受信出来ました。(~o~)
こちらも安心しました。
> (マウスとキーボードを分けてグローバルフックするのですか。
> 何故、"WH_GETMESSAGE"では駄目なのでしょうか?)
最初の書き込みにマウスの情報を取得したいということだったので。。。
一番の理由は、私はメッセージフックを使ったことが無かったということです。
多分、メッセージフックでも問題なくできると思います。

> 終了時に、Beep(デバッグ用)が鳴り続け終了出来ません。
こちらではそのような問題は起きていないので何ともいえませんが
どうせなのでメッセージの受信側のソースも見せていただけると
何が問題なのか分かるかも知れません。
> MOUSEHOOKSTRUCT構造体中の"hwnd As HWND"を"hwnd As DWord"にして問題無いですか?
全く問題ありませんよ。
ミスに気付いたらドンドン自分で修正していただく方が力になると思います。
> それと、ファイルマッピングは、ローカルフックが出来る様に使っているのですか?
> それとも、どんなDLLでも作成する時には必要なのでしょうか?
ファイルマッピングはグローバルフックの為に必要です。
システムフックがセットされると
全てのプロセスにDLLが自動的にロードされるのですが
そのDLLのグローバル変数は全て、同じ値をとる必要があるので
ファイルマッピングを使って同じメモリ領域からデータを読み取るように
する必要があるんです。※特にActiveBasicではCのように#pragmaとか
使えませんので、、、

ファイルマッピング自体は特にDLLに必要という訳ではありません。



>
> 宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月22日(月) 17:34

NoWest様、ありがとう御座います。

ウィンドウ外も、修正コードで受信出来ました。(~o~)

(マウスとキーボードを分けてグローバルフックするのですか。
何故、"WH_GETMESSAGE"では駄目なのでしょうか?)

終了時に、Beep(デバッグ用)が鳴り続け終了出来ません。

MOUSEHOOKSTRUCT構造体中の"hwnd As HWND"を"hwnd As DWord"にして問題無いですか?

それと、ファイルマッピングは、ローカルフックが出来る様に使っているのですか?
それとも、どんなDLLでも作成する時には必要なのでしょうか?


宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月22日(月) 16:11

> カーソルが自アプリのウィンドウ外でも、受信出来たのでしょうか?
>
> ウィンドウ内は、修正コードで受信出来ましたが、私もBeep()で動作確認しているのですが
> 終了時に、鳴り続け終了出来無く成りました。
デスクトップ上でクリックしても何も起きませんか?

それではもう少し修正したものがあるのでもう一度テストしてみてください。

コード: 全て選択

Type MOUSEHOOKSTRUCT
    pt As POINTAPI
    hwnd As HWND
    wHitTestCode As DWord
    dwExtraInfo As DWord
End Type

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (idHook As DWord, lpfn As DWord,hMod As DWord, dwThreadId As DWord) As DWord
Declare Function UnhookWindowsHookEx Lib "user32" (hHook As DWord) As DWord 
Declare Function CallNextHookEx Lib "user32" (hHook As DWord, nCode As Long, wParam As DWord, lParam As DWord) As DWord

Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" (hFile As HANDLE, ByRef lpFileMappingAttributes As SECURITY_ATTRIBUTES, flProtect As DWord, dwMaximumSizeHigh As DWord, dwMaximumSizeLow As DWord, lpName As BytePtr) As HANDLE
Declare Function MapViewOfFile Lib "kernel32" (hFileMappingObject As HANDLE, dwDesiredAccess As DWord, dwFileOffsetHigh As DWord, dwFileOffsetLow As DWord, dwNumberOfBytesToMap As DWord) As VoidPtr
Declare Function UnmapViewOfFile Lib "kernel32" (lpBaseAddress As VoidPtr) As Long

Dim hMF As HANDLE
Dim pData As *DWord
Dim hInst As DWord

Const WM_MusKeyMOVE = (WM_USER+1)

Function Export DllMain(hinstDLL As DWord, fdwReason As DWord, lpvReserved As VoidPtr) As Long
    'DLLエントリポイント
    Select Case fdwReason
        Case DLL_PROCESS_ATTACH
            'DLLがプロセス空間にロードされた時に実行されます。
            _System_StartupProgram()
            DllMain=1
            hInst=hinstDLL

            'メモリマップトファイルを作成
            hMF=CreateFileMapping(-1,ByVal NULL,PAGE_READWRITE,0,(4*8)*2,"Mouse Hook Test DLL")
            pData=MapViewOfFile(hMF,FILE_MAP_ALL_ACCESS,0,0,0)
        Case DLL_PROCESS_DETACH
            'DLLがプロセス空間から解除された時に実行されます。
            'メモリマップトファイルを破棄
            UnmapViewOfFile(pData)
            CloseHandle(hMF)
    End Select
 End Function

Function Export StartHook(hWnd As DWord) As Long
    'Hookのインストール
    pData[0]=SetWindowsHookEx(WH_MOUSE, AddressOf(GetMouseMsgProc), hInst, 0)
    pData[1]=hWnd
    If pData[0]=0 Then StartHook=-1
End Function
 
 
Function Export EndHook() As Long
    'Hookのアンインストール
    If pData[0] Then UnhookWindowsHookEx(pData[0]) Else EndHook=-1
End Function

Function GetMouseMsgProc(code As Long, wParam As DWord, lParam As DWord) As DWord
    Dim pmh As *MOUSEHOOKSTRUCT
    'Dim c        As Long
    pmh=lParam
    If code<0 Then
        GetMouseMsgProc=CallNextHookEx(pData[0],code,wParam,lParam)
        Exit Function
    End If
    Select Case wParam
        Case WM_LBUTTONDOWN
            Dim buf[255] As Byte
            wsprintf(buf,"x:%d y:%d hwnd:%d",pmh->pt.x,pmh->pt.y,pmh->hwnd)
            SetWindowText(pData[1],buf)
            PostMessage(pData[1],WM_MusKeyMOVE,0,0)
            Exit Function
    End Select
    '次のフックを呼び出す
    GetMouseMsgProc = CallNextHookEx(pData[0],code,wParam,lParam)
End Function

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月22日(月) 14:45

NoWest様、ありがとう御座います。
>ポインタ変数を使うことでメモリへのデータの書き込みが
>あたかも配列のように行えるようになります
説明して頂くと「なるほど」と解るのですが、どの様な時に使用するのか
結び付かず困ったものです。
>私はマウスフックでやっているんですが、KICO様はメッセージフックを
>使っているから動かないのは当然です。

>全体を修正しないから間違うんですね。

>とりあえず、私の方では動作を確認しました。
カーソルが自アプリのウィンドウ外でも、受信出来たのでしょうか?

ウィンドウ内は、修正コードで受信出来ましたが、私もBeep()で動作確認しているのですが
終了時に、鳴り続け終了出来無く成りました。


宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月22日(月) 13:15

> NoWest様、連日ありがとう御座います。
>
> AB Ver3.13 なものですから、"Dim pData As *DWord"とか使えないので、
そういえばAB3には*DWordは使えませんでしたね。忘れていました。

AB3では代わりDWordPtrを使ってください。

コード: 全て選択

Dim pData As DWordPtr
"Dim pData[1] As DWord"にしましたが、
"pData=MapViewOfFile(hMF,FILE_MAP_ALL_ACCESS,0,0,0)"との
関係でマズイですか?
はい、マズイです。

というのもMapViewOfFileの戻り値はアドレスだからです。
アドレスを格納するのはポインタ変数というお約束です。
ポインタ変数を使うことでメモリへのデータの書き込みが
あたかも配列のように行えるようになります。

例えば以下のコードは同じことをしています。
細かいことはヘルプのキーワード検索とかで
関数を調べると分かると思います。

コード: 全て選択

Dim p As DWord
p=malloc(4*2)
SetDWord[p,123]
SetDWord[p+4,456]
Print GetDWord(p)
Print GetDWord(p+4)
free(p)

コード: 全て選択

Dim p As DWordPtr
p=malloc(4*2)
p[0]=123
p[1]=456
Print p[0]
Print p[1]
free(p)

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月22日(月) 12:36

NoWest様、連日ありがとう御座います。

AB Ver3.13 なものですから、"Dim pData As *DWord"とか使えないので、"Dim pData[1] As DWord"にしましたが、"pData=MapViewOfFile(hMF,FILE_MAP_ALL_ACCESS,0,0,0)"との関係でマズイですか?
> Beep()で動作確認していたんですが、
> WM_MOUSEMOVEイベント常にメッセージが送信されてくる状態になって
> ヒドイ目に合いました。(笑
御手数かけまして、申し訳御座いません。(-_-;)


宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by NoWest » 2005年8月22日(月) 12:09

> DLLを修正しましたが、ウィンドウ内でも受信出来なくなりました。
> というか、DLL内の"PostMessage(pData[1], WM_MusKeyMOVE, 0, 0)"行は通っていません。

> ひょっとして前回書いて頂いたコールバックスレッドを使用するのでしょうか?
>
>
> 宜しくお願いします。

すみません、私のミスです。
私はマウスフックでやっているんですが、KICO様はメッセージフックを
使っているから動かないのは当然です。

全体を修正しないから間違うんですね。

とりあえず、以下で私の方では動作を確認しました。

コード: 全て選択

Type MOUSEHOOKSTRUCT
    pt As POINTAPI
    hwnd As HWND
    wHitTestCode As DWord
    dwExtraInfo As DWord
End Type

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (idHook As DWord, lpfn As DWord,hMod As DWord, dwThreadId As DWord) As DWord
Declare Function UnhookWindowsHookEx Lib "user32" (hHook As DWord) As DWord 
Declare Function CallNextHookEx Lib "user32" (hHook As DWord, nCode As Long, wParam As DWord, lParam As DWord) As DWord

Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" (hFile As HANDLE, ByRef lpFileMappingAttributes As SECURITY_ATTRIBUTES, flProtect As DWord, dwMaximumSizeHigh As DWord, dwMaximumSizeLow As DWord, lpName As BytePtr) As HANDLE
Declare Function MapViewOfFile Lib "kernel32" (hFileMappingObject As HANDLE, dwDesiredAccess As DWord, dwFileOffsetHigh As DWord, dwFileOffsetLow As DWord, dwNumberOfBytesToMap As DWord) As VoidPtr
Declare Function UnmapViewOfFile Lib "kernel32" (lpBaseAddress As VoidPtr) As Long


Dim hMF As HANDLE
Dim pData As *DWord
Dim hInst As DWord

Const WM_MusKeyMOVE = (WM_USER+1)

Function Export DllMain(hinstDLL As DWord, fdwReason As DWord, lpvReserved As VoidPtr) As Long
    'DLLエントリポイント
    Select Case fdwReason
        Case DLL_PROCESS_ATTACH
            'DLLがプロセス空間にロードされた時に実行されます。
            _System_StartupProgram()
            DllMain=1
            hInst=hinstDLL

            'メモリマップトファイルを作成
            hMF=CreateFileMapping(-1,ByVal NULL,PAGE_READWRITE,0,(4*8)*2,"Mouse Hook Test DLL")
            pData=MapViewOfFile(hMF,FILE_MAP_ALL_ACCESS,0,0,0)
        Case DLL_PROCESS_DETACH
            'DLLがプロセス空間から解除された時に実行されます。
            'メモリマップトファイルを破棄
            UnmapViewOfFile(pData)
            CloseHandle(hMF)
    End Select
 End Function

Function Export StartHook(hWnd As DWord) As Long
    'Hookのインストール
    pData[0]=SetWindowsHookEx(WH_MOUSE, AddressOf(GetMsgProc), hInst, 0)
    pData[1]=hWnd
    If pData[0]=0 Then StartHook=-1
End Function
 
 Function Export EndHook() As Long
    'Hookのアンインストール
    If pData[0] Then UnhookWindowsHookEx(pData[0]) Else EndHook=-1
End Function

Function GetMsgProc(code As Long, wParam As DWord, lParam As DWord) As DWord
    Dim pmh As *MOUSEHOOKSTRUCT
    Dim a        As Byte
    Dim f        As Long
    'Dim c        As Long
    pmh=lParam
    If code<0 Then
        GetMsgProc=CallNextHookEx(pData[0],code,wParam,lParam)
        Exit Function
    End If
    Select Case wParam
        Case WM_NCHITTEST
        a=1
        Case WM_MOUSEMOVE
            a=1
        Case WM_NCMOUSEMOVE
            a=1
        Case WM_MOUSEWHEEL
            a=2
        Case WM_RBUTTONDOWN
            a=3
        Case WM_LBUTTONDOWN
            a=4
        Case WM_MBUTTONDOWN
            a=5
        Case WM_RBUTTONUP
            a=6
        Case WM_LBUTTONUP
            a=7
        Case WM_MBUTTONUP
            a=8
    End Select
    If a Then
        PostMessage(pData[1],WM_MusKeyMOVE,0,0)
        Exit Function
        'CallNextHookEx(pData[0],code,wParam,lParam)
        'GetMsgProc=1
        'Exit Function
    End If
    '次のフックを呼び出す
    GetMsgProc = CallNextHookEx(pData[0],code,wParam,lParam)
End Function
Beep()で動作確認していたんですが、
WM_MOUSEMOVEイベント常にメッセージが送信されてくる状態になって
ヒドイ目に合いました。(笑

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月21日(日) 16:32

DLLを修正しましたが、ウィンドウ内でも受信出来なくなりました。
というか、DLL内の"PostMessage(pData[1], WM_MusKeyMOVE, 0, 0)"行は通っていません。

ひょっとして前回書いて頂いたコールバックスレッドを使用するのでしょうか?


宜しくお願いします。

Re: 自分のアプリにメッセージ送信するには?

by KICO » 2005年8月21日(日) 15:44

NoWest様、ありがとう御座います。
>やっぱり、私のイメージと少し違いましたね。
タイトルを「マウス及びキーのグローバル監視」と、しておけば良かったですかネェ?

グローバルフックにすれば、ウィンドウ内は勿論、デスクトップ領域や他のアプリケーション使用中でも
フック出来ているので、後は情報が欲しいウィンドウに送信すれば良いと思ったものですから、この様なタイトルにしたのです。


コールバックスレッドについて説明して頂きましてありがとう御座います。
今後の参考にさせて頂きます。
まだ私は、バージョン3.13 を使用しているものですからクラス関係の事は、まったく解りませんが勉強します。(ガンバ×2 (^_^;)←自分に)

<デスクトップ領域のマウスフックの方法があれば誰か教えてください。
宜しくお願いします。

ページトップ