ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2018年12月17日(月) 22:56

All times are UTC+09:00




新しいトピックを投稿する  トピックへ返信する  [ 6 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2005年12月11日(日) 00:27 
オフライン

登録日時: 2005年7月19日(火) 07:02
記事: 183
住所: 宮城県
「おぉ!!できるんだ、こういうことも☆」ってノリが全てです(笑)。

【やってること】
DLLを呼び出し、呼び出した先のDLLの内部でウィンドウを作成し、
呼び出し元のウィンドウはロック。
処理が終わった後に、DLL側のウィンドウを破棄し、
ロックを解除し制御を、呼び出し元に返します。
動作確認AB3.13+AB2.59


【以下、コードなど】
『プロジェクト→DLL-プロシージャライブラリ』で作成。
※DLL内部でグローバル変数を使っていることに注意。
  ['DLLのインスタンス記録用]の部分
※DLLエントリポイント云々[DllMain()の中]にも一行書き込んでいることに注意。
  ['窓作成に使うのでDLLのインスタンスを保持。]の部分
[hide=DLLコードはこちら。]
コード:
'#include "DLLonWnd.idx"'ここは任意ですね^^;

'-------------------------------------------------------------------
' メモ - このファイルには、DLLの構成要素を記述します。
'        (例:関数定義、グローバル変数、定数定義など)
'
'        エクスポートが必要な関数には、"Export" 修飾子を指定します。
'        (例:Function Export FuncName() As Long)
'-------------------------------------------------------------------

'DLLのインスタンス記録用
Dim g_hInstance As Long

Function Export DllMain(hinstDLL As DWord, fdwReason As DWord, lpvReserved As VoidPtr) As Long
	'DLLエントリポイント
	Select Case fdwReason
		Case DLL_PROCESS_ATTACH
			'DLLがプロセス空間にロードされた時に実行されます。
			g_hInstance = hinstDLL '窓作成に使うのでDLLのインスタンスを保持。
			_System_StartupProgram()
			DllMain=1
	End Select
End Function


'DLLの外から呼ばれる関数。
'窓を作って任意の処理をする。
'実際の処理の内容は下のメッセージループMainProc()に記述する。
Function Export DllWnd( hBaseWnd As Long ) As Long
	Dim hInstance As DWord
	Dim WinClass As WNDCLASSEX
	Dim hWnd As DWord
	Dim msgMain As MSG

	'初期値設定処理
	FillMemory( VarPtr(WinClass), Len(WinClass), NULL )
	hInstance = g_hInstance'GetModuleHandle( NULL )

	'ウインドウクラス生成
	With WinClass
		.cbSize			= Len( WinClass )
		.hInstance		= hInstance
		.style			= CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS
		.lpszClassName	= "WsSelfWnd"
		.lpszMenuName	= "WsSelfMenu"
		.lpfnWndProc	= AddressOf( MainProc )
		.hbrBackground	= GetStockObject( WHITE_BRUSH )
		.cbClsExtra		= NULL
		.cbWndExtra		= NULL
		.hIcon			= LoadIcon( hInstance, NULL )
		.hCursor		= LoadCursor( NULL, IDC_ARROW )
	EndWith
	If( NULL=RegisterClassEx( WinClass ) )Then
		DllWnd = FALSE
	EndIf

	'ウインドウ生成
	hWnd = CreateWindowEx( NULL, "WsSelfWnd", "テストAB3", (WS_OVERLAPPEDWINDOW or WS_VISIBLE), _
							CW_USEDEFAULT , CW_USEDEFAULT, _
							CW_USEDEFAULT , CW_USEDEFAULT, _
							hBaseWnd, NULL, hInstance, NULL )

	EnableWindow( hBaseWnd, FALSE )'親窓をロック
		'メッセージループ
		While( GetMessage( msgMain, NULL, 0, 0 ) )
			TranslateMessage( msgMain )
			DispatchMessage( msgMain )
		Wend
		DllWnd = msgMain.wParam
	EnableWindow( hBaseWnd, TRUE )'親窓のロックを解除
EndFunction



'メッセージループ
Function MainProc( hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord ) As DWord
	SelectCase dwMsg
	Case WM_DESTROY
		'窓の破棄処理
		PostQuitMessage(0)
		MainProc = 0
		ExitFunction
	'Case
	'以下、ここに処理を書いていく。
	EndSelect
    ' デフォルトプロシージャを呼び出す。
    MainProc = DefWindowProc( hWnd, dwMsg, wParam, lParam )
End Function
[/hide]それの呼び出し元のAB2のコードの例は以下です。
DLLファイル名をDLLonWnd.dllとしています。
スペースを押すと、DLLの中のDllWnd()を呼び出して窓を表示します。
それを閉じればAB2側の窓に制御が戻ります。
[hide=AB2からの利用例。]
コード:
Declare Function DllWnd Lib "DLLonWnd.dll" ( ByVal hBaseWnd As Long ) As Long

Ver2Wnd( Ownerwnd() )

End

Sub Ver2Wnd( ByVal hBaseWnd As Long )
	dim hThisWnd As Long
	dim Message As Long
	dim wParam As Long
	dim lParam As Long
	dim hWnd As Long
	Dim retAns As Long
	Window hWnd, hBaseWnd, -1, -1, _
			320, 240, _
			"AB2テスト", _
			WS_OVERLAPPED or WS_CAPTION or WS_DLGFRAME or WS_SYSMENU or WS_VISIBLE, _
			"NORMAL"
	While 1
		GetWndMsg hThisWnd, Message, wParam, lParam
		If ( hThisWnd<>hBaseWnd ) Then
			SelectCase Message
				'終了操作
				Case WM_CLOSE
					Msgbox hWnd, "終了処理"
					ExitWhile
			EndSelect
			'スペースでDLLの関数呼び出し
			If KeyState(Asc(" ")) And &H8000 Then
				retAns = DllWnd( hWnd )
				Msgbox hWnd, "ほげ"
			EndIf
		EndIf
	Wend
	DelWnd hWnd
EndSub
[/hide]


AB2でプログラムを組んでいて、
負荷の高い処理はAB3/AB4で作ったDLLを呼び出して処理する、
などという変なことをしている人(=私の仲間w)にしか
参考にならないかもしれません(苦笑)。


ついでに。
DLL作成のときは、デバックモードが無いので、
大抵別途に組んで動作を確かめてから関数だけをコピペしてますよね、きっと。
そのときの『動作の確かめ用』のコードも以下に載せておきます。
『プロジェクト→EXE-N88プロンプトベース』で作成。
でも当然ながらN88BASICのプロンプト画面は使いません^^;
使ったらDLLに移したときにエラーします。
あ、Print文とかでデバッグするのは楽になるかも?
(『EXE-ベース無し』を選べばよかったのかな?)
なにはともあれ、そのときのコードです。
[hide=窓作成]
コード:
#N88BASIC

' ↓ ここからプログラムが実行されます
Dim retAns As Long


retAns = WinMain( _PromptSys_hWnd )
End 'ExitProcess(0)を呼んでいます。



Function WinMain( hBaseWnd As Long ) As Long
	Dim hInstance As DWord
	Dim WinClass As WNDCLASSEX
	Dim hWnd As DWord
	Dim msgMain As MSG

	'初期化
	FillMemory( VarPtr(WinClass), Len(WinClass), NULL )
	hInstance = GetModuleHandle( NULL )

	'ウインドウクラス生成
	With WinClass
		.cbSize			= Len( WinClass )
		.hInstance		= hInstance
		.style			= CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS
		.lpszClassName	= "WsSelfWnd"
		.lpszMenuName	= "WsSelfMenu"
		.lpfnWndProc	= AddressOf( MainProc )
		.hbrBackground	= GetStockObject( WHITE_BRUSH )
		.cbClsExtra		= NULL
		.cbWndExtra		= NULL
		.hIcon			= LoadIcon( hInstance, NULL )
		.hCursor		= LoadCursor( NULL, IDC_ARROW )
	EndWith
	If( NULL=RegisterClassEx( WinClass ) )Then
		WinMain = FALSE
	EndIf

	'ウインドウ生成
	hWnd = CreateWindowEx( NULL, "WsSelfWnd", "テストAB3", (WS_OVERLAPPEDWINDOW or WS_VISIBLE), _
							CW_USEDEFAULT , CW_USEDEFAULT, _
							CW_USEDEFAULT , CW_USEDEFAULT, _
							hBaseWnd, NULL, hInstance, NULL )

	While( GetMessage( msgMain, NULL, 0, 0 ) )
	    TranslateMessage( msgMain )
    	DispatchMessage( msgMain )
	Wend
	WinMain = msgMain.wParam
EndFunction
[/hide][hide=メッセージループ]
コード:
'メッセージループ
Function MainProc( hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord ) As DWord
    ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
	SelectCase dwMsg
	Case WM_DESTROY
		PostQuitMessage(0)
		MainProc = 0
		ExitFunction
	'Case
	'以下、ここに処理を書いていく。
	EndSelect

    ' デフォルトプロシージャを呼び出す。
    MainProc = DefWindowProc( hWnd, dwMsg, wParam, lParam )
End Function
[/hide]以上二つをプロジェクトに参加させて下さい。
なお、こちらは親ウィンドウ(=DLLでの呼び出し元の窓)であるプロンプトウインドウはロックしていません。



ふむ。
『Win32プログラミング講座 ~ Step14. DLLを作る ~』で思いっきり
DLLに窓ハンドル渡して内部で保存ダイアログなどを呼んでいるわけだから、
出来て当然なのか^^;

12/11 2:30修正しました。


最後に編集したユーザー 淡幻星 on 2005年12月11日(日) 02:27 [ 編集 1 回目 ]

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

登録日時: 2005年5月31日(火) 09:34
記事: 141
住所: 北海道
微妙なツッコミですが
"WinMain"という名前にすると,C言語のWindowsプログラムの始動時関数と同じ名前になるので名前を変えたほうがよいかと思われます(笑)。

_________________
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================


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

登録日時: 2005年7月19日(火) 07:02
記事: 183
住所: 宮城県
引用:
微妙なツッコミですが
"WinMain"という名前にすると,C言語のWindowsプログラムの始動時関数と同じ名前になるので名前を変えたほうがよいかと思われます(笑)。
あ、やっぱ気になりますか?^^;
そうですね。DLLの方WinMain()→DillWnd()に書き換えておきました。
私もちょっと気になってたのでAB2の呼び出しでAliasなんぞ使ってたのでしたし(笑)。

でもDLLの動作確認用コードの方はそのままに(こっちはEXEですし)。
窓クラスを登録して、CreateWindowして、って作業する関数ですから、
WinMain()そのままなわけで問題はないかと。
こっちの方がしっくり来るんですよね、私としては^^;
引数が違うじゃないか、というツッコミは知りません(笑)。

ん~、Cのコードから写したことがバレバレw


あ、蛇足なんですけどせっかくなので≫Sinryowさん
AB4のクラスで、仮想メソッドって、
関数の形を宣言するだけで、内容は定義できないんですか?
ヘルプを読んだ限りではそう思えたのですが、
C++だったら「オーバーライドされなかったときの動作」として
内容も定義できるんで、どうなんだろうとちょっと疑問。
自分で確かめれば良いんですが(人に聞いたほうが早い♪/マテ)
知ってましたら&気が向きましたら、お願いします^^;


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

登録日時: 2005年5月31日(火) 09:34
記事: 141
住所: 北海道
引用:
あ、蛇足なんですけどせっかくなので≫Sinryowさん
AB4のクラスで、仮想メソッドって、
関数の形を宣言するだけで、内容は定義できないんですか?
ヘルプを読んだ限りではそう思えたのですが、
C++だったら「オーバーライドされなかったときの動作」として
内容も定義できるんで、どうなんだろうとちょっと疑問。
自分で確かめれば良いんですが(人に聞いたほうが早い♪/マテ)
知ってましたら&気が向きましたら、お願いします^^;
自分もよく知らなかったので調べてみましたが,ABのVirtualって,C++とかのとは全く違うようです。
C++などでは淡幻星さんのおっしゃった通り「オーバーライドされなかったときの動作」なのです。
http://hwb.ecc.u-tokyo.ac.jp/current/CD ... 8BFF4.html(仮想関数についての簡単な説明。Yahooのキャッシュ)
http://wisdom.sakura.ne.jp/programming/cs/cs26.html(C#だがプログラムの例があり分かりやすい)

※自分はABでもC++でもVirtualを使ったことはありません。(核爆)

_________________
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================


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

登録日時: 2005年5月31日(火) 17:59
記事: 895
住所: 東京都
そこのサイトにはC++のもありますよ。
http://wisdom.sakura.ne.jp/programming/cpp/cpp31.html

そしておそらくAB5ではC++などと同じように仮想関数が扱えるようになると思います。
(AB4.2でそうなるという話でしたがどうやらAB4.2は出ないようなので)


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

登録日時: 2005年7月19日(火) 07:02
記事: 183
住所: 宮城県
引用:
自分もよく知らなかったので調べてみましたが,ABのVirtualって,C++とかのとは全く違うようです。
わざわざ調べていただいてありがとうございますm(_ _)m
ふむ。全然違うものなんですね^^;
私の中ではVirtual宣言=仮想関数=オーバーライドだと思ってたんですが、
これが間違いでないにしても、全てじゃなかったんですね(^^;)。
現在のABは
引用:
仮想関数は主にCOMインターフェイスを定義する際に活用します。
にターゲットを絞っているんですね。


気になった理由は、
ABでCreateWindow()+WndProcをクラス化してみようと思ったからです。
そうすると継承の際にメンバ関数のオーバーライドが使えないと不便なわけで、
「AB4にはVirtual宣言も導入されてたよな・・・」と思ったしだいでした。
[hide=目的としては・・・(略)。]一行で必要最低限の窓を作成(最低限の機能を持った窓プロシージャも自動で生成される)できて、後は必要に応じて機能拡張(イベント動作の追加)できるクラスがあると、コード書くとき便利だよな~、というものです。先日C++で組んでみましたが、少なくとも私にとっては思った以上に便利に仕上がりました♪ まぁMFCに、それそのままのCWndクラス?があるみたいですけど^^;[/hide]ABにはRADがありますから、そんなに必要ないですかw よってノープロブレムかな(笑)
引用:
※自分はABでもC++でもVirtualを使ったことはありません。(核爆)
ちなみに私は、つい最近C++で
「おぉ、仮想関数って便利じゃねーか。継承するときは様々だな☆」って
思ったばかりでして(つーか、そのための仕様ですね^^;)。だから使ってみたいのです(笑)。


http://wisdom.sakura.ne.jp/
そこのサイト様は、すごく利用させてもらってます。分かりやすいですよね☆
私はそこでC/C++の基本と、C/C++でのウィンドウの生成を学びました(^^)

引用:
AB5ではC++などと同じように仮想関数が扱えるようになると思います。
そうなんですか。
ではそのときを楽しみに待ちます。
詳しい情報をありがとうございました。おかげですっきりしました。


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

All times are UTC+09:00


オンラインデータ

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


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

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