【やってること】
DLLを呼び出し、呼び出した先のDLLの内部でウィンドウを作成し、
呼び出し元のウィンドウはロック。
処理が終わった後に、DLL側のウィンドウを破棄し、
ロックを解除し制御を、呼び出し元に返します。
動作確認AB3.13+AB2.59
【以下、コードなど】
『プロジェクト→DLL-プロシージャライブラリ』で作成。
※DLL内部でグローバル変数を使っていることに注意。
['DLLのインスタンス記録用]の部分
※DLLエントリポイント云々[DllMain()の中]にも一行書き込んでいることに注意。
['窓作成に使うのでDLLのインスタンスを保持。]の部分
DLLコードはこちら。 [ここをクリックすると内容が表示されます]
それの呼び出し元のAB2のコードの例は以下です。コード: 全て選択
'#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 FunctionDLLファイル名をDLLonWnd.dllとしています。
スペースを押すと、DLLの中のDllWnd()を呼び出して窓を表示します。
それを閉じればAB2側の窓に制御が戻ります。
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
EndSubAB2でプログラムを組んでいて、
負荷の高い処理はAB3/AB4で作ったDLLを呼び出して処理する、
などという変なことをしている人(=私の仲間w)にしか
参考にならないかもしれません(苦笑)。
ついでに。
DLL作成のときは、デバックモードが無いので、
大抵別途に組んで動作を確かめてから関数だけをコピペしてますよね、きっと。
そのときの『動作の確かめ用』のコードも以下に載せておきます。
『プロジェクト→EXE-N88プロンプトベース』で作成。
でも当然ながらN88BASICのプロンプト画面は使いません^^;
使ったらDLLに移したときにエラーします。
あ、Print文とかでデバッグするのは楽になるかも?
(『EXE-ベース無し』を選べばよかったのかな?)
なにはともあれ、そのときのコードです。
窓作成 [ここをクリックすると内容が表示されます]
コード: 全て選択
#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メッセージループ [ここをクリックすると内容が表示されます]
以上二つをプロジェクトに参加させて下さい。コード: 全て選択
'メッセージループ
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なお、こちらは親ウィンドウ(=DLLでの呼び出し元の窓)であるプロンプトウインドウはロックしていません。
ふむ。
『Win32プログラミング講座 ~ Step14. DLLを作る ~』で思いっきり
DLLに窓ハンドル渡して内部で保存ダイアログなどを呼んでいるわけだから、
出来て当然なのか^^;
12/11 2:30修正しました。