スクリプトからMessageBox?()に引数を渡す †
step1でMessageBox?()を呼び出すことが出来たので、今度は文字列パラメータを受け取って指定した文字列を表示するメッセージボックスを作ってみる。
BCC 5.5.1
- スクリプトに
1
|
| msgbox2 "Hello, world !", "msgbox2 test"
|
と書けばメッセージボックスのテキストに「Hello, world !」を表示し、タイトルに「msgbox2 test」と表示するhsmsgbox2プラグインを作る。
- スクリプトで記述した文字列引数をプラグイン側で取得する方法を学ぶ。
+
| | dllmain.cpp
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
-
|
|
|
-
|
|
|
|
|
!
|
!
-
|
|
!
-
|
!
| #include <windows.h>
#include "hsp3plugin.h"
#include "msgbox2.h"
static int cmdfunc( int cmd )
{
code_next();
switch( cmd ) {
case 0x00:
msgbox2(); break;
default:
puterror( HSPERR_UNSUPPORTED_FUNCTION ); }
return RUNMODE_RUN;
}
EXPORT void WINAPI register_hsmsgbox2( HSP3TYPEINFO *info )
{
hsp3sdk_init( info ); info->cmdfunc = cmdfunc; }
BOOL WINAPI DllEntryPoint(HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}
|
|
+
| | msgbox2.h
|
1
2
3
4
5
6
|
| #ifndef _HSMSGBOX_MSGBOX2_H_
#define _HSMSGBOX_MSGBOX2_H_
void msgbox2( void );
#endif
|
|
+
| | msgbox2.cpp
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
!
| #include <windows.h>
#include "hsp3plugin.h"
#include "msgbox2.h"
void msgbox2( void )
{
char *sprm, *text, *title;
sprm = code_gets();
text = hspmalloc( lstrlen( sprm ) + 1 ); lstrcpy( text, sprm );
sprm = code_gets();
title = hspmalloc( lstrlen( sprm ) + 1);
lstrcpy( title, sprm );
MessageBox( NULL, text, title, MB_OK);
}
|
|
+
| | プラグイン定義ファイル
|
1
2
3
|
| #regcmd "register_hsmsgbox2","hsmsgbox2.hpi"
#cmd msgbox2 $00
|
|
+
| | サンプルスクリプト
|
1
2
3
4
5
|
| #include "hsmsgbox2.as"
msgbox2 "Hello, world !", "MessageBox test"
s = "Good-bye !"
msgbox2 s, "MessageBox test"
|
|
まずはじめに微妙な変更点があります。
- プラグイン登録関数を○○initからregister_hsmsgbox2()にしました。(好みです。)
- ファイルを分割。
文字列型のパラメータを取得するにはcode_getds()、code_gets()を使って文字列へのポインタを取得します。
この二つの関数の違いですが、省略可能なパラメータにはcode_getds()を使い、必須パラメータにはcode_gets()を使います。
文字列を取得するに当たって注意する点が1つあります。
得られたポインタは次のパラメータ(型は問わない)を取得するまでの間に限って有効であるということです。
よって複数のパラメータを扱う場合はデータのコピーが必要になります。
データを保持するための領域に静的変数を使うか、動的確保にするかの制限はありません。
C/C++ならmalloc()で動的割り当ても可能です。
ただしこの場合メモリ管理はプログラマが全責任を負って行う必要があります。
動的に割り当てたメモリのルートなどを管理しておいてコールファンクションの終了処理で一括解放というのもいいと思います。
その他にはHSPのバッファマネージャを利用して動的に確保するという手段があります。
バッファマネージャを利用したメモリの動的確保はバッファマネージャが管理するメモリブロックにエントリーされ、HSPの終了時に自動的に解放されます。
バッファマネージャによるメモリ管理の仕組みはstrbuf.cppで定義されています。
バッファマネージャを利用した動的確保はhspmalloc()によって行います。サンプルでは、
1
2
3
4
|
|
sprm = code_gets();
text = hspmalloc( lstrlen( sprm ) + 1 ); lstrcpy( text, sprm );
|
のように文字列長+ヌル文字分の領域を確保してコピーしています。
ただしこの方法、あまりいいとは思えません。^^;
この関数(msgbox2)は実行されるたびに新しい領域を割り当て、以前割り当てた領域はそのままバッファマネージャにエントリーされたままです。
関数を抜ける前に解放するか、既存の領域を使いまわして領域オーバーしそうだったら拡張させるとかが一般的だと思います。
バッファマネージャは領域の解放にhspfree()、内容を保持したままの拡張にhspexpand()を提供しています。
特に文字列の長さにあわせるのではなく「○○長以上の文字列は○○以降は切り捨てられます。」といった仕様なら静的変数を使ってもいいと思います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-
|
|
|
|
|
|
|
|
|
|
|
|
!
| static char text[ HSMSGBOX_MAXCHAR + 1 ];
static char title[ HSMSGBOX_MAXCHAR + 1 ];
void msgbox2( void )
{
char *sprm;
int len;
sprm = code_gets();
len = lstrlen( sprm ) + 1;
lstrcpyn( text, sprm, len < HSMSGBOX_MAXCHAR ? len : HSMSGBOX_MAXCHAR );
sprm = code_gets();
len = lstrlen( sprm ) + 1;
lstrcpyn( title, sprm , len < HSMSGBOX_MAXCHAR ? len : HSMSGBOX_MAXCHAR );
MessageBox( NULL, text, title, MB_OK );
}
|
- 本人以外がソースの解説するのもアリですよ。(ぁ
あといきなりメモリの動的割り当てやってます。諸プログラミング本の流れでは静的変数->動的割り当て・・・と思って「解説」のところに静的変数を用いた例をコメントアウトしています。 -- kz3
- 僕もstep1のソースに、beep 16としたら音が出るようにMessageBeep?を追加したらうまくいってくれました。まだ戻り値の取得方法ががいまいち?です。 -- hiroki?
- HSPCTX構造体にhspのシステム変数statを表すstatメンバがありますよ。プラグイン側でctx->stat=MessageBeep?();みたいなこと(笑)をやればスクリ側のstatで戻り値を得られるかも知れません。(思いつきで言ってます。) -- kz3
- 下記の方法で試してみたら返りました。(-_-;)
static void beep( int mbn )
{
stat=MessageBeep(
mbn // サウンドの形式
);
return;
}
- あ、hsp3plugin.hで#define stat ctx->statってマクロで定義されていましたね〜^^思いつきは合っていたので良かったです。 -- kz3
- int mbn って書いたけど、UINT mbn なのかな。 -- hiroki?
- やっばりint mbn でした。 UNITではエラーが出ます。 -- hiroki?