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

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
KICO

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

#16 投稿記事 by KICO »

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

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

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

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


宜しくお願いします。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

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

#17 投稿記事 by NoWest »

> カーソルが自アプリのウィンドウ外でも、受信出来たのでしょうか?
>
> ウィンドウ内は、修正コードで受信出来ましたが、私も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
KICO

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

#18 投稿記事 by KICO »

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

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

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

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

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

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


宜しくお願いします。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

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

#19 投稿記事 by NoWest »

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

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

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



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

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

#20 投稿記事 by KICO »

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キー押下の場合は、大丈夫です。)

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


宜しくお願いします]。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

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

#21 投稿記事 by NoWest »

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

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



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

ですので

コード: 全て選択

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を使って本来
メッセージが通知されるべきウィンドウにメッセージを通知させるわけです。
KICO

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

#22 投稿記事 by KICO »

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

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


宜しくお願いします。
KICO

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

#23 投稿記事 by KICO »

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

宜しくお願いします。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

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

#24 投稿記事 by NoWest »

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

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

#25 投稿記事 by KICO »

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

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

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

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