Alternative to TextViewCreated such as (TextViewChanged)? - c#

I am creating a small Visual Studio 2010 extension in C# which uses the IWpfTextViewCreationListener and TextViewCreated to capture when a new TextView is opened in the VS environment. The problem I am having is that this method only fires when a new window is opened via the VS Solution Explorer window, and not fired when VS already contains opened windows when started, and switching window tabs. I have tried looking for something like TextViewChanged, but could not find such method. Is there anyway to capture the new TextView when another tabbed window is selected?
Any help would be greatly appreciated.
This question has also been posted on the MSDN VS Extensibility forum:
VSX 2010 - Alternative to TextViewCreated such as (TextViewChanged)?
Thanks
John

There is no TextViewCreated, but if you register to IWpfTextView.GotAggregateFocus as it is created, you get a hook to every switch between files:
public void TextViewCreated(IWpfTextView textView)
{
textView.GotAggregateFocus += TextViewCameToFocus;
// Do stuff when a new IWpfTextView is created...
}
void TextViewCameToFocus(object sender, EventArgs e)
{
var focusedTextView = (IWpfTextView)sender;
// Do stuff when a specific IWpfTextView comes to focus...
}
You may also want to keep track of the IWpfTextView objects, if you want to be able to link between the fired events to your logic of each textview.

Related

How Do You Edit a Second (Non-Main) C# Form Window In Visual Studio Designer?

I am writing a C# Windows Forms program in Visual Studio. I have a button that creates and shows (opens) a new Form (window) called VideoWindow. I can edit the MainWindow in the Design workspace in Visual Studio which allows me to visually edit its contents. However, I can't find a way to do the same thing with the VideoWindow. I have tried right clicking on VideoWindow and clicking View Designer, but it just takes me to the MainWindow designer. How do I open the designer for the second VideoWindow? Is this possible? Below is the code that creates and opens the new form:
private void ButtonWindow(object sender, EventArgs e)
{
Form VideoWindow = new Form();
VideoWindow.Size = new Size(500, 300);
VideoWindow.Show();
}
Edit: I know you can (and usually should) access the Designer when you create a form through the Visual Studio wizard via Project -> Add Form. However my question was for if you manually write a form class like NewForm.cs. In that case there would be no auto-generated NewForm.Designer.cs file.
You can customize a new form, and then create the corresponding object after modification. Here are the relevant steps:
1.Create a new form videoform
2.Relevant code:
.Show(); and .ShowDialog();
Note the difference between the two.
private void button1_Click(object sender, EventArgs e)
{
VideoWindow videoWindow = new VideoWindow();
videoWindow.Show();
//videoWindow.ShowDialog();
}
3.Ouput:
After some testing I found that it is possible to access the Visual Studio GUI-based Designer for a form class that was created manually (i.e. not created through the usual Project -> Add Form wizard).
If you create a CustomForm.cs file in your project and, importantly, have that class inherit from Form (System.Windows.Forms), then hit Shift F7, Visual Studio will make a GUI Designer for that form.
It will also automatically create the InitializeComonent method in CustomForm.cs and add the SuspendLayout and ResumeLayout calls and Client size, and Name properties in that method.
In this arrangement, the designer elements will not be separated from the class definitions in a separate form.Designer.cs file like usual. Any change through the Designer GUI will directly effect CustomForm.cs. Of course this is less than ideal because there's a higher likelihood of a developer breaking the form since the auto-generated code is mixed in with the manually written code.

Minimizing an application into tray [duplicate]

I am finished making my application and now I want to incorporate " minimizing into the system tray feature " for it . I read up a good article minimize app to system tray . I realized that these make use of the Windows.Form class .
Unfortunately I have used Windows Presentation Foundation WPF reference to make my applications UI . Now I see that the NotifyIcon is not supported in WPF. I see that there is an open source library on CodePlex that simulates the NotifyIcon properties WPF Contrib I have not used it as yet .
Now I am in a fix . Here are my questions :-
a) I don't want to incorporate a 3'rd party library just for one single component .
b) Can I do the minimizing feature without NotifyIcon on WPF? If yes then how can someone give me leads please ?
Or maybe I should revert my UI back to using Windows Forms ?
If you'll reconsider your reluctance to using an external component, I recommend WPF NotifyIcon. I've used it. It's straightforward and works well.
It does not just rely on the corresponding WinForms component, but is a purely independent control which leverages several features of the WPF framework in order to display rich tooltips, popups, context menus, and balloon messages.
I just came across this post today.
For reference, I also solved this some time back. It works very well and the only time I have had a bit of an issue is occasionally on some multi-display set ups.
This was before GITs and NuGets were the in-thing, I will place it in a GIT repo if there is interest.
CodeProject Article Here
Solution with System.Windows.Forms.NotifyIcon
Here is a thread , which helped me a lot .
https://stackoverflow.com/a/12428063/10305444
public partial class Window : System.Windows.Window{
public Window()
{
InitializeComponent();
System.Windows.Forms.NotifyIcon ni = new System.Windows.Forms.NotifyIcon();
ni.Icon = new System.Drawing.Icon("Main.ico");
ni.Visible = true;
ni.DoubleClick +=
delegate(object sender, EventArgs args)
{
this.Show();
this.WindowState = WindowState.Normal;
};
}
protected override void OnStateChanged(EventArgs e)
{
if (WindowState == WindowState.Minimized)
this.Hide();
base.OnStateChanged(e);
}}

