Ticket Q492480
Visible to All Users

Creating a subdirectory and navigating to in a TcxShellTreeView

created 12 years ago

Hi,
I'm stuck! This code works under limited cases. And I understand why it doesn't work but don't understand PIDLs well enough to know how to work around DX's ShellTreeView implementation. Here's the code:

Delphi
procedure TfmSelectFolder.actFolderCreateExecute(Sender: TObject); var sNewPath, sNewFolder : string; node : TTreeNode; pidl : PItemIDList; begin sNewFolder := 'New Folder'; if not InputQuery('Create New Folder', 'New Folder Name', sNewFolder) then exit; FolderTreeView.SetFocus; pidl := FolderTreeView.GetNodeAbsolutePIDL(FolderTreeView.InnerTreeView.Selected); msginfo(GetPIDLName(pidl)); sNewPath := backslashPath(FolderTreeView.Path) + sNewFolder; if not CreateDir(sNewPath) then raise exception.createFmt('New Folder "%s" could not be created.', [sNewFolder]); FolderTreeView.UpdateContent; application.ProcessMessages; FolderTreeView.Path := sNewPath; <-- neds to be relative path (relative to root) FolderTreeView.Path := 'MyDir\Tenders\' + sNewFolder; // open the new node pidl := PathToAbsolutePIDL(sNewPath, FolderTreeView.Root, THackShellTreeView(FolderTreeView).GetViewOptions); node := THackcxCustomInnerShellTreeView(FolderTreeView.InnerTreeView).GetNodeByPIDL(pidl); if node <> nil then node.Expand(false); end;

Drat! One line again - this HTML editor not so great.
Here's the code again…

Delphi
procedure TfmSelectFolder.actFolderCreateExecute(Sender: TObject); var sNewPath, sNewFolder : string; node : TTreeNode; pidl : PItemIDList; begin sNewFolder := 'New Folder'; if not InputQuery('Create New Folder', 'New Folder Name', sNewFolder) then exit; FolderTreeView.SetFocus; pidl := FolderTreeView.GetNodeAbsolutePIDL(FolderTreeView.InnerTreeView.Selected); msginfo(GetPIDLName(pidl)); sNewPath := backslashPath(FolderTreeView.Path) + sNewFolder; if not CreateDir(sNewPath) then raise exception.createFmt('New Folder "%s" could not be created.', [sNewFolder]); FolderTreeView.UpdateContent; application.ProcessMessages; FolderTreeView.Path := sNewPath; // Works off ROOT only // FolderTreeView.Path := 'MyDir\Tenders\' + sNewFolder; // Works! // open the new node pidl := PathToAbsolutePIDL(sNewPath, FolderTreeView.Root, THackShellTreeView(FolderTreeView).GetViewOptions); node := THackcxCustomInnerShellTreeView(FolderTreeView.InnerTreeView).GetNodeByPIDL(pidl); if node <> nil then node.Expand(false); end;

The above code will work if you are in the root directory eg "My Docs". If you are NOT on the root, it will fail. but I hard coded a test (see MyDirs) above and it works.
The reason it fails when you are in a sub-dir off the root is due to the implementation of the TcxShellTreeView Path and AbsolutePath. I don't know why DX has market AbsolutePath as deprected in the source - it is the thing that isn't returning the correct path!
IMHO the Path property should return the fully qualified path. And the AbsolutePath should return the relative path - relative to the root. Of course it looks like DX is thinking about heading that direction based on this:
// property RelativePIDL: PItemIDList write SetRelativePIDL; // TODO
Yes please TODO it as I'm fairly sure that if you did, my problem is solved. But since it doens't exist I need to role-my-own. Anyway, since both AbsolutePath and Path return a fully qualified path, and I am working in a different root then bfDesktop, it fails.
So my end objective is to press a button that creates a new directory (a tree node) and then set focus to that node. The above does all that except the last bit: it doesn't set focus to the newly created node.
So, we can solve this in one of two ways - 1) a sample that demonstrates how to do this or 2) a sample that shows how I can get the relative path (relative to the root.pidl)
FWIW, I've seen a LOT of people struggling and asking questions about PIDLs and such out here. And I reckon one of the core reasons the shell components have so many problems is that DX (IMHO) is making the assumption that everyone wants to work off bfDesktop. Myself, I want the user to be as focused as I can get them into some special folder such as My docs or Common Docs, etc. to remove the clutter.
thanx,
-randall sell

Show previous comments (9)
DevExpress Support Team 12 years ago

    Hello Randall,
    I have examined our code and clearly see the PostMessage procedure in the cxShellControls unit:

    Delphi
    procedure TcxCustomInnerShellTreeView.RestoreTreeState; //.. procedure RestoreCurrentPath; var ACurrentPath, ATempPIDL: PItemIDList; begin if FStateData.CurrentPath = nil then Exit; ACurrentPath := GetPidlCopy(FStateData.CurrentPath); try repeat if GetNodeByPIDL(ACurrentPath) <> nil then begin PostMessage(Handle, DSM_SHELLTREERESTORECURRENTPATH, WPARAM(GetPidlCopy(ACurrentPath)), 0); //<-- //..

    This procedure is the cause of the Application.ProcessMessages method utilized in Chet's sample.
    It looks strange that this code is not called on your side during the tracing process because when I set the breakpoint at this line, the compiler always stops here (on creating a new folder). Would you please check whether or not the debugging mode is enabled in your IDE? Please refer to the How to get the callstack in the IDE? Knowledge Base article that contains helpful information on the debugging mode.

      Thanx Paulo. It does trigger on my end - I had just stepped over it. Hard to know what to step into and what to step over when it isn't your code. But now it all makes complete sense.
      thanx
      -randall

      DevExpress Support Team 12 years ago

        Thanks. I have posted Chet's demo to the answer section.

        Answers approved by DevExpress Support

        created 12 years ago (modified 12 years ago)

        Attached is small sample project demonstrating how to accomplish this task.

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.