Windows Forms ToolTip will not re-appear after first use - c#

I have a Windows Forms C# application where I would like to use a tooltip on one of the text boxes. I initialize the tool-tip in the constructor of the Form class, and it works the first time. So when I hover over the text box with my mouse it works, but once the toolTip times out and it goes away, it does not re-appear when I move my mouse away and back onto the control. I would expect it to come back. What am I doing wrong?
Here is how I initialize the tooltip:
myTip = new ToolTip();
myTip.ToolTipIcon = ToolTipIcon.Info;
myTip.IsBalloon = true;
myTip.ShowAlways = true;
myTip.SetToolTip(txtMyTextBox,"My Tooltip Text");

I had a similar problem today. Sometimes, the tooltip would not show. I had one ToolTip control for all the controls in my form.
I also had a MouseEnter event on all the controls added automatically, so I modified the MouseEnter event to do:
_tooltip.Active = false;
_tooltip.Active = true;
It fixed the bug, but I don't know why.
Also, the bug always happened on Windows XP machines, but not on Windows Vista.

I guess you'll be happy to know that Microsoft knows about it...since about 5 years...
2/21/2005 Bug acknowledged as reproducable
3/29/2005 Hum we might fix it, but later...
11/15/2005 Well actually it's not a big bug, and it doesn't happen much, so we won't fix it.
Damn I love it when I stumble on bugs Microsoft doesn't want to solve! This time it's called a corner case, last time it was simply too difficult to resolve...
http://connect.microsoft.com/VisualStudio/feedback/details/115385/tooltip-stop-showing-after-autopopdelay
I'm off to tell my client that the bugs in my program are just corner cases and too difficult to resolve...

I had a similar problem today. VS 2010 SP1 .Net 3.5
After AutoPopDelay-Time the ToolTip do not show the Controls ToolTipText.
Kevins solution is the only way to solve the problem.
I encapsulate this in my own ToolTip class:
public class ToolTip : System.Windows.Forms.ToolTip
{
public ToolTip() : base() { }
public ToolTip(System.ComponentModel.IContainer components) : base(components) { }
public new void SetToolTip(System.Windows.Forms.Control ctl, string caption)
{
ctl.MouseEnter -= new System.EventHandler(toolTip_MouseEnter);
base.SetToolTip(ctl, caption);
if(caption != string.Empty)
ctl.MouseEnter += new System.EventHandler(toolTip_MouseEnter);
}
private void toolTip_MouseEnter(object sender, EventArgs e)
{
this.Active = false;
this.Active = true;
}
}

I had this issue in VB.NET. What I did was drop a TooTip control on the form, and then on the target control's MouseHover event, I set the properties of the ToolTip. I did this because I used one ToolTip control for five different Label controls. It worked great. (Really, I wanted the ToolTip to show immediately, so I used the MouseEnter event instead.) I can post my exact code tomorrow when I get to work.

I solved this problem by this
if (t == null)
{
t = new ToolTip();
}
t.IsBalloon = true;
t.ToolTipTitle = "Stop";
t.ToolTipIcon = ToolTipIcon.Error;
t.Show("", yourControlonWhichToApplyToolTip, 0);
t.Show("PDescription", yourControlonWhichToApplyToolTip, 1000);
Note i have added an empty tooltip.

For what it's worth, I was having this problem on my Windows XP system until I noticed that if I placed at least one tooltip control on my form manually (from the toolbox) I could create as many tooltips as needed within my code, and they would all work.
If, however, I tried to create all tooltips in code (say for instance in the formload event) the tips would only show once and never to be seen again. I can't give you the exact "why this happens" story, but I have duplicated this issue several times always with the same effect. It might have something to do with the object scope, but I'm not sure.
So now just as a habit, I always include at least one Visual Studio tooltip control and then the rest within my code.

I just had the the problem on Windows 7 so I found this thread.
In my case this did not work in tooltip_MouseEnter:
tooltip.Active = false;
tooltip.Active = true;
So I tried the following:
this.toolTip.SetToolTip(this.txtbx1, "tooltip-text");
This worked fine for me.

In my case after setting the tooltip text with the SetToolTip method, I used the Show overload with duration parameter, i.e.
toolTip.Show(text, textEdit, 1000);
After that tooltip did not reappear on mouse hover, and resetting tooltip.Active didn't work..
A workaround that worked for me was to use Show overload without the duration, and hide it manually afterwards:
toolTip.Show(text, textEdit);
new Task(() =>
{
Thread.Sleep(750);
textEdit.Invoke(new Action(() => toolTip.Hide(textEdit)));
}).Start();
With this code I have the desired behaviour, i.e.
The tooltip is shown at once for 750 millisec. after the tooltip text has changed
The tooltip does appear for the specified time when the mouse is over the control

System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();
private void textBox_MouseHover(object sender, EventArgs e)
{
ToolTip1.Show("YOUR TEXT", textBox);
}
private void textBox_MouseLeave(object sender, EventArgs e)
{
ToolTip1.Active = false;
ToolTip1.Active = true;
}

Related

How to make the WinForms ToolTip.Show method not display the previous tooltip string for a fraction of second?

I encountered this issue while trying to make a custom tooltip system for the custom hit-testing system of OxyPlot. The sample code is below, it moves the mouse cursor automatically when handling the event Form.Click to show the problem.
Steps to reproduce
create an empty Form (example size: 500x500)
handle the Click event of the Form
on Click
show the tooltip string "test 1"
move the mouse
hide the tooltip
wait a few seconds
show the tooltip string two-line "test 123456789\n\nanother line"
For a fraction of second the one-line "test 1" string is shown in the last cursor position too.
Screen recording (the issue is not visible in it)
Code
public partial class Form1 : Form
{
private ToolTip toolTip;
public Form1()
{
InitializeComponent();
Click += Form1_Click;
toolTip = new ToolTip();
toolTip.UseAnimation = false;
toolTip.UseFading = false;
}
private void Form1_Click(object sender, EventArgs e)
{
_ = DoIt();
}
private async Task DoIt()
{
Point pos = PointToClient(MousePosition);
pos.Y += Cursor.Current.Size.Height;
// Without the -2000, the duration of the tooltip is too long (because of the fade-in/out animation)
toolTip.Show("test", this, pos, Math.Max(0, toolTip.AutoPopDelay - 2000));
await Task.Delay(5000);
Cursor.Position = new Point(Cursor.Position.X + 100, Cursor.Position.Y);
toolTip.Hide(this);
Application.DoEvents();
await Task.Delay(5000);
pos = PointToClient(MousePosition);
pos.Y += Cursor.Current.Size.Height;
toolTip.Show("test 123456789\n\nanother line", this, pos, Math.Max(0, toolTip.AutoPopDelay - 2000));
}
}
What I tried
I made the code sample above to show the issue... I have also searched on StackOverflow and did not find something to help me.
Expected result
The second tooltip shows like the first tooltip, without a flashing image of the previous tooltip string.
Actual result
The old tooltip string flashes in the place of the new tooltip string. It is not very visible, mostly when the animations are enabled, but it is still ugly to me.
Ideas of possible solutions
Use a Timer or some trick with async-await.
Create two alternating ToolTip objects.
System configuration
I use for this .NET Framework v4.5.2 but I have tried the code above with .NET Framework v4.7.2 and it has the same problem. I use Windows 10 and VS 2019.
Thank you.
I might be a little late to the party, but anyhow.
The solution is to simply instantiate a new ToolTip component each time you want to display one. That's it, no flicking of the previous text anymore. (You might want to dispose the old one to make sure there are no leaks.)

WinForms tooltips not showing up

I have a WinForms application. Each form and user control sets up its tooltips as follows:
// in the control constructor
var toolTip = new ToolTip();
this.Disposed += (o, e) => toolTip.Dispose();
toolTip.SetToolTip(this.someButton, "...");
toolTip.SetToolTip(this.someCheckBox, "...");
...
However, the tooltips don't appear when I hover over the controls. Is this an appropriate way to use tooltips? Is there something that could be happening in another part of the application (e. g. listening to some event) that would stop tooltips from working?
Note that tooltips on my outer form's toolstrip buttons (which are configured via the button's tooltip property) do work as expected.
EDIT:
I've observed this more and I've noticed that sometimes the tooltip does show up, it is just extremely "flaky". Basically, sometimes when I mouse over a control it will show up very briefly and then flicker away. I can get it to show manually with .Show() and a long AutoPopDelay, but then it never disappears!
Your code seems ok to me. I couldnt find anything wrong in your code. But, it could be failed only when control is disabled. BTW, you can try another method like this. but, i would not like to suggest you to show the tooltip like this.
private void someButton_MouseEnter(...)
{
toolTip.Show("Tooltip text goes here", (Button)sender);
}
You can also assign the location where tooltip should be displayed in .Show() method. there are some overloaded function that you can use. Read the msdn for more information about ToolTip.Show() method.
I faced similar issue when my tooltip was not showing up over the RichTextBox once in about 3-5 times it normally should. Even forcing it to show explicitly with toolTip.Show didn't help. Until I changed to the way mentioned by Shell - you have to tell where you want your tooltip to appear:
'Dim pnt As Point
pnt = control.PointToClient(Cursor.Position)
pnt.X += 10 ' Give a little offset
pnt.Y += 10 ' so tooltip will look neat
toolTip.Show(text, control, pnt)
This way my tooltip always appears when and where expected.
Good luck!
I wrote the following method to "propagate" ToolTips from parent controls (that have a tool tip set) to its child controls (unless they have their own overriding ToolTip).
It's designed to be dropped into the form or control you're starting with, but it could also just be turned into a static method where the "parent" argument is required.
/// <summary>Setting a toolTip on a custom control unfortunately doesn't set it on child
/// controls within its drawing area. This is a workaround for that.</summary>
private void PropagateToolTips(Control parent = null)
{
parent = parent ?? this;
string toolTip = toolTip1.GetToolTip(parent);
if (toolTip == "")
toolTip = null;
foreach (Control child in parent.Controls)
{
// If the parent has a toolTip, and the child control does not
// have its own toolTip set - set it to match the parent toolTip.
if (toolTip != null && String.IsNullOrEmpty(toolTip1.GetToolTip(child)))
toolTip1.SetToolTip(child, toolTip);
// Recurse on the child control
PropagateToolTips(child);
}
}
Note that the behaviour is undefined if you're using more than one ToolTip instance to manage parent and child control toolTips.

