• ベストアンサー

VS2005環境でのSHBrowseForFolderの使用について

SHBrowseForFolderについて質問です。 フォルダを選択するダイアログボックスを表示させようとしています。 それで http://rararahp.cool.ne.jp/vc/class/browseFolderDialog.htm http://www.geocities.co.jp/SiliconValley-PaloAlto/5610/vc/03030422/index.html などのサンプルを用いて表示部分の作成を行いました。 デバッグモードで実行し、 ダイアログボックスを表示させたり、フォルダ名を取得したりといった動作は行えるのですが、 右上の×ボタンを押して終了しようとすると終了処理の途中で固まってしまい正常に終了できません。 いずれのサンプルの場合もSHBrowseForFolderをコメントアウトして実行してみると正常にデバッグモードを終了することができます。 ちなみにVS6.0で作成している別のソフトでもSHBrowseForFolderを使用していますが,こちらは問題ありません。 環境のせいだと思うのですが原因が分かりません。 ご回答をお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

 こんばんは。  興味深いので、試してみましたが、其の通りの様です。  MFCは使用出来ない状況にあるのですが、Visual Studio 2005 Express アンド OpenCV 1.1pre1. October, 2008の組み合わせにて、コンソールアプリから確認していますが、確かに「xボタン」を押すとプロセスが固まって動かなくなりました。  逆にOpenCV 1.1pre1. October, 2008関連の関数をコメントアウトすると、プロセスは確かに正常終了しました。  どうやら、cvLoadImage()関数がいけないようです(ファイルの"test.bmp"は確かに読み込めている事をデバッガにて確認済み)。 // test32.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // //win32関連 #include"stdafx.h" #include<windows.h> #include<shlobj.h> //OpenCV 1.1pre1, October, 2008関連 #include<cv.h> #include<cxcore.h> #include<highgui.h> //win32関連 #pragma comment(lib, "user32.lib") #pragma comment(lib, "shell32.lib") #pragma comment(lib, "ole32.lib") //OpenCV 1.1pre1, October, 2008関連 #pragma comment(lib, "cxcore.lib") #pragma comment(lib, "highgui.lib") int main() { BROWSEINFO bInfo = {0}; TCHAR szDisplayName[MAX_PATH]; bInfo.hwndOwner = NULL; bInfo.pidlRoot = NULL; bInfo.pszDisplayName = szDisplayName; bInfo.lpszTitle = TEXT("選択"); bInfo.ulFlags = BIF_RETURNONLYFSDIRS; bInfo.lpfn = NULL; bInfo.lParam = 0; LPITEMIDLIST pIDList = ::SHBrowseForFolder(&bInfo); if(pIDList == NULL) { ::MessageBox(NULL, TEXT("Error"), TEXT("None Selected Close"), IDOK); } else { if(!::SHGetPathFromIDList(pIDList, szDisplayName)) { ::MessageBox(NULL, TEXT("Error"), TEXT("SHGetPathFromIDList() <- Returned Error"), IDOK); return 0; } //OpenCV 1.1pre1, October, 2008関連 ↓ IplImage* ipl = ::cvLoadImage("test.bmp", 0); if(ipl == NULL) { ::MessageBox(NULL, TEXT("Error"), TEXT("IPL is NULL"), IDOK); return 0; } ::cvReleaseImage(&ipl); //OpenCV 1.1pre1, October, 2008関連 ↑ ::CoTaskMemFree(pIDList); } }

komehon
質問者

お礼

ありがとうございます。 やはり無理なようですね。 バージョンを1.0に落として試してみると 正常に動作しました。 バージョンを落としても問題はなさそうなので これでいこうかと思います。 どうもありがとうございました。

すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

