I'm wondering if it's possible to use ToolTip.SetToolTip or something similar to open a control as a tooltip instead of just a string (i.e. SetToolTip(controlToWhichToAdd, panelToDisplayAsToolTip) instead of passing a string as your second parameter).
If this isn't possible I'm guessing next best thing is displaying a panel on the mouse location on mouse_enter event on the control and removing it (or making it invisible) on mouse_leave.
Or are there other practices that make this possible in an easier way?
This is not possible out of the box. You have two choices. First option is to override the Draw Event, which will let you customize how the tooltip looks. Here is an example of this. Be sure you set the OwnerDraw property to true if you use this method!
Although the first method will work if you just need some simple customization, the second option will work best if you need more flexible options. The second option is to do what you already suggested and create your own sort of tooltip. Simply put, you would first create an event handler for the MouseEnter event. When that event fires, you'd enable a Timer. This timer would be the delay that occurs before the tooltip is show. Then finally, you'd just make your panel appear at the mouse coordinates.
Suppose you have a form with a button and timer on it and you want the button to have a tooltip that is a panel:
public partial class Form1 : Form
{
private Panel _myToolTipPanel;
private void Form1_Load(object sender, EventArgs e)
{
_myToolTipPanel = new Panel {Visible = false};
Controls.Add(_myToolTipPanel);
Label myLabel = new Label();
myLabel.Text = "Testing";
_myToolTipPanel.Controls.Add(myLabel);
}
private void button1_MouseEnter(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void button1_MouseLeave(object sender, EventArgs e)
{
timer1.Enabled = false;
_myToolTipPanel.Visible = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
Point position = Cursor.Position;
Point formPoisition = PointToClient(position);
_myToolTipPanel.Visible = true;
_myToolTipPanel.Location = formPoisition;
}
}
Now of course you will have to do some beautifying of the tooltip, but this is the general idea!
One Approach could be inheriting the ToolTip control and then override the SetToolTip and Show methods . Inside the SetToolTip the private method - SetToolTipInternal needs to be re-written , but most of the functionality could be reuse - it uses the Mouse Events ( leave , move) to bind region. but since tooltip uses internal's of windows to show the baloon window. you will have to override quite a bit of code.
but this could be time consuming and needs quite a bit of testing.
You could write a handler for the Tooltip.Popup event, and cancel the popup to display your own panel.
You'd need to clean it up at the appropriate time, though.
For example:
private void ToolTip1_Popup(Object sender, PopupEventArgs e)
{
e.Cancel = true;
//Do work here to display whatever control you'd like
}
If you're just looking for more formatting options in the tooltip display, an alternative is something like this CodeProject entry, which implements an HTML-enabled tooltip:
Related
I have project with several hundreds of buttons, created dynamically within for-loop. I also have timer to update toolstripstatuslabel (labelClock) with current time every second:
static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
...
timer.Tick += new System.EventHandler(timer_Tick);
...
private void timer_Tick(object sender, EventArgs e)
{
labelClock.Text = DateTime.Now.ToString();
}
Here's the problem: last clicked button will be focused, of course. So if I scroll page down, everytime timer ticks page scrolls up (or down), so the focused button becomes visible.
How can I prevent that?
Stupid solution (won't work, if you need to save focus of button):
private void timer_Tick(object sender, EventArgs e)
{
justAnotherButton.Focus();
labelClock.Text = DateTime.Now.ToString();
}
You need to pass focus to another focusable control, it may be another Button, TextBox, etc. You may use button with zero Width and Height, so user won't see it.
If you are not concerned with keeping the same button focussed, set the focus to the parent form. Although this sounds like a bit of a nightmare to deal with, and i'd look for a way not not needing hundreds of buttons!
private void timer_Tick(object sender, EventArgs e)
{
formMain.Focus()
labelClock.Text = DateTime.Now.ToString();
}
You could create a container control that extends System.Windows.Forms.ContainerControl and override the ScrollToControl to return the current scroll position. Then add all your buttons to this control.
class MyContainer : ContainerControl
{
protected override System.Drawing.Point ScrollToControl(Control activeControl)
{
return base.AutoScrollPosition;
}
}
In my Windows forms application written in C# I have a bunch of buttons. When the user's mouse hovers over a button, I want the button's border to change.
Currently I have multiple instances of the following (a copy for each button):
private void btnStopServer_MouseEnter(object sender, EventArgs e)
{
oldColor = btnStopServer.FlatAppearance.BorderColor;
btnStopServer.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnStopServer_MouseLeave(object sender, EventArgs e)
{
btnStopServer.FlatAppearance.BorderColor = oldColor;
}
Since I have a lot of buttons, the code to change the color of the button's border takes up a lot of space.
Is there any simpler way that I could do this?
You should wire-up a single MouseEnter and MouseLeave to each control that needs this functionality (rather than writing a new version of each method for each control). Assuming you're using Visual Studio, this can be done by changing the target method name for the event, in each Button's property pane. If you write the following code first, then this method will appear in the property's MouseEnter and MouseLeave events' drop-down lists.
The code would then need to check which button from which the event was fired, as follows:
private void btnWithHoverBorder_MouseEnter(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
oldColor = eventButton.FlatAppearance.BorderColor;
eventButton.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnWithHoverBorder_MouseLeave(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.FlatAppearance.BorderColor = oldColor;
}
I presume oldColor is a global? This might get out of sync if something "odd" happens where your MouseEnter event is fired for another button, before the corresponding MouseLeave is caught. To make this more robust, I'd consider storing the old color on the Button's .tag property, so that it's self-contained.
Eg:
private void btnWithHoverBorder_MouseEnter(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.tag = eventButton.FlatAppearance.BorderColor;
eventButton.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnWithHoverBorder_MouseLeave(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.FlatAppearance.BorderColor = (Color)eventButton.tag;
}
(The tag is basically a hook on which to tag "anything" relevant to a specific instance of a control, that there is not already a property for. It's of type Object which means you can tag anything there, but when you read from it, you need to cast it back to whatever type you put there in the first place. But because it's an Object you can put anything there, including eg a custom class that contains multiple properties, or an array, etc if you need to tag a control with more than one thing).
I am new to C# and I want to design a GUI for a image processing application in c#. I have a very basic rudimentary layout designed as shown below
Here, the image plane is fixed and it will show a live stream video. I have designed all the buttons frame and the side panel. But I do not know how to dynamically change the side panel for each button I click. For example, If I click button1_1, I want some things in the side panel and for button1_2, some other things in it. How do I go about doing it.
EDIT:
Thanks for the answers. I see tab controls is an option. But I want a new panel evertime a click a button. which can further open forms. Is it possible?
OK, let's see. It's easy to do with "TabControl" or array of "Panel"s.
1.Do it with TabControl.
You can design GUI in TabControl in multiple subTabs(if you don't know how please ask.). Then you change it in button click event, to make subTab you wanna show(which means make it visiable and not visiable for other subTabs.)
2.Do it with array of panel.
You can use panel[] panels. In button click event, you hide other panels and show the one you want.
Hope answer helps you!
private void button1_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 0;
tabControl1.TabPages[0].Text = "First";
}
private void button2_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 1;
}
private void button3_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 2;
}
you may want to add split container in your form.
Create UserControl for each buttons.
Code for the button click event
//Button1Click Event
private void button1_Click(object sender, EventArgs e)
{
UserControl1 m_UserControl = new UserControl1();
splitContainer1.Panel2.Controls.Clear();
splitContainer1.Panel2.Controls.Add(m_UserControl);
}
//Button2Click Event
private void button2_Click(object sender, EventArgs e)
{
UserControl2 m_Usercontrol2 = new UserControl2();
splitContainer1.Panel2.Controls.Clear();
splitContainer1.Panel2.Controls.Add(m_Usercontrol2);
}
you can do this if you want to change what usercontrol display in a panel at run time.
Correct me if i misunderstood your question.
In WinForms, you could use a tab control and just change the selected tabs index when a button is pressed. More specifically, when its click event is fired. Here is a good tutorial on using the TabControl and here is a tutorial on wiring up click events.
EDIT:
This is a better tutorial.
Since you can't hide the tabs of a tabcontrol without using WPF, you may need to use something else, if you don't like the way they look. A good workaround if you only have a couple of buttons and thus views, would be to use panels. When button one is clicked show panel one and hide panel two, etc. Here would be the code:
private void button1_Click(object sender, EventArgs e)
{
pane2.visible = false;
pane1.visible = true;
}
private void button2_Click(object sender, EventArgs e)
{
pane1.visible = false;
pane2.visible = true;
}
Hope this helps you!
I have an application with a Panel containing children Form objects. When I click one of the children Form it brings to front. I would like to know which one is in front now...
I've looked in event list but cant find proper event form my purpose :(
These methods doesn't work:
protected void OpenedFileForm_Enter(object sender, EventArgs e)
{
MessageBox.Show("enter");
}
protected void OpenedFileForm_Click(object sender, EventArgs e)
{
MessageBox.Show("click");
}
protected void OpenedFileForm_Activated(object sender, EventArgs e)
{
MessageBox.Show("activated");
}
protected void OpenedFileForm_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("mouse click");
}
protected void OpenedFileForm_Shown(object sender, EventArgs e)
{
MessageBox.Show("shown");
}
OpenFileDialog openFile1 = new OpenFileDialog();
openFile1.DefaultExt = "*.txt";
openFile1.Filter = "TXT Files|*.txt|RTF Files|*.rtf";
if (openFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
openFile1.FileName.Length > 0)
{
switch (Path.GetExtension(openFile1.FileName))
{
case ".txt":
txtForm childTXT = new txtForm();
this.childForms.Add(childTXT);
childTXT.Parent = this.mainPanel;
childTXT.richTextBox1.LoadFile(openFile1.FileName, RichTextBoxStreamType.PlainText);
childTXT.Show();
break;
}
}
Have you tried the Form.Activated Event?
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.activated(v=vs.80).aspx
Edit:
If you are in an MDI application, you might need to use MdiChildActivate instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.mdichildactivate.aspx
This code can only work when you set the Form.TopLevel property to false. Which makes it turn into a child control, almost indistinguishable from a UserControl.
This has many side-effects, for one there is no notion of "front" anymore. The Z-order of child controls is determined by their position in their parent's Controls collection. And it affects the events it fires, Activated and Deactivated will never fire. Furthermore, the Form class was designed to be a container control, it doesn't like taking the focus itself. Its child controls get the focus, the Form class doesn't have any use for focus. Which is why the Enter, Click and MouseClick events don't fire, they are events that require focus.
Long story short, what you are trying to do doesn't make a wholeheckofalot of sense. If it is strictly the Z-order you want to fix then write an event handler for the MouseDown event:
void OpenedFileForm_MouseDown(object sender, MouseEventArgs e) {
var frm = (Form)sender;
frm.BringToFront();
}
You could add frm.Select() to get the Enter event to fire, but only do that if the form doesn't contain any focusable controls itself. Do note that there is evidence that you don't assign the events correctly in your code. The Shown event does fire. It is also important that you set the FormBorderStyle to None, the title bar cannot indicate activation status anymore.
Ok, I got this! Thx for help everyone. You gave me a hint to think about equity of my strange MDI idea where Panel is parent for other Forms. I Removed SplitContainer containing Panel and just did standard MDI application, where Forms are MDIChildren of main Form.
childTXT.MdiParent = this;
I'm trying to add a tooltip to an OvalShape (Microsoft.VisualBasic.PowerPacks.OvalShape). Since its not a Control, I can't use the simple SetToolTip() method in the ToolTip class. How might I go about showing a ToolTip on an OvalShape? I don't absolutely have to use the ToolTip class if anyone has any better ideas. I'd also like to keep the OvalShape, unless anyone has a better solution that can give me inheritence from Control while keeping a nice circular shape.
You'll have to take advantage of the MouseHover event you can get out of the control. This worked well enough:
bool hoverSeen = false;
private void ovalShape1_MouseHover(object sender, EventArgs e) {
if (!hoverSeen) {
hoverSeen = true;
// Todo, fix position
Point pos = ovalShape1.Parent.PointToClient(Cursor.Position);
toolTip1.Show("On oval", ovalShape1.Parent, pos);
}
}
private void ovalShape1_MouseLeave(object sender, EventArgs e) {
if (hoverSeen) toolTip1.Hide(ovalShape1.Parent);
hoverSeen = false;
}