Reputation: 35
Is there a way to implement useful 'open next/previous file in folder' functionality when a program is launched as a result of the user opening a file found using an Explorer search?
For example, an application is associated with *.jpg. The user searches for foo*.jpg in Explorer and opens foobar1.jpg. The application launches. When the user uses the application's 'next file in folder' command, the application opens the next file returned by the search, not the next file in the same folder as foobar1.jpg.
Is this possible?
Upvotes: 0
Views: 396
Reputation: 3317
When user opens file in Windows Explorer shell enumerates all available context menu commands and run first default command. So just create new context menu shell extension and register it on your file extension ProgID. Your shell extension must implement 3 interfaces: IObjectWithSite, IShellExtInit and IContextMenu. Don`t forget to create MayChangeDefaultMenu reg subkey.
Your context menu can be used from any program. If caller calls IObjectWithSite.SetSite it means the file(s) was opened in Windows Explorer. If IObjectWithSite.SetSite was not called - file was opened from any other app.
When shell calls IShellExtInit extract filenames from passed IDataObject and store them. When shell calls IContextMenu.QueryContextMenu add command to menu with MFS_DEFAULT flag. When shell calls IContextMenu.GetCommandString(GCS_VERB) you must return "open" string. When shell call IContextMenu.InvokeCommand run your app and pass filename(s) and CMINVOKECOMMANDINFO.hwnd in parameters.
Inside your app analyze parameters and if hwnd is found it means you must get file list from hwnd.
Find Explorer instance:
OleCheck(CoCreateInstance(CLASS_ShellWindows, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IShellWindows, ShellWindows));
for i := ShellWindows.Count - 1 downto 0 do
begin
Dispatch := ShellWindows.Item(i);
Dispatch.QueryInterface(IServiceProvider, ServiceProvider);
ServiceProvider.QueryService(SID_STopLevelBrowser, IShellBrowser, ShellBrowser);
ShellBrowser.GetWindow(Hwnd);
if Hwnd = HwndFromParams then InstanceFound;
end;
Create file list:
ShellBrowser.QueryActiveShellView(ShellView);
ShellView.QueryInterface(IFolderView, FolderView);
FolderView.Items(SVGIO_ALLVIEW)
Now you have all files from Windows Explorer instance and you can use them in your navigation.
Upvotes: 3