Hide Properties/Toolbox Pane when not in Resource View? - visual-studio

Every time I view a form or dialog in Visual Studio (2005) the Properties and Toolbox panes show up on the right side of my screen. That's good to have because they are useful for manipulating dialogs.
However once I switch back to source code these panes just get in the way... is there a way to get them to go away automatically?

I've done something recently in VS2010 using a macro that shows and hides the Tools panel when switching back and forth from code to design view in asp.net MVC3 views. It could be easily adapted to do the same for your situation I think.
This goes in the EnvironmentEvents class file in in the VS Macro IDE after the pre-generated content.
<System.ContextStaticAttribute()> Public WithEvents CommandEvents As EnvDTE.CommandEvents
Public Sub DTEEvents_OnMacrosRuntimeReset() Handles _
DTEEvents.OnMacrosRuntimeReset
CommandEvents = DTE.Events.CommandEvents
End Sub
Private Sub DTEEvents_OnStartupComplete() Handles _
DTEEvents.OnStartupComplete
CommandEvents = DTE.Events.CommandEvents
End Sub
Public Sub CommandEvents_AfterExecute( _
ByVal Guid As String, _
ByVal ID As Integer, _
ByVal CustomIn As Object, _
ByVal CustomOut As Object) _
Handles CommandEvents.AfterExecute
If DTE.Commands.Item(Guid, ID).Name = "View.ViewDesigner" Then
DTE.ExecuteCommand("View.Toolbox")
End If
If DTE.Commands.Item(Guid, ID).Name = "View.ViewMarkup" Then
DTE.Windows.Item(Constants.vsWindowKindToolbox).Close()
End If
End Sub
It could probably be better optimized using the guids of the event rather than the if statements. It works when you use the hot keys for switching views as well as the view menu, but not the context menu.

for vs2015:
Menu > Tools > Extensions and Updates
install "Visual Commander". (Now you have New Menu called "VCmd")
Menu > "VCmd" > Extensions ... (You will see an Extensions Pane At Right)
Press Add Button at the Extensions Pane. (New tab Wİndow will open.)
write a name for extention.
select language as C#.
paste the code below:
Press Save. Then Press Compile. Then Press Install
using EnvDTE;
using EnvDTE80;
public class E : VisualCommanderExt.IExtension
{
private EnvDTE80.DTE2 DTE;
private EnvDTE.WindowEvents windowEvents;
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) {
this.DTE = DTE;
DTE.Events.WindowEvents.WindowActivated += OnWindowActivated;
}
public void Close() {
// i read somewhere this has to be done on close.
// but it gives gives me error on every IDE close. so i commented it .
//DTE.Events.WindowEvents.WindowActivated -= OnWindowActivated;
}
private void OnWindowActivated(Window gotFocus, Window lostFocus) {
HidePropertiesWindowInCodeOrTextView(gotFocus );
}
public void HidePropertiesWindowInCodeOrTextView(Window gotFocus ) {
if (gotFocus.Document == null) return;
var pwin = DTE.Windows.Item(Constants.vsWindowKindProperties);
pwin.AutoHides = !gotFocus.Caption.EndsWith(" [Design]") ;
}
}

Rather than give up the space on the right side of the screen, I dragged my properties and toolbox panes over to the left-side frame that hosts the solution explorer and class view, etc. I'd rather have one multi-purpose box on one side of the screen than to have the code surrounded. If you need them both, you can put the toolbox in the solution explorer pane, then stack the properties pane beneath the solution explorer, which keeps a few properties in view at all times along with the toolbox.
I know it's not quite the answer you were looking for, but it's a different way of keeping that screen real estate available for code without messing with auto-hide (I find auto-hide to be really an annoyance more than a help.)

