ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月28日(日) 02:36

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 7 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2005年11月01日(火) 08:17 
はじめまして。けんどん と申します。

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

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

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

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

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

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


通報する
ページトップ
   
投稿記事Posted: 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
テストしないまま即興で書いたのでなんとも言えませんが、
必要な所で上記プロシージャを呼び出せば
メッセージがある時だけメッセージを処理してくれると思います。


通報する
ページトップ
   
投稿記事Posted: 2005年11月01日(火) 14:40 
こんにちは、再びてふろんです。

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

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


通報する
ページトップ
   
投稿記事Posted: 2005年11月01日(火) 18:43 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
> 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を呼んでも良いと思いますが。


通報する
ページトップ
投稿記事Posted: 2005年11月01日(火) 19:23 
オフライン

登録日時: 2005年5月31日(火) 10:52
記事: 264
お住まい: 高知
引用:
> > 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が返るようです。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年11月01日(火) 21:00 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
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
各命令の詳細はヘルプをご覧下さい。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年11月01日(火) 23:40 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
そうは言ってもマルチスレッドよりシングルスレッドとDoEventsのほうが簡単です。
(ウィンドウプロシージャへの再入さえ気をつければ)
ちょっとしたツール程度には良いではないでしょうか。

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


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 7 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[13人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean