What I'm attempting to create is very similar to the "Toolbox" in VS 2008 and VS 2010. It will be on the left side of my MDI parent, and will pop out when the user hovers their mouse over it. Again, this is just like the VS Toolbox.
My question is what is the best way to implement this? Please keep in mind I am putting this on the left side of a MDI parent and am using VS 2008, C#, and .NET 3.5. In addition, I plan on putting a TreeView inside the toolbar, so whatever is used must support the addition of a TreeView object.
Thanks!
A vertical auto-hiding toolbar, from what I've gathered online and by testing, is best implemented with a ToolStrip object, docked to the left in my case. To give the appearance of a TreeView object popping out of that, add a ToolStripButton. Then, add a MouseHover Event to the ToolStripButton that makes a Panel object (that is docked to the left as well) visible. Obviously, it would be best to make the Panel object invisible by default. Then, add a MouseLeave event for the Panel so when the user leaves the Panel, the Panel then becomes invisible again or "pops" back in.
It doesn't have the nice effect of it popping out like Visual Studio 2008/2010 does, but it has the basic functionality that I need.
Here is the code for the MouseHover and MouseLeave events. Very simple.
private void openPanel1ToolStripButton_MouseHover(object sender, EventArgs e)
{
if(panel1.Visible == false)
{
panel1.Visible = true;
}
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
if (panel2.Visible == true)
{
panel2.Visible = false;
}
}
Take a look at the DockPanel Suite on SourceForge. I have seen many Custom Controls on the web trying to mimic the VS Toolbar, but none work as well as this one does. It has a high user rating also.
Related
I would like some help with code so my panels get brought to front when I click a button.
I have tried
private void button22_Click(object sender, EventArgs e)
{
panel4.BringToFront();
}
but that didn't seem to work for me.
Does anyone know what I'm doing wrong or how I could get this working?
I am in c# winforms.
That should work fine. You code says panel4 so I assume you have multiple panels.
If you have placed panel3 on panel4, then BringToFront() will bring both forward and may look like there is no change. Make sure both panels have the form as their parent. You can do this by cut and paste, or making sure that you click the form canvas (not an existing panel) when you add the other panels.
The same for buttons, textboxes etc, if you draw them on to a panel, they will stay as is on that panel when you bring them forwards.
I would like to simulate/route right click on a WPF "control".
To make a long story short. I have an Adorner which should react to left click (so is hit test visible must be true) but at the same time I would like it to be "transparent" for the right clicks. (In another words i would like for a control under it to receive this click - btw right click makes Adorner disappear).
I tried to raise MouseRightButtonUp event on control directly under mouse (after Adorner disappears but it doesn't seem to work). I would like to avoid calling system functions (like mouse_event through P/Invoke). Can it be even done in wpf?
As far as I remember, I had troubles with routing events and changing Adorners IsHitTestVisible property. The main problem was, if I recall it correctly, that adorner and controls are on different branches of visual tree, so routed events spawned on the adorner won't make it to your controls.
I can't say much without you providing the code, but the simplest thing that should work would be to find a control under your mouse position and do
private void myAdorner_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
MouseButtonEventArgs revent = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Right);
revent.RoutedEvent = e.RoutedEvent;
//find you control
control.RaiseEvent(revent);
}
I am working on a simple C# program that allows the user to use the mouse to move simple controls (Buttons, textareas, etc), similar to a visual designer like visual studio. The controls are contained in a panel and they all work as expected. However, when I call MouseDown() on the panel the controls are contained in, the event only fires when clicking on an empty part of the panel, not when I click on a Control contained within the form.
Here is my MouseDown() Code:
private void splitContainer2_Panel2_MouseDown(object sender, MouseEventArgs e)
{
Console.WriteLine("MOUSE GRABBED");
...
//More code that uses the X and Y co-ords of the mouse to check which
//Control is selected
...
}
As you can see it is very straightforward. The writeLine() is not triggered when I click on a control.
I have looked at questions such as:
ignore mouse event on label inside panel
To no avail.
Any help would be appreciated, even a better method to do what I am trying to acomplish.
Instead of using a MouseDown() event for the panel, why not trying to use the same one for every object? Based on what you are trying to do, add the following code:
Where you create each form element:
nameOfElement.MouseDown += new System.Windows.Forms.MouseEventHandler(this.splitContainer2_Panel2_Objects_MouseDown);
The mouse down method:
Control ctrl = (Control)sender;
Console.WriteLine("Moused down on: " + ctrl.Name);
//Code to manipulate mouse down
Hope this helps!
Use PreviewMouseDown. The WPF hit testing engine will not raise events on parent elements if the child element absorbs the event.
I am having a strange problem with the .NET TabControl in C# (Visual Studio 2010). Start a Windows Forms Application. Add a tab control and a button. Add two different labels to the two tab pages so you can differentiate them. The purpose of the button is just to act as a next button; subscribe to the its Click event with the code:
tabControl1.SelectTab(1);
Let's assume the user entered something wrong on the first tab, so when they try to go to the second tab we want to send them back, so subscribe to the tab control's SelectedIndexChanged event with the code:
if(tabControl1.SelectedIndex == 1)
{
tabControl1.SelectTab(0);
}
Now run the program and click the button. You will notice that as judged by the highlighted tab at the top, the first tab page is the one that appears to be selected, as you'd expect. However, as judged by the tab page that actually appears in the body of the tab control, it's still the second tab page that shows up! Calls to various controls' Focus(), Update(), and Refresh() functions don't seem to help. What is going on here?
I repro. This is a generic problem with event handlers, you can confuse the stuffing out the native Windows control by jerking the floor mat like that. TreeView is another control that's very prone to this kind of trouble.
There's an elegant and general solution for a problem like this, you can use Control.BeginInvoke() to delay the command. It will execute later after the native control is done with the event generation and all side-effects have been completed. Which solves this problem as well, like this:
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
if (tabControl1.SelectedIndex == 1) {
this.BeginInvoke(new Action(() => tabControl1.SelectTab(0)));
}
}
I'm implementing a custom control that inherits from Control. I want it to be focusable (it's a kind of list box).
In the constructor, I do
SetStyle(ControlStyles.Selectable, true);
I can now use Tab to navigate to the control.
However, when the control receives a mouse click, it does not automatically claim focus. I can work around this, of course:
protected override void OnMouseDown(MouseEventArgs e)
{
Focus();
base.OnMouseDown(e);
}
But this feels like a kludge that should not be necessary. Is this really the way to go? Or is there some way to tell Control to claim focus automatically when it receives a mouse click?
Disassembly to the rescue! It turns out that
SetStyle(ControlStyles.UserMouse, true);
does the trick.
Ironically, I had read in the documentation:
UserMouse: If true, the control does its own mouse processing, and mouse events are not handled by the operating system.
That seemed the exact opposite of what I wanted, so I had only tried setting it to false... Way to go, WinForms documentation.
Yes, that what you should do. There are many controls that don't have a meaningful way to take the focus. PictureBox, Panel are good examples. Anything that derives from ContainerControl. Control.OnMouseDown() therefore doesn't automatically call Focus() in OnMouseDown().
Just overriding the OnMouseDown method isn't enough, you should also make it clear to the user that your control has the focus. So she'll have an idea where the keyboard strokes go. That requires overriding OnPaint() so you can draw a focus rectangle. ControlPaint.DrawFocusRectangle() is a boilerplate implementation for that.
But taking the focus is really only useful if you do something meaningful with keyboard messages. So you'll have to override OnKeyDown and/or OnKeyPressed as well. And show feedback to the user so she can see what she typed. If you don't have a useful implementation for that, you shouldn't take the focus. Which is why PictureBox doesn't.
compile in a WinForms project for FrameWork 3.5
drag an instance of Control1 from the ToolBox to a Form Surface ... make sure its TabStop property is set to 'true
put some other controls on the form.
verify that when the instance of Control1 is tabbed to: it shows a selection rectangle which disappears as you "tab away" from it.
verify if you click on the instance of Control1 that it shows the selection rectangle, and if you click on some other control it disappears.
namespace testFocusableControl
{
// VS Studio 2010 RC1 : Tested against FrameWork 3.5 Full (not 'Client)
public class Control1 : Control
{
public Control1()
{
SetStyle(ControlStyles.UserMouse, true);
}
protected override void OnLostFocus(EventArgs e)
{
this.Invalidate();
base.OnLostFocus(e);
}
protected override void OnGotFocus(EventArgs e)
{
this.Invalidate();
base.OnGotFocus(e);
}
protected override void OnPaint(PaintEventArgs e)
{
if (this.Focused)
{
ControlPaint.DrawFocusRectangle(e.Graphics, this.ClientRectangle, Color.Red, Color.Blue);
}
base.OnPaint(e);
}
}
}
The only "loose end" here for me is that this solution will show the selection rectangle on a mouse-click, but I did not implement any MouseDown code as Thomas suggested.
Note that if you make the Control above a 'ContainerControl via 'SetStyle(ControlStyles.ContainerControl, true); and add some other control to it, even if you set the TabStop property of the added control to 'false : ... if it clicked ... it will get focus, and you will lose the focus rectangle shown on the ContainerControl.