トップ回答者
ActiveXからDragDropイベントでクライアント側にBSTRの配列を渡したい

質問
-
いつもお世話になっております。今MFC ActiveX ControlWizardでActiveXコントロールを作っています。標準ではDrag&Dropイベントが用意されていないようなので、自分でDragDropというイベントをつくり、ファイルがドロップされたタイミングで発行しようとしています。それでドロップされたファイルが複数の可能性があるため、文字列の配列をクライアント側に渡したく重い、SafeArrayを作ってVARIANT型として渡そうとしているのですが、SafeArrayもVARIANTも初めて使うので勝手がよく分からず、うまくいかず悩んでいます。次のようにコーディングしました。[xxxx.odl][id(4)] void DragDropEx(VARIANT Files);[xxxxCtrl.cpp]xxxxCtrl::OnDropFiles(HDROP hDropInfo){UINT fileCount = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0); // ドロップされたファイル数を取得if (fileCount < 1)return;SAFEARRAY *psa;SAFEARRAYBOUND rgb[1];rgb[0].cElements = fileCount; // 作成するSAFEARRAYの要素数 = 32rgb[0].lLbound = 0; // 作成するSAFEARRAYの添字の下限値 = 0psa = ::SafeArrayCreate(VT_BSTR, 1, rgb); // SAFEARRAY作成if(psa == NULL)return;BSTR* data;::SafeArrayAccessData(psa, (void**)&data);TCHAR szFileName[_MAX_PATH];for (UINT i = 0; i < fileCount; i++){::DragQueryFile(hDropInfo, i, szFileName, _MAX_PATH);data[i] = szFileName;}::SafeArrayUnaccessData(psa); // SAFEARRAYアンロックVARIANT filesData;filesData.vt = VT_BYREF;filesData.pparray = &psa;FireDragDropEx(filesData);}SafeArrayをVARIANTにするところが特にこれで良いのか不安です。ビルドしてActiveX Test ContainerでテストするとD&Dしたとき次のようなメッセージが出ます。XXXXl Control: DragDropEx {Files=}次にC#のフォームで作ったテストクライアントアプリで試すとD&Dしたとき、Main()のApplication.Run(new Form1())で止まり、「マネージデバッグアシスタント 'Invalid Variant'では・・・・.exeに問題を検出しました。 追加情報:アンマネージVARIANTからマネージオブジェクトへの変換中に、無効なVARIANTが検出されました。」というエラーダイアログが表示されます。どうも無効なVARIANTと認識されてしまっているようです。どなたか、どこがおかしいかご指摘いただけないでしょうか?
回答
-
>data[i] = szFileName;
TCHARはUnicodeですよね。
BSTRは文字コードはUnicodeですが、通常のUnicode文字列とは構造が異なります。
APIを使用する場合SysAllocStringを使用して、通常のUnicode文字列からBSTRに変換します。
まずはここを直してみてください。
[String Manipulation Functions]
http://msdn.microsoft.com/en-us/library/ms221105.aspx
BSTRがどういう構造になっているか、上記を読めばわかります。
[BSTR 用のメモリの割り当てと解放]
http://msdn.microsoft.com/ja-jp/library/xda6xzx7.aspx
[SysAllocString]
http://msdn.microsoft.com/en-us/library/ms221458.aspx
[CStringT::AllocSysString]
http://msdn.microsoft.com/ja-jp/library/za1865s1(VS.80).aspx
[_bstr_t Class]
http://msdn.microsoft.com/ja-jp/library/zthfhkd6(VS.80).aspx
[ConvertStringToBSTR]
http://msdn.microsoft.com/ja-jp/library/t58y75c0(VS.80).aspx
多々手段はありますが、要件に応じて使い分けてください。 -
ちょっと待った。
CStringArray sa;
for (UINT i = 0; i < fileCount; i++){::DragQueryFile(hDropInfo, i, szFileName, _MAX_PATH);sa.Add(szFileName);data[i] = sa[i].AllocSysString();}そこで、CStringArray である必要はありますか?
よく考え直してください。
主に AllocSysString が何をするものか、CStringArray は何のためのものかを理解して頂きたいと思っています。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年2月4日 4:58
すべての返信
-
>data[i] = szFileName;
TCHARはUnicodeですよね。
BSTRは文字コードはUnicodeですが、通常のUnicode文字列とは構造が異なります。
APIを使用する場合SysAllocStringを使用して、通常のUnicode文字列からBSTRに変換します。
まずはここを直してみてください。
[String Manipulation Functions]
http://msdn.microsoft.com/en-us/library/ms221105.aspx
BSTRがどういう構造になっているか、上記を読めばわかります。
[BSTR 用のメモリの割り当てと解放]
http://msdn.microsoft.com/ja-jp/library/xda6xzx7.aspx
[SysAllocString]
http://msdn.microsoft.com/en-us/library/ms221458.aspx
[CStringT::AllocSysString]
http://msdn.microsoft.com/ja-jp/library/za1865s1(VS.80).aspx
[_bstr_t Class]
http://msdn.microsoft.com/ja-jp/library/zthfhkd6(VS.80).aspx
[ConvertStringToBSTR]
http://msdn.microsoft.com/ja-jp/library/t58y75c0(VS.80).aspx
多々手段はありますが、要件に応じて使い分けてください。 -
kozzさん、こんにちは。なんとか解決しました。ありがとうございました。BSTR* data;::SafeArrayAccessData(psa, (void**)&data);TCHAR szFileName[_MAX_PATH];CStringArray sa;for (UINT i = 0; i < fileCount; i++){::DragQueryFile(hDropInfo, i, szFileName, _MAX_PATH);sa.Add(szFileName);data[i] = sa[i].AllocSysString();}::SafeArrayUnaccessData(psa); // SAFEARRAYアンロックVARIANT vrt;::VariantInit(&vrt);vrt.vt = VT_ARRAY|VT_BSTR;vrt.parray = psa;FireDragDrop(vrt);COleControl::OnDropFiles(hDropInfo);
-
ちょっと待った。
CStringArray sa;
for (UINT i = 0; i < fileCount; i++){::DragQueryFile(hDropInfo, i, szFileName, _MAX_PATH);sa.Add(szFileName);data[i] = sa[i].AllocSysString();}そこで、CStringArray である必要はありますか?
よく考え直してください。
主に AllocSysString が何をするものか、CStringArray は何のためのものかを理解して頂きたいと思っています。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年2月4日 4:58
-
こんにちは。フォーラムオペレーターの高橋春樹です。
kozzさん、Azuleanさん、いつもお世話になっております。
hiro-taさん、MSDNフォーラムのご利用有難うございます。
Azuleanさんから、ご指摘を頂いたと思うのですが、確認して頂けたでしょうか?今回、kozzさんとAzuleanさんからの投稿が、フォーラムを閲覧している方にとっても
有用な情報になるのではないか、と思いましたので、勝手ながら回答マークを付けさせてもらいました。今後ともMSDNフォーラムを宜しくお願いします(^_^)
マイクロソフト株式会社 フォーラム オペレーター 高橋春樹