C# WPF Frame->UserControl->Usercontrol Loaded event doesn't fire

I'm new into WPF and have a problem I can't seem to find a solution for.
I'm writing a G19 (Keyboard) applet. This Keyboard has a 320x240 display attached, which you can access with C#.
I'm using WPF for this, because I don't need to do any GDI drawing anymore and use the normal controls instead.
So. It works as I wish. Everything draws properly except one UserControl. I have downloaded this control -> http://marqueedriproll.codeplex.com/
In the designer, the control works, the Loaded event get's fired and the animation is good.
When I run my application, I just see the label and the text. The animation does not work, and the Loaded event does not fire anymore.
Any help is appreciated.
The main function is my wrapper. The wrapper is already a Usercontrol and displays plugins which are switchable. This wrapper has the Frame Control(Wrapper1). I replace the content of this frame every time I switch the plugin.
public void SetPlugin(IPlugin plugin)
{
if (this.MainPlugin != null)
{
this.MainPlugin.OnHide();
((UserControl)this.MainPlugin).Visibility = System.Windows.Visibility.Hidden;
}
this.MainPlugin = plugin;
((UserControl)this.MainPlugin).Visibility = System.Windows.Visibility.Visible;
this.MainPlugin.OnShow();
this.Wrapper1.Content = this.MainPlugin;
}
I think it's the right approach to handle a plugin system that way. The plugin get's drawed on my keyboard.
What I don't understand is why the usercontrol only works in the designer view and not in the running application.
The basic code of the scrolling label is so:
public MarqueeText()
{
this.Loaded += new RoutedEventHandler(MarqueeText_Loaded);
InitializeComponent();
canMain.Height = this.Height;
canMain.Width = this.Width;
}
void MarqueeText_Loaded(object sender, RoutedEventArgs e)
{
StartMarqueeing(_marqueeType);
}
I don't see a reason why it doesn't work. Actually Ive always found a way to fix a problem but this time I see nothing.
Thanks in advance. Your help is really required today.
Have a great saturday! :)
I am guessing you are rendering to a bitmap target, rather than onscreen. If you are using RenderTargetBitmap, you have a couple of responsibilities. You need to set both a presentation source, and make sure you run events on the dispatcher.
Normally, App.xaml or Application.Run does this for you, but if you are not using a Window, you are on your own.
See this related question for details.

Buttons Enabled Property not Working Properly

