How to add additional tool windows to a Visual Studio Extension? - c#

When creating an Extension for Visual Studio 2013 a tool window gets set up by default. However, I'd like to have a second tool window and can't see how one is supposed to go about that.

I have created a guide:
HOWTO: Create a toolwindow with a ToolWindowPane class in a Visual Studio package
http://www.visualstudioextensibility.com/2015/02/20/mz-tools-articles-series-howto-create-a-toolwindow-with-a-toolwindowpane-class-in-a-visual-studio-package/

Well I just found a few things - so I'm gonna answer my own question so that other people having the same problem may take advantage of it:
Set up your extension as in this tutorial but check "Tool Window"
Create a new UserControl for the ToolWindow "ToolWindow2Control" and copy paste the contents of ToolWindowControl.xaml & ToolWindowControl.xaml.cs accordingly
Add a class "ToolWindow2" and copy paste the contents from ToolWindow.cs. Change the GUID to a new one (Tools->Create GUID)
In NameOfYourProject.vsct add the code for displaying a second entry in View->Other Windows by duplicating the Button found in the Buttons section. Change the ButtonText, the priority, the id of the Button and the id of the Icon.
Add the id of the Button to the entries under Symbols on the bottom of the page. It should be a third entry under guidNameOfYourProjectCmdSet.
Open PkgCmdID.cs (or PkgCmdIDList.cs) and add the id of the Button there as well, e.g.
public const uint cmdidMyTool2 = 0x102;
Add another icon to your project / resources. Then add another Bitmap entry in the Bitmaps section of NameOfYourProject.vsct with the GUID-id that you previously gave the Icon. Like so:
<Bitmap guid="guidImages2" href="Images\test.ico" usedList="testIcon"/>
And create another GuidSymbol entry in the Symbols section with a new GUID and a single IDSymbol entry which has the same name as the one you used in the usedList, like so:
<GuidSymbol name="guidImages2" value="{7BC1F97F-2693-4186-91CC-A35AE95886CE}" >
<IDSymbol name="testIcon" value="1" />
</GuidSymbol>
Add this line to NameOfYourProjectPackage.cs:
[ProvideToolWindow(typeof(ToolWindow2))]
In NameOfYourProjectPackage.cs edit the Initialize method by copy-pasting the 3 lines under // Create the command for the tool window beneath it. In the first line use the id we gave in step #6 (cmdidMyTool2). In the 2nd line use a new MenuCommand Event handler ShowToolWindow2. And change the variable names.
Create a new method ShowToolWindow2. Copy paste from the ShowToolWindow method and change the typeof in the first line to ToolWindow2
This should be it. I hope I haven't forgot anything. You can then open the two windows under Views->Other Windows

Related

How to create a custom cursor in C# UWP with CoreCursorType.Custom?