>bi.hwndOwner = m_pParentWnd->GetSafeHwnd(); >のように値が代入されています。 >ちなみに >CWnd* m_pParentWnd; // 親ウィンドウ >と定義されています。 「bi.hwndOwnerに、デスクトップウィンドウを示すNULLを指定したらどうかな?」と思ったんですが、もう既にANo.3の回答で「NULLを指定しても駄目」って判ってしまいましたね。 >あと、調べているとOpenCV1.1とSHBrowseForFolder APIと併用すると >プロセスが終了できなくなる不具合が出るとありました。 >(OpenCV1.1使ってます…) http://tessy.org/wiki/index.php?%A5%E1%A5%E2#n127daa9 これですね。 もう既に回答が付いてますが、OpenCV1.1でSHBrowseForFolderとcvLoadImageを同時に使うとコケるようです。 http://tessy.org/wiki/index.php?%A5%E1%A5%E2#n127daa9 に書いてあるリンク先を見ると「OpenCV1.0に戻した」って書いてあるので、1.0にすれば問題は出ないみたいです。

komehon
質問者

お礼

ありがとうございます。 >これですね。 そうです。このページも見ました。 OpenCVのバージョンを落とすと正常に動作しました。 なんかすっきりしないですが、仕方ないですねw

すると、全ての回答が全文表示されます。
回答No.2

BROWSEINFO構造体のhwndOwnerにウィンドウプロシージャを持っている正しいオーナーウィンドウハンドルをセットしてますか? これが不正だと、フォルダブラウザダイアログのウィンドウプロシージャのデフォルト処理がコケるため、メッセージポンプがうまく動作しなくなり、ウィンドウプロシージャがWM_QUITをメッセージキューから取り出せなくなります。 「WM_QUITをメッセージキューから取り出せない」と「WM_QUITを受け取ったのにも関わらず、メッセージループから脱出せずにループし続ける」と言う事になります。 つまり「終了処理中にハングアップする」と言う事です。 「よく判らないけど、サンプルで、構造体をこうやって初期化しているから」と、サンプルの丸写しをしてしまったりすると、本来指定しちゃいけない値を指定する結果になってしまう事があります。

komehon
質問者

お礼

回答ありがとうございます。 BROWSEINFO構造体のhwndOwnerには // BROWSINFO 構造体 設定 BROWSEINFO bi; bi.hwndOwner = m_pParentWnd->GetSafeHwnd(); のように値が代入されています。 ちなみに CWnd* m_pParentWnd; // 親ウィンドウ と定義されています。 ブレイクポイントを設定してbi.hwndOwnerを見ると 「unused = CXX0030: エラーです: 式を評価できません」 となっています。 これがおかしいのでしょうか? あと、調べているとOpenCV1.1とSHBrowseForFolder APIと併用すると プロセスが終了できなくなる不具合が出るとありました。 (OpenCV1.1使ってます…) まさにこれのような気がしてきました。 OpenCVバージョンを1.0に落として試してみようかと思いますが、 何か分かればまたよろしくお願いいたします。

すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.1

サンプルのままなのですか? いくらか手を入れているのでしたら、周辺のコードを掲示された方がよいかと。

komehon
質問者

補足

サンプルではクラスが提供されています。 クラスの中身はいじっていません。 こちらで作ったプログラム(C++ MFCです。すいません書いてませんでした。) の方でボタンクリックで呼び出されるようにしたのみです。 例えば、 http://www.geocities.co.jp/SiliconValley-PaloAlto/5610/vc/03030422/index.html にあるサンプルで試した場合、 ↓のように呼び出してます。 void CTest::OnBnClickedButtonTest() {   CDirectoryDialog dlg;   CString      strDir;   dlg.SetRootDir( "指定のルートフォルダ");   dlg.SetInitDir( "指定の初期フォルダ" );   dlg.SetTitle( _T( "フォルダを選択してください" ) );   if( dlg.DoModal() != IDOK ) return;   strDir = dlg.GetPathName();   //エディットボックスに表示   this->GetDlgItem( IDC_EDIT_TEST )->SetWindowText( strDir ); } ビルドの時点ではエラーは出ないんですが、デバッグモードで実行時に終了ができません。 終了時に1行ずつ追っていくと afxstate.cppの AfxWndProcBase(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { AFX_MANAGE_STATE(_afxBaseModuleState.GetData()); return AfxWndProc(hWnd, nMsg, wParam, lParam); } でreturnの行を通った後に 「現在の場所のソースコードを表示できません」と表示され止まってしまいます。

すると、全ての回答が全文表示されます。

関連するQ&A