• ベストアンサー

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)

  • chie65535
  • ベストアンサー率43% (8520/19368)
回答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

  • chie65535
  • ベストアンサー率43% (8520/19368)
回答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% (2177/4070)
回答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

  • SHBrowseForFolderについて

    SHBrowseForFolderを使用してフォルダ参照ダイアログを表示しています。Win2000の場合は新しいフォルダの作成ボタンが表示されるのですが、NT4.0の場合は新しいフォルダの作成ボタンが表示されません。 SHELL32.dllのバージョンの違いなのですが、NT4.0で新しいフォルダの 表示ボタンを追加したい場合はどうすればよろしいのでしょうか? 追加は無理なんでしょうか?

  • SHBrowseForFolderが固まる

    VC++2008です。 SHBrowseForFolderでulFlagsにBIF_NEWDIALOGSTYLEを指定すると、 ダイアログが表示されて必ず3秒くらい固まってしまうのですが、なぜでしょうか? 下のソースで、ulFlagsの行をコメントアウトすると正常に使えます。 しかし、他のPC1台ではコメントアウトしなくても正常でした。 SHBrowseForFolderを扱うshell32.dllのバージョンが関係あるのかな?と思ったのですが、 現象が起きる方がバージョンが新しかったです。 6.0.2900.6072 6.0.2900.2180 ITEMIDLIST* pidl; BROWSEINFO bi; ZeroMemory( &bi, sizeof( BROWSEINFO )); bi.hwndOwner = NULL; bi.ulFlags = BIF_NEWDIALOGSTYLE; pidl = SHBrowseForFolder(&bi);

  • SHBrowseForFolderに関する質問

    WinAPIを使ってプログラムを作成中です。 SHBrowseForFolder関数でフォルダを選択するようにしていて、それは成功したのですが、一つ問題が出てきました。 プログラムの用途上、フォルダを選択する時にUSBドライブの差し替えが必要になります。ところがSHBrowseForFolderで表示されたフォルダ一覧は、USBドライブを抜いたり差したりしても一切更新されません。BROWSEINFO.lpfnに指定したプロセジャーにイベントでも送られてくれれば対処もできるのですが、それも無いようです。 何か良い対処方法はないでしょうか?

  • 【VC++6.0(MFC)】適切なSHBrowseForFolder使用方法について教えてください。

    いつも大変お世話になっております。 VC++初心者です。 前回質問した内容と重複しますが、 改めて質問させて頂きたいと思います。 現在、SHBrowseForFolderを使用すると、 デバグモードで実行すると以下のようなエラーが出力され困っています。 「例外処理 (初回) は XXXX.exe (NTDLL.DLL) にあります: 0xC0000005: Access Violation」 ※実行環境:WindowsXp(sp3) VC++6.0(Sp6) (ちなみ、このエラーは、PCによって発生したりしなかったりしています。) http://msdn.microsoft.com/ja-jp/library/bb762115%28en-us,VS.85%29.aspx を参照すると、「SHBrowseForFolderを使う前に、Component Object Model (COM)を初期化しなければいけません。」と表記されてますが、 初期化処理を行った後、SHBrowseForFolderを実行している サンプルを見つけられません。 お手数ですが、上記サンプルをご提示して頂けませんでしょうか 現在、ここまで書いたので、ご指摘いただけると幸いです。 (ほとんど、他のページからの転用なのですが、、、) **************** void CAAAAAA::OnButtonSelectFolder() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください UpdateData(TRUE); BROWSEINFO bInfo; LPITEMIDLIST pIDList; TCHAR szDisplayName[MAX_PATH]; // BROWSEINFO構造体に値を設定 bInfo.hwndOwner = AfxGetMainWnd()->m_hWnd; // ダイアログの親ウインドウのハンドル bInfo.pidlRoot = NULL; // ルートフォルダを示すITEMIDLISTのポインタ (NULLの場合デスクトップフォルダが使われます) bInfo.pszDisplayName = szDisplayName; // 選択されたフォルダ名を受け取るバッファのポインタ bInfo.lpszTitle = _T("フォルダの選択"); // ツリービューの上部に表示される文字列 bInfo.ulFlags = BIF_RETURNONLYFSDIRS; // 表示されるフォルダの種類を示すフラグ bInfo.lpfn = NULL; // BrowseCallbackProc関数のポインタ bInfo.lParam = (LPARAM)0; // コールバック関数に渡す値 // フォルダ選択ダイアログを表示 pIDList = ::SHBrowseForFolder(&bInfo); if(pIDList == NULL){ // 戻り値がNULLの場合、フォルダが選択されずにダイアログが閉じられたことを意味します。 }else{ // ItemIDListをパス名に変換します if(!::SHGetPathFromIDList(pIDList, szDisplayName)){ // エラー処理 } // szDisplayNameに選択されたフォルダのパスが入っています m_csFolderName = szDisplayName; // 最後にpIDListのポイントしているメモリを開放します ::CoTaskMemFree( pIDList ); } UpdateData(FALSE);//データ初期化(反映) }

  • ブレークポイントが設定できない。。。

    VC++6.0、OSはWindows2000 を使用しています。 MFCのダイアログベースのEXEを造っています。 デバッグするためにブレークポイントを設定したのですが、実行時に 止まりません。 デバッグモードでリビルドし、pdbファイルも作成されています。 デバッグ対象のEXEは ~/debug/xxx.exe となっているのも確認しています。 デバッグ実行前に設定すると、赤丸でちゃんとマークされますが、 実行すると以下の文言のメッセージボックスが表示され、設定した ブレークポイントは無効になっています。 「1つ以上のブレークポイントが設定できませんでした。 これらのブレークポイントは無効です。実行プログラムはプログラムの始めで 停止します。」 この後、実行中にブレークポイントを設定しようとしてもできません。 考えられる原因としては何があるでしょうか? 識者の方、ご教授願います。

  • VC++でダイアログボックスを表示させるプログラム

    VC++のプログラミングで、実行できない原因が 判らないので、ヒントをいただけないでしょうか。 現在VC++の勉強中で、ダイアログボックスを 表示するプロジェクトを作成しています。 ビルドエラーは出ないのですが、実行しても 何も表示されません。 メニューを持った親ウインドウを表示し、 メニューから「加算」を選択すると 計算用のダイアログボックスが表示されるプログラムです。 ダイアログボックスは三個のテキストボックスと 二個のボタンがあり、数字を二箇所入れ ボタンを押すと計算結果を表示します。 長くなる為ソースは書けないのですが、 こういう場合まず何からチェックすればいいでしょうか? 初心者なのでちょっとしたことで間違えているかも しれません。どなたかアドバイス下さい。

  • C#:VS2008について

    現在VS2008C#で開発を行っています。 そこで、デバッグで実行するとSaveFileDialogの表示時に下記のエラーが発生しています。 "OLE が呼び出される前に、現在のスレッドが Single Thread Apartment (STA) モードに設定されていなければなりません。Main 関数に STAThreadAttribute が設定されていることを確認してください。 この例外はデバッガがプロセスにアタッチされている場合にのみ発生します。" しかし、EXEで実行した場合上記エラーが発生せず、正常にSaveFileDialogが表示されます。 そこで質問なのですが、デバッグで実行した場合と、EXEで実行した場合では何か違いがあるのでしょうか?また、なぜ上記エラーはデバッグ実行時のみ発生しているのでしょうか?回答よろしくお願い致します。

  • VBがデバッグ時落ちてしまう

    VC6.0でDLLを作成し、VB6.0で呼び出すプログラムを作成しています。 DLLの内容はWindowハンドルを引数にしてそのハンドルを持つWindow上にListboxを作成するというようなものです。(もともとC言語用のDLLだったものをVBで使いまわしています) このプログラムをデバッグ実行し、デバッガ上で停止[実行->終了]とすると、VB6.exeがアプリケーションエラーで落ちてしまいます。(DLLの関数を呼ばない限り大丈夫です) デバッグ実行でも普通に終了(アプリケーションでの終了)であれば正常に終了してくれます。 このままですと、実行時エラーで止まる度にVB6.exeが落ちてしまい非常に不便です。 このような現象で困った方いませんか? 解決策がありましたら教えてください。

  • VisualStudio2005で「デバッグ開始」「デバッグなしで開始」がうまくいかない

    VisualStudio2005で開発をしているのですが、 あるときPCが強制終了する際に、開発途中の状態のままVisualStudioも終了してしまいました。 「~を保存しますか」というダイアログがでていたのですが、良く分からず「いいえ」を選択してしまい、次に立ち上げたとき、「デバッグ開始」ボタンを押すと「~がありません」と(~のところはもう覚えていません……)出たのでVisualStudioのexeを指定しました。 以後、「デバッグ開始」「デバッグなしで開始」を押しても、作成中のプログラムを実行してくれず、VisualStudioがもう一つ立ち上がってしまいます。 これを正常にするにはどこの設定をどう変えれば良いのでしょうか?

  • VS2008 C++ リリースモードでエラー

    表題の環境でMFCベースのプログラムを開発しています。 リリースモードで実行を試したところ、同じようなタイミングで強制終了が発生します。 (おそらく、自前のDLL内で落ちている?) デバッグモードのEXEを直接起動しても、強制終了が発生します。 りかし、VSからリリースモード(当然、デバッグモードも)の実行を行うと、エラーが発生しません。 VSから実行する場合、参照するDLLはVSを使用しない場合とは違うDLLを参照するのでしょうか。 その他、このような状況での対処方法について、アドバイスをいただけませんでしょうか。

専門家に質問してみよう