Cela peut être fait. Voici une solution (bien que quelque peu hacky): utilisez F1 Help Context. Pour que l'aide F1 fonctionne, Visual Studio pousse le nom de type complet de la sélection ou du point d'insertion actuel dans un sac de paires nom/valeur appelé «F1 Help Context». Et il existe des API publiques dans Visual Studio SDK pour interroger le contenu de F1 Help Context. Pour rester sain, vous devez activer la clé de registre de débogage pour le contexte d'aide F1. Cela vous permet de voir à tout moment ce qu'il y a dans le contexte d'aide via la fenêtre d'aide dynamique souvent décriée. Pour ce faire:
- Démarrez Visual Studio et choisissez Aide dynamique dans le menu Aide.
- définir la clé de Registre ci-dessous (vous devez l'étape 1 pour créer l'arborescence du Registre)
- restart Visual Studio pour ramasser les changements
- Maintenant, dans la fenêtre d'aide dynamique, il y aura sortie de débogage afin que vous puissiez voir Qu'y a-t-il dans le contexte d'aide F1? Le reste de cette réponse décrit comment accéder à ce contexte par programmation afin que votre complément puisse l'utiliser.
Voici la clé de Registre:
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Dynamic Help]
"Display Debug Output in Retail"="YES"
Comme vous le verrez de regarder à la sortie de débogage F1, Visual Studio ne vous dit pas explicitement «c'est le type de l'identifiant ». Au lieu de cela, il colle simplement le nom de type complet à la tête d'un ou plusieurs "Mots-clés d'aide" que F1 utilise pour afficher de l'aide. Par exemple, vous pouvez avoir System.String, VS.TextEditor et VS.Ambient dans votre contexte d'aide, et seul le premier est lié au code actuel.
L'astuce pour faciliter les choses est la suivante: Visual Studio peut marquer les mots-clés en fonction de la casse ou de la casse. AFAIK, la seule partie de Visual Studio qui injecte des mots-clés sensibles à la casse est l'éditeur de code des langages sensibles à la casse (C#, C++) en réponse au contexte de code. Par conséquent, si vous filtrez tous les mots clés en mots clés sensibles à la casse, vous savez que vous examinez le code. Malheureusement, l'éditeur C# pousse également les mots-clés de langage (pas seulement les identifiants) dans le contexte d'aide si le point d'insertion est au-dessus d'un mot-clé de langue. Vous devrez donc filtrer les mots clés de la langue. Il y a deux façons de faire ça. Vous pouvez simplement essayer de les rechercher dans le système de type, et comme ce ne sont pas des noms de types valides (surtout pas la manière dont VS les écrase, par exemple "string_CSharpKeyword" pour le mot-clé string). Ou vous pouvez détecter le manque de points et supposer que ce n'est pas un nom de type. Ou vous pouvez détecter le suffixe _CSharpKeyword et espérer que l'équipe VS ne le change pas. :-)
Un autre problème potentiel est celui des génériques.Le nom du type que vous obtiendrez de VS pour un type générique ressemble à ceci:
System.Collections.Generic.List`1
et les méthodes ressemblent à ceci:
System.Collections.Generic.List`1.FindAll.
Vous aurez besoin d'être intelligent sur la détection de l'arrière-tique et faire avec. En outre, vous pourriez avoir un comportement intéressant dans des cas comme les fichiers ASP.NET MVC .ASPX où il y a du code C# et un autre code sensible à la casse (par exemple javascript) sur la page. Dans ce cas, vous devrez également regarder les attributs. Outre les mots-clés, le contexte d'aide comporte également des «attributs», qui sont des paires nom/valeur décrivant le contexte actuel. Par exemple, devlang = csharp est un attribut. Le code ci-dessous peut être utilisé pour extraire des attributs aussi. Vous aurez besoin d'expérimenter pour trouver les bons attributs à rechercher afin de ne pas finir par agir sur javascript ou tout autre code impair. Quoi qu'il en soit, maintenant que vous comprenez (ou au moins avez été exposé à!) Tous les avertissements, voici un code pour retirer le mot clé sensible à la casse (s'il existe) du contexte d'aide, ainsi que le reste de les paires nom/valeur. (Les mots-clés sont simplement des paires nom/valeur dont le nom est "mot-clé"). Gardez à l'esprit que ce code nécessite Visual Studio SDK (et pas seulement l'installation standard de VS) pour générer Microsoft.VisualStudio.Shell.Interop, Microsoft.VisualStudio.Shell et Microsoft. Les espaces de noms VisualStudio.OLE.Interop (que vous devrez ajouter comme références dans votre projet addin). OK, amusez-vous et bonne chance!
using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
using System.Globalization;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.OLE.Interop;
using System.Collections.Generic;
public class HelpAttribute
{
public string Name;
public string Value;
public VSUSERCONTEXTPRIORITY Priority;
public VSUSERCONTEXTATTRIBUTEUSAGE Usage;
}
public class HelpContext2 : List<HelpAttribute>
{
public static HelpContext2 GetHelpContext(DTE2 dte)
{
// Get a reference to the current active window (presumably a code editor).
Window activeWindow = dte.ActiveWindow;
// make a few gnarly COM-interop calls in order to get Help Context
Microsoft.VisualStudio.OLE.Interop.IServiceProvider sp = (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)activeWindow.DTE;
Microsoft.VisualStudio.Shell.ServiceProvider serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(sp);
IVsMonitorUserContext contextMonitor = (IVsMonitorUserContext)serviceProvider.GetService(typeof(IVsMonitorUserContext));
IVsUserContext userContext;
int hresult = contextMonitor.get_ApplicationContext(out userContext);
HelpContext2 attrs = new HelpContext2(userContext);
return attrs;
}
public HelpContext2(IVsUserContext userContext)
{
int count;
userContext.CountAttributes(null, 1, out count);
for (int i = 0; i < count; i++)
{
string name, value;
int priority;
userContext.GetAttributePri(i, null, 1, out priority, out name, out value);
VSUSERCONTEXTATTRIBUTEUSAGE[] usageArray = new VSUSERCONTEXTATTRIBUTEUSAGE[1];
userContext.GetAttrUsage(i, 1, usageArray);
VSUSERCONTEXTATTRIBUTEUSAGE usage = usageArray[0];
HelpAttribute attr = new HelpAttribute();
attr.Name = name;
attr.Value = value;
attr.Priority = (VSUSERCONTEXTPRIORITY)priority;
attr.Usage = usage; // name == "keyword" ? VSUSERCONTEXTATTRIBUTEUSAGE.VSUC_Usage_Lookup : VSUSERCONTEXTATTRIBUTEUSAGE.VSUC_Usage_Filter;
this.Add(attr);
}
}
public string CaseSensitiveKeyword
{
get
{
HelpAttribute caseSensitive = Keywords.Find(attr =>
attr.Usage == VSUSERCONTEXTATTRIBUTEUSAGE.VSUC_Usage_LookupF1_CaseSensitive
|| attr.Usage == VSUSERCONTEXTATTRIBUTEUSAGE.VSUC_Usage_Lookup_CaseSensitive
);
return caseSensitive == null ? null : caseSensitive.Value;
}
}
public List<HelpAttribute> Keywords
{
get
{
return this.FindAll(attr=> attr.Name == "keyword");
}
}
}
Merci beaucoup, cela fonctionne parfaitement !! – ste
excellent! heureux de vous aider. Heureusement, j'ai eu ce code qui traînait à partir de certaines enquêtes précédentes ... comprendre comment faire cela la première fois était un peu plus difficile. :-) –
Vous êtes officiellement mon héros personnel. Je me promenais dans le désert de CodeElement et essayais de déterminer comment dériver la chaîne d'aide. Vous m'avez remis sur la bonne voie. Merci encore! – Batgar