VB6から自作ActiveXへ配列(文字)を渡したい

解決


VB梅  2006-10-05 22:51:21  No: 63197

表題のような事は可能ですか?

今まで
exeファイルにコマンドプロンプトから次のように複数の引数を渡して使用していました。

C:\>test.exe "a" "b" "c" "d" "e" "f"

test.exeは次のように受け取りしてました。
int  main(int argc, char *argv[])
{
  // 省略
}

今回はこのtest.exeをActiveX化したいのです

VB6で

v(0) = "a":v(1) = "b":v(2)= "c" ・・・・・・・・
test.main(v(0))

と言うように配列を渡す事は可能でしょうか?

出来ない場合は別な方法を教えてください。
よろしくお願いします。

追伸
v= "a_b_c_d_e" '_は区切り文字
test.main(v)
が無難でしょうか


Blue  2006-10-05 23:03:11  No: 63198

>今回はこのtest.exeをActiveX化したいのです
ということは COM になるわけですよね?(VBでは参照設定してNewして使う)
Declareで使えるようにするのは単なるDLLです。

どちらにせよ、文字列型配列ですのでSAFEARRAYを使うことになります。


Blue  2006-10-05 23:08:19  No: 63199

ちなみに、文字型配列ですので,
>test.main(v(0))
のように先頭要素をByRefで渡すといらぬ変換(Unicode→Ascii変換)が起こりそうなので
配列全体をByRefで渡すような形にしたほうがいいです。

文字列型配列ではなくて、StrPtrの入ったLong型配列ならば簡単そうだけど。

>v= "a_b_c_d_e" '_は区切り文字
>test.main(v)
>が無難でしょうか
でしょうね。


VB梅  2006-10-05 23:11:34  No: 63200

Blue さん返事ありがとうございます。
DLLでは可能なのですね^^

書き忘れました、ごめんなさい。
OCXとして使用します。
アクティブXコンポーネントです。

よろしくお願いします。


Blue  2006-10-05 23:19:05  No: 63201

>よろしくお願いします。
はSAFEARRAYを調べた上での発言なんでしょうか?
ActiveXは作ったことないですが、

v(0) = "a":v(1) = "b":v(2)= "c" ・・・・・・・・
test.main(v) ' ByRef s() As String

のような指定をして呼ぶ場合、C側では、LPSAFEARRAY* 型で受けることになります。
過去ログやWeb検索で一度 SAFEARRAY について検索してみるといいでしょう。


VB梅  2006-10-05 23:29:54  No: 63202

>SAFEARRAYを調べた上での発言なんでしょうか?
もちろん、調べつくしました。

VC++でActiveX コントロールを作成しているのですが
メソッドの追加から、引数のタイプを設定する項目に
LPSAFEARRAY*がありません。制約があるのかと思われます。


Blue  2006-10-05 23:35:25  No: 63203

> LPSAFEARRAY*がありません。制約があるのかと思われます。
ではVARIANT*で受けてはどうでしょうか?

参考
http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200609/06090040.txt


VB梅  2006-10-06 00:28:54  No: 63204

>VARIANT*で受けてはどうでしょうか?
質問する以前に参考を確認して色々と試しました。DLLでは可能でした。(MSDNにもありますよね)
ActiveX コントロールでは次の通りです。

ActiveX コントロールのVC++は
long CTestddCtrl::foo(VARIANT FAR* v) 
{
    SAFEARRAY* psa;
    if ( v->vt != ( VT_ARRAY | VT_BSTR | VT_BYREF ) ) return 1;
    psa = *( v->pparray );
    if ( psa->cDims != 1 ) return 2;
    return 0;
}
となっています。

VB6では
Private Sub Command1_Click()
Dim v(2) As String
    v(0) = "こんにちわ"
    v(1) = "テスト"
    v(2) = "test"
    MsgBox Testdd1.foo(v(0))  ←ここで型が一致しません
End Sub