As far as I know "Cursor" don't exits in UWP.
I can change cursor with this code:
Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0);
How do I create a custom cursor with CoreCursorType.Custom?
CoreCursorType.Custom
You should create your own cursor *.res resource file and contains the custom cursor to your project by add it to your package.manifest file. After that, you can use CoreCursorType.Custom enumeration option, and specify the Id of the custom cursor to use the custom cursor. There also have a thread in which #Azat Tazayan has introduced the detailed steps to implement it and you can refer to it:
https://social.msdn.microsoft.com/Forums/en-US/14001796-bcd5-4b9d-9d7e-13bc6ba59d2d/uwp-how-to-set-a-pointer-cursor-as-a-circle-instead-of-a-window-default-cursor?forum=wpdevelop
Here is the answer
https://learn.microsoft.com/en-us/uwp/api/windows.ui.core.corecursor?view=winrt-20348
To use a custom cursor, use the CoreCursorType.Custom enumeration
option, and specify the Id of the custom cursor. You can add a .res
resource file that contains the custom cursor to your project and
include it in your assembly with the /win32res compiler option. The Id
is the Cursor Resource ID specified in the .res file.
Personally I have used this working manual
https://social.msdn.microsoft.com/Forums/en-US/14001796-bcd5-4b9d-9d7e-13bc6ba59d2d/uwp-how-to-set-a-pointer-cursor-as-a-circle-instead-of-a-window-default-cursor?forum=wpdevelop
We need just proper .res file
For that we should do following
Create any C++ project. For example Dll, Add new C++ Dll project name it for example as ResourcesComponent.
Add a resource file to the project. [right-mouse] the project name "ResourcesComponent" => Add New Item => Visual C++ => Resource File (.rc)
Name the resource file for example Resources.rc
Add a cursor resource. Double click on Resources.rc the it will open in Resource View tab then Right click on "Resources.rc" => Add Resource => Cursor => New (Here you can modify cursor appearance by pen)
Go back to solution explorer and now you will see resource.h file where you can find its id
#define IDC_CURSOR1 101
Build dll in Release mode
In Release sub folder you can find Resource.res file
Now we have proper .res file, We should add it to our UWP project root folder.
Copy Resource.res file to UWP project root directory. (You can delete DLL project as it is no longer needed )
Unload UWP project in VS.
Rigth click on unloaded project and select edit .csproj
in first or second PropertyGroup (where is Appname, TargetPlatform, etc ) add
<PropertyGroup>
.....
<Win32Resource>Resource.res</Win32Resource>
</ PropertyGroup>
Reload project
Use following code for set cursor in your image PointerEnter event handler
Window.Current.CoreWindow.PointerCursor =
new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.Custom, 101);
If you need to create a colorized *.cur file use any free tools like I did here. And just replace the source *.cur with a new one.
And if you need a small *.cur file just remember that by default its size is 32 x 32 pixels and you have draw your small image like I did.
Enjoy!

Xamarin.Android Material Design Icons

A bit of context:
I was looking into the Material Design Support Library for Xamarin and found this article about various controls from this library.
I tried to reproduce the Toolbar from the last example (for now I'm not even thinking about implementing the whole hamburger navigation example, just the toolbar with the button). I set it up, created MyTheme with my colors, added the fixes for style-v21 and so on. Everything works well so far, though the <include ... /> node throws a warning that it's not a recognized child for RelativeLayout. Still, it's building correctly so I can deal with it for the most part.
The problem:
Here's where my problem starts:
...
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.main_layout);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar (toolbar);
//Enable support action bar to display hamburger
SupportActionBar.SetHomeAsUpIndicator (Resource.Drawable.ic_menu);
SupportActionBar.SetDisplayHomeAsUpEnabled (true);
...
With the SupportActionBar set up like that, it doesn't display the button. Also, the ic_menu drawable seems to be missing. In fact, there aren't any that start with ic_, only abc_.
Am I missing something here?
Cheers!
Go to https://material.io/icons/ and download menu icon and then add that icon to the drawable folder and then replace ic_menu in your code with the image name.
NOTE: Do not add image extension name like .jpg,.png with image name

Changing "Color theme" within a Visual Studio Extension

