Recent

Author Topic: Q Win SHBrowseForFolder API, possible to influence the name sorting behaviour?  (Read 769 times)

d7_2_laz

  • Hero Member
  • *****
  • Posts: 531
Does anybody use the Windows (10, x64) SHBrowseForFolder API (shlobj.pas) and had also wished to influence the sort order, and found how to?

Q is motivated by the same intention as originally for the ShellTreeview (had been solved here); see:
https://forum.lazarus.freepascal.org/index.php/topic,61347.msg462091.html#msg462091

Sample:
Sort order is (conflicts the sort order of other file explorers, eg. windows explorer):
   Work1
   _tempStuff
   __savedVersions

Sort order expected by conventional habits:
   __savedVersions
   _tempStuff
   Work1

Some existing code snippet for the SHBrowseForFolder (as used for a very lean/slim folder selection purpose) that would need improvement:

Code: Pascal  [Select][+][-]
  1. // SelectADirectory(Self);
  2.  
  3. function BrowseCallbackProc(dhwnd:HWND; uMsg:longint;
  4.                            lParam:longint; lpData:longint) : integer; stdcall;
  5. type _exData=record
  6.           Path:PWideChar; Caption:PWideChar;
  7.       end;
  8. var sFName: ^_exData; r1, r2 : TRect; Y : Integer; hwndOwner: HWnd;
  9. begin
  10.   case uMsg of
  11.             BFFM_INITIALIZED:
  12.                 begin
  13.                     sFName:=Pointer(lpData);
  14.                     if Length(sFName.Path)<>0 then
  15.                           SendMessage(dhwnd, BFFM_SETSELECTION , 1, Integer(sfname.Path));
  16.                     if Length(sFName.Caption)<>0 then
  17.                           SendMessage(dhwnd, BFFM_SETSTATUSTEXT , 1, Integer(sfname.Caption));
  18.                     GetWindowRect(dhwnd, r1);   // Center in owning window
  19.                     hwndOwner := GetWindow(dhwnd, GW_OWNER);
  20.                     GetWindowRect(hwndOwner, r2);
  21.                     Y := CenterVertical(r2, r1.Bottom-r1.Top) + 10;
  22.                     if Y < r2.Top then
  23.                        Y := r2.Top + 30;
  24.                     MoveWindow(dhwnd, CenterHorizontal(r2, r1.Right-r1.Left),
  25.                                       Y, r1.Right - r1.Left, r1.Bottom - r1.Top, False);
  26.                 end;
  27.              BFFM_VALIDATEFAILED:
  28.                 begin
  29.                     result:=1;
  30.                     exit;
  31.                 end;
  32.   end;
  33.   result:=0;
  34. end;
  35.  
  36. procedure TMyButtonDirSelector.SelectADirectory(Sender : TObject);
  37. type _exData=record
  38.           Path:PWideChar; Caption:PWideChar;
  39.       end;
  40. var  buffer: WideString;
  41.      idList, RootItemIDList: PItemIDList;
  42.      info: TBrowseInfoW;
  43.      _inData:_exData;
  44. begin
  45.  SetLength(buffer, MAX_PATH);
  46.  with info do begin
  47.       hwndOwner := Handle;
  48.       pidlRoot := nil;
  49.       pszDisplayName := PWideChar(buffer);
  50.       lpszTitle :=  PWideChar('Select A Folder:');
  51.       ulFlags := BIF_RETURNONLYFSDIRS;
  52.       _inData.Path:=PWideChar(FDirectory);
  53.       _inData.Caption := nil;
  54.       lParam:=integer(@_inData);
  55.       lpfn:=@BrowseCallbackProc;
  56.       iImage := 0;
  57.  end;
  58.  idList := SHBrowseForFolderW(info);
  59.  if idList <> nil then begin
  60.     SHGetPathFromIDListW(idList, PWideChar(buffer));
  61.     SetLength(buffer, StrLen(PWideChar(buffer)));
  62.     FDirectory := buffer;
  63.     CoTaskMemFree( idList );
  64.  end;
  65. end;
  66.  
Lazarus 3.6  FPC 3.2.2 Win10 64bit

ASerge

  • Hero Member
  • *****
  • Posts: 2337
I haven't checked your code, but...
Quote
Windows (10, x64)
1. BrowseCallbackProc wrong declaration. lParam and lpData must be LPARAM (PtrInt) type, not longint.
2. Data loss in transformations: Integer(sfname.Path), Integer(sfname.Caption), integer(@_inData).

d7_2_laz

  • Hero Member
  • *****
  • Posts: 531
I haven't checked your code, but...

When preparing the snippet from the original very old context i'd realized that it was not yet WideString-ready, and i'd adjusted that lately on the fly, so it might not to be final. Also it actually needs the $mode delphi, i recognized.
I'll check your advice surely.
Nevertheless basically it works (see attached POC), i'd mainly intended to point out the sort order issue (with this API, not Lazarus of course).

Beneath the sort order there's another inconsistency to the main app. Without going to deep yet i had not been able to tell
the SHBrowseForFolder dialog to use the metadarkstyle's dark theme, so the look-amd-feel differs; not severe, but not nice either.

So i'm thinking about to replace the SHBrowseForFolder dialog by an own one based on the ShellTreeView, which is less bound to OS-specifics btw.

The attached POC has 3 buttons:
#1. using TSelectDirectoryDialog (imo too many capavilities for some specific purpose; elaborated "new gui")
#2. using SHBrowseForFolder dialog (minimalistic as desired; "old gui")
#3. A FoiderSelector POC based on ShellTreeView instead of #2 (using it's new custom sort capability fortunately offered by wp).

A remaining ToDo in the dialog #3 is that the dialog's icon here unwantedly reappears when hovering the STV.
(The hack shown here
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/19321
does not work).
EDIT: solved when having set the dialog's BorderIcons := []
« Last Edit: October 05, 2024, 07:44:03 pm by d7_2_laz »
Lazarus 3.6  FPC 3.2.2 Win10 64bit

d7_2_laz

  • Hero Member
  • *****
  • Posts: 531
Quote
EDIT: solved when having set the dialog's BorderIcons := []

Unfortunately NOT solved as the 'BorderIcons := []' does remove the Cancel button in the upper right corner of the dialog, what is not wanted.
I revoked this emptying of the BorderIcons,  tried to track this issue more down and found:

- it does occur when, in the ShellTreeview, the cursor hovers a long item, so that the Hint does appear (via ShowHint).
- The same does happen using a regular TTreeview. Hint appears -> the application's icon is back, ugly.
- This does NOT happen for the normal light theme, but only if dark mode is activated.
So i'll report this subtopic to zamtmn at another place. Somehow the dark mode's handling of treeview's hints resets border styles.

Back to the original topic: do any ideas exist if basically it's possible to have a more appropriate sorting when working with SHBrowseForFolder?
I'd assume. no ...

Lazarus 3.6  FPC 3.2.2 Win10 64bit

 

TinyPortal © 2005-2018