Christopher Schene
asked on
CFileDialog problem: can't obtain browser window pointer
It seems that the CFileDialog functionality has changed after .net 2003.
When I invoked the CFileDialog to browse in .net 2003 This line of code (see below) returned a pointer to the file browser window but in .net 2005 and .net 2012 it returns null.
How do I obtain the browser dialog window pointer in VS 2012?
Question:
CWnd *pp = GetParent();
I have a class
class MyFolderBrowser : public CFileDialog
Which is derived from CFileDialog.
I construct it and invoke it from a function as follows:
MyFolderBrowser browser(m_projectBasePath) ;
if (browser.DoModal() == IDOK)
{
m_projectBasePath = browser.GetPath();
OnChangeProjectName();
}
The DoModal invokes this code:
void MyFolderBrowser::OnFolderC hange()
{
CWnd *pp = GetParent();
VERIFY(pp);
ASSERT(::IsWindow(pp->m_hW nd));
ASSERT(pp->GetDlgItem(IDC_ MC_DIR) != NULL);
In .net 2003 this call: " CWnd *pp = GetParent(); "
would return the browse dialog window pointer,. but in .net 2005 and later it returns a null.
How doi I get the pointer to the file dialog window in .net 2012?
When I invoked the CFileDialog to browse in .net 2003 This line of code (see below) returned a pointer to the file browser window but in .net 2005 and .net 2012 it returns null.
How do I obtain the browser dialog window pointer in VS 2012?
Question:
CWnd *pp = GetParent();
I have a class
class MyFolderBrowser : public CFileDialog
Which is derived from CFileDialog.
I construct it and invoke it from a function as follows:
MyFolderBrowser browser(m_projectBasePath)
if (browser.DoModal() == IDOK)
{
m_projectBasePath = browser.GetPath();
OnChangeProjectName();
}
The DoModal invokes this code:
void MyFolderBrowser::OnFolderC
{
CWnd *pp = GetParent();
VERIFY(pp);
ASSERT(::IsWindow(pp->m_hW
ASSERT(pp->GetDlgItem(IDC_
In .net 2003 this call: " CWnd *pp = GetParent(); "
would return the browse dialog window pointer,. but in .net 2005 and later it returns a null.
How doi I get the pointer to the file dialog window in .net 2012?
ASKER
I am still a bit confused. I am actually modifying some code I did not write (the original was in VC 6, C++ MFC).
I am not even sure what m_bVistaStyle is.
Is there someway I can modify the code below to accomplish the same functionality. I see that the original author was using the window to be able to access a dialog field that has the path information in it.
I tried (1) setting m_bVistaStyle=FLASE and it crashed in some internal dialog code (2) Commenting out all the window references and it crashed in some internal on a window ASSERT check after the CFileDialog::OnFolderChang e();
I am still confused as to how I can fix this:
void MyFolderBrowser::OnFolderC hange()
{
CWnd *pp = GetParent(); // Parent window = the dialog itself
VERIFY(pp);
ASSERT(::IsWindow(pp->m_hW nd));
ASSERT(pp->GetDlgItem(IDC_ MC_DIR) != NULL);
m_sPath = GetFolderPath();
int len = m_sPath.GetLength();
if (len > 0 && m_sPath[len-1] != '\\')
{
m_sPath += "\\";
++len;
}
pp->GetDlgItem(IDC_MC_DIR) ->SetWindo wText(m_sP ath);
m_oEdit.SetSel(len, len);
CFileDialog::OnFolderChang e();
m_oEdit.SetFocus();
}
I am not even sure what m_bVistaStyle is.
Is there someway I can modify the code below to accomplish the same functionality. I see that the original author was using the window to be able to access a dialog field that has the path information in it.
I tried (1) setting m_bVistaStyle=FLASE and it crashed in some internal dialog code (2) Commenting out all the window references and it crashed in some internal on a window ASSERT check after the CFileDialog::OnFolderChang
I am still confused as to how I can fix this:
void MyFolderBrowser::OnFolderC
{
CWnd *pp = GetParent(); // Parent window = the dialog itself
VERIFY(pp);
ASSERT(::IsWindow(pp->m_hW
ASSERT(pp->GetDlgItem(IDC_
m_sPath = GetFolderPath();
int len = m_sPath.GetLength();
if (len > 0 && m_sPath[len-1] != '\\')
{
m_sPath += "\\";
++len;
}
pp->GetDlgItem(IDC_MC_DIR)
m_oEdit.SetSel(len, len);
CFileDialog::OnFolderChang
m_oEdit.SetFocus();
}
Can you also show your OnInitDialog? I do not understand how you are able to create a IDC_MC_DIR if you can't access the parent.
ASKER
Strange: there is no OnInitDialog in the class: perhaps there is an internal OnInitDialog method as part of the CFileDialog class?
There is the following method:
// only called back if OFN_EXPLORER is set
virtual void OnInitDone();
What he is doing seems like overkill as the code below will grab the directory just fine.
CString m_DataDir;
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
if (dirDlg.DoModal() == IDOK ) {
m_DataDir = dirDlg.GetFolderPath();
}
There is the following method:
// only called back if OFN_EXPLORER is set
virtual void OnInitDone();
What he is doing seems like overkill as the code below will grab the directory just fine.
CString m_DataDir;
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
if (dirDlg.DoModal() == IDOK ) {
m_DataDir = dirDlg.GetFolderPath();
}
ASKER
Please explain to me a bit more about IFileDialog.
Isn't that used with the Automation Template Library and/or COM?
Isn't that used with the Automation Template Library and/or COM?
IFileDialog is COM/ATL interface for the new-looking file Open/Save dialog that you see in the latest versions of Windows (starting from Vista) CFileDialog magically wraps both (classic and new style). Just examine the source code (dlgfile.cpp) and you will see it yourself. BTW, how is IDC_MC_DIR defined in your application?
ASKER
"how is IDC_MC_DIR defined in your application? "
That is an edit entry field---which is part of the dialog.
That is an edit entry field---which is part of the dialog.
I can't see defined anywhere in the MFC library. Looks like it is defined locally somewhere in your code
ASKER
Ok, I have decided that probably using CFolderPickerDialog is a better approach (do you agree?).
But I have a problem with it: If I specify a valid starting path in the constructor as follows
CFolderPickerDialog dirDlg(CString("C:\\temp") );
Then dirDlg.GetFolderPath(); always returns the path I set in the constructor, but I I don't specify a valid path
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
Then dirDlg.GetFolderPath(); will return the path I chose in the dialog.
How do I both specify a starting path AND obtain the chosen path from dirDlg.GetFolderPath()?
CString m_DataDir;
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
if (dirDlg.DoModal() == IDOK ) {
m_DataDir = dirDlg.GetFolderPath();
}
But I have a problem with it: If I specify a valid starting path in the constructor as follows
CFolderPickerDialog dirDlg(CString("C:\\temp")
Then dirDlg.GetFolderPath(); always returns the path I set in the constructor, but I I don't specify a valid path
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
Then dirDlg.GetFolderPath(); will return the path I chose in the dialog.
How do I both specify a starting path AND obtain the chosen path from dirDlg.GetFolderPath()?
CString m_DataDir;
CFolderPickerDialog dirDlg(CString("Please Choose a folder"));
if (dirDlg.DoModal() == IDOK ) {
m_DataDir = dirDlg.GetFolderPath();
}
According to MSDN you can only use GetFolderPath under these conditions:
lder, like this:
You can call this method only while the dialog box is being displayed. After the dialog box has been closed, this function will no longer work, and the method will fail with an assertion.Use GetPathName. This will return the whole path of the selected file.
CString m_DataDir;
CFolderPickerDialog dirDlg(CString("c:\\temp"));
if (dirDlg.DoModal() == IDOK ) {
m_DataDir = dirDlg.GetPathName();
}
BTW, there is a better alternative. You can use CShellManager::BrowseForFo{
CString m_DataDir;
CString initialPath(_T("C:\\temp"));
if(theApp.GetShellManager ()->BrowseForFolder (m_DataDir,
this, initialPath, _T("Please Choose a folder:")))
{
// do something. m_DataDir will already contain the selected path
}
}
ASKER
This might be a really dumb question, but "theApp" is undefined.
What shall I set that to?
What shall I set that to?
Use AfxGetApp(), like this:
{
CString m_DataDir;
CString initialPath(_T("C:\\temp"));
if(AfxGetApp()->GetShellManager ()->BrowseForFolder (m_DataDir,
this, initialPath, _T("Please Choose a folder:")))
{
// do something. m_DataDir will already contain the selected path
}
}
ASKER
I found
CWinApp* AFXAPI AfxGetApp(); in afxwin.h
but the compiler says:
error C2039: 'GetShellManager' : is not a member of 'CWinApp'
CWinApp* AFXAPI AfxGetApp(); in afxwin.h
but the compiler says:
error C2039: 'GetShellManager' : is not a member of 'CWinApp'
In this case then, please try this function. It does the same thing as Shellmanager's BrowseForFolder:
CString ChooseAFolder(HWND hwnd, const CString &strIniDir, const CString &strDisplayName)
{
CoInitialize(NULL);
CString strRet;
LPITEMIDLIST pidlSelected = NULL;
BROWSEINFO bi = {0};
bi.hwndOwner = hwnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = strRet.GetBuffer(MAX_PATH);
bi.lpszTitle = strDisplayName;
bi.ulFlags = 0;
bi.lpfn = NULL;
bi.lParam = 0;
pidlSelected = SHBrowseForFolder(&bi);
strRet.ReleaseBuffer();
if(pidlSelected)
{
SHGetPathFromIDList(pidlSelected, strRet.GetBuffer(2*MAX_PATH));
strRet.ReleaseBuffer();
}
else
{
strRet.ReleaseBuffer();
strRet.Empty();
}
CoUninitialize();
return strRet;
}
Usage:{
CString m_DataDir;
CString initialPath(_T("C:\\temp"));
m_DataDir = ChooseAFolder(GetSafeHwnd(), initailPath, CString( _T("Please Choose a folder:")));
if(!m_DataDir.IsEmpty())
{
// do something. m_DataDir will already contain the selected path
}
}
ASKER
This works expect for one thing:
const CString &strIniDir: the initial directory is not used as far as I can tell
const CString &strIniDir: the initial directory is not used as far as I can tell
ASKER
I think I need to find a way to set this variable:
bi.pidlRoot
To the path I wish to search in but there is no conversion that I can figure ouy
bi.pidlRoot
To the path I wish to search in but there is no conversion that I can figure ouy
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
We are getting closer. Note the two pictures: (1) The old dialog and (2) the new dialog.
the old dialog is the version compiled with .net 2003 (prior to the MFC breaking change) and the new one is the version compiled under .net 2012 (after the breaking change).
How do I get the new one to have the same appearance as the old? Is there some option I can set?
Screenshot-2014-06-19-21.41.59-n.png
Screenshot-2014-06-19-21.41.27-o.png
the old dialog is the version compiled with .net 2003 (prior to the MFC breaking change) and the new one is the version compiled under .net 2012 (after the breaking change).
How do I get the new one to have the same appearance as the old? Is there some option I can set?
Screenshot-2014-06-19-21.41.59-n.png
Screenshot-2014-06-19-21.41.27-o.png
ASKER
Hi,
This seems to work OK----except I think I need a few more options. So far I have tried in the constructor
m_bi.ulFlags = dwFlags | BIF_STATUSTEXT | BIF_EDITBOX | BIF_BROWSEINCLUDEFILES | BIF_USENEWUI;
If you know what those options are I would appreciate if you would show me. Otherwise, I'll eventually figure it out on my own,
This seems to work OK----except I think I need a few more options. So far I have tried in the constructor
m_bi.ulFlags = dwFlags | BIF_STATUSTEXT | BIF_EDITBOX | BIF_BROWSEINCLUDEFILES | BIF_USENEWUI;
If you know what those options are I would appreciate if you would show me. Otherwise, I'll eventually figure it out on my own,
All these options are described in the MSDN article for BROWSEINFO. I think, your choice of options is quite good, as it includes all the features on can expect from a good folder selection dialog
ASKER
I've requested that this question be closed as follows:
Accepted answer: 0 points for cschene's comment #a40146410
for the following reason:
It took multiple try's but it is working now.
Accepted answer: 0 points for cschene's comment #a40146410
for the following reason:
It took multiple try's but it is working now.
ASKER
Sorry-----I made a mistake: I meant I accept the experts answer. Please re-open.
Open in new window