Archives

Archives / 2006 / July
  • How to Determine the Localized Name of the Scope for a Key Binding (Dirty Hack)

    Here’s a tip I actually wanted to share some time ago, but kind of forgot about it until I got reminded by a recent post by Thomas Müller who I had nice contact with some months ago.

    In order to assign a keyboard shortcut to a Visual Studio command from code (e.g. in an add-in), one has to specify a binding consisting of the shortcut’s scope (e.g. “Global”, or “Text Editor”) and the actual keys to be pressed (e.g. “ctrl+shift+d”). For example in C#:

     

    DTE2 objApplication;
    ...
    Command cmd=objApplication.Commands.Item("TheNamespace.TheClass.TheCommand", -1);
    cmd.Bindings="Text Editor::Ctrl+Shift+D";

     

    (The example shows how to assign a single shortcut. Multiple shortcuts can be assigned, please see this entry in the MSDN libary for more details)

    When Microsoft released the international versions of Visual Studio 2005, I received a lot of feedback from users of my add-in GhostDoc who ran into problems during setup with the creation of the hotkey for the “Document This” command. Debugging GhostDoc on a German version of Visual Studio 2005 (which by the way was a strange experience as I never had used a developer tool in my native language before), I found out the following:

    • When you read a binding of a command (in C# by casting the Bindings property of a Command instance to object[], and casting an array item to string), you get the localized text (e.g. “Text-Editor::Strg+Umschalt+D” in German Visual Studio 2005)
    • When you define a binding using the localized text, you get an error (hmm…).
    • When you define a binding using the non-localized text, you get an error (huh?).
    • You have to define a binding using the localized scope and the non-localized key names (…mkay).

    But where to get the localized name of the scope from? I couldn’t find anything on the web, and posting a question in the MSDN Extensibility Forum didn’t help either.

    What I did in the end must be considered a dirty hack and should be used with caution:

    • In my case, I needed the localized name for “Text Editor” (“Text-Editor” in German, “Editor de Texto” in Spanish).
    • I chose a command that – at least with a high probability – never would be assigned to an other scope than “Text Editor” (Edit.DeleteBackwards) and read the first entry of its bindings.
    • The sub-string up to the “::” was the desired localized name of the scope.

    Here's the C# code to do that (all error handling stripped):

    Command cmd=objApplication.Commands.Item("Edit.DeleteBackwards", -1);
    object[] arrBindings = (object[]) cmd.Bindings;
    string strBinding = (string)arrBindings[0];
    string strScope = strBinding.Substring(0, strBinding.IndexOf("::"));

     

    By now, every professional developer should have bad feeling about this solution – there are just too many coding catastrophes in the history of computing that started with “it should be safe to do that, nobody will ever…”. So if you have a better solution, please let me know. If you do chose to go that route and need the localized name of an other scope than “Text Editor”, make sure you chose the command veeeery wisely.

  • Three Years of Blogging

    Three years ago on this day I started this blog… Originally, I had planned to write a blog entry looking back at some of the stuff that happened since my “Two years of Blogging” post. But suddenly outside the wind died down completely, so I took my little electric R/C plane (which doesn’t like any wind at all) to the next football (soccer) field.

    The weather was just incredible (not a single cloud to be seen!) and with the moon up in the sky, I just had to take a picture. Unfortunately I didn’t have my digital camera with me, so – in true geek style – I used my XDA Neo (aka HTC Prophet). Taking a picture and controlling the plane at the same time proved to be a bit difficult, so I made only one attempt, but that turned out pretty well:

    20060702_ThreeYears1

    A little closer:

    20060702_ThreeYears2