🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
13 messages
13 total messages Started by Mark Jacobs Mon, 05 Mar 2007 12:46
Shbrowseforfolder edit box problems
#2346
Author: Mark Jacobs
Date: Mon, 05 Mar 2007 12:46
39 lines
2519 bytes
I am using BCB5 Pro SP1, and I have the following code :-

int CALLBACK mjBrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM 
lpData)
{
  if (uMsg==BFFM_INITIALIZED) SendMessage(hwnd,BFFM_SETSELECTION,TRUE,lpData);
  return 0;
}
//---------------------------------------------------------------------------
void __fastcall Tmjgrabstr::xbtnClick(TObject *Sender)
{
  AnsiString Dir=Edit1->Text;
  BROWSEINFO mjbi;
  char rcvdir[999];
  if (!DirectoryExists(Dir)) Dir=GetCurrentDir();
  strcpy(rcvdir,Dir.c_str());
  mjbi.hwndOwner=Application->Handle;
  mjbi.pidlRoot=0;
  mjbi.pszDisplayName=rcvdir;
  mjbi.lpszTitle="Choose a Directory :-";
  mjbi.ulFlags=BIF_USENEWUI;
  mjbi.lpfn=mjBrowseCallbackProc;
  mjbi.lParam=(long)rcvdir;
  ITEMIDLIST *mjites=SHBrowseForFolder(&mjbi);
  rcvdir[0]='\0'; if (mjites) SHGetPathFromIDList(mjites,rcvdir);
  CoTaskMemFree(mjites);
  if (rcvdir[0]) Edit1->Text=AnsiString(rcvdir);
}

This is to present a directory selector with an edit box to manually enter a 
directory name. The directory chosen or entered, does not have to exist. When 
the dialog appears, it changes itself to the current directory. When I enter 
text into the edit box on this dialog, and hit OK, the dialog returns the 
directory in the window above the text box, but not that entered into the text 
box itself. How do I get to the text in the edit box in this dialog?
-- 
Mark Jacobs
DK Computing
http://www.dkcomputing.co.uk
Re: Shbrowseforfolder edit box problems
#2347
Author: Bob Gonder
Date: Mon, 05 Mar 2007 15:58
51 lines
2421 bytes
"Mark Jacobs" <http://www.jacobsm.com/mjmsg.htm?BorlandNG> wrote:

>This is to present a directory selector with an edit box to manually enter a 
>directory name. The directory chosen or entered, does not have to exist. When 
>the dialog appears, it changes itself to the current directory. When I enter 
>text into the edit box on this dialog, and hit OK, the dialog returns the 
>directory in the window above the text box, but not that entered into the text 
>box itself. How do I get to the text in the edit box in this dialog?

It looks like you are almost there.

>int CALLBACK mjBrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM 
>lpData)
>{
>  if (uMsg==BFFM_INITIALIZED) SendMessage(hwnd,BFFM_SETSELECTION,TRUE,lpData);

	 if( uMsg == BFFM_INITIALIZED )
	{
	    if( lpData )
	    {
		if( *lpData)
		    SendMessage(hwnd,BFFM_SETSELECTION,TRUE,lpData);
		* lpData = 0;
	    };
		return 0;
	};

	if (uMsg==BFFM_VALIDATEFAILED )
	{
		lstrcpy( lpData, lParam );
		return 0; /*end dialog*/
	};

    - - - - -
  mjbi.ulFlags=BIF_USENEWUI |
		BIF_VALIDATE;
>  mjbi.lpfn=mjBrowseCallbackProc;
>  mjbi.lParam=(long)rcvdir;
>  ITEMIDLIST *mjites=SHBrowseForFolder(&mjbi);

	if( rcvdir[0] == 0 )
	{	get rcvdir from pidl
	}else{
		use rcvdir directly
	}

>  rcvdir[0]='\0'; if (mjites) SHGetPathFromIDList(mjites,rcvdir);
>  CoTaskMemFree(mjites);
>  if (rcvdir[0]) Edit1->Text=AnsiString(rcvdir);
>}
>
Re: Shbrowseforfolder edit box problems
#2350
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 18:24
24 lines
1685 bytes
"Mark Jacobs" <http://www.jacobsm.com/mjmsg.htm?BorlandNG> wrote in
message news:45ec10db$1@newsgroups.borland.com...

> This is to present a directory selector with an edit box to manually
> enter a directory name. The directory chosen or entered, does not
> have to exist.

Then you are using the wrong dialog, as it can only return directories
that do exist.

> When I enter text into the edit box on this dialog, and hit OK, the
> dialog returns the directory in the window above the text box

That is what the dialog is designed to do.

> How do I get to the text in the edit box in this dialog?

You don't.  That box is not for your code to use at all.  It is only
for the user to use.  The dialog only returns the final folder that is
selected.  An ITEMIDLIST cannot point to a non-existant item.


Gambit
Re: Shbrowseforfolder edit box problems
#2349
Author: Mark Jacobs
Date: Mon, 05 Mar 2007 18:30
10 lines
1386 bytes
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message 
news:99dou21t2sbmue94iobfekf2en3dfgegek@4ax.com...
> It looks like you are almost there.
><code snips>

