7

I have a shell extension built using SharpShell. I am wondering if it is possible to append to the tooltip you see when you mouse over a file:

enter image description here

I have read and tried to use a Shell Info Tip Handler, but the problem with this is that it overrides the entire tooltip with what you set it to, instead of giving you the ability to append a line of text to the default tooltip you normally would see, which is my desired outcome.

I have a feeling this may not be supported in SharpShell, as a result, it would help for me to get insights from people as to how I could additionally approach this problem within MSVC++ shell extensions as well.

Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • Did you try calling the base class from your override? – Ben Voigt Sep 08 '16 at 18:56
  • @BenVoigt I wish, it is an abstract base method unfortunately. – Alexandru Sep 08 '16 at 18:59
  • Here's someone else who had the same question -- they asked in the wrong place and got no answer. https://social.microsoft.com/Forums/en-US/d3a0b665-019d-41cb-9e6e-b9ff99c70234/iqueryinfo-getinfotip-how-get-the-default-window-tip-text?forum=Offtopic – Ben Voigt Sep 08 '16 at 19:02
  • 2
    @BenVoigt We need Raymond Chen up in here, but the first thing he's going to say before providing a suitable answer is *don't write your shell extensions in C#* :) – Alexandru Sep 08 '16 at 19:11
  • One, .NET 4 introducing the ability to load multiple CLR versions into a single process got rid of the worst of the complications of using C# (it might still not be the best idea). Two, even for a native shell extension, the question "How does my Info Tip Handler get the text that would have been displayed had my handler never been registered?" is still interesting. Since the registry registration doesn't maintain a stack of handlers, just one, this probably never can be answered... but perhaps one can still get the default text as if no handlers were registered at all. – Ben Voigt Sep 08 '16 at 19:56
  • Really it's the whole subclassing debacle all over again -- To undo subclassing, you put back the former window procedure. And instead of calling the default handler, you call the procedure you supplanted. But what if a middle subclass wants to remove itself? It doesn't know where the pointer to it is stored, and so cannot remove itself. Same issue here, if you remember what handler was installed before you replaced it, you can't assume the software providing that hasn't been uninstalled in the meantime, so you can neither usefully chain to it nor put it back in the registry. – Ben Voigt Sep 08 '16 at 20:00
  • Win32 eventually added `SetWindowSubclass` and `RemoveWindowSubclass` functions to make operations on the linked list available to all comers. But no such infrastructure exists for Shell Info Tip Handlers. – Ben Voigt Sep 08 '16 at 20:01
  • @BenVoigt I get what you're saying, but in this case its not that complicated, because I want to get the resulting tooltip for the file or folder as if *no shell extensions or their corresponding handlers were to exist* on the system. So like, a simple library which pre-computes this from the HKCR registry would suffice for my needs, anyways. – Alexandru Sep 08 '16 at 20:08
  • The point of a custom handler is to do custom stuff, why not print the default text with the extra info? Appending you run the risk of appending to an appended other custom handler. – Ňɏssa Pøngjǣrdenlarp Sep 11 '16 at 01:28
  • @Plutonix Because I am not certain of a suitable mechanism to obtain the default tool tip text of any given file shown in Explorer. It seems to be highly configurable via the HKCR registry, where some InfoTip strings can even reference assembly resources, and other things. I am not looking for a simple answer on parsing the HKCR registry though, as there's no way anyone's answer would get it right, right off the bat. I am trying to get a concrete answer on whether or not there is a standard way of doing this (Windows APIs or some undocumented Windows APIs, etc.) – Alexandru Sep 11 '16 at 05:21
  • I have a solution but with using of Delphi (a lot of Delphi code). Do you need it? – Denis Anisimov Sep 15 '16 at 12:24
  • @DenisAnisimov Possibly, but can you describe how it works in a comment first? – Alexandru Sep 15 '16 at 12:51

1 Answers1

1

This is possible, but not through a shell tooltip extension. Instead, through a shell property handler. The Recipe Property Handler is documented here and can be downloaded in full from this repository. Here's a picture of it in action in Windows 10:

enter image description here

It essentially adds extra file properties to the PerfectSteaks.recipe file by registering itself as a property handler, such as the property for Recipe difficulty who's key is Microsoft.SampleRecipe.Difficulty and can easily be set to show in Explorer by modifying the HKCR key HKEY_CLASSES_ROOT\SystemFileAssociations\.recipe to have InfoTip (of type REG_SZ) set as prop:System.ItemType;System.Author;System.Rating;Microsoft.SampleRecipe.Difficulty which causes it to display.

The properties are stored within the file itself. The .recipe file is an XML file which contains, among other things, the actual difficulty which the handler retrieves:

<RecipeInfo>
    <Difficulty>Hard</Difficulty>
    <PreparationTime>5</PreparationTime>
    <CookTime>20</CookTime>
    <Yield>2 servings</Yield>
</RecipeInfo>

This is not something unique these days because a lot of file formats do provide some form of extra internal API for storage. If you are working with Office files (which I am), you may notice they expose properties for storage within them for persistence using OLE. The DSOFile.dll (click here to download the source) is of utmost interest for Office files, and generally other files too. You will see it tries OLE storage within the Office file format itself, barring that it tries the Microsoft Office Metadata Handler for storage. If that fails, it finally tries using alternate streams (not a fan of alternate streams myself because they won't persist).

So that being said, with a combination of a shell property handler and similar tactics to DSOFile.dll, you can merge a solution for getting this job done in a proper way.

Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • I see the big problem if you use this method for files like .doc. Such file extensions already have installed Property handlers and your handler will override the existing. And as result shell will not be able to show properties processed by initial Property handler. In case of .doc format it will be Author, Comments and so on. – Denis Anisimov Sep 16 '16 at 06:08
  • And minor note. This method is not universal. Default tooltip can be generated with another combination of PropertyKeys or can be generated with another InfoTip handler or can be generated with string from resources. So this method don`t append to the default tooltip, it creates the new one. – Denis Anisimov Sep 16 '16 at 06:09
  • @DenisAnisimov I'll admit I was quick to jump the gun here, as that's exactly something I wanted to test today, if you can have multiple shell property handlers live side by side. – Alexandru Sep 16 '16 at 11:04
  • @DenisAnisimov Why don't you post your Delphi-based solution in the meantime? – Alexandru Sep 16 '16 at 11:27
  • I will but some later. The code is a part my big shell lib and I must to extract and create independent version that can be understood by you. – Denis Anisimov Sep 16 '16 at 11:47
  • @DenisAnisimov Are you hosting it somewhere so I can check the source? – Alexandru Sep 19 '16 at 08:55