-1

I have this:

ShellExecute(Application.Handle, nil, PWideChar('explorer.exe'), PWideChar(ImagesDir), nil, SW_SHOWNORMAL);

where the variable ImagesDir is the directory of Images that I want to show by the Windows Explorer...

How can I run the Windows Explorer beside my application at a specified Bounds, for exemple like this?

image

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Pedro
  • 1
  • 3
  • Once the window has been opened, use `FindWindow()` or better [`IShellWindows.FindWindowSW()`](https://learn.microsoft.com/en-us/windows/desktop/api/exdisp/nf-exdisp-ishellwindows-findwindowsw) to locate the HWND of the window, and then you can reposition it as needed. – Remy Lebeau Aug 26 '18 at 00:47
  • a very nice and clear answer ... but Mr : Remy Lebeau if you don't mind of course i need just how to use this function (ishellwindows.findwindowsw()) to get repositioning the opened windows explorer ... and i want you to answer me inside the answer box plz instead of the comment box to give me the option to vot with positive on your answer ... – Pedro Aug 26 '18 at 06:13
  • 1
    Embed a view into your application, place it however you like. Search for iExplorerBrowser. – Sertac Akyuz Aug 26 '18 at 11:00

2 Answers2

0

when you open any File Explorer window (such as going to C:\ ), File Explorer has a specific saved window size that it opens with. So when you resize it, either horizontally and/or vertically, close it and re-open it again, it saves the size of the window,
and the location within the Registry where this information is saved is this:
On my system, HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell\WinPos1366x768x96(1)..position, where position is left, right, top or bottom, gives the position of the window border in pixels.

I assume the name of the key depends on the screen resolution.here and the code will be like that:

.....
const
   AMainKey = '\Software\Classes\Local 
   Settings\Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell\';

var
  FrmMain: TFrmMain;
  ImagesDir: string;
  AWinPos_left, AWinPos_Top,
  AWinPos_Right, AWinPos_Bottom: string;

implementation
  Uses
    ShellApi, Registry;
  {$R *.dfm}

procedure ExploreDir_With_Bounds(AFile_Dir: string;ALeft, ATop, AWidth, AHieght: DWORD);
  FUNCTION ExploreDirectory(CONST Dir : STRING) : BOOLEAN;
  BEGIN
    Result :=(ShellExecute(GetDesktopWindow,'open',PWideChar(Dir),'','',SW_SHOW)>32)
  END;
var
  ListNames, ListPosition: TStringList;
  I, AScreen_Width, AScreen_Hieght, APixelPI: Integer;
  AWinPos_Uses: string;
begin
  ListNames    := TStringList.Create;
  ListPosition := TStringList.Create;
  With TRegistry.Create Do
  Try
    RootKey := HKEY_CURRENT_USER;
    OpenKey(AMainKey,FALSE);
    GetValueNames(ListNames);

    AScreen_Width  := Screen.Width;
    AScreen_Hieght := Screen.Height;
    APixelPI := Screen.PixelsPerInch;
    AWinPos_Uses := 'WinPos'+AScreen_Width.ToString+'x'+AScreen_Hieght.ToString+'x'+APixelPI.ToString;

    for I := 0 to ListNames.Count - 1 do
    begin
      if Pos(AWinPos_Uses, ListNames[I]) <> 0 then
      begin
        ListPosition.Add(ListNames[I]);
      end;
    end;

    for I := 0 to ListPosition.Count - 1 do
    begin
      if (Pos('left', ListPosition[I]) <> 0) then
      begin
        AWinPos_left := ListPosition[I];
        Lbl_Left.Caption := AWinPos_left;
        Continue;
      end else
      if (Pos('top', ListPosition[I]) <> 0) then
      begin
        AWinPos_Top := ListPosition[I];
        Lbl_Top.Caption := AWinPos_Top;
        Continue;
      end else
      if (Pos('right', ListPosition[I]) <> 0) then
      begin
        AWinPos_Right := ListPosition[I];
        Lbl_Right.Caption := AWinPos_Right;
        Continue;
      end else
      if (Pos('bottom', ListPosition[I]) <> 0) then
      begin
        AWinPos_Bottom := ListPosition[I];
        Lbl_Bottom.Caption := AWinPos_Bottom;
      end;
    end;

    if (AWinPos_left <> '')and(AWinPos_Top <> '')and
      (AWinPos_Right <> '')and(AWinPos_Bottom <> '') then
    begin
      WriteInteger(AWinPos_left, ALeft);
      WriteInteger(AWinPos_Top, ATop);
      WriteInteger(AWinPos_Right, ALeft + AWidth);
      WriteInteger(AWinPos_Bottom, ATop + AHieght);
    end;

    CloseKey;
  Finally
    Free;
    ListNames.Free;
    ListPosition.Free;
  End;

  ExploreDirectory(AFile_Dir);
end;  

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  ImagesDir := TDirectory.GetParent(TDirectory.GetParent(ExtractFileDir(ParamStr(0))))+ '\My Images To Test';

  ExploreDir_With_Bounds(ImagesDir, (50 + Width)+10{Left}, 50{TOP},
                         Screen.Width - (Left + Width +20){width},
                         Screen.Height - 150{hieght});
end;

procedure TFrmMain.FormShow(Sender: TObject);
begin
  Left := 0;
  Top  := (Screen.WorkAreaHeight div 2)-(Height div 2);
end;  

end.

the Result here

Pedro
  • 1
  • 3
-1

You can use the following function to open an explorer window and have it point to a specific directory.

USES Windows,ShellAPI;

FUNCTION ExploreDirectory(CONST Dir : STRING) : BOOLEAN;
  BEGIN
    Result:=(ShellExecute(GetDesktopWindow,'open',PChar(Dir),'','',SW_SHOW)>32)
  END;

Note, however, that you can't (with this code) make the Explorer window "follow" your program, ie. the opened window is a completely autonomous window that has no link to your program, just as if the user had browsed to the directory himself. If you call this function again with a new directory, Explorer will open a new window with that directory (and keep the old one opened).

UPDATE: If you want to be able to manipulate the explorer window after it is opened, you need to use the various interfaces that Explorer exposes. I have made a UNIT that allows you to do what you seek as well as returning the interface needed to be able to manipulate the window afterwards. It is heavily based on the code found in this answer:

Check if windows explorer already opened on given path

by Victoria

UNIT WindowsExplorer;

INTERFACE

USES Types,ShDocVw;

FUNCTION ExploreDirectory(CONST Dir : STRING) : BOOLEAN;
FUNCTION OpenFolder(CONST Dir : STRING) : IWebBrowserApp; OVERLOAD;
FUNCTION OpenFolderAt(CONST Dir : STRING ; Left,Top,Width,Height : INTEGER) : IWebBrowserApp; OVERLOAD;
FUNCTION OpenFolderAt(CONST Dir : STRING ; CONST Rect : TRect) : IWebBrowserApp; OVERLOAD; INLINE;

IMPLEMENTATION

USES Windows,Variants,ShlObj,Ole2,OleAuto,ShellAPI,ActiveX,SysUtils;

FUNCTION ExploreDirectory(CONST Dir : STRING) : BOOLEAN;
  BEGIN
    Result:=(ShellExecute(GetDesktopWindow,'open',PChar(Dir),'','',SW_SHOW)>32)
  END;

FUNCTION GetFolderIDList(CONST Dir : STRING) : PItemIDList;
  VAR
    ShellFolder : IShellFolder;
    Attributes  : ULONG;
    Count       : ULONG;

  BEGIN
    OleCheck(SHGetDesktopFolder(ShellFolder));
    Attributes:=SFGAO_FOLDER or SFGAO_STREAM;
    OleCheck(ShellFolder.ParseDisplayName(0,NIL,PWideChar(WideString(Dir)),Count,Result,Attributes));
    IF NOT ((Attributes AND SFGAO_FOLDER=SFGAO_FOLDER) AND (Attributes AND SFGAO_STREAM<>SFGAO_STREAM)) THEN BEGIN
      CoTaskMemFree(Result);
      Result:=NIL
    END
  END;

FUNCTION OpenFolder(CONST Dir : STRING ; OpenIfNotFound : BOOLEAN) : IWebBrowserApp; OVERLOAD;
  CONST
    IID_IServiceProvider: System.TGUID = '{6D5140C1-7436-11CE-8034-00AA006009FA}';

  VAR
    FolderID        : PItemIDList;
    ShellWindows    : IShellWindows;
    I               : INTEGER;
    WndIFace        : System.IDispatch;
    WebBrowserApp   : IWebBrowserApp;
    ServiceProvider : IServiceProvider;
    ShellBrowser    : IShellBrowser;
    ShellView       : IShellView;
    FolderView      : IFolderView;
    PersistFolder   : IPersistFolder2;
    CurFolderID     : PItemIDList;

  BEGIN
    FolderID:=GetFolderIDList(Dir);
    IF Assigned(FolderID) THEN TRY
      OleCheck(CoCreateInstance(CLASS_ShellWindows,NIL,CLSCTX_LOCAL_SERVER,IID_IShellWindows,ShellWindows));
      FOR I:=0 TO PRED(ShellWindows.Count) DO BEGIN
        WndIface:=ShellWindows.Item(VarAsType(I,VT_I4));
        IF Assigned(WndIface) AND
           Succeeded(WndIface.QueryInterface(IID_IWebBrowserApp,WebBrowserApp)) AND
           Succeeded(WebBrowserApp.QueryInterface(IID_IServiceProvider,ServiceProvider)) AND
           Succeeded(ServiceProvider.QueryService(SID_STopLevelBrowser,IID_IShellBrowser,ShellBrowser)) AND
           Succeeded(ShellBrowser.QueryActiveShellView(ShellView)) AND
           Succeeded(ShellView.QueryInterface(IID_IFolderView,FolderView)) AND
           Succeeded(FolderView.GetFolder(IID_IPersistFolder2,PersistFolder)) AND
           Succeeded(PersistFolder.GetCurFolder(CurFolderID)) AND
           ILIsEqual(FolderID,CurFolderID) THEN BEGIN
          IF IsIconic(WebBrowserApp.HWnd) THEN Win32Check(ShowWindow(WebBrowserApp.HWnd,SW_RESTORE));
          Win32Check(SetForegroundWindow(WebBrowserApp.HWnd));
          Exit(WebBrowserApp)
        END
      END
    FINALLY
      CoTaskMemFree(FolderID)
    END;
    Result:=NIL;
    IF OpenIfNotFound THEN BEGIN
      IF NOT ExploreDirectory(Dir) THEN EXIT;
      FOR I:=1 TO 20 DO BEGIN
        Result:=OpenFolder(Dir,FALSE);
        IF Assigned(Result) THEN EXIT;
        Sleep(100)
      END
    END
  END;

FUNCTION OpenFolder(CONST Dir : STRING) : IWebBrowserApp;
  BEGIN
    Result:=OpenFolder(Dir,TRUE)
  END;

FUNCTION OpenFolderAt(CONST Dir : STRING ; Left,Top,Width,Height : INTEGER) : IWebBrowserApp;
  BEGIN
    Result:=OpenFolder(Dir);
    IF Assigned(Result) THEN BEGIN
      Result.Left:=Left; Result.Top:=Top; Result.Width:=Width; Result.Height:=Height
    END
  END;

FUNCTION OpenFolderAt(CONST Dir : STRING ; CONST Rect : TRect) : IWebBrowserApp;
  BEGIN
    Result:=OpenFolderAt(Dir,Rect.Left,Rect.Top,Rect.Width,Rect.Height)
  END;

END.

It is made for use with Delphi Tokyo 10.2.3 so if you use an earlier version (you didn't specify Delphi version in your question), you may need to adapt the USES list to match.

HeartWare
  • 7,464
  • 2
  • 26
  • 30