For vs2019:
I improve bh_earth0's solution. Now it saves visibility states of Properties and ToolBox when you jump to code. And when design tab is activated it loads previous state of panes.
Menu > Extensions > Manage Extensions
Find and install "Visual Commander". (Now you have New Menu called "VCmd")
Menu > "VCmd" > Extensions ... (You will see an Extensions Pane At Right)
Press Add Button at the Extensions Pane. (New tab Wİndow will open.)
write a name for extention (e.g. AutoHide).
select language as C#.
copy and paste the code below:
Press Save. Then Press Compile. Then Press Install
Restart the Visual Studio and enjoy :-)
using EnvDTE;
using EnvDTE80;
public class E : VisualCommanderExt.IExtension
{
private EnvDTE80.DTE2 DTE;
private EnvDTE.WindowEvents windowEvents;
private bool bPropWinVisible = false;
private bool bToolWinVisible = false;
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) {
this.DTE = DTE;
DTE.Events.WindowEvents.WindowActivated += OnWindowActivated;
}
public void Close() {
}
private void OnWindowActivated(Window gotFocus, Window lostFocus) {
if (gotFocus.Document == null) return;
if (lostFocus.Document == null) return;
var pwin = DTE.Windows.Item(Constants.vsWindowKindProperties);
var twin = DTE.Windows.Item(Constants.vsWindowKindToolbox);
if(gotFocus.Caption.EndsWith(".cs [Design]") && lostFocus.Caption.EndsWith(".cs") ) {
pwin.AutoHides = bPropWinVisible;
twin.AutoHides = bToolWinVisible;
}
else if(gotFocus.Caption.EndsWith(".cs") && lostFocus.Caption.EndsWith(".cs [Design]")) {
bPropWinVisible = pwin.AutoHides;
bToolWinVisible = twin.AutoHides;
pwin.AutoHides = true;
twin.AutoHides = true;
}
}
}

If you click the 'pin' icon on those tool windows, you can toggle whether the windows stay open all the time, or only when the mouse is near them. Of course, sometimes my mouse strays over in that direction and they pop out when I don't want them to, but such is life...

Related

Visual Studio - Keyboard Shortcut to close Solution Explorer

CtrlAltL Opens Solution Explorer in Visual Sutdio.
But I'm unable to close it with the same keyboard shortcut.
As I need to do this often (to get more real estate on the screen), how do you close the Solution Explorer with a keyboard shortcut?
You can create the following command with Visual Commander (language: C#) and assign a shortcut to close Solution Explorer:
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
var serviceProvider = package as System.IServiceProvider;
var shell = (Microsoft.VisualStudio.Shell.Interop.IVsUIShell)serviceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Interop.SVsUIShell));
var SolutionExplorer = new System.Guid(Microsoft.VisualStudio.Shell.Interop.ToolWindowGuids80.SolutionExplorer);
Microsoft.VisualStudio.Shell.Interop.IVsWindowFrame frame;
shell.FindToolWindow(0, ref SolutionExplorer, out frame);
frame.Hide();
}
}

How to tell if the active document is a text document?

I'm developing a Visual Studio extension in which one of the implemented commands needs to be available only when the active document is a text document (like e.g. the Visual Studio's "Toggle Bookmark" does). The problem is that I can't figure out how to tell when that's the case.
Right now I have a half working solution. In the package's Initialize method I subscribe to DTE's WindowActivated event, and then whenever a window is activated I check if the window DocumentData property is of type TextDocument:
protected override void Initialize()
{
base.Initialize();
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
dte.Events.WindowEvents.WindowActivated += WindowEventsOnWindowActivated;
//More initialization here...
}
//This is checked from command's BeforeQueryStatus
public bool ActiveDocumentIsText { get; private set; } = false;
private void WindowEventsOnWindowActivated(Window gotFocus, Window lostFocus)
{
if (gotFocus.Kind != "Document")
return; //It's not a document (e.g. it's a tool window)
TextDocument textDoc = gotFocus.DocumentData as TextDocument;
ActiveDocumentIsText = textDoc != null;
}
The problem with this approach is that 1) Window.DocumentData is documented as ".NET Framework internal use only", and 2) this gives a false positive when a document that has both a code view and a design view (e.g. a .visxmanifest file) is open in design mode.
I have tried to use IVsTextManager.GetActiveView as well, but this is returning the last active text view opened - so if I open a .txt file and then a .png file, it returns data for the .txt file even if it's not the active document anymore.
So, how do I check if the active document is a text document, or the code view of a document that can have a designer... and if possible, not using "undocumented" classes/members?
UPDATE: I found a slightly better solution. Inside the window activated handler:
ActiveDocumentIsText = gotFocus.Document.Object("TextDocument") != null;
At least this one is properly documented, but I still have the problem of false positives with designers.
I finally got it. It's somewhat tricky, but it works and is 100% "legal". Here's the recipe:
1- Make the package class implement IVsRunningDocTableEvents. Make all the methods just return VSConstants.S_OK;
2- Add the following field and the following auxiliary method to the package class:
private IVsRunningDocumentTable runningDocumentTable;
private bool DocIsOpenInLogicalView(string path, Guid logicalView, out IVsWindowFrame windowFrame)
{
return VsShellUtilities.IsDocumentOpen(
this,
path,
VSConstants.LOGVIEWID_TextView,
out var dummyHierarchy2, out var dummyItemId2,
out windowFrame);
}
3- Add the following to the Initialize method of the package class:
runningDocumentTable = GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
runningDocumentTable.AdviseRunningDocTableEvents(this, out var dummyCookie);
4- Don't blink, here comes the magic! Implement the IVsRunningDocTableEvents.OnBeforeDocumentWindowShow method as follows:
public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
runningDocumentTable.GetDocumentInfo(docCookie,
out var dummyFlags, out var dummyReadLocks, out var dummyEditLocks,
out string path,
out var dummyHierarchy, out var dummyItemId, out var dummyData);
IVsWindowFrame windowFrameForTextView;
var docIsOpenInTextView =
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_Code, out windowFrameForTextView) ||
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_TextView, out windowFrameForTextView);
//Is the document open in the code/text view,
//AND the window for that view is the one that has been just activated?
ActiveDocumentIsText = docIsOpenInTextView && pFrame == logicalViewWindowFrame;
return VSConstants.S_OK;
}