I am creating an Windows Application. I have two buttons.
I have written the following code snippet.
frmRb obj = new frmrb();
private void btnPd_Click(object sender, EventArgs e)
{
btnCancel.Enabled = true;
obj.btnRtn.Enabled = true;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
obj.BringToFront();
obj.Focus();
}
The above coding does not generate any error.
All the statements are working properly but the following statement is not working properly:
obj.btnRtn.Enabled = true;
is not executed.
The frmrb forms is bring to front and it is focussed but btnRtn is not Enabled that is the statement obj.btnRtn.Enabled = true; is not working.
By default I have set the property of btnRtn Enabled to false.
And Please note the Modifier property of btnRtn button is set to PUBLIC.
Now how should I change the coding so that I can get this statement executed.
obj.btnRtn.Enabled = true;
Can anybody help me out?
Thanks in Advance!!
SOLUTION
You should never disable a button, or change it´s visibility before it is initialized, otherwise you won't be able to enable it again, or turn it visible again.
Instead, you should disable it on it's own "Initialized" event, and then it will work properly!
I had the same problem.
Is the button placed inside a panel or any container. If yes then please check the enabled status of the container also.
You not mention that where you obj(which is the instance of frmRb) show. because it is very important point.
from your coding it seem that frmRb is already visible. so u never called the
obj.Show() ;
instead you call the
obj.BringToFront();
so the problem is that you never show the frmRb object. which is you create u in 1st line. each time u write the line
frmRb obj = new frmrb();
new instance of frmrb is created. So u must again show it, with the line obj.Show() ;
Now u rewrite ur code as ::
frmRb obj = new frmrb();
private void btnPd_Click(object sender, EventArgs e)
{
btnCancel.Enabled = true;
obj.btnRtn.Enabled = true;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
obj.Show();
obj.BringToFront();
obj.Focus();
}
I hope it is helpful for u and solve ur problem.
I've been using VB rather than C#, but the languages are very similiar. in VB, you have to add "handles SomeButton.Click" to make it handle the Click events.
According to google, the equivalent in C# is to go into the Designer.cs file, find where the controls are, and manually change the click event hookup to point to your new event handler.
As mentioned by the previous poster, use a breakpoint (F9) and the debugger to see if that method is ever called when you execute the event. If it is not called, then the problem is probably not with the enabled property, but the wiring of the method so that it is invoked when the event occurs.
Here's a reference:
http://www.tek-tips.com/viewthread.cfm?qid=1442702&page=5
I strongly suspect that either the click handler isn't being called or you're not looking at the form you think you are.
Where are you setting up the click handler for btnPd_Click? Check that's still wired up correctly.
Then put a breakpoint on the first line of the handler and run it in the debugger - if you don't hit the breakpoint when you click the button, that's the problem.
EDIT: Okay, next steps:
Check that you're looking at the right button. Change its text as well as enabling it.
Check that its container is enabled, as suggested by phoenix. Not just its direct parent, but all the way up.
Check what else your UI thread is doing afterwards - are you blocking it for some reason? Does the rest of the UI work at that point?
I would try just switching the sequence of statements to:
private void btnPd_Click(object sender, EventArgs e)
{ obj.btnRtn.Enabled = true;
btnCancel.Enabled = true; }
and see if that helps you debug
Your code really should produce an error... C# is case sensitive, meaning frmRb is not the same as frmrb. Anyway, I copied it, created 2 forms and 3 buttons, and set up the handler, and it worked fine.
private void InitializeComponent()
{
this.btnPd = new System.Windows.Forms.Button();
this.btnPd.Location = new System.Drawing.Point(90, 116);
this.btnPd.Name = "btnPd";
this.btnPd.Size = new System.Drawing.Size(75, 23);
this.btnPd.TabIndex = 1;
this.btnPd.Text = "button1";
this.btnPd.UseVisualStyleBackColor = true;
this.btnPd.Click += new System.EventHandler(this.btnPd_Click);
}
public System.Windows.Forms.Button btnRtn;
Are you sure you were handling btnPd? Perhaps you may have locked your enabling code inside a disabled button? Hopefully this small working sample helps you find the problem. As for the rest of the code, All I changed was the frmRb to frmrb so they match.
If the form that your are trying to show on the screen is properly shown, may be you can try this:
Create a public method in the form that will set the button property enabled = true;
After creating the form, and showing, you can call that public method;
frmRb obj = new frmrb();
obj.EnableButton
It's been a while since anyone commented or answered I thought I would pose this answer/comment as it may be be helpful to others who stumble on it.
I recently had some CheckBoxes and NumericUpDowns not changing enabled state but it was simply due to the fact they were in a GroupBox that had not been enabled. A forehead slapping moment for me, but took me 20 min to figure out why those controls weren't responding!
Just a hunch. May be the 'Locked' property of button is 'true'
Pl check btnRtn situation if btnRtn is in panel or open ,if it in the panel pl check the panel enabled property and your coding is ok

Editbox portion of ComboBox gets selected automatically

