by NoWest » 2005年11月12日(土) 17:36
			
			
			すみません。上のゲストは私です。
何を血迷ったのか、編集しようとして引用返信してしまいました。
PM_REMOVEメッセージ→PM_REMOVEフラグ
お詫びにメッセージスレッドとかコールバックスレッドと呼ばれるものを
ご紹介しておきます。
コード: 全て選択
Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As *SECURITY_ATTRIBUTES, bManualReset As Long, bInitialState As Long, lpName As *Char) As HANDLE
Declare Function SetEvent Lib "kernel32" (hEvent As HANDLE) As Long
Declare Function ResetEvent Lib "kernel32" (hEvent As HANDLE) As Long
Sub MessageThreadProc(hEvent As HANDLE)
	/* スレッドメッセージキューの作成 */
	Dim msg As MSG
	Do
		PostThreadMessage(GetCurrentThreadId(),WM_USER,0,0)
		If PeekMessage(msg,NULL,WM_USER,WM_USER,PM_REMOVE)=TRUE Then Exit Do
		Sleep(0)
	Loop
	/* メインスレッドに準備の完了を通知 */
	If hEvent<>NULL Then SetEvent(hEvent)
	/* スレッドメッセージループ */
	While GetMessage(msg,0,0,0)>0
		Select Case msg.message
			Case WM_USER+1
				MessageBox(0,"テスト",0,0)
		End Select
	Wend
	/* メインスレッドに終了の完了を通知 */
	If hEvent<>NULL Then SetEvent(hEvent)
	/* メインスレッドの終了 */
	ExitThread(&HE0F)
End Sub
Class CMessageThread
Private
	m_hThread As HANDLE
	m_idThread As DWord
	m_hEvent As HANDLE
Public
	Sub CMessageThread()
		/* イベントを作成 */
		m_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL)
		/* スレッドを作成 */
		m_hThread=CreateThread(ByVal NULL,0,AddressOf(MessageThreadProc),m_hEvent,0,VarPtr(m_idThread))
		/* スレッドメッセージキュー作成まで待機 */
		If m_hEvent<>NULL and m_hThread<>NULL Then WaitForSingleObject(m_hEvent,INFINITE)
	End Sub
	Sub ~CMessageThread()
		If m_hEvent<>NULL Then ResetEvent(m_hEvent)
		/* スレッドへ終了を通知 */
		SendMsg(WM_QUIT,0,0)
		/* スレッド終了まで待機 */
		If m_hEvent<>NULL and m_hThread<>NULL Then WaitForSingleObject(m_hEvent,INFINITE)
		/* ハンドルを破棄 */
		If m_hEvent<>NULL Then CloseHandle(m_hEvent)
		If m_hThread<>NULL Then CloseHandle(m_hThread)
	End Sub
	Function SendMsg(dwMsg As DWord, wParam As DWord, lParam As DWord) As Long
		/* スレッドにメッセージを送信 */
		SendMsg=PostThreadMessage(m_idThread,dwMsg,wParam,lParam)
	End Function
End Class
 
どんなものか分かりにくいと思いますが簡単に説明すると、スレッドとメッセージループを組み合わせて「いいとこ取り」しようというものです。
使い方は
コード: 全て選択
Dim cmt As CMessageThread
オブジェクトを作成して
好きなタイミングで
コード: 全て選択
cmt.SendMsg(WM_USER+1,0,0)
とメッセージをスレッドに送信してやればよいです。
メッセージはWM_USER+1以降であれば自由に追加することができます。
またGetMessage()の代わりにPeekMessage()を使って流動的に制御できます。
これは少し前にも紹介していたんですが、スレッド関数をクラス内に入れると
誤動作するようなので改良したものです。
私はこれを使ってよくMCIのサウンド・BGMエンジンを作成します。
時間があればそっちをコード掲示板の方に掲載します。
 
			
			
							すみません。上のゲストは私です。
何を血迷ったのか、編集しようとして引用返信してしまいました。
[quote]PM_REMOVEメッセージ→PM_REMOVEフラグ[/quote]
お詫びにメッセージスレッドとかコールバックスレッドと呼ばれるものを
ご紹介しておきます。
[code]Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As *SECURITY_ATTRIBUTES, bManualReset As Long, bInitialState As Long, lpName As *Char) As HANDLE
Declare Function SetEvent Lib "kernel32" (hEvent As HANDLE) As Long
Declare Function ResetEvent Lib "kernel32" (hEvent As HANDLE) As Long
Sub MessageThreadProc(hEvent As HANDLE)
	/* スレッドメッセージキューの作成 */
	Dim msg As MSG
	Do
		PostThreadMessage(GetCurrentThreadId(),WM_USER,0,0)
		If PeekMessage(msg,NULL,WM_USER,WM_USER,PM_REMOVE)=TRUE Then Exit Do
		Sleep(0)
	Loop
	/* メインスレッドに準備の完了を通知 */
	If hEvent<>NULL Then SetEvent(hEvent)
	/* スレッドメッセージループ */
	While GetMessage(msg,0,0,0)>0
		Select Case msg.message
			Case WM_USER+1
				MessageBox(0,"テスト",0,0)
		End Select
	Wend
	/* メインスレッドに終了の完了を通知 */
	If hEvent<>NULL Then SetEvent(hEvent)
	/* メインスレッドの終了 */
	ExitThread(&HE0F)
End Sub
Class CMessageThread
Private
	m_hThread As HANDLE
	m_idThread As DWord
	m_hEvent As HANDLE
Public
	Sub CMessageThread()
		/* イベントを作成 */
		m_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL)
		/* スレッドを作成 */
		m_hThread=CreateThread(ByVal NULL,0,AddressOf(MessageThreadProc),m_hEvent,0,VarPtr(m_idThread))
		/* スレッドメッセージキュー作成まで待機 */
		If m_hEvent<>NULL and m_hThread<>NULL Then WaitForSingleObject(m_hEvent,INFINITE)
	End Sub
	Sub ~CMessageThread()
		If m_hEvent<>NULL Then ResetEvent(m_hEvent)
		/* スレッドへ終了を通知 */
		SendMsg(WM_QUIT,0,0)
		/* スレッド終了まで待機 */
		If m_hEvent<>NULL and m_hThread<>NULL Then WaitForSingleObject(m_hEvent,INFINITE)
		/* ハンドルを破棄 */
		If m_hEvent<>NULL Then CloseHandle(m_hEvent)
		If m_hThread<>NULL Then CloseHandle(m_hThread)
	End Sub
	Function SendMsg(dwMsg As DWord, wParam As DWord, lParam As DWord) As Long
		/* スレッドにメッセージを送信 */
		SendMsg=PostThreadMessage(m_idThread,dwMsg,wParam,lParam)
	End Function
End Class[/code]
どんなものか分かりにくいと思いますが簡単に説明すると、スレッドとメッセージループを組み合わせて「いいとこ取り」しようというものです。
使い方は
[code]Dim cmt As CMessageThread[/code]
オブジェクトを作成して
好きなタイミングで
[code]cmt.SendMsg(WM_USER+1,0,0)[/code]
とメッセージをスレッドに送信してやればよいです。
メッセージはWM_USER+1以降であれば自由に追加することができます。
またGetMessage()の代わりにPeekMessage()を使って流動的に制御できます。
これは少し前にも紹介していたんですが、スレッド関数をクラス内に入れると
誤動作するようなので改良したものです。
私はこれを使ってよくMCIのサウンド・BGMエンジンを作成します。
時間があればそっちをコード掲示板の方に掲載します。