Accessing IExplorerCommandProvider from IShellFolder - windows-shell

I am writing an Explorer extension for Vista and Windows 7. I read that if you are making a namespace extension you can provide your own commands using IExplorerCommandProvider. This is done in response to IShellFolder::CreateViewObject.
I am not writing a namespace extension, but a toolbar that lets you perform operations in Explorer. So I need to get IExplorerCommandProvider from an existing IShellFolder.
I get IShellView from the IShellBrowser, then I convert it to IFolderView, then I get IShellFolder. So far so good. I get a valid folder pointer.
This however doesn't work:
pShellFolder->CreateViewObject(NULL,IID_IExplorerCommandProvider,&p); // returns E_NOINTERFACE
I tried passing different values for the hwnd parameter of CreateViewObject, starting with the file pane and going all the way up to the top level Explorer window, and none of them worked.
So my questions are:
1) Do regular file system folders even support IExplorerCommandProvider?
2) If they do, how do I get my hands on that interface?
Thanks
Ivo

Related

Mimic Win 7 Favorites on Windows 10 (Shell Namespace Extension)

Hello dear stackoverflow friends
A few months ago I asked you a question about QuickAccess (Pin/Unpin). Unfortunately we are still facing this issue (Unable to unpin virtual objects). After having called Microsoft Support a few times, they replied us we should subscribe to premier support... Too expensive for a small company.
So we have decided to Mimic the Windows 7 Favorites in our Shell Namespace Extension.
No big deal in the Explorer, calling ShellExecuteEx with view's handle and lnk's target object absolute pidl works like a charm.
Too good to be true, yeah, as it is not working as expected in IFileDialogs...
First the lnks (wrapped in a virtual object, but parsing name is Filesystem Path) weren't for obvious reasons shown in the dialogs. So we tried with attributes such as "SFGAO_FOLDER", "SFGAO_FILESYSANCESTOR" etc. but then the shell was calling IShellFolder's EnumObjects and that's not what we want.
So we decided to have a go with the Interface IObjectWithSite, implementing it in our Favorites' folder. We were then able to consume events from IFileDialogs such as OnSelectionChange. Then we tried the same method as in the explorer, getting view handle (first querying IOleWindow interface, getting window handle, creating view in parent IShellFolder using window handle) and calling ShellExecuteEx... And the result is.. A big application (Notepad, Word etc.) crash and a new Explorer Window with the right virtual object selected.
Probably is my approach too complicated, have you got any ideas?
Thanks a lot!
Thank to Simon, I was able to find a solution, still work in progress. The issue is that the IContextMenu, IContextMenu2 and also IContextMenu3 interfaces are implemented in the solution. On Windows 7, the .lnk menu handler was called, fine, on Windows 10 on the other hand you need to call SHCreateDefaultContextMenu, then merging the menu handlers (SHCreateDefaultContextMenu will then Call IShellFolder::GetUIObjectOf with IID_IQueryAssociations). So the code was dated... Thanks!

"The target can't handle this type of document" move to custom virtual folder

I have some code in VC++ that create windows explorer shell integration and shows some remote database folders in windows explorer as native folders. When I use "move to folder..." from the explorer menu and move some file to that virtual folder, windows give me error message "The target can't handle this type of document", even though the shell integration successfully moves the file to the database.
I am not able to find out what is the cause of that error and how to disable the same from my code, what configuration is needed.
Does anyone has an idea about the same.
I finally figured it out, Drop was returning hr instead of S_OK. the hr value came from some other method call and was wrongly returned as something else instead of S_OK.
It just in one of the if condition, the original developer has forgotten to set the hr value correctly. normally hr values are not used, it just for storing the result of a method call and returning the same at the end, so its very hard to figure what is wrong, because all methods are working properly.
These silly mistakes are hard to find, though easy to fix.
Thanks Denis for pointing where to look.

Allow selection in Explorer-style list view to start in the first column

In Windows 7's Windows Explorer list view (what allegedly is not list view at all) in the Details view, you can start selection marquee in the first (Name) column. You just need to start outside the actual name.
The same is true for default-style list view control in Details view.
But if you set the list view control to the Explorer style (using the SetWindowTheme), what should mimic the Windows Explorer, this does not work anymore. You can start selection in the second and later columns only.
SetWindowTheme(listView1.Handle, "explorer", null);
Is there any way to make list view mimic the Explorer selection style?
I suppose there's no settings to enable such behavior and this would have to be coded. Like handling the mouse down and triggering selection. But I have no idea how to do that.
Thanks.
Ntb, I'm using C++Builder, but this should be purely Win32 issue. I've tested this with WinForms too (hence the C# sample above).
Is there any way to make list view it mimic the Explorer selection style?
No, SysListView32 in explorer theme does not behave that way. The control used by the modern Explorer is actually DirectUIHwnd. And you are not able to use one of them.
The only way to get the behaviour of DirectUIHwnd is to code it yourself. I expect that's possible to do but I'd also expect it to be very difficult to achieve.
Actually there is a way to mimic Explorer selection behavior. It requires a lot of additional declarative work, but it is possible.
You need to get undocumented IListView interface via undocumented LVM_QUERYINTERFACE message (note that interface declaration and GUIDs are different for Windows Vista and Windows 7+). Details about constants and declarations can be found here:
IListView at Geoff Chappell - Software Analyst or
Undocumented List View Features at Code Project.
After acquiring the interface all you need is simply a call to SetSelectionFlags(1, 1) method. Voila you are done.

How can I get the name of a Visual Basic control given its HWND?

I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.

Problem debugging shell extension in Vista (IShellFolder)

I have created a Windows Shell Extension using ATL (Visual Studio 2008). It has the following modules and each module is a separate ATL Simple Object with its own .rgs file for registration:-
IShellFolder/IShellView -> For a virtual drive in windows explorer
IContextMenu/IShellExtInit -> For a popup menu files and folders
IShellIconOverlayIdentifier - To display overlay icons on files and folders
IShellPropSheetExt/IShellExtInit -> For a custom property page in File & Folder's properties
The above work fine in WinXP and I am able to debug this shell extension in WinXP. But a soon as I switch to Vista, I only get method calls for (2) and (4). The drive gets created in Windows Explorer but the underlying methods are not called when I click it.
Although when I right click I get called for (2) and when I select "Properties" for a file or folder I get into the code for (4).
Is there some interface that I am missing for (1) and (3) on Vista. I could not find full and detailed documentation on writing Shell Extensions for Vista on MSDN. I had already gone through the CodeProject articles on shell extensions.
The problem was because of a Xml SMART Pointer usage. It was has problems when Release() was called on it.
Check this link
Internet Explorer crashes when MSXML2::IXMLDOMDocumentPtr -> Release() is called
Make sure that your extensions are handling the initialization properly, otherwise the verclsid.exe won't let your extension getting loaded.
verclsid.exe first loads the shell extensions and does a quick check on them before it sends an 'ok' to the shell indicating that it's safe to load the extension.
See here for some details about verclsid.exe.

Resources