Add button to the Visual Studio unloaded project context menu (Can't find the CommandBar its name)

NuGet package restore does not play well with the PostSharp package, this is of great annoyance to me and manually editing the csproj files is quickly becoming old.
I want to make a small Visual Studio AddIn that fixes the project for me by adding an extra button to the unloaded project context menu.
The problem I am facing sounds simple but haunts me: I somehow can't locate the CommandBar for the unloaded project context menu.
Thus, summarizing the question: What is the CommandBar name for the unloaded project context menu.
Many thanks!
Apparantly: "Stub Project". Found in the list at: CommandBar names
To sum up the OnConnection method to register this:
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
if (connectMode == ext_ConnectMode.ext_cm_UISetup)
{
object[] contextGUIDS = new object[] { };
Commands2 commands = (Commands2)_applicationObject.Commands;
string toolsMenuName = "Tools";
//Place the command on the tools menu.
//Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];
//Find the Tools command bar on the MenuBar command bar:
CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
CommandBars cmdBars = (CommandBars)(_applicationObject.CommandBars);
CommandBar vsBarProject = cmdBars["Stub Project"];
CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;
//This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
// just make sure you also update the QueryStatus/Exec method to include the new command names.
try
{
//Add a command to the Commands collection:
Command command = commands.AddNamedCommand2(_addInInstance, "FixNuGetPostSharp", "Fix NuGet PostSharp", "Executes the command for VsextensionTest", true, 0, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
//Add a control for the command to the tools menu:
if ((command != null) && (toolsPopup != null))
{
command.AddControl(vsBarProject);
}
}
catch (System.ArgumentException)
{
//If we are here, then the exception is probably because a command with that name
// already exists. If so there is no need to recreate the command and we can
// safely ignore the exception.
}
}
}

C# - Is there any OnShapeMoved or OnShapeDeleted event in Visio?

I think the title or the question is clear enough. I saw something about the EventSink, but I found it difficult to use. Any hint?
The Visio Primary Interop Assembly exposes these events as C# events therefore you can simply hook the event with a delegate.
See this simple example:
namespace VisioEventsExample
{
using System;
using Microsoft.Office.Interop.Visio;
class Program
{
public static void Main(string[] args)
{
Application app = new Application();
Document doc = app.Documents.Add("");
Page page = doc.Pages[1];
// Setup event handles for the events you are intrested in.
// Shape deleted is easy.
page.BeforeShapeDelete +=
new EPage_BeforeShapeDeleteEventHandler(onBeforeShapeDelete);
// To find out if a shape has moved hook the cell changed event
// and then check to see if PinX or PinY changed.
page.CellChanged +=
new EPage_CellChangedEventHandler(onCellChanged);
// In C# 4 for you can simply do this:
//
// page.BeforeShapeDelete += onBeforeShapeDelete;
// page.CellChanged += onCellChanged;
// Now wait for the events.
Console.WriteLine("Wait for events. Press any key to stop.");
Console.ReadKey();
}
// This will be called when a shape sheet cell for a
// shape on the page is changed. To know if the shape
// was moved see of the pin was changed. This will
// fire twice if the shape is moved horizontally and
// vertically.
private static void onCellChanged(Cell cell)
{
if (cell.Name == "PinX" || cell.Name == "PinY")
{
Console.WriteLine(
string.Format("Shape {0} moved", cell.Shape.Name));
}
}
// This will be called when a shape is deleted from the page.
private static void onBeforeShapeDelete(Shape shape)
{
Console.WriteLine(string.Format("Shape deleted {0}", shape.Name));
}
}
}
If you haven't already downloaded the Visio SDK you should do so. Recent versions of the SDK it contains many useful examples include one called "Shape Add\Delete Event". If you have the 2010 version can browse the examples by going to Start Menu\Programs\Microsoft Office 2010 Developer Resources\Microsoft Visio 2010 SDK\Microsoft Visio Code Samples Library.
I believe that you have to implement EvenSink to get access to "ShapesDeleted", i.e.
(short)Microsoft.Office.Interop.Visio.VisEventCodes.visEvtCodeShapeDelete
the code above will help you if you are looking for the event "BeforeShapeDelete" not the "after"ShapeDelete ;)

