Discussion:
Get tree control from SHBrowseForFolder
(too old to reply)
Timothy Madden
2010-07-21 12:06:38 UTC
Permalink
Raw Message
Hello

I want to open the last used folder in my Browse for Folder dialog, and
the problem is after I send BFFM_SETSELECTION and BFFM_SETEXPANDED
messages when the SHBrowseForFolder callback function receives
BFFM_INITIALIZED notification, the selected item is not visible in the
newly-opened directory tree.

Looks like SHBrowseForFolder finds it more important to have the root
node visible, than the selected node, and altough I have my folder
selected, the tree control needs to be scrolled to get the folder into view.

I call hWndTree = ::FindWindowEx(hWnd, NULL, WC_TREEVIEW, NULL); to get
the tree view control and than invoke
TreeView_EnsureVisible(hWndTree, TreeView_GetSelection(hWndTree));
but FindWindowEx just returns NULL.

hWnd is just the HWND paramter to SHBrowseForFolder callback function
BrowseCallbackProc, and it is valid because the other messages
(BFFM_SETSELECTION, ...) sent to the handle work.

I would not think that the tree control in the browse for folder dialog
is not really a tree-view control, so do you know why FindWindowEx fails ?

Thank you,
Timothy Madden
David Lowndes
2010-07-21 13:08:19 UTC
Permalink
Raw Message
Post by Timothy Madden
I call hWndTree = ::FindWindowEx(hWnd, NULL, WC_TREEVIEW, NULL); to get
the tree view control and than invoke
TreeView_EnsureVisible(hWndTree, TreeView_GetSelection(hWndTree));
but FindWindowEx just returns NULL.
hWnd is just the HWND paramter to SHBrowseForFolder callback function
BrowseCallbackProc, and it is valid because the other messages
(BFFM_SETSELECTION, ...) sent to the handle work.
I would not think that the tree control in the browse for folder dialog
is not really a tree-view control, so do you know why FindWindowEx fails ?
Timothy,

If you use Spy++ you can find what the control is and it's
parent/child relations. It appears to be a tree view control
"SysTreeView32". However, it's a grandchild of the dialog.

Dave
Timothy Madden
2010-07-21 13:21:04 UTC
Permalink
Raw Message
Post by Timothy Madden
Hello
I want to open the last used folder in my Browse for Folder dialog, and
the problem is after I send BFFM_SETSELECTION and BFFM_SETEXPANDED
messages when the SHBrowseForFolder callback function receives
BFFM_INITIALIZED notification, the selected item is not visible in the
newly-opened directory tree.
Looks like SHBrowseForFolder finds it more important to have the root
node visible, than the selected node, and altough I have my folder
selected, the tree control needs to be scrolled to get the folder into view.
I call hWndTree = ::FindWindowEx(hWnd, NULL, WC_TREEVIEW, NULL); to get
the tree view control and than invoke
TreeView_EnsureVisible(hWndTree, TreeView_GetSelection(hWndTree));
but FindWindowEx just returns NULL.
hWnd is just the HWND paramter to SHBrowseForFolder callback function
BrowseCallbackProc, and it is valid because the other messages
(BFFM_SETSELECTION, ...) sent to the handle work.
I would not think that the tree control in the browse for folder dialog
is not really a tree-view control, so do you know why FindWindowEx fails ?
Ok it looks like FindWindowEx might not recursively search all child and
descendant windows, so I tried with EnumChildWindows. Now I can send
TVM_ENSUREVISIBLE to the tree view, except that the item is only some of
the times scrolled into view, while at some other times it is not !

It must be a timing issues because it looks random. Do you know why this
might happen ?

Here is my code:

int CALLBACK BrowseCallbackProc
(
HWND hWnd,
UINT uMsg,
LPARAM lParam,
LPARAM lpData
)
{
lParam = lParam;

if (uMsg == BFFM_INITIALIZED)
{
CStringW strPath(reinterpret_cast<LPCTSTR>(lpData));

SendMessage
(
hWnd,
BFFM_SETSELECTION,
TRUE,
LPARAM(strPath.GetString())
);

SendMessage
(
hWnd,
BFFM_SETEXPANDED,
TRUE,
LPARAM(strPath.GetString())
);

class EnumChildWindowProc
{
public:
static
BOOL CALLBACK EnumChildProc
(
HWND hWndChild,
LPARAM lParam
)
{
vector<TCHAR> vectClassName(32);

vector<TCHAR>::size_type
iLen = ::GetClassName(hWndChild,
&vectClassName[0],
vectClassName.size());

while (iLen && iLen >= vectClassName.size() - 1)
vectClassName.resize(vectClassName.size()*2);

if
(
iLen
&&
_tcscmp
(
WC_TREEVIEW,
&vectClassName[0]
)
== 0
)
{
*reinterpret_cast<HWND *>
(
reinterpret_cast<void *>(lParam)
)
= hWndChild;

return FALSE; // child window found
}
else
return TRUE;
}
};


// find the first treeview control
HWND hWndTree = NULL;
EnumChildWindows
(
hWnd,
EnumChildWindowProc::EnumChildProc,
reinterpret_cast<LPARAM>(&hWndTree)
);

if (hWndTree)
PostMessage
(
hWndTree,
TVM_ENSUREVISIBLE,
0,
reinterpret_cast<LPARAM>
(
TreeView_GetSelection(hWndTree)
)
);
}

return 0;
}

Loading...