none
How to force update the core editor ContextAttributes? RRS feed

  • Question

  • 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


    • Edited by 11vm Friday, August 26, 2016 2:16 PM Formatting...
    Friday, August 26, 2016 2:10 PM

All replies

  • Hi 11vm

    >>So the question is how can I force the ContextAttributes to be update like the inbuilt F1 command does?

    If you want to use keyboard shortcut, you could refer to the following link, which provide a sample about keyboard shortcut.

    https://github.com/Microsoft/VSSDK-Extensibility-Samples/tree/master/Menu_And_Commands

    Best regards,

    Li Wang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, August 30, 2016 6:07 AM
    Moderator
  • Hi,

    many thanks for your response. One question still remains: Did you read the actual question?

    I'm looking for a way to force update the ContextAttributes provided by the ActiveWindow, e.g. by forcing the C++ language service to write the F1 keywords. I know how to work with menus.

    Best regards,
    Karsten

    Thursday, September 1, 2016 9:26 AM
  • Hi 11vm,

    From the following thread, Justin Grant provide a Visual Studio add-in solution for your reference.

    1. take over the F1 key binding
    2. when F1 is pressed, get the help context and turn it into a set of name=value pairs
    3. pass that set of name=value pairs into some external code to do something with the F1 request.

    http://stackoverflow.com/questions/13942657/visual-studio-intercepting-f1-help-command

    I hope it is helpful to you.

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Saturday, September 10, 2016 6:57 AM
    Moderator
  • Hi cole wu,


    many thanks for your reply. The link you gave me points to an question -article I already found before posting here. My code is more or less equivalent to the one on Stack Overflow. Still, even if I follow close to what's written there, the Attributes I'm interested in are only updated *after*

    dte2.ExecuteCommand("Help.F1Help");

    has been executed. I really would like to know how to force the Language Service to update the Context attributes of the current windows active editor. Most likely I need to call

    IVsLanguageContextProvider.UpdateLanguageContext

    but I do not know how.  Link to the above mentioned method: https://msdn.microsoft.com/de-de/library/microsoft.visualstudio.textmanager.interop.ivslanguagecontextprovider.updatelanguagecontext(v=vs.90).aspx

    Best regards,
    Karsten

    Wednesday, September 14, 2016 8:32 AM