I have a small problem that has been annoying me for some hours.
In my WinForms (.NET 3.5) application I create some ComboBoxes (DropDownStyle = DropDown) in a TableLayoutPanel at runtime and fill it with strings. The ComboBoxes are configured to resize automatically (Anchor = Left | Right).
The problem is that whenever the ComboBoxes are resized (i.e. the dialog is resized), the editbox portion of the ComboBox gets selected/highlighted entirely. In my opinion this creates a very confusing effect for the customer which I want to avoid.
The problem doesn't appear if the ComboBox has a fixed size.
Also note that changing the DropDownStyle is not an option - I need the possibility to enter text manually.
I already tried messing around with overriding the OnPaint method, which didn't quite work.
I also tried clearing the selection in the ComboBox.Resize event, which worked in a way, but seemed like a very ugly solution - there was a lot of flicker, intentionally selected text became deselected and I would have to add the event handler to each and every ComboBox on my dialog.
Is there a better solution to this problem?
Thank you in advance.
Regards,
Andy
This is an old question, but I found it searching for an answer and ended up implementing my own solution. Might as well post it here, right?
foreach (var cb in Controls.OfType<ComboBox>())
{
cb.Resize += (sender, e) => {
if (!cb.Focused)
cb.SelectionLength = 0;
};
}
intentionally selected text became deselected
This WinForms bug doesn't affect selected ComboBoxes, so by ignoring the ones with Focus, we take care of the problem of losing current selections.
I would have to add the event handler
to each and every ComboBox on my
dialog.
Taken care of by the foreach loop. Put it in InitializeComponent() or your .ctor if you don't want to break the designer, or have the designer break this.
there was a lot of flicker
I'm only seeing flicker if I resize very fast, but I'm on Win7 so it might be different on XP.
This appears to be a bug in the native Windows implementation of ComboBox with DropDownStyle of DropDown.
The fix detailed in the other answers here (setting the SelectionLength property to 0 (zero) in the ComboBox's Resize event) works well most of the time.
However, I found that even that fix to work around this bug does not always work. If the ComboBox is in a TableLayoutPanel, and if that TableLayoutPanel has more than one column with a Percent Size Type, then that fix often does not work.
A picture is worth a thousand words. See the following screen shot of a form I made to demonstrate the problem.
Worked for me to change the selectionLength to 0 when the WM_WINDOWPOSCHANGED gets called.
Works even with the tableLayoutPanel set to %.
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if(m.Msg == 0x0047) { // WM_WINDOWPOSCHANGED = 0x0047
if (SelectionLength != 0) {
SelectionLength = 0;
}
}
}
Wow. Thank you guys!
Apparently this bug has persisted many years.
I'm building a UserControl with .Net 4 (Visual Studio 2010).
Here's is my slightlty modified version of bsneeze's code.
Cheers
using System.Windows.Forms;
using System.Linq;
public MyUserControlCtor()
{
InitializeComponent();
foreach( Control ctrl in Controls)
{
ComboBox cb = ctrl as ComboBox;
if (cb != null)
{
cb.Resize += (sender, e) =>
{
if (!cb.Focused)
this.FCHZ_ComboBox.SelectionLength = 0;
};
}
}
}
None of the answers so far worked for me. The only reliable method I have found was to post a message asynchronously via BeginInvoke that sets SelectionLength back to zero after all other activity on the control has completed. The amount of flicker is very annoying and unprofessional, but it is the best I could come up with...so far.
internal class FixedComboBox : ComboBox
{
protected override void OnResize(EventArgs e)
{
if (IsHandleCreated && !Focused)
{
BeginInvoke((Action)(() =>
{
SelectionLength = 0;
}));
}
base.OnResize(e);
}
}
I found setting the selection length to 0 for the combo-box on the resize event of whatever control the combo-box is on causes a lot less flickering instead of doing it on the resize of the combo itself.
I actually achieved this in VB.Net but it should apply the same to C#.
Handle the Resize event for the ComboBox's parent container. Put this line in there:
MyComboBox.SelectionLength = 0
An Example (VB, obviously):
Private Sub MyControl_Resize(sender As Object, e As EventArgs) Handles Me.Resize
MyComboBox.SelectionLength = 0
End Sub
Good Luck to you!
--BP
For a ComboBox inside a TableLayoutPanel setting the .SelectionLength = 0 on the ComboBox.Resize event does not work, but doing this on the TableLayoutPanel.Resize event does:
Private Sub TableLayoutPanel_Resize(sender As Object, e As EventArgs)
Dim curr_panel = TryCast(sender, System.Windows.Forms.TableLayoutPanel)
For Each curr_combo As ComboBox In curr_panel.Controls.OfType(Of ComboBox)
If ((Not curr_combo.Focused) And curr_combo.DropDownStyle = ComboBoxStyle.DropDown) Then
curr_combo.SelectionLength = 0
End If
Next
End Sub
dim panel as new TableLayoutPanel with {
...
}
AddHandler panel.Resize, AddressOf TableLayoutPanel_Resize

Categories

Resources