Hi,
I've been trying to implement help support for our toolkit in Visual Studio and so far I got some ideas where to look at. A sketch would be:
- Intercepting the F1 key and re-route it to my own handler
- parse the core ActiveWindow ContextAttributes looking for some F1 keyword identifier I know about
- open a browser window with the matching html (located on disc already) if I find something
- reroute the command with DTE2.ExecuteCommand("Help.F1Help") if there is nothing important for me
To be able to better debug I enabled "Dynamic Help" "Display Debug Output in Retail" and that lists the Active context attributes. No I wonder how the F1 processing code inside Visual Studio forces an update of these attributes, cause
calling ContextAttributes.Refresh() inside my code does not lead to updated attributes (see next). They are only updated once the help from Vs was executed.
Following the C++ source where I try to get the 'keywords' about. The cursor is placed inside 'exec' when pressing F1.
#include <QtCore/QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
auto blub = QCoreApplication::tr("Desktop", "Main");
return a.exec();
}Output while fetching the attributes before the call to DTE2.ExecuteCommand("Help.F1Help"):
keyword=VS.TextEditor;VS.Ambient item=cpp;project;project sourcecontrol=false;false projtype=Qt4VSv1.0;Qt4VSv1.0 project=exe;exe target=win32;win32 product=VS;vc;VS;vc ShellMode=Design Solution=Any;Single LCID=1033 ApplicationID=VisualStudio keyword=VS.TextEditor;VS.Ambient item=cpp;project;project sourcecontrol=false;false projtype=Qt4VSv1.0;Qt4VSv1.0 project=exe;exe target=win32;win32 product=VS;vc;VS;vc ShellMode=Design Solution=Any;Single LCID=1033
Output while fetching the attributes after the call to DTE2.ExecuteCommand("Help.F1Help"):
keyword=exec;QCoreApplication::exec;QCOREAPPLICATION/QCoreApplication::exec;VS.TextEditor;VS.Ambient TargetOS=Windows devlang=C++ item=cpp;project;project sourcecontrol=false;false projtype=Qt4VSv1.0;Qt4VSv1.0 project=exe;exe target=win32;win32 product=VS;vc;VS;vc ShellMode=Design Solution=Any;Single LCID=1033 ApplicationID=VisualStudio keyword=exec;QCoreApplication::exec;QCOREAPPLICATION/QCoreApplication::exec;VS.TextEditor;VS.Ambient TargetOS=Windows devlang=C++ item=cpp;project;project sourcecontrol=false;false projtype=Qt4VSv1.0;Qt4VSv1.0 project=exe;exe target=win32;win32 product=VS;vc;VS;vc ShellMode=Design Solution=Any;Single LCID=1033 ApplicationID=VisualStudio
Note the difference in the "keyword" section.
And here the code in question:
List<string> GetContextAttributes(DTE2 dte2)
{
var activeWindow = dte2.ActiveDocument.ActiveWindow;
var contextAttributes = activeWindow.DTE.ContextAttributes;
contextAttributes.Refresh();
var attributes = new List<string>();
try {
var highPriorityAttr = contextAttributes ?? contextAttributes.HighPriorityAttributes;
highPriorityAttr.Refresh();
if (highPriorityAttr != null) {
foreach (ContextAttribute contextAttr in highPriorityAttr) {
var values = new List<string>();
foreach (var value in (ICollection) contextAttr.Values)
values.Add(value.ToString());
attributes.Add(contextAttr.Name + "=" + string.Join(";", values));
}
}
} catch { }
foreach (ContextAttribute contextAttr in contextAttributes) {
var values = new List<string>();
foreach (var value in (ICollection) contextAttr.Values) {
values.Add(value.ToString());
}
attributes.Add(contextAttr.Name + "=" + string.Join(";", values));
}
return attributes;
}
private void MenuItemCallback(object sender, EventArgs args)
{
var dte2 = ServiceProvider.GetService(typeof(SDTE)) as DTE2;
//var attributes = GetContextAttributes(dte2);
//VsShellUtilities.ShowMessageBox(ServiceProvider,
// string.Join(Environment.NewLine, attributes), "Context Attributes",
// OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK,
// OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
dte2.ExecuteCommand("Help.F1Help");
var attributes = GetContextAttributes(dte2);
VsShellUtilities.ShowMessageBox(ServiceProvider,
string.Join(Environment.NewLine, attributes), "Context Attributes",
OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
}
So the question is how can I force the ContextAttributes to be update like the inbuilt F1 command does? Any help would be highly appreciated.
Kind regards,
Karsten