However, if one uses this code over and over, one quickly becomes tired of threading one's way all the way from root directory C:\. There is undoubtedly some way to designate a starting directory. The most obvious candidate to set such a target is the:

Code:

bi.pidlRoot = NULL;

But attempting to set bi.pidlRoot to a CString (directory address) errors because 'no suiitable conversion from CString to LPCITEMIDLIST exists'

How can I set the code to open at a designated address in the directory tree?

January 22nd, 2013, 06:41 PM

Philip Nicoletti

Re: How to set a starting root directory for this code that selects a folder name?

But notice there are 2 LPARAMS in this CALLBACK. I have not figured out how either one can be used.

Please help. Thanks.

January 23rd, 2013, 09:26 PM

Philip Nicoletti

Re: How to set a starting root directory for this code that selects a folder name?

1) Does that compile ? The third parameter to _tcscpy is not an LPARAM. I should probably be:

Code:

_tcscpy_s(szDir,MAX_PATH,reinterpret_cast<LPCTSTR>(pData));

2) I don't think you need to use GetBuffer/ReleaseBuffer

Code:

bi.lParam = (LPARAM)(LPCTSTR)m_csMyLastDir;

January 24th, 2013, 08:07 AM

Igor Vartanov

Re: How to set a starting root directory for this code that selects a folder name?

Quote:

Originally Posted by Mike Pliam

The most obvious candidate to set such a target is the:

Code:

bi.pidlRoot = NULL;

Mike, common sense misguides too often. From MSDN:

Quote:

pidlRoot

Type: PCIDLIST_ABSOLUTE

A PIDL that specifies the location of the root folder from which to start browsing. Only the specified folder and its subfolders in the namespace hierarchy appear in the dialog box. This member can be NULL; in that case, the namespace root (the Desktop folder) is used.

Setting pidlRoot to some particular IDList has a very special meaning: user will be able to select a path under or equal to the root, and won't be able to go above. Say you select "C:\My data\options" as a root. Then you never be able to select "C:\My data", "C:\" or any other drive. Evidently this is not just a "starting folder" that you want.

Quote:

But attempting to set bi.pidlRoot to a CString (directory address) errors because 'no suiitable conversion from CString to LPCITEMIDLIST exists'

How can I set the code to open at a designated address in the directory tree?

Re: How to set a starting root directory for this code that selects a folder name?

Why wouldn't you want to call ReleaseBuffer?

January 24th, 2013, 04:33 PM

Mike Pliam

Re: How to set a starting root directory for this code that selects a folder name?

Arjay, I know we've discussed this in the past. I have been under the impression that it was good practice to call ReleaseBuffer anytime one uses GetBuffer(0) on a given CString, in order to 'free' the buffer (whatever that implies). I almost always do that, even though it makes the code less 'pretty'. Then one of the gurus, I don't recall which one of you, said something to the effect 'No well-designed function would require such a release', implying either CString is well-designed and consequently should not need such followup, or that CString is poorly designed and does. What the consensus on this?

January 24th, 2013, 05:19 PM

Paul McKenzie

Re: How to set a starting root directory for this code that selects a folder name?

Quote:

Originally Posted by Mike Pliam

'No well-designed function would require such a release', implying either CString is well-designed and consequently should not need such followup, or that CString is poorly designed and does. What the consensus on this?

This will call ReleaseBuffer() on destruction of whatever MFC/ATL string type that it is constructed with. So if you forget to call ReleaseBuffer(), this class will do it for you.

As a matter fof fact, it is a good idea in general to create or use classes that will "release" or "close" on destruction (RAII). This way, you're not writing code where at every single return point, catch handler, etc., you're scrambling doing this work yourself.

Regards,

Paul McKenzie

January 24th, 2013, 05:23 PM

Mike Pliam

Re: How to set a starting root directory for this code that selects a folder name?

Paul,

Quote:

This is possible because the wrapper object goes out of scope naturally in the case of an exception or multiple exiting code paths; causing its destructor to free the string resource.

But what if one uses the same string source repeatedly in the same function (scope) ? I suspect it's safer to use ReleaseBuffer in each instance of GetBuffer(0) and let M$ worry about implementing the details of cleanup.

January 24th, 2013, 05:28 PM

Paul McKenzie

Re: How to set a starting root directory for this code that selects a folder name?

If you forget to call ReleaseBuffer when the function exits, what happens? Does the constructor for CString call ReleaseBuffer()? If it doesn't then I don't know what happens.

Look at it this way, you want a safe way to make sure you aren't leaking memory or resources. The sure-fire way to make sure of this is to use a class that guarantees that on destruction, the proper cleanup occurs.

If an exception is thrown, how is your "ReleaseBuffer" everywhere approach going to work, unless you remember to write a try/catch handler and call it there also? See how unwieldly it gets -- that's why the adapter class was created, so as to make it safer if you do plan to use GetBuffer() and ReleaseBuffer() continuously in your code.