None of your code helped. But thanks all the same. Anyone else know how to 
get the contents of the edit box in a Shbrowseforfolder dialog?
-- 
Mark Jacobs
http://jacobsm.com
Re: Shbrowseforfolder edit box problems
#2352
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 18:40
68 lines
2858 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:45ec6a71@newsgroups.borland.com...

> You don't.  That box is not for your code to use at all.  It is only
> for the user to use.

I stand corrected.  Bob's approach is the key.  It just needs some
cleaning up.  The following code works fine for me:

    int CALLBACK mjBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM
lParam, LPARAM lpData)
    {
        switch( uMsg )
        {
            case BFFM_INITIALIZED:
            {
                LPTSTR ptr = reinterpret_cast<LPTSTR>(lpData);
                if( ptr[0] != 0 )
                {
                    SendMessage(hwnd, BFFM_SETSELECTION, TRUE,
lpData);
                    ptr[0] = 0;
                }
                break;
            }

            case BFFM_VALIDATEFAILED:
            {
                lstrcpyn(reinterpret_cast<LPTSTR>(lpData),
reinterpret_cast<LPTSTR>(lParam), MAX_PATH);
                break;
            }
        }

        return 0;
    }

    void __fastcall Tmjgrabstr::xbtnClick(TObject *Sender)
    {
        AnsiString Dir = Edit1->Text;
        if( !DirectoryExists(Dir) )
            Dir = GetCurrentDir();

        TCHAR rcvdir[MAX_PATH+1] = {0};
        lstrcpy(rcvdir, Dir.c_str(), MAX_PATH);

        BROWSEINFO mjbi = {0};
        mjbi.hwndOwner = Application->Handle;
        mjbi.lpszTitle = TEXT("Choose a Directory :-");
        mjbi.ulFlags = BIF_EDITBOX | BIF_VALIDATE;
        mjbi.lpfn = mjBrowseCallbackProc;
        mjbi.lParam = reinterpret_cast<LPARAM>(rcvdir);

        LPITEMIDLIST mjites = SHBrowseForFolder(&mjbi);
        if( mjites )
        {
            rcvdir[0] = 0;
            SHGetPathFromIDList(mjites, rcvdir);
            CoTaskMemFree(mjites);
        }

        if( rcvdir[0] != 0 )
            Edit1->Text = rcvdir;
    }


Gambit
Re: Shbrowseforfolder edit box problems
#2351
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 18:41
11 lines
1144 bytes
"Mark Jacobs" <www.jacobsm.com/mjmsg.htm?Borland Newsgroup> wrote in
message news:45ec61b9@newsgroups.borland.com...

> None of your code helped.

Yes, it does.  His approach is exactly what you need.  See my other
reply.


Gambit
Re: Shbrowseforfolder edit box problems
#2355
Author: Bob Gonder
Date: Mon, 05 Mar 2007 22:49
28 lines
1768 bytes
Remy Lebeau (TeamB) wrote:

>        LPITEMIDLIST mjites = SHBrowseForFolder(&mjbi);
>        if( mjites )
>        {
>            rcvdir[0] = 0;
>            SHGetPathFromIDList(mjites, rcvdir);
>            CoTaskMemFree(mjites);
>        }

I seem to always get a pidl returned when Validate closes the dialog
(return 0;) So the above should always run unless the Cancel was
pressed. But that would overwrite the manual entry copied by the
Validate code.
That's why I checked rcvdir[0] instead of mjites after the call.

(another way)

>        if( mjites )
>        {
	if( rcvdir[0] == 0 )
	{
>            SHGetPathFromIDList(mjites, rcvdir);
	}else{
	//nothing, rcvdir filled in by Validate
	};
>            CoTaskMemFree(mjites);
>        }
Re: Shbrowseforfolder edit box problems
#2356
Author: Mark Jacobs
Date: Mon, 05 Mar 2007 23:26
15 lines
1648 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:45ec71a5
>        mjbi.ulFlags = BIF_EDITBOX | BIF_VALIDATE;
...

Thanks for your help. However, I also need the new UI as in BIF_USENEWUI

This makes your code *not* return the edit box contents when stuff is typed 
in. Try it. Without the BIF_USENEWUI (as in your code), I agree, it returns 
the contents of that edit box. But I want the new UI. complete with make new 
folder functionality, and simply or'ing in the BIF_USENEWUI flag makes it 
*not* return the box contents! Perhaps it's a limitation of the Windows 
folder UI.
-- 
Mark Jacobs
www.jacobsm.com 
Re: Shbrowseforfolder edit box problems
#2358
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 23:47
44 lines
2562 bytes
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message
news:5t6pu2922athot41785ihioe33et7h0mao@4ax.com...

> I seem to always get a pidl returned when Validate closes
> the dialog (return 0;)

The only way a non-NULL ITEMIDLIST can be returned is if there is a
valid folder selected in the dialog's TreeView when the dialog is
closed.

