プロが教える店舗&オフィスのセキュリティ対策術

SHBrowseForFolderについて質問です。

フォルダを選択するダイアログボックスを表示させようとしています。
それで
http://rararahp.cool.ne.jp/vc/class/browseFolder …
http://www.geocities.co.jp/SiliconValley-PaloAlt …
などのサンプルを用いて表示部分の作成を行いました。

デバッグモードで実行し、
ダイアログボックスを表示させたり、フォルダ名を取得したりといった動作は行えるのですが、
右上の×ボタンを押して終了しようとすると終了処理の途中で固まってしまい正常に終了できません。

いずれのサンプルの場合もSHBrowseForFolderをコメントアウトして実行してみると正常にデバッグモードを終了することができます。

ちなみにVS6.0で作成している別のソフトでもSHBrowseForFolderを使用していますが,こちらは問題ありません。

環境のせいだと思うのですが原因が分かりません。
ご回答をお願いいたします。

A 回答 (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#n12 …
これですね。

もう既に回答が付いてますが、OpenCV1.1でSHBrowseForFolderとcvLoadImageを同時に使うとコケるようです。

http://tessy.org/wiki/index.php?%A5%E1%A5%E2#n12 …
に書いてあるリンク先を見ると「OpenCV1.0に戻した」って書いてあるので、1.0にすれば問題は出ないみたいです。
    • good
    • 0
この回答へのお礼

ありがとうございます。

>これですね。
そうです。このページも見ました。

OpenCVのバージョンを落とすと正常に動作しました。
なんかすっきりしないですが、仕方ないですねw

お礼日時:2009/07/01 19:16

 こんばんは。


 興味深いので、試してみましたが、其の通りの様です。
 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);
}
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
やはり無理なようですね。

バージョンを1.0に落として試してみると
正常に動作しました。

バージョンを落としても問題はなさそうなので
これでいこうかと思います。

どうもありがとうございました。

お礼日時:2009/07/01 19:14

BROWSEINFO構造体のhwndOwnerにウィンドウプロシージャを持っている正しいオーナーウィンドウハンドルをセットしてますか?



これが不正だと、フォルダブラウザダイアログのウィンドウプロシージャのデフォルト処理がコケるため、メッセージポンプがうまく動作しなくなり、ウィンドウプロシージャがWM_QUITをメッセージキューから取り出せなくなります。

「WM_QUITをメッセージキューから取り出せない」と「WM_QUITを受け取ったのにも関わらず、メッセージループから脱出せずにループし続ける」と言う事になります。

つまり「終了処理中にハングアップする」と言う事です。

「よく判らないけど、サンプルで、構造体をこうやって初期化しているから」と、サンプルの丸写しをしてしまったりすると、本来指定しちゃいけない値を指定する結果になってしまう事があります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

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に落として試してみようかと思いますが、
何か分かればまたよろしくお願いいたします。

お礼日時:2009/06/30 15:07

サンプルのままなのですか?


いくらか手を入れているのでしたら、周辺のコードを掲示された方がよいかと。

この回答への補足

サンプルではクラスが提供されています。
クラスの中身はいじっていません。

こちらで作ったプログラム(C++ MFCです。すいません書いてませんでした。)
の方でボタンクリックで呼び出されるようにしたのみです。
例えば、
http://www.geocities.co.jp/SiliconValley-PaloAlt …
にあるサンプルで試した場合、
↓のように呼び出してます。
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の行を通った後に
「現在の場所のソースコードを表示できません」と表示され止まってしまいます。

補足日時:2009/06/30 09:23
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!