次に
    MsgBox Testdd1.foo(v)  ←ここで型が一致しません

次に
Dim v(2) As Variant  に変更した
MsgBox Testdd1.foo(v)  ←ここで型が一致しません

次に
MsgBox Testdd1.foo(v(0))  メッセージボックスで”1”が表示

次にVC++の
   // if ( v->vt != ( VT_ARRAY | VT_BSTR | VT_BYREF ) ) return 1;
として削除した。
MsgBox Testdd1.foo(v(0))  メッセージボックスで”2”が表示

以上まで確認しました。


Blue  2006-10-06 00:35:21  No: 63205

適当にやってみた。

VC

void CActiveXTestCtrl::ShowList(VARIANT FAR* list) 
{
    // TODO: ここにディスパッチ ハンドラ コードを追加してください。
    SAFEARRAY* psa;
    BSTR wcs;
    long i, lb, ub;
    CString s;

    if ( list->vt != ( VT_ARRAY | VT_BSTR ) ) return;

    psa = list->parray;
    if ( psa->cDims != 1 ) return;

    SafeArrayLock( psa );

    SafeArrayGetLBound( psa, 1u, &lb );
    SafeArrayGetUBound( psa, 1u, &ub );

    for ( i = lb; i <= ub; i++ )
    {
        SafeArrayGetElement( psa, &i, ( void* )&wcs );
        AfxMessageBox( CString( wcs ) );
    }

    SafeArrayUnlock( psa ); 
}

VB

Option Explicit

Sub test()
    Dim v As Variant
    Dim s(2) As String
    Dim a As New ActiveXTest
    v = Split("ABC,あいう,a", ",")
    a.ShowList v
    
    s(0) = "漢字"
    s(1) = "#%"
    s(2) = "カタカナ"
    v = s
    a.ShowList v
End Sub


Blue  2006-10-06 01:07:46  No: 63206

ActiveXならばBSTR*でもいけるようです。

VC

void CActiveXTestCtrl::ShowList2(BSTR FAR* list, long count) 
{
  // TODO: ここにディスパッチ ハンドラ コードを追加してください。
  for ( int i = 0; i < count; i++ )
  {
    AfxMessageBox( CString( list[ i ] ) );
  }
}

VB

Sub test()
    Dim a As New ActiveXTest
    Dim s(2) As String
    s(0) = "おはよう"
    s(1) = "こんにちは"
    s(2) = "さようなら"
    a.ShowList2 s(0), 3
End Sub


VB梅  2006-10-06 01:22:31  No: 63207

Blueさんありがとうございます。
Dim v As Variant  ○
Dim v(4) As Variant  ×

VB6の変数設定が悪かったのですね
勉強になりました。


Blue  2006-10-06 10:16:52  No: 63208

よくよく考えてみたら、VARIANT*にする必要もなく、VARIANT型でよかったです。
それと、VB側でいちいち Variant型変数に入れなくてもString型配列渡せますね。

void CActiveXTestCtrl::ShowList(const VARIANT FAR& list)
{
    // TODO: ここにディスパッチ ハンドラ コードを追加してください。
    SAFEARRAY* psa;
    BSTR wcs;
    long i, lb, ub;
    CString s;

    if ( list.vt != ( VT_ARRAY | VT_BSTR ) ) return;

    psa = list.parray;
    if ( psa->cDims != 1 ) return;

    SafeArrayLock( psa );

    SafeArrayGetLBound( psa, 1u, &lb );
    SafeArrayGetUBound( psa, 1u, &ub );

    for ( i = lb; i <= ub; i++ )
    {
        SafeArrayGetElement( psa, &i, ( void* )&wcs );
        AfxMessageBox( CString( wcs ) );
    }

    SafeArrayUnlock( psa ); 
}

Sub test()
    Dim s(2) As String
    Dim a As New ActiveXTest
    
    s(0) = "漢字"
    s(1) = "#%"
    s(2) = "カタカナ"
    a.ShowList s
End Sub


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加