I tested the code before I posting it, and was able to get the edit
box's text as expected, even with a folder selected in the TreeView,
as the edit box has priority.

> So the above should always run unless the Cancel was pressed.
> But that would overwrite the manual entry copied by the Validate
code.

No, it would not.  The value would remain untouched when canceling the
dialog.  However, because a NULL ITEMIDLIST is returned when the
dialog is cancelled, there is no way to differentiate between a cancel
and a failed validation.

> That's why I checked rcvdir[0] instead of mjites after the call.

If the dialog returns a valid ITEMIDLIST, you have to use that as the
chosen path, so you should be checking the ITEMIDLIST first before
then falling back to the captured value.

> if( rcvdir[0] == 0 )
> {
> >            SHGetPathFromIDList(mjites, rcvdir);
> }else{
> //nothing, rcvdir filled in by Validate
> };

That condition can never happen.  If the dialog returns a valid
ITEMIDLIST, then the edit box text had to pass validation first, so
the contents of the captured buffer would not represent the folder the
user actually chose.


Gambit
Re: Shbrowseforfolder edit box problems
#2357
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 23:53
13 lines
1434 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:45ecac3f$1@newsgroups.borland.com...

> However, because a NULL ITEMIDLIST is returned when the
> dialog is cancelled, there is no way to differentiate between a
> cancel and a failed validation.

Scratch that.  The capture buffer will be empty if the dialog is
canceled, but not if the validation fails.


Gambit
Re: Shbrowseforfolder edit box problems
#2359
Author: Remy Lebeau (TeamB)
Date: Mon, 05 Mar 2007 23:59
89 lines
3434 bytes
"Mark Jacobs" <mark@jacobsm.com> wrote in message
news:45eca715@newsgroups.borland.com...

> Thanks for your help. However, I also need the new UI as in
> BIF_USENEWUI
>
> This makes your code *not* return the edit box contents when
> stuff is typed in.

The following code works for me now:

    #include <shlobj.h>

    int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM
lParam, LPARAM lpData)
    {
        switch( uMsg )
        {
            case BFFM_INITIALIZED:
            {
                LPTSTR ptr = reinterpret_cast<LPTSTR>(lpData);
                if( ptr[0] != 0 )
                {
                    SendMessage(hwnd, BFFM_SETSELECTION, TRUE,
lpData);
                    ptr[0] = 0;
                }
                break;
            }

            case BFFM_VALIDATEFAILED:
            {
                lstrcpyn(reinterpret_cast<LPTSTR>(lpData),
reinterpret_cast<LPTSTR>(lParam), MAX_PATH);
                break;
            }
        }

        return 0;
    }

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        AnsiString Dir = Edit1->Text;
        if( !DirectoryExists(Dir) )
            Dir = GetCurrentDir();

        TCHAR path[MAX_PATH+1] = {0};
        lstrcpyn(path, Dir.c_str(), MAX_PATH);

        BROWSEINFO bi = {0};
        bi.hwndOwner = Handle;
        bi.ulFlags = BIF_USENEWUI | BIF_EDITBOX | BIF_VALIDATE;
        bi.lpfn = BrowseCallbackProc;
        bi.lParam = reinterpret_cast<LPARAM>(path);

        LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
        if( pidl )
        {
            if( path[0] != 0 )
            {
                 // user text was entered ...
            }
            else
            {
                 // no user text was entered ...
                SHGetPathFromIDList(pidl, path);
            }

            CoTaskMemFree(pidl);
            Edit1->Text = path;
        }
        else
        {
            // dialog canceled...
        }
    }

> Without the BIF_USENEWUI (as in your code), I agree, it returns
> the contents of that edit box. But I want the new UI. complete with
> make new folder functionality, and simply or'ing in the BIF_USENEWUI
> flag makes it *not* return the box contents!

That is because the TreeView has priority over the edit box when that
flag is enabled.  Without it, the edit box has priority instead.


Gambit
Re: Shbrowseforfolder edit box problems
#2360
Author: Bob Gonder
Date: Tue, 06 Mar 2007 02:30
31 lines
1897 bytes
Remy Lebeau (TeamB) wrote:

>        LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
>        if( pidl )
>        {
>            if( path[0] != 0 )
>            {
>                 // user text was entered ...
>            }
>            else
>            {
>                 // no user text was entered ...
>                SHGetPathFromIDList(pidl, path);
>            }
>
>            CoTaskMemFree(pidl);
>            Edit1->Text = path;
>        }
>        else
>        {
>            // dialog canceled...
>        }

Hey!
That's my code!
Glad I'm not terminally stupid.
Also see now that SHBrowseForFolder returns NULL when Validate returns
0 and BIF_NEWDIALOGSTYLE is turned off (I was testing with the OPs
settings)

Thanks for the elephant, MS !
Re: Shbrowseforfolder edit box problems
#2361
Author: Mark Jacobs
Date: Tue, 06 Mar 2007 10:27
5 lines
1430 bytes
Thanks guys - everything works fine now. Thanks for your perseverance.
-- 
Mark Jacobs
DK Computing
http://www.dkcomputing.co.uk
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads