diff --git a/Combo_Box/C#/Reference.ComboBox.csproj b/Combo_Box/C#/Reference.ComboBox.csproj index 39191474..7c306c35 100644 --- a/Combo_Box/C#/Reference.ComboBox.csproj +++ b/Combo_Box/C#/Reference.ComboBox.csproj @@ -8,15 +8,14 @@ IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. --> - - - + 14.0 $(VisualStudioVersion) $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + @@ -32,7 +31,7 @@ PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. Reference.ComboBox True Key.snk - v4.5 + v4.7.2 true @@ -58,95 +57,7 @@ PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. true - - True - - - True - - - True - - - True - - - - - packages\Microsoft.VisualStudio.Imaging.14.0.23205\lib\net45\Microsoft.VisualStudio.Imaging.dll - True - - - packages\Microsoft.VisualStudio.OLE.Interop.7.10.6070\lib\Microsoft.VisualStudio.OLE.Interop.dll - True - - - packages\Microsoft.VisualStudio.Shell.14.0.14.0.23205\lib\Microsoft.VisualStudio.Shell.14.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Immutable.10.0.10.0.30319\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Immutable.11.0.11.0.50727\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Immutable.12.0.12.0.21003\lib\net45\Microsoft.VisualStudio.Shell.Immutable.12.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Immutable.14.0.14.0.23205\lib\net45\Microsoft.VisualStudio.Shell.Immutable.14.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Interop.7.10.6071\lib\Microsoft.VisualStudio.Shell.Interop.dll - True - - - True - packages\Microsoft.VisualStudio.Shell.Interop.10.0.10.0.30319\lib\Microsoft.VisualStudio.Shell.Interop.10.0.dll - True - - - True - packages\Microsoft.VisualStudio.Shell.Interop.11.0.11.0.61030\lib\Microsoft.VisualStudio.Shell.Interop.11.0.dll - True - - - True - packages\Microsoft.VisualStudio.Shell.Interop.12.0.12.0.30110\lib\Microsoft.VisualStudio.Shell.Interop.12.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.Shell.Interop.8.0.dll - True - - - packages\Microsoft.VisualStudio.Shell.Interop.9.0.9.0.30729\lib\Microsoft.VisualStudio.Shell.Interop.9.0.dll - True - - - packages\Microsoft.VisualStudio.TextManager.Interop.7.10.6070\lib\Microsoft.VisualStudio.TextManager.Interop.dll - True - - - packages\Microsoft.VisualStudio.TextManager.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.TextManager.Interop.8.0.dll - True - - - packages\Microsoft.VisualStudio.Threading.14.0.50702\lib\net45\Microsoft.VisualStudio.Threading.dll - True - - - packages\Microsoft.VisualStudio.Utilities.14.0.23205\lib\net45\Microsoft.VisualStudio.Utilities.dll - True - - - packages\Microsoft.VisualStudio.Validation.14.0.50702\lib\net45\Microsoft.VisualStudio.Validation.dll - True - + @@ -156,15 +67,6 @@ PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. - - {1CBA492E-7263-47BB-87FE-639000619B15} - 8 - 0 - 0 - primary - False - False - {00020430-0000-0000-C000-000000000046} 2 @@ -198,7 +100,6 @@ PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. - Designer @@ -220,22 +121,55 @@ PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. true + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 3.3.3 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + 16.10.10 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 17.0.31902.203 + + + 17.0.64 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + 17.0.5232 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + true - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - \ No newline at end of file diff --git a/Combo_Box/C#/Reference.ComboBox.sln b/Combo_Box/C#/Reference.ComboBox.sln index 7f375d1e..9602fb0f 100644 --- a/Combo_Box/C#/Reference.ComboBox.sln +++ b/Combo_Box/C#/Reference.ComboBox.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22723.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reference.ComboBox", "Reference.ComboBox.csproj", "{D8407669-D43D-47E9-8A5F-B81DC0606A89}" EndProject diff --git a/Combo_Box/C#/Resources.Designer.cs b/Combo_Box/C#/Resources.Designer.cs index 4bf28d41..5d3133f9 100644 --- a/Combo_Box/C#/Resources.Designer.cs +++ b/Combo_Box/C#/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.Samples.VisualStudio.ComboBox { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { diff --git a/Combo_Box/C#/VsPkg.cs b/Combo_Box/C#/VsPkg.cs index 905bd129..6ea50aa5 100644 --- a/Combo_Box/C#/VsPkg.cs +++ b/Combo_Box/C#/VsPkg.cs @@ -16,8 +16,10 @@ IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; -[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Microsoft.Samples.VisualStudio.ComboBox")] +[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "~N:Microsoft.Samples.VisualStudio.ComboBox")] namespace Microsoft.Samples.VisualStudio.ComboBox { /// @@ -33,7 +35,7 @@ namespace Microsoft.Samples.VisualStudio.ComboBox // This attribute tells the registration utility (regpkg.exe) that this class needs // to be registered as package. - [PackageRegistration(UseManagedResourcesOnly = true)] + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] // This attribute is used to register the informations needed to show the this package // in the Help/About dialog of Visual Studio. @@ -44,7 +46,7 @@ namespace Microsoft.Samples.VisualStudio.ComboBox // This attribute registers a tool window exposed by this package. [Guid(GuidList.guidComboBoxPkgString)] - public sealed class ComboBoxPackage : Package + public sealed class ComboBoxPackage : AsyncPackage { /// /// Default constructor of the package. @@ -65,162 +67,162 @@ public ComboBoxPackage() /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initilaization code that rely on services provided by VisualStudio. /// - protected override void Initialize() + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) { - base.Initialize(); - - // Add our command handlers for menu (commands must be declared in the .vsct file) - OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; - if (null != mcs) - { - // NOTE: For further explanantions of the various types of combos and their differences see the .vsct file where they are declared. - // - // A DropDownCombo combobox requires two commands: - // One command (cmdidMyCombo) is used to ask for the current value for the display area of the combo box - // and to set the new value when the user makes a choice in the combo box. - // - // The second command (cmdidMyComboGetList) is used to retrieve the list of choices for the combo box drop - // down area. - // - // Normally IOleCommandTarget::QueryStatus is used to determine the state of a command, e.g. - // enable vs. disable, shown vs. hidden, etc. The QueryStatus method does not have enough - // flexibility for combos which need to be able to indicate a currently selected (displayed) - // item as well as provide a list of items for their dropdown area. In order to communicate - // this information actually IOleCommandTarget::Exec is used with a non-NULL varOut parameter. - // You can think of these Exec calls as extended QueryStatus calls. There are two pieces of - // information needed for a combo, thus it takes two commands to retrieve this information. - // The main command id for the command is used to retrieve the current value and the second - // command is used to retrieve the full list of choices to be displayed as an array of strings. - CommandID menuMyDropDownComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDropDownCombo); - OleMenuCommand menuMyDropDownComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyDropDownCombo), menuMyDropDownComboCommandID); - mcs.AddCommand(menuMyDropDownComboCommand); - - CommandID menuMyDropDownComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDropDownComboGetList); - MenuCommand menuMyDropDownComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyDropDownComboGetList), menuMyDropDownComboGetListCommandID); - mcs.AddCommand(menuMyDropDownComboGetListCommand); - - // An IndexCombo box requires two commands: - // One command is used to ask for the current value of the combo box and to set the new value when the user - // makes a choice in the combo box. - // - // The second command is used to retrieve this list of choices for the combo box. - CommandID menuMyIndexComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyIndexCombo); - OleMenuCommand menuMyIndexComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyIndexCombo), menuMyIndexComboCommandID); - mcs.AddCommand(menuMyIndexComboCommand); - - CommandID menuMyIndexComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyIndexComboGetList); - MenuCommand menuMyIndexComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyIndexComboGetList), menuMyIndexComboGetListCommandID); - mcs.AddCommand(menuMyIndexComboGetListCommand); - - // MRUCombo - // An MRU Combo box requires only one command: - // One command is used to ask for the current value of the combo box and to set the new value when the user - // makes a choice in the combo box. - // - // The list of choices entered is automatically remembered by the IDE on a per-user/per-machine basis. - CommandID menuMyMRUComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyMRUCombo); - OleMenuCommand menuMyMRUComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyMRUCombo), menuMyMRUComboCommandID); - mcs.AddCommand(menuMyMRUComboCommand); - - // A DynamicCombo combo box requires two commands: - // One command is used to ask for the current value of the combo box and to set the new value when the user - // makes a choice in the combo box. - // - // The second command is used to retrieve this list of choices for the combo box. - CommandID menuMyDynamicComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDynamicCombo); - OleMenuCommand menuMyDynamicComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyDynamicCombo), menuMyDynamicComboCommandID); - mcs.AddCommand(menuMyDynamicComboCommand); - - CommandID menuMyDynamicComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDynamicComboGetList); - MenuCommand menuMyDynamicComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyDynamicComboGetList), menuMyDynamicComboGetListCommandID); - mcs.AddCommand(menuMyDynamicComboGetListCommand); - } - } + await base.InitializeAsync(cancellationToken, progress); + + // When initialized asynchronously, the current thread may be a background thread at this point. + // Do any initialization that requires the UI thread after switching to the UI thread. + await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + // Add our command handlers for menu (commands must be declared in the .vsct file) + if (await GetServiceAsync(typeof(IMenuCommandService)) is OleMenuCommandService mcs) + { + // NOTE: For further explanantions of the various types of combos and their differences see the .vsct file where they are declared. + // + // A DropDownCombo combobox requires two commands: + // One command (cmdidMyCombo) is used to ask for the current value for the display area of the combo box + // and to set the new value when the user makes a choice in the combo box. + // + // The second command (cmdidMyComboGetList) is used to retrieve the list of choices for the combo box drop + // down area. + // + // Normally IOleCommandTarget::QueryStatus is used to determine the state of a command, e.g. + // enable vs. disable, shown vs. hidden, etc. The QueryStatus method does not have enough + // flexibility for combos which need to be able to indicate a currently selected (displayed) + // item as well as provide a list of items for their dropdown area. In order to communicate + // this information actually IOleCommandTarget::Exec is used with a non-NULL varOut parameter. + // You can think of these Exec calls as extended QueryStatus calls. There are two pieces of + // information needed for a combo, thus it takes two commands to retrieve this information. + // The main command id for the command is used to retrieve the current value and the second + // command is used to retrieve the full list of choices to be displayed as an array of strings. + CommandID menuMyDropDownComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDropDownCombo); + OleMenuCommand menuMyDropDownComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyDropDownCombo), menuMyDropDownComboCommandID); + mcs.AddCommand(menuMyDropDownComboCommand); + + CommandID menuMyDropDownComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDropDownComboGetList); + MenuCommand menuMyDropDownComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyDropDownComboGetList), menuMyDropDownComboGetListCommandID); + mcs.AddCommand(menuMyDropDownComboGetListCommand); + + // An IndexCombo box requires two commands: + // One command is used to ask for the current value of the combo box and to set the new value when the user + // makes a choice in the combo box. + // + // The second command is used to retrieve this list of choices for the combo box. + CommandID menuMyIndexComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyIndexCombo); + OleMenuCommand menuMyIndexComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyIndexCombo), menuMyIndexComboCommandID); + mcs.AddCommand(menuMyIndexComboCommand); + + CommandID menuMyIndexComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyIndexComboGetList); + MenuCommand menuMyIndexComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyIndexComboGetList), menuMyIndexComboGetListCommandID); + mcs.AddCommand(menuMyIndexComboGetListCommand); + + // MRUCombo + // An MRU Combo box requires only one command: + // One command is used to ask for the current value of the combo box and to set the new value when the user + // makes a choice in the combo box. + // + // The list of choices entered is automatically remembered by the IDE on a per-user/per-machine basis. + CommandID menuMyMRUComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyMRUCombo); + OleMenuCommand menuMyMRUComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyMRUCombo), menuMyMRUComboCommandID); + mcs.AddCommand(menuMyMRUComboCommand); + + // A DynamicCombo combo box requires two commands: + // One command is used to ask for the current value of the combo box and to set the new value when the user + // makes a choice in the combo box. + // + // The second command is used to retrieve this list of choices for the combo box. + CommandID menuMyDynamicComboCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDynamicCombo); + OleMenuCommand menuMyDynamicComboCommand = new OleMenuCommand(new EventHandler(OnMenuMyDynamicCombo), menuMyDynamicComboCommandID); + mcs.AddCommand(menuMyDynamicComboCommand); + + CommandID menuMyDynamicComboGetListCommandID = new CommandID(GuidList.guidComboBoxCmdSet, (int)PkgCmdIDList.cmdidMyDynamicComboGetList); + MenuCommand menuMyDynamicComboGetListCommand = new OleMenuCommand(new EventHandler(OnMenuMyDynamicComboGetList), menuMyDynamicComboGetListCommandID); + mcs.AddCommand(menuMyDynamicComboGetListCommand); + } + } #endregion #region Combo Box Commands - private string[] dropDownComboChoices = { Resources.Apples, Resources.Oranges, Resources.Pears, Resources.Bananas }; + private readonly string[] dropDownComboChoices = { Resources.Apples, Resources.Oranges, Resources.Pears, Resources.Bananas }; private string currentDropDownComboChoice = Resources.Apples; - private void OnMenuMyDropDownCombo(object sender, EventArgs e) + private async void OnMenuMyDropDownCombo(object sender, EventArgs e) { - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - - if (eventArgs != null) - { - string newChoice = eventArgs.InValue as string; - IntPtr vOut = eventArgs.OutValue; - - if (vOut != IntPtr.Zero) - { - // when vOut is non-NULL, the IDE is requesting the current value for the combo - Marshal.GetNativeVariantForObject(currentDropDownComboChoice, vOut); - } - - else if (newChoice != null) - { - // new value was selected or typed in - // see if it is one of our items - bool validInput = false; - int indexInput = -1; - for (indexInput = 0; indexInput < dropDownComboChoices.Length; indexInput++) - { - if (string.Compare(dropDownComboChoices[indexInput], newChoice, StringComparison.CurrentCultureIgnoreCase) == 0) - { - validInput = true; - break; - } - } - - if (validInput) - { - currentDropDownComboChoice = dropDownComboChoices[indexInput]; - ShowMessage(Resources.MyDropDownCombo, currentDropDownComboChoice); - } - else - { - throw (new ArgumentException(Resources.ParamNotValidStringInList)); // force an exception to be thrown - } - } - } - else - { - // We should never get here; EventArgs are required. - throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown - } - } + if (e is OleMenuCmdEventArgs eventArgs) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + IntPtr vOut = eventArgs.OutValue; + + if (vOut != IntPtr.Zero) + { + // when vOut is non-NULL, the IDE is requesting the current value for the combo + Marshal.GetNativeVariantForObject(currentDropDownComboChoice, vOut); + } + + else if (eventArgs.InValue is string newChoice) + { + // new value was selected or typed in + // see if it is one of our items + bool validInput = false; + int indexInput; + for (indexInput = 0; indexInput < dropDownComboChoices.Length; indexInput++) + { + if (string.Compare(dropDownComboChoices[indexInput], newChoice, StringComparison.CurrentCultureIgnoreCase) == 0) + { + validInput = true; + break; + } + } + + if (validInput) + { + currentDropDownComboChoice = dropDownComboChoices[indexInput]; + ShowMessage(Resources.MyDropDownCombo, currentDropDownComboChoice); + } + else + { + throw (new ArgumentException(Resources.ParamNotValidStringInList)); // force an exception to be thrown + } + } + } + else + { + // We should never get here; EventArgs are required. + throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown + } + } private void OnMenuMyDropDownComboGetList(object sender, EventArgs e) { - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - - if (eventArgs != null) - { - object inParam = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (inParam != null) - { - throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown - } - else if (vOut != IntPtr.Zero) - { - Marshal.GetNativeVariantForObject(dropDownComboChoices, vOut); - } - else - { - throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown - } - } - - } - - private string[] indexComboChoices = { Resources.Lions, Resources.Tigers, Resources.Bears}; + if (e is OleMenuCmdEventArgs eventArgs) + { + object inParam = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (inParam != null) + { + throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown + } + else if (vOut != IntPtr.Zero) + { + Marshal.GetNativeVariantForObject(dropDownComboChoices, vOut); + } + else + { + throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown + } + } + + } + + private readonly string[] indexComboChoices = { Resources.Lions, Resources.Tigers, Resources.Bears}; private int currentIndexComboChoice = 0; - private void OnMenuMyIndexCombo(object sender, EventArgs e) + private async void OnMenuMyIndexCombo(object sender, EventArgs e) { if ((null == e) || (e == EventArgs.Empty)) { @@ -228,62 +230,63 @@ private void OnMenuMyIndexCombo(object sender, EventArgs e) throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown } - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - if (eventArgs != null) - { - object input = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (vOut != IntPtr.Zero && input != null) - { - throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown - } - if (vOut != IntPtr.Zero) - { - // when vOut is non-NULL, the IDE is requesting the current value for the combo - Marshal.GetNativeVariantForObject(indexComboChoices[currentIndexComboChoice], vOut); - } - - else if (input != null) - { - int newChoice = -1; - if(!int.TryParse(input.ToString(), out newChoice)) - { - // user typed a string argument in command window. - for (int i = 0; i < indexComboChoices.Length; i++) - { - if (string.Compare(indexComboChoices[i], input.ToString(), StringComparison.CurrentCultureIgnoreCase) == 0) - { - newChoice = i; - break; - } - } - } - - // new value was selected or typed in - if (newChoice != -1) - { - currentIndexComboChoice = newChoice; - ShowMessage(Resources.MyIndexCombo, currentIndexComboChoice.ToString(CultureInfo.CurrentCulture)); - } - else - { - throw (new ArgumentException(Resources.ParamMustBeValidIndexOrStringInList)); // force an exception to be thrown - } - } - else - { - // We should never get here; EventArgs are required. - throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown - } - } - else - { - // We should never get here; EventArgs are required. - throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown - } - } + if (e is OleMenuCmdEventArgs eventArgs) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + object input = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (vOut != IntPtr.Zero && input != null) + { + throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown + } + if (vOut != IntPtr.Zero) + { + // when vOut is non-NULL, the IDE is requesting the current value for the combo + Marshal.GetNativeVariantForObject(indexComboChoices[currentIndexComboChoice], vOut); + } + + else if (input != null) + { + int newChoice = -1; + if (!int.TryParse(input.ToString(), out newChoice)) + { + // user typed a string argument in command window. + for (int i = 0; i < indexComboChoices.Length; i++) + { + if (string.Compare(indexComboChoices[i], input.ToString(), StringComparison.CurrentCultureIgnoreCase) == 0) + { + newChoice = i; + break; + } + } + } + + // new value was selected or typed in + if (newChoice != -1) + { + currentIndexComboChoice = newChoice; + ShowMessage(Resources.MyIndexCombo, currentIndexComboChoice.ToString(CultureInfo.CurrentCulture)); + } + else + { + throw (new ArgumentException(Resources.ParamMustBeValidIndexOrStringInList)); // force an exception to be thrown + } + } + else + { + // We should never get here; EventArgs are required. + throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown + } + } + else + { + // We should never get here; EventArgs are required. + throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown + } + } private void OnMenuMyIndexComboGetList(object sender, EventArgs e) { @@ -293,31 +296,30 @@ private void OnMenuMyIndexComboGetList(object sender, EventArgs e) throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown } - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - if (eventArgs != null) - { - object inParam = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (inParam != null) - { - throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown - } - else if (vOut != IntPtr.Zero) - { - Marshal.GetNativeVariantForObject(indexComboChoices, vOut); - } - else - { - throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown - } - } - } + if (e is OleMenuCmdEventArgs eventArgs) + { + object inParam = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (inParam != null) + { + throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown + } + else if (vOut != IntPtr.Zero) + { + Marshal.GetNativeVariantForObject(indexComboChoices, vOut); + } + else + { + throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown + } + } + } private string currentMRUComboChoice = null; - private void OnMenuMyMRUCombo(object sender, EventArgs e) + private async void OnMenuMyMRUCombo(object sender, EventArgs e) { if (e == EventArgs.Empty) { @@ -325,59 +327,59 @@ private void OnMenuMyMRUCombo(object sender, EventArgs e) throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown } - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - - if (eventArgs != null) - { - object input = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (vOut != IntPtr.Zero && input != null) - { - throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown - } - else if (vOut != IntPtr.Zero) - { - // when vOut is non-NULL, the IDE is requesting the current value for the combo - Marshal.GetNativeVariantForObject(currentMRUComboChoice, vOut); - } - - else if (input != null) - { - string newChoice = input.ToString(); - - // new value was selected or typed in - if (!string.IsNullOrEmpty(newChoice)) - { - currentMRUComboChoice = newChoice; - ShowMessage(Resources.MyMRUCombo, currentMRUComboChoice); - } - else - { - // We should never get here - throw (new ArgumentException(Resources.EmptyStringIllegal)); // force an exception to be thrown - } - } - else - { - throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown - } - } - else - { - // We should never get here; EventArgs are required. - throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown - } - } - - private double[] numericZoomLevels = { 4.0, 3.0, 2.0, 1.5, 1.25, 1.0, .75, .66, .50, .33, .25, .10 }; - private string zoomToFit = Resources.ZoomToFit; - private string zoom_to_Fit = Resources.Zoom_to_Fit; + if (e is OleMenuCmdEventArgs eventArgs) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + object input = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (vOut != IntPtr.Zero && input != null) + { + throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown + } + else if (vOut != IntPtr.Zero) + { + // when vOut is non-NULL, the IDE is requesting the current value for the combo + Marshal.GetNativeVariantForObject(currentMRUComboChoice, vOut); + } + + else if (input != null) + { + string newChoice = input.ToString(); + + // new value was selected or typed in + if (!string.IsNullOrEmpty(newChoice)) + { + currentMRUComboChoice = newChoice; + ShowMessage(Resources.MyMRUCombo, currentMRUComboChoice); + } + else + { + // We should never get here + throw (new ArgumentException(Resources.EmptyStringIllegal)); // force an exception to be thrown + } + } + else + { + throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown + } + } + else + { + // We should never get here; EventArgs are required. + throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown + } + } + + private readonly double[] numericZoomLevels = { 4.0, 3.0, 2.0, 1.5, 1.25, 1.0, .75, .66, .50, .33, .25, .10 }; + private readonly string zoomToFit = Resources.ZoomToFit; + private readonly string zoom_to_Fit = Resources.Zoom_to_Fit; private string[] zoomLevels = null; private NumberFormatInfo numberFormatInfo; private double currentZoomFactor = 1.0; - private void OnMenuMyDynamicCombo(object sender, EventArgs e) + private async void OnMenuMyDynamicCombo(object sender, EventArgs e) { if ((null == e) || (e == EventArgs.Empty)) { @@ -385,82 +387,82 @@ private void OnMenuMyDynamicCombo(object sender, EventArgs e) throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown } - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - - if (eventArgs != null) - { - object input = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (vOut != IntPtr.Zero && input != null) - { - throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown - } - else if (vOut != IntPtr.Zero) - { - // when vOut is non-NULL, the IDE is requesting the current value for the combo - if (currentZoomFactor == 0) - { - Marshal.GetNativeVariantForObject(zoom_to_Fit, vOut); - } - else - { - string factorString = currentZoomFactor.ToString("P0", numberFormatInfo); - Marshal.GetNativeVariantForObject(factorString, vOut); - } - - } - else if (input != null) - { - // new zoom value was selected or typed in - string inputString = input.ToString(); - - if (inputString.Equals(zoomToFit) || inputString.Equals(zoom_to_Fit)) - { - currentZoomFactor = 0; - ShowMessage(Resources.MyDynamicCombo, zoom_to_Fit); - } - else - { - // There doesn't appear to be any percent-parsing routines in the framework (even though you can create - // a localized percentage in a string!). So, we need to remove any occurence of the localized Percent - // symbol, then parse the value that's left - try - { - float newZoom = Single.Parse(inputString.Replace(NumberFormatInfo.InvariantInfo.PercentSymbol, ""), CultureInfo.CurrentCulture); - - newZoom = (float)Math.Round(newZoom); - if (newZoom < 0) - { - throw (new ArgumentException(Resources.ZoomMustBeGTZero)); // force an exception to be thrown - } - - currentZoomFactor = newZoom / (float)100.0; - - ShowMessage(Resources.MyDynamicCombo, newZoom.ToString(CultureInfo.CurrentCulture)); - } - catch (FormatException) - { - // user typed in a non-numeric value, ignore it - } - catch (OverflowException) - { - // user typed in too large of a number, ignore it - } - } - } - else - { - // We should never get here - throw (new ArgumentException(Resources.InOutParamCantBeNULL)); // force an exception to be thrown - } - } - else - { - // We should never get here; EventArgs are required. - throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown - } - } + if (e is OleMenuCmdEventArgs eventArgs) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + object input = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (vOut != IntPtr.Zero && input != null) + { + throw (new ArgumentException(Resources.BothInOutParamsIllegal)); // force an exception to be thrown + } + else if (vOut != IntPtr.Zero) + { + // when vOut is non-NULL, the IDE is requesting the current value for the combo + if (currentZoomFactor == 0) + { + Marshal.GetNativeVariantForObject(zoom_to_Fit, vOut); + } + else + { + string factorString = currentZoomFactor.ToString("P0", numberFormatInfo); + Marshal.GetNativeVariantForObject(factorString, vOut); + } + + } + else if (input != null) + { + // new zoom value was selected or typed in + string inputString = input.ToString(); + + if (inputString.Equals(zoomToFit) || inputString.Equals(zoom_to_Fit)) + { + currentZoomFactor = 0; + ShowMessage(Resources.MyDynamicCombo, zoom_to_Fit); + } + else + { + // There doesn't appear to be any percent-parsing routines in the framework (even though you can create + // a localized percentage in a string!). So, we need to remove any occurence of the localized Percent + // symbol, then parse the value that's left + try + { + float newZoom = Single.Parse(inputString.Replace(NumberFormatInfo.InvariantInfo.PercentSymbol, ""), CultureInfo.CurrentCulture); + + newZoom = (float)Math.Round(newZoom); + if (newZoom < 0) + { + throw (new ArgumentException(Resources.ZoomMustBeGTZero)); // force an exception to be thrown + } + + currentZoomFactor = newZoom / (float)100.0; + + ShowMessage(Resources.MyDynamicCombo, newZoom.ToString(CultureInfo.CurrentCulture)); + } + catch (FormatException) + { + // user typed in a non-numeric value, ignore it + } + catch (OverflowException) + { + // user typed in too large of a number, ignore it + } + } + } + else + { + // We should never get here + throw (new ArgumentException(Resources.InOutParamCantBeNULL)); // force an exception to be thrown + } + } + else + { + // We should never get here; EventArgs are required. + throw (new ArgumentException(Resources.EventArgsRequired)); // force an exception to be thrown + } + } private void OnMenuMyDynamicComboGetList(object sender, EventArgs e) { @@ -470,52 +472,53 @@ private void OnMenuMyDynamicComboGetList(object sender, EventArgs e) throw (new ArgumentNullException(Resources.EventArgsRequired)); // force an exception to be thrown } - OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs; - - if (eventArgs != null) - { - object inParam = eventArgs.InValue; - IntPtr vOut = eventArgs.OutValue; - - if (inParam != null) - { - throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown - } - else if (vOut != IntPtr.Zero) - { - // initialize the zoom value array if needed - if (zoomLevels == null) - { - numberFormatInfo = (NumberFormatInfo)CultureInfo.CurrentUICulture.NumberFormat.Clone(); - if (numberFormatInfo.PercentPositivePattern == 0) - numberFormatInfo.PercentPositivePattern = 1; - if (numberFormatInfo.PercentNegativePattern == 0) - numberFormatInfo.PercentNegativePattern = 1; - - zoomLevels = new string[numericZoomLevels.Length + 1]; - for (int i = 0; i < numericZoomLevels.Length; i++) - { - zoomLevels[i] = numericZoomLevels[i].ToString("P0", numberFormatInfo); - } - - zoomLevels[zoomLevels.Length - 1] = zoom_to_Fit; - } - - Marshal.GetNativeVariantForObject(zoomLevels, vOut); - } - else - { - throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown - } - } - } + if (e is OleMenuCmdEventArgs eventArgs) + { + object inParam = eventArgs.InValue; + IntPtr vOut = eventArgs.OutValue; + + if (inParam != null) + { + throw (new ArgumentException(Resources.InParamIllegal)); // force an exception to be thrown + } + else if (vOut != IntPtr.Zero) + { + // initialize the zoom value array if needed + if (zoomLevels == null) + { + numberFormatInfo = (NumberFormatInfo)CultureInfo.CurrentUICulture.NumberFormat.Clone(); + if (numberFormatInfo.PercentPositivePattern == 0) + numberFormatInfo.PercentPositivePattern = 1; + if (numberFormatInfo.PercentNegativePattern == 0) + numberFormatInfo.PercentNegativePattern = 1; + + zoomLevels = new string[numericZoomLevels.Length + 1]; + for (int i = 0; i < numericZoomLevels.Length; i++) + { + zoomLevels[i] = numericZoomLevels[i].ToString("P0", numberFormatInfo); + } + + zoomLevels[zoomLevels.Length - 1] = zoom_to_Fit; + } + + Marshal.GetNativeVariantForObject(zoomLevels, vOut); + } + else + { + throw (new ArgumentException(Resources.OutParamRequired)); // force an exception to be thrown + } + } + } #endregion // Helper method to show a message box using the SVsUiShell/IVsUiShell service - public void ShowMessage(string title, string message) - { + public async void ShowMessage(string title, string message) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); - Guid clsid = Guid.Empty; + Assumes.Present(uiShell); + Guid clsid = Guid.Empty; int result = VSConstants.S_OK; int hr = uiShell.ShowMessageBox(0, ref clsid, diff --git a/Combo_Box/C#/packages.config b/Combo_Box/C#/packages.config deleted file mode 100644 index 2181d95c..00000000 --- a/Combo_Box/C#/packages.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Combo_Box/Readme.md b/Combo_Box/Readme.md index f5f561e7..8cbae4e5 100644 --- a/Combo_Box/Readme.md +++ b/Combo_Box/Readme.md @@ -2,7 +2,7 @@ Add a toolbar to Visual Studio that has four different kinds of dropdown combo boxes. -* Technologies: Visual Studio 2017 SDK +* Technologies: Visual Studio 2019-2022 SDK * Topics: Visual Studio Editor, VSX @@ -32,7 +32,7 @@ There are four styles of Combo Boxes: **Requirements** -[ Visual Studio 2017 ](https://www.visualstudio.com/products/visual-studio-community-vs?wt.mc_id=o~display~github~vssdk) +[ Visual Studio 2019 or VS2022 ](https://visualstudio.microsoft.com/downloads/)