I'm writing a Visual Studio extension in C# that I hope will change the color theme depending on the time of day (After sunset the dark theme will be applied - at sunrise either the blue/light theme will be applied depending on the users preference).
I'm able to change the color theme using the WriteableSettingsStore exposed by a ShellSettingsManager object. When I execute the following code, the theme changes after restarting Visual Studio.
var settingsManager = new ShellSettingsManager(this);
var writeableUserStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);
writeableUserStore.SetString("General", "CurrentTheme", GuidList.guidDarkTheme);
What I'd prefer is to have the theme update automatically - I've tried making use of the UpdateWindow and RedrawWindow functions of the User32 API, but the window doesn't reload.
So the question is - How do I "redraw" Visual Studio after changing the CurrentTheme property in the registry?
ShellSettingsManager enables you to access and modify Visual Studio settings but only in the Windows registry. Any changes you make will not be picked up by Visual Studio until it is restarted because VS reads settings from the registry only when it starts. So this is the wrong approach.
To both change settings and apply them without requiring a restart, you will have to use DTE2.Properties as discussed in here. The following code snippet shows all the settings that can be changed programmatically from the Environment/General page (this is where you can change the theme):
EnvDTE.Properties generalProps = dte2Obj.Properties["Environment", "General"];
for (int i = 1; i <= generalProps.Count; ++i)
{
System.Diagnostics.Debug.WriteLine(
generalProps.Item(i).Name + ": " + generalProps.Item(i).Value);
}
By default in VS2013, this code will produce the following output:
AnimationSpeed: 5
RichClientExperienceOptions: 65535
WindowMenuContainsNItems: 10
CloseButtonActiveTabOnly: True
UseTitleCaseOnMenu: False
AutoAdjustExperience: True
Animations: True
AutohidePinActiveTabOnly: False
ShowStatusBar: True
MRUListContainsNItems: 10
All of these settings can be changed and VS will immediately apply the changes. The problem is that there is no property that enables you to change the theme. That's why I think it cannot be done.
Here's the simplest way to do it:
Overview:
Use the "Import & Export Settings" feature to create two files:
DarkTheme.vssettings and LightTheme.vssettings
Programmatically invoke the Tools.ImportandExportSettings command to import those files at the appropriate time.
Details:
To create the two settings files:
Launch Visual Studio and set the theme to "Light" through the UI
From the Tools menu select "Import and Export Settings..."
In the wizard, select "Export selected environment settings" and click "Next"
In the "Which settings do you want to export?" page, deselect everything except "Options/Fonts and Colors" and click "Next"
Name this file "Light.vssettings" and save it in a known location.
Repeat steps 1 through 5 for the "Dark" theme, naming the file "Dark.vssettings".
To import these files programmatically use DTE.ExecuteCommand with the "/import" parameter like this:
Add a reference to EnvDTE.dll if you don't have it already.
var dte = GetService(typeof(EnvDTE._DTE)) as EnvDTE.DTE;
dte.ExecuteCommand("Tools.ImportandExportSettings", #"/import:""C:\yourpath\LightTheme.vssettings""");
I hope that helps.

Form Regions for Outlook and VSTO remove WebViewPane

I have just purchased: http://www.add-in-express.com/outlook-regions/
The reason why I have purchased that product is because I need to show a custom form on the main view of outlook when a specific folder is selected. I have managed to do so by doing the following:
Create a new Project int visual studio of type (Outlook 2010 Add-in)
Once that project is created I add:
Because I want that form to show on the main folder view of mail (replace all other views) I select this option:
I click next and follow all the defaults in order to create the form.
Once that form is created I add the buttons and images I need. In this example I will just add a button.
when I then run outlook and select my inbox folder this is what shows up:
(In other words every time I select a folder of type olMailItem that form shows up)
So now I solve my goal to display my custom form on the "main view of outlook"
Now my question is how can I show that form only on specific folders. For example I do not want to show that form when the folder "Inbox" is selected but I do want to show it when the folder "Outbox" is selected for example
Let's try to hide the form and show the default view when the button is clicked.
In order to solve that problem I have looked at: http://www.add-in-express.com/forum/read.php?FID=5&TID=4540
I have done the same steps but the form shows up again! In other words the code behind of the button looks like:
private void button1_Click(object sender, EventArgs e)
{
// get current folder in this case its inbox the one that is selected
MAPIFolder currentFolder = Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder;
Globals.ThisAddIn.ADXOlForm1Item.FolderName = string.Empty;
// clear web properties DO NOT SHOW WEB VIEW
currentFolder.WebViewURL = string.Empty;
currentFolder.WebViewOn = false;
// RESET FOLDER BY SELECTING A DIFFERENT ONE THEN THE SAME ONE
NameSpace nameSpace = Globals.ThisAddIn.Application.GetNamespace("MAPI");
MAPIFolder outboxFolder = nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderOutbox);
Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder = outboxFolder; // CHANGE FOLDER TO A DIFFERNT ONE
System.Windows.Forms.Application.DoEvents();
Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder = currentFolder; // SET INBOX AGAIN
}
when I run that code the default view shows up for 1 second then it get's replaced with the form!
-------------------------------------------Edit-------------------------------------------
When I add the form region Addin Express adds a ADXOlFormsManager and a ADXOlFormsCollectionItem for the form that I created. Based on your answer I have done:
#region ADXOlForm1
// TODO: Use the ADXOlForm1Item properties to configure the region's location, appearance and behavior.
// See the "The UI Mechanics" chapter of the Add-in Express Developer's Guide for more information.
ADXOlForm1Item = new ADXOlFormsCollectionItem();
ADXOlForm1Item.FolderName = "MyCustomFolder"; // <---- ADDED THIS LINE HOPING TO SHOW THIS FORM ONLY WHEN THAT FOLDER IS SELECTED
ADXOlForm1Item.ExplorerLayout = ADXOlExplorerLayout.WebViewPane;
ADXOlForm1Item.ExplorerItemTypes = ADXOlExplorerItemTypes.olMailItem;
ADXOlForm1Item.UseOfficeThemeForBackground = true;
ADXOlForm1Item.FormClassName = typeof(ADXOlForm1).FullName;
this.FormsManager.Items.Add(ADXOlForm1Item);
#endregion
I was hoping for that form to only show up in MyCustomFolder but it does shows up when selecting any folder of type ADXOlExplorerItemTypes.olMailItem. Perhaps I am doing something wrong....
In other words I was hoping for only the MAPIFolder MyCustomFolder folder had the properties
WebViewOn=true;
WebViewURL = "...AppData\Local\Temp\AddinExpress\ADXOlFormGeneral.html"
but as I traverse all the folders in outlook I can see that all of them have those properties even after specifying ADXOlForm1Item.FolderName = "MyCustomFolder";
Thank you for choosing Add-in Express Regions.
I understand the "main view of outlook" as the folder that Outlook shows when it is started. By default, that folder is the top-level folder of the message store. Note that this can be changed, see File | Options | Advanced | Start Outlook in this folder. I use this setting so that my Outlook shows me the Inbox at start-up.
The below is a citation from the section Context-Sensitivity of Your Outlook Form, see see the PDF file in the folder {Add-in Express}\Docs\ on your development PC:
ADXOlFormsCollectionItem provides a number of properties that allow specifying the context settings for your form. Say, you can specify item types for which your form will be shown. Note that in case of explorer, the item types that you specify are compared with the default item type of the current folder. In addition, you can specify the names of the folders for which your form will be shown in the FolderName and FolderNames properties; these properties also work for Inspector windows – in this case, the parent folder of the Outlook item is checked. An example of the folder path is "\Personal Folders\Inbox".
A special value in FolderName is an asterisk ('*'), which means "all folders". You can also specify message class(es) for which your form will be shown. Note that all context-sensitivity properties of an ADXOlFormsCollectionItem are processed using the OR Boolean operation. That is, specifying e.g. folder names extends, but not limits, the list of contexts for which your form will be shown.
That is, if you need to show the form for a given folder, specify the path to that folder in the FolderName/*FolderNames* property.
Regards from Belarus (GMT+3),
Andrei Smolin, Add-in Express Team Leader

How do I cast an icon from a resource file to an image for use on a button?

I'm trying to use an icon that I've added as a resource as the image on a button. I know it's possible because I can do it in other projects through the designer. However, I'm trying to do this with code. I added the icon as a resource to my project by following the steps in the accepted answer to this question. The resource is named CancelButtonIcon.
Now, I'm trying to add that icon as the image on a standard button with this code:
this.CancelButton.Image = (System.Drawing.Image)Properties.Resources.CancelButtonIcon;
However, I get an error message:
Cannot convert type 'System.Drawing.Icon' to 'System.Drawing.Image'
In the code that Visual Studio automatically generates when I use the designer, it looks like this:
((System.Drawing.Image)(resources.GetObject("SaveButton.Image")));
which results from manually adding a resource through the Properties window. How can I convert this icon resource to an image so it can be used on the button? Adding it through the designer is not an option (this button is created programmatically and thus isn't present in the designer).
You can use the Icon.ToBitmap method for this purpose. Note that a Bitmap is an Image.
CancelButton.Image = Properties.Resources.CancelButtonIcon.ToBitmap();
Not sure why, but any time I tried using the accepted answer's approach, the .ToBitmap() call was giving me array index out of bounds exceptions. I solved this by doing it this way instead:
System.Drawing.Icon.FromHandle(Properties.Resources.CancelButtonIcon.Handle).ToBitmap();

Categories