Display a message in Visual Studio's output window when not debug mode?

In Java, you can use System.out.println(message) to print a message to the output window.
What's the equivalent in Visual Studio ?
I know when I'm in debug mode I can use this to see the message in the output window:
Debug.WriteLine("Debug : User_Id = "+Session["User_Id"]);
System.Diagnostics.Trace.WriteLine("Debug : User_Id = "+Session["User_Id"]);
How can this be done without debugging in Visual Studio?
The results are not in the Output window but in the Test Results Detail (TestResult Pane at the bottom, right click on on Test Results and go to TestResultDetails).
This works with Debug.WriteLine and Console.WriteLine.
The Trace messages can occur in the output window as well, even if you're not in debug mode.
You just have to make sure the the TRACE compiler constant is defined.
The Trace.WriteLine method is a conditionally compiled method. That means that it will only be executed if the TRACE constant is defined when the code is compiled. By default in Visual Studio, TRACE is only defined in DEBUG mode.
Right Click on the Project and Select Properties. Go to the Compile tab. Select Release mode and add TRACE to the defined preprocessor constants. That should fix the issue for you.
This whole thread confused the h#$l out of me until I realized you have to be running the debugger to see ANY trace or debug output. I needed a debug output (outside of the debugger) because my WebApp runs fine when I debug it but not when the debugger isn't running (SqlDataSource is instantiated correctly when running through the debugger).
Just because debug output can be seen when you're running in release mode doesn't mean you'll see anything if you're not running the debugger. Careful reading of Writing to output window of Visual Studio? gave me DebugView as an alternative. Extremely useful!
Hopefully this helps anyone else confused by this.
For me this was the fact that debug.writeline shows in the Immediate window, not the Output. My installation of VS2013 by default doesn't even show an option to open the Immediate window, so you have to do the following:
Select Tools -> Customize
Commands Tab
View | Other Windows menu bar dropdown
Add Command...
The Immediate option is in the Debug section.
Once you have Ok'd that, you can go to View -> Other Windows and select the Immediate Window and hey presto all of the debug output can be seen.
Unfortunately for me it also showed about 50 errors that I wasn't aware of in my project... maybe I'll just turn it off again :-)
To write in the Visual Studio output window I used IVsOutputWindow and IVsOutputWindowPane. I included as members in my OutputWindow class which look like this :
public class OutputWindow : TextWriter
{
#region Members
private static readonly Guid mPaneGuid = new Guid("AB9F45E4-2001-4197-BAF5-4B165222AF29");
private static IVsOutputWindow mOutputWindow = null;
private static IVsOutputWindowPane mOutputPane = null;
#endregion
#region Constructor
public OutputWindow(DTE2 aDte)
{
if( null == mOutputWindow )
{
IServiceProvider serviceProvider =
new ServiceProvider(aDte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
mOutputWindow = serviceProvider.GetService(typeof(SVsOutputWindow)) as IVsOutputWindow;
}
if (null == mOutputPane)
{
Guid generalPaneGuid = mPaneGuid;
mOutputWindow.GetPane(ref generalPaneGuid, out IVsOutputWindowPane pane);
if ( null == pane)
{
mOutputWindow.CreatePane(ref generalPaneGuid, "Your output window name", 0, 1);
mOutputWindow.GetPane(ref generalPaneGuid, out pane);
}
mOutputPane = pane;
}
}
#endregion
#region Properties
public override Encoding Encoding => System.Text.Encoding.Default;
#endregion
#region Public Methods
public override void Write(string aMessage) => mOutputPane.OutputString($"{aMessage}\n");
public override void Write(char aCharacter) => mOutputPane.OutputString(aCharacter.ToString());
public void Show(DTE2 aDte)
{
mOutputPane.Activate();
aDte.ExecuteCommand("View.Output", string.Empty);
}
public void Clear() => mOutputPane.Clear();
#endregion
}
If you have a big text to write in output window you usually don't want to freeze the UI. In this purpose you can use a Dispatcher. To write something in output window using this implementation now you can simple do this:
Dispatcher mDispatcher = HwndSource.FromHwnd((IntPtr)mDte.MainWindow.HWnd).RootVisual.Dispatcher;
using (OutputWindow outputWindow = new OutputWindow(mDte))
{
mDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
outputWindow.Write("Write what you want here");
}));
}

Resources