VBでいう DoEvents をAPI等々で実現したい。。。

返信する


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

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

トピックのレビュー
   

展開ビュー トピックのレビュー: VBでいう DoEvents をAPI等々で実現したい。。。

by イグトランス » 2005年11月01日(火) 23:40

そうは言ってもマルチスレッドよりシングルスレッドとDoEventsのほうが簡単です。
(ウィンドウプロシージャへの再入さえ気をつければ)
ちょっとしたツール程度には良いではないでしょうか。

もちろん本格的に作り込むのならマルチスレッドのほうがよっぽど便利なのは間違いありません。

by マティ » 2005年11月01日(火) 21:00

Winは基本的にメッセージ駆動(擬似的なマルチスレッド)なので、各アプリケーションは一定時間以内に処理をシステムに返す必要があります。
(アプリケーションは基本的にプロセス管理です。また、WinAPIを呼び出すことにより、処理をシステムに戻せたはずです)

そうしないと、他のアプリケーション動作に影響を与えます。

NoWestさんも書いているように、DoEventsはVBでマルチスレッドが扱えなかった頃に、処理をシステムに強制的に戻す為の関数です。
その副作用としてDoEventsを呼び出した再に別メッセージの処理が始まってしまい、整合性を取るのに苦労する場合があります。
(スレッドの処理時間は、システムが管理しますので、ユーザで処理時間を意識する必要は無かったと思います。)

ActiveBasicにはマルチスレッドをサポートする関数があるので、
メッセージを処理する関数から、DoEventsを必要とする処理を呼び出す場合は、マルチスレッド対応に変更する事をお勧めします。

コード: 全て選択


CreateThread(ByVal 0,0,AddressOf(SubName),0,0,VarPtr(ThreadID))	'マルチスレッド実行


Sub SubName
	DoEeventsの必要な処理
	ExitThread(0)
End Sub
各命令の詳細はヘルプをご覧下さい。

Re: VBでいう DoEvents をAPI等々で実現したい。。。

by NoWest » 2005年11月01日(火) 19:23

> > While( PeekMessage( wndMsg, NULL, 0, 0, PM_NOREMOVE ) )
> > Result = GetMessage( wndMsg, NULL, 0, 0 )
> 単にWhile PeekMessage(wndMsg, NULL, 0, 0, PM_REMOVE)でいいと思いますよ。
> そのときはその代わりに次のIfを次のようにする必要があります。
> If wndMsg.message = WM_QUIT Then
>
> まあWM_QUITが来たらそのままExitProcessを呼んでも良いと思いますが。

そもそもDoEvents関数はC++のようにマルチスレッドが扱えなかった頃のVBの苦肉の策といった代物です。
DoEvents関数を呼び出す時点でパフォーマンスが低下するので、本来使用は極力避けるべきものだと私は思っていますが、人によって便利といえば便利なんでしょうね。

P.S.1 私は出来る限りイベントプロシージャがCPUを占有することがないようにプロシージャ内のプログラムは短くしたりFor文を避けるようにしています。

P.S.2 メッセージイベント実行中に別のメッセージを動かすというのは
グローバル変数が絡んでくると誤動作の原因になりそうな気もしますね


てふろん様とイグラトス様のご意見を参考にすると以下のようになります。

コード: 全て選択

Function DoEvents() As Long
	Dim msg As MSG
	While PeekMessage(msg,NULL,0,0,PM_REMOVE)=TRUE
		Select Case msg.message
			Case WM_QUIT
				ExitProcess(0)
			Case Else
				TranslateMessage(msg)
				DispatchMessage(msg)
		End Select
		Sleep(0)/*←不要かもね(別のスレッドに迷惑かけないように。。。)*/
	Wend
End Function
古いVBではDoEvents関数の戻り値はコントロールの数になっているようですが最近のVBでは常に0が返るようです。

Re: VBでいう DoEvents をAPI等々で実現したい。。。

by イグトランス » 2005年11月01日(火) 18:43

> While( PeekMessage( wndMsg, NULL, 0, 0, PM_NOREMOVE ) )
> Result = GetMessage( wndMsg, NULL, 0, 0 )
単にWhile PeekMessage(wndMsg, NULL, 0, 0, PM_REMOVE)でいいと思いますよ。
そのときはその代わりに次のIfを次のようにする必要があります。
If wndMsg.message = WM_QUIT Then

まあWM_QUITが来たらそのままExitProcessを呼んでも良いと思いますが。

Re: VBでいう DoEvents をAPI等々で実現したい。。。

by てふろん » 2005年11月01日(火) 14:40

こんにちは、再びてふろんです。

> If 0 = Result Or -1 == Result Then
ついつい、Cの癖が...

> If 0 = Result Or -1 = Result Then
と読み替えてください。
失礼致しました。

Re: VBでいう DoEvents をAPI等々で実現したい。。。

by てふろん » 2005年11月01日(火) 14:36

こんにちは、てふろんです。

DoEvent がどんな物か分からなかったんですが、
ググッてみるとどうやらメッセージを処理させるようで。

コード: 全て選択


Function DoEvent( ByRef ExitCode As Long ) As Long

Dim wndMsg As MSG
Dim Result As Long

While( PeekMessage( wndMsg, NULL, 0, 0, PM_NOREMOVE ) )
Result = GetMessage( wndMsg, NULL, 0, 0 )
If 0 = Result Or -1 == Result Then
ExitCode = wndMsg.wParam
DoEvent = FALSE
Exit Function
End If
TranslateMessage( wndMsg )
DispatchMessage( wndMsg )
Wend

DoEvent = TRUE

End Function
テストしないまま即興で書いたのでなんとも言えませんが、
必要な所で上記プロシージャを呼び出せば
メッセージがある時だけメッセージを処理してくれると思います。

VBでいう DoEvents をAPI等々で実現したい。。。

by けんどん » 2005年11月01日(火) 08:17

はじめまして。けんどん と申します。

みなさんのお知恵を拝借したく、トピックを新規投稿いたしました。

内容としては、ABでVB言語の'DoEvents'関数はないことは認識していますが、
この関数をAPIにて実装できないものかと考えています。

私もそうですが、使えたら良いのに・・・という人が以外と多いのではないでしょうか?

一時期、Sleep関数などを代替案に考えたのですが、結果的にイマイチでした。

自分なりに色々と調べて努力してみましたが、見当が付かずに困っています。
よろしければ、ヒントだけでもいただけないでしょうか?
やはり実現不可でしょうか?

最終的に完成したモジュールをみなさんに公開したいと思っています。

ページトップ