分類:[C#]
2011/03/13(Sun) 21:09:58 編集(投稿者)
(複数選択できなかったため分類はC#とさせていただいていますが、C++/CLIも利用しています。)
OS:Windows XP SP3
開発環境:Visual C# 2010 Express, Visual C++ 2010 Express
C#のフォームアプリケーションでエクスプローラー的なものを作成しようとしています。
ファイル/フォルダ名の右クリック押下でエクスプローラーの右クリックメニューと同様の
メニューを表示させようとしているのですが、エラーにより停止してしまいます。
以下に、作成したコンテキストメニュー表示のためのコードの一部抜粋を記載します。
○ C#コード
// .NET Framework のListViewを継承したクラスの定義
class ListView : System.Windows.Forms.ListView
{
// 右クリックメニュー押下時に呼ばれる
private void ShowContextMenu()
{
// C++/CLI で定義しているインスタンスを生成
var contextMenu = new ContextMenu();
// Handleプロパティ、ファイルパス文字列を引数にメンバ関数呼び出し
contextMenu.show(Handle, /* ファイルパス */);
}
}
○ C++/CLI コード
void ContextMenu::show(IntPtr handleOwner, String^ contentPath)
{
// マネージ文字列からアンマネージ文字列に変換
char* path = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(contentPath);
// IntPtrからHWNDに変換して下記メソッド呼び出し
show(reinterpret_cast<HWND>(handleOwner.ToPointer()), path);
System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr)path);
}
int ContextMenu::show(HWND windowHandle, char* filePath)
{
// メニューを作成
HMENU menu = ::CreatePopupMenu();
// デスクトップフォルダのインターフェースを取得
IShellFolder* desktopFolder;
::SHGetDesktopFolder(&desktopFolder);
// ファイルパスを元にアイテムIDリストを取得
// (自作メソッドですが、詳細は省略します。)
LPCITEMIDLIST itemIdList = GetItemIDList(filePath);
// コンテキストメニューのインターフェースを取得
LPCONTEXTMENU contextMenu;
HRESULT hRes = desktopFolder->GetUIObjectOf(windowHandle, 1, (LPCITEMIDLIST *)&itemIdList
, IID_IContextMenu, 0, (LPVOID *)&contextMenu );
if( hRes != NOERROR )
return FALSE;
// メニューにメニュー項目を追加
hRes = contextMenu->QueryContextMenu( menu, 0, 1, 0xffff, CMF_NORMAL );
if( hRes == NULL )
goto CleanUp;
// メニューを表示
// !! エラー発生 !!
int iCommand;
iCommand = ::TrackPopupMenu( menu
, TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON
, 0, 0, 0, windowHandle, NULL );
// 以下省略
・・・
}
上記コードをVisual Studio でデバッグ実行しますと
以下のような内容のウィンドウが表示され、::TrackPopupMenu 関数内で停止してしまいます。
・タイトル:FatalExecutionEngineErrorが検出されました。
・メッセージ内容:
"ランタイムの重大なエラーが発生しました。エラーのアドレスは 0x792d884c、スレッド 0xe58 です。エラー コードは 0xc0000005 です。
これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。
このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。"
TrackPopupMenu 呼び出しの直前で
・第一引数 menu には、::CreatePopupMenu 関数の戻り値が格納されていること
・第六引数 windowHandle には、C#側のListView.Handleと同じ値が格納されていること
は確認したのですが、何が原因なのかわかりません。
原因について何かお分かりになる方いらっしゃいましたら、教えていただけませんでしょうか?