How to create navigation inside program Form

Warning! This is noob question probably! Sorry in advance.
I'm learning C# (using MS Studio 2013) and I'm having hard time creating some kind of decent navigation in simple desktop program.
Basically what I want is this: MenuStrip with options like "calculate something", "Calculate somethingelse"... and other (that I can easily add later - like dynamic menu on a webpage). If you click first option inside the Form connected with the StripMenu you will get some controls that allows you to do something(like inputs on a webpage). If you click the second all these options will disappear and you will get a fresh set of controls where you can do somethingelse (simply another webpage to play with).
What is the best way to do it (I find it amazing hard to find out :) ). Only way I figured out (more from experience in js then tutorials) is to use show/hide like in javascript/html.
ExamplePanel.Visible = false;
ExampleOtherPanel.Visible = true;
But this doesn't seem right - I think it would be impossible to manage in bigger program (not only in code, but visual designer too - you can only fit that much Panels inside Form).
Any advice? Or at least a link to material where I can find out?
EDIT:
Finaly I gave up and used multiple Forms as sugested in answer.
private void MenuStripExample_Click_1(object sender, EventArgs e)
{
SomeForm SomeForm = new SomeForm();
this.Hide(); //Hide the main form before showing the secondary
SomeForm.ShowDialog(); //Show secondary form, code execution stop until SomeForm is closed
//this.Show(); //You may uncomment this if you want to have the previous Form to get back after you close new one
}
You normaly don't hide and show panels with different layouts. This is not a good design.
If you have complete different navigations/control sets, then create a new Form which is responsible for the control set.
If you don't want to use new Forms take a look at the TabControl.
You may also want to take a look at MDI-Container. You can use a Form as a MDI-Container and display various other Forms as child-elements inside of this container.

VSTO splash screen or progress bar

I have a project that I'm doing with
Microsoft VSTO (office 2013 excel)
I have certain things that make calls that take maybe 10 seconds to come back.
Ideally I would like to display an progress bar or some status... After a lot of searching I found an article that is titled:
How do I create a splash screen window for the VSTO applications?
http://www.datazx.cn/Fv7p5a/xw/oa2v/2q7xs6/mcccjfti-988m-f8r8-8d44-bstb4rfsi4xm23rsdfd.html
So I started creating this code in a form, but then I realize that I need to call it up within my methods and really attach events etc...
The article says to
"display a modal form on a background thread" What is the best way to do this?
I find it easier to use modal less form on main thread and so far haven't seen any problem with modal less approach. Something like code below
var splashWindow = new SplashWindow();
splashWindow.Show();
splashWindow.SetMessage("Starting please wait...");
DoSomeWork(splashWindow);
splashWindow.Close();
Following you will see a way I programmed a Splash Screen for Excel-VSTO in C#. My Excel file is enabled for macros (.xlsm). These are the steps:
Create your splash screen. Let's assume the name of the form is SplashScreen.
Go to the code of the object ThisWorkbook.cs
Check the code looks like:
public partial class ThisWorkbook
{
SplashScreen SC = new SplashScreen();
private async void ThisWorkbook_Startup(object sender, System.EventArgs e)
{
SC.Show();
await Task.Delay(3500);
SC.Close();
more code...
}
}
It is important that you notice that I added the word async to the subroutine.
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
I hope this is very useful.

Strange Bug with .NET 4.0/4.5 WinForms MenuStrip Stealing Focus

We recently upgraded to VS 2012 which is accompanied by an upgrade to .NET Framework 4.5. This introduces a strange and pesky bug in connection with WinForms MenuStrip control. The same bug also occurs in applications targetting .NET Framework 4.0 as 4.5's installer obviously updates parts of 4.0 as well. Therefore, a perfectly working code pattern is now broken just because of the framework upgrade.
Problem description:
I have a Form1 with a MenuStrip. For one of the drop down items, the event handler opens another Form2 (not neccessarily a child, just another Form). If the user right-clicks into the new Form2 or one of its child controls and this triggers a Show() of a ContextMenuStrip, then the original Form1 pops into foreground again.
This happens independent of all previous other UI actions in Form2. One can resize, move, minimize, maximize Form2, switch between controls, enter text etc. Somehow MenuStrip of Form1 seems to remember that it caused opening of Form2 and grabs focus on first right-click.
I was experimenting with different approaches but was unable to find a workaround so far. The constellation is not uncommon and might affect lots of WinForms applications around. Therefore I decided to post it here since a viable solution might be of general interest. I would be very glad if someone knows a workaround or has at least some clues for me.
I was able to distill it's essence in the following code. It should be reproducible on any machine with .NET 4.5 installed and it occurs when targetting 4.0 and 4.5 each - but not on 3.5 or lower.
using System;
using System.Windows.Forms;
namespace RightClickProblem {
static class Program {
[STAThread]
static void Main() {
// Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup"
var mainMenu = new MenuStrip();
var mainItem = new ToolStripMenuItem("Menu");
mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup));
mainMenu.Items.Add(mainItem);
// Create form with MenuStrip and Show
var form1 = new Form();
form1.Controls.Add(mainMenu);
Application.Run(form1);
}
private static void Popup(object sender, EventArgs e) {
// Create a form with a right click handler and show
var form2 = new Form();
var contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("Just an item...");
form2.ContextMenuStrip = contextMenu;
form2.Show();
// Problem: contextMenu.Show() will give focus to form1
}
}
}
EDIT: I spent some time stepping through .NET Framework source code and found the root cause to be very likely in System.Windows.Forms.ToolStripManager. There, Microsoft is using a message filter to track window activation which is somehow incorrectly implemented for MenuStrip.
In the meantime I also found that Microsoft already adressed this issue in a hotfix (see http://support.microsoft.com/kb/2769674) and hopefully this will find its way into a future update of .NET Framework 4.5.
Unfortunately it is difficult to enforce this hotfix to be applied on all client machines. Therefore a viable workaround would still be greatly appreciated. I myself have been unable so far to find a practical solution...
EDIT#2: The original KB number is for Win8 but there is similar Hotfix for Win7 & Vista under KB 2756203. If somebody can use it, found the hotfix for download here: http://thehotfixshare.net/board/index.php?autocom=downloads&showfile=15569. We tested it and it really fixes the problem. If we find definitely no workaround soon, we'll go with the hotfix.
EDIT#3: Remarks to the accepted solution proposed by spajce
Obviously calling Show() on any ContextMenu will convince the original MenuStrip to forget about its claim on focus. This can be done in a way so that the dummy ContextMenu is not even shown on screen. I found the shortest and most easy to implement way to insert the following snippet in any Form's constructor:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
using (var dummyMenu = new ContextMenuStrip()) {
dummyMenu.Items.Add(new ToolStripMenuItem());
dummyMenu.Show(Point.Empty);
}
}
}
So every Form that opens cleans up the corrupted state of the ToolStripMenu system. One might as well put this code in a static method like FormHelper.FixToolStripState() or put it in OnCreateControl(...) of a template Form and inherit all Forms from that (what is what we luckily do anyway).
this is my solution :)
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup"
var mainMenu = new MenuStrip();
var mainItem = new ToolStripMenuItem("Menu");
mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup));
mainMenu.Items.Add(mainItem);
// Create form with MenuStrip and Show
var form1 = new Form();
form1.Controls.Add(mainMenu);
Application.Run(form1);
}
private static void Popup(object sender, EventArgs e)
{
// Create a form with a right click handler and show
var form2 = new Form();
var contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("Just an item...");
var loc = form2.Location; //<---- get the location
var p2 = new Point(loc.X, loc.Y); //<---- get the point of form
form2.ContextMenuStrip = contextMenu;
form2.ContextMenuStrip.Show(form2, p2); //<---- just add this code.
form2.Show();
// Problem: contextMenu.Show() will give focus to form1
}
}
I was having this problem too. I didn't want to change code, because I felt my program was doing it right. I found the fix here on Microsofts website:
http://support.microsoft.com/kb/2750147
It does make a difference and we just installed it on 2 user computers this morning. Our IT guy is installing it on all the computers today now that it has been tested and shown to work.

Categories