(design) 2 Elements blocking each other - c#

simple question here:
I have a problem with one of my labels.
My problem is that the (!!!) label corresponding to the textbox "Datei Name" is being blocked by said textbox. Is there a setting that I have missed that puts said label behind/in front of the textbox?
How the (this part of the) program works:
When something is incorrectly entered in one of the textboxes a label containing (!!!) and a Messagebox show up which tell the user where the error is located.

As i mentioned in the comment to the question, i'd use ErrorProvider instead of spending time to write code to manipulate controls on the form.
Here is MSDN example: How to: Display Error Icons for Form Validation with the Windows Forms ErrorProvider Component
How it works?
When the form is NOT valid, you'll see:
When you move cursor over icon, you'll see error details:
If you've got LinqPad, you can use this script to check how it works:
void Main()
{
MyForm mf = new MyForm();
mf.Show();
}
// Define other methods and classes here
public class MyForm: Form
{
private TextBox TxtDateiName = null;
private TextBox TxtDateiNr = null;
private Label Label1 = null;
private Label Label2 = null;
private Button BtnValidate = null;
Dictionary<Control, ErrorProvider> ValidatedControls = null;
public MyForm()
{
Initialize();
}
private void Initialize()
{
this.Size = new Size(250, 180);
this.MinimizeBox = false;
this.MaximizeBox = false;
this.Text = "ErrorProvider Example";
Label1 = new Label(){Text="Datei Name:", Location =new Point(10,12), AutoSize = true};
Label2 = new Label(){Text="Datei Nr:", Location =new Point(10,42), AutoSize = true};
TxtDateiName = new TextBox(){Name="TxtDateiName", Size= new Size(140,24), Location =new Point(78,10)};
TxtDateiNr = new TextBox(){Name="TxtDateiNr", Size= new Size(140,24), Location =new Point(78,42)};
BtnValidate = new Button(){Size = new Size(220, 48), Text = "Validate", Location = new Point(10, 78) };
BtnValidate.Click += BtnValidate_Click;
this.Controls.Add(Label1);
this.Controls.Add(Label2);
this.Controls.Add(TxtDateiName);
this.Controls.Add(TxtDateiNr);
this.Controls.Add(BtnValidate);
ValidatedControls = new Dictionary<Control, ErrorProvider>();
ValidatedControls.Add(TxtDateiName, new ErrorProvider(this));
ValidatedControls.Add(TxtDateiNr, new ErrorProvider(this));
ValidatedControls[TxtDateiName].SetIconAlignment(TxtDateiName, ErrorIconAlignment.MiddleRight);
ValidatedControls[TxtDateiName].SetIconPadding (TxtDateiName, 2);
ValidatedControls[TxtDateiName].BlinkRate = 1000;
ValidatedControls[TxtDateiName].BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink;
ValidatedControls[TxtDateiNr].SetIconAlignment(TxtDateiName, ErrorIconAlignment.MiddleRight);
ValidatedControls[TxtDateiNr].SetIconPadding (TxtDateiName, 2);
ValidatedControls[TxtDateiNr].BlinkRate = 1000;
ValidatedControls[TxtDateiNr].BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink;
}
private void BtnValidate_Click(object sender, EventArgs e)
{
bool ans = true;
foreach(var k in ValidatedControls.Keys)
{
switch(k.Name)
{
case "TxtDateiName":
ans = IsValidName(((TextBox)k).Text);
ValidatedControls[k].SetError(k, ans ? "" : "Name is wrong!");
break;
case "TxtDateiNr":
ans = IsValidNumber(((TextBox)k).Text);
ValidatedControls[k].SetError(k, ans ? "" : "Number is wrong!");
break;
}
}
ans = ValidatedControls.All(kvp=>kvp.Value.GetError(kvp.Key)=="");
MessageBox.Show(ans ? "Form is valid!" : "Form contains errors!", "Information");
if(ans) this.Close();
}
private bool IsValidName(string dName)
{
return Regex.IsMatch(dName, #"^(\w{3,})$");
}
private bool IsValidNumber(string dNumber)
{
return Regex.IsMatch(dNumber, #"^(\d{3,5})$");
}
}
Do not forget to add references (F4) to: System.Windows.Forms.dll
and then add the following namespaces:
System.Drawing
System.Windows.Forms
Final note:
This is just an example. So, the code is not optimized.

Related

How to create custom message in C#?

I am design a custom message box. This message box will show a list of string. But it's not work. Can you hep me to fix it.
You can see in the picture, I have a list with 7 items. When i click the "Grade Project", the Message box don't show any item.
And this is the result I need
//Main form
private void btnGrade_Click(object sender, EventArgs e)
{
List<string> result = new List<string>();
result.Add("True");
result.Add("False");
result.Add("True");
result.Add("False");
result.Add("True");
result.Add("False");
result.Add("False");
MsgBox.Show(result,"Project 1",MsgBox.Buttons.OK);
}
This is code in msgbox form
//MsgBox form
public partial class MsgBox : Form
{
private static MsgBox _msgBox;
// Header, Footer
private Panel _plHeader = new Panel();
private Label _lblTitle;
private Panel _plFooter = new Panel();
private Panel _plIcon = new Panel();
// Panel
private FlowLayoutPanel _flpButtons = new FlowLayoutPanel();
// button
private List<Button> _buttonCollection = new List<Button>();
// Kết quả
private static DialogResult _buttonResult;
// Message
private List<String> _lblMessage;
private MsgBox()
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.BackColor = Color.FromArgb(45, 45, 48);
this.StartPosition = FormStartPosition.CenterScreen;
this.Padding = new System.Windows.Forms.Padding(3);
this.Width = 800;
// Header
_lblTitle = new Label();
_lblTitle.ForeColor = Color.White;
_lblTitle.Font = new System.Drawing.Font("Segoe UI", 18);
_lblTitle.Dock = DockStyle.Top;
_lblTitle.Height = 60;
// Message
_lblMessage = new List<string>();
for (int i = 0; i < _lblMessage.Count; i++)
{
TextBox txt = new TextBox(); //Create Textbox có name txt
txt.Text = _lblMessage[i];
txt.ForeColor = Color.Red;
txt.Font = new System.Drawing.Font("Segoe UI", 30);
this.Controls.Add(txt); //add control txt
}
_flpButtons.FlowDirection = FlowDirection.RightToLeft;
_flpButtons.Dock = DockStyle.Fill;
_plHeader.Dock = DockStyle.Fill;
_plHeader.Padding = new Padding(20);
// _plHeader.Controls.Add(_lblMessage);
_plHeader.Controls.Add(_lblTitle);
_plFooter.Dock = DockStyle.Bottom;
_plFooter.Padding = new Padding(20);
_plFooter.BackColor = Color.FromArgb(37, 37, 38);
_plFooter.Height = 80;
_plFooter.Controls.Add(_flpButtons);
// Add controls vào form
this.Controls.Add(_plHeader);
//this.Controls.Add(_plIcon);
this.Controls.Add(_plFooter);
}
public static DialogResult Show(List<String> message, string title, Buttons buttons)
{
_msgBox = new MsgBox();
_msgBox._lblMessage = message;
_msgBox._lblTitle.Text = title;
_msgBox._plIcon.Hide();
MsgBox.InitButtons(buttons);
_msgBox.ShowDialog();
return _buttonResult;
}
Thank you for your watching.
Something wrong with your codes:
private MsgBox()
{
...
// Message
_lblMessage = new List<string>();
...
}
Your _lblMessage will always be an empty list so you see no message at all.
You can change your codes like this:
private MsgBox(List<String> messages)
{
...
// Message
_lblMessage = messages;
...
}
public static DialogResult Show(List<String> message, string title)
{
_msgBox = new MsgBox(message);
//_msgBox._lblMessage = message;
....
}
And also, you'd better set TextBox position otherwise all the TextBox will overlap with each other.

Form based on selected menu item

I have made a sidebar that I dock on the left side of my application.
Now I'm wondering what's the best way to show a form based on the menu option they've selected from my sidebar.
This is basically what I want to do:
http://www.dreamincode.net/forums/topic/176782-building-an-application-poscash-register-part-one/
On the left is my menu bar, on the right side I want to have a form based on the option clicked on the left.
I have looked into MDI but when I do that I always get a ControlBox even though I've disabled it in the child form.
Update: Seems that this works as well:
Looks like you can also create your own user controls to do it:
User controls
If you want second wont allow you to access your main form unless its closed.then use this...
second_form_name sfn = new second_form_name();
sfn.ShowDialog();
If you want second allow you to access your main form unless its closed.then use
second_form_name sfn = new second_form_name();
sfn.Show();
First create a panel in your form that will hold your current form's contents (add it to the form but leave it empty for now).
Panel active = new Panel();
this.Controls.Add(active);
Then create a panel containing controls for each form you want to display.
Panel firstFormPanel = new Panel();
firstFormPanel.Add(new Button());
Panel secondFormPanel = new Panel();
secondFormPanel.Add(new Button());
Now assign which panel you want by default:
active = firstFormPanel;
Then when you want to change to a new form (click event in sidebar), assign one of the panels to the active panel like so:
active.Visible = false;
active = secondFormPanel;
active.Visible = true;
Here's a little example i have of a sidebar from my game im making being able to slide a new submenu into visual range. I use a timer to control movement and a list of submenus also a index to determine which to show. as far as i've gotten along theres only one so far so not a prime example.
public List<UserControl> Submenus = new List<UserControl>();
Multiplayer_Menu MPM;
enum At { Left, Right }
At Current = At.Right;
At Go_to = At.Right;
int Submenu_Index = 0;
bool done = false;
public void Load_Submenus()
{
Multiplayer_Menu MM = new Multiplayer_Menu(this);
MainMenu.Controls.Add(MM);
MM.Location = new Point(MainMenu.Size.Width, 0);
MM.Visible = false;
Submenus.Add(MM);
PictureBox PB = new PictureBox();
MainMenu.Controls.Add(PB);
PB.Location = new Point(MainMenu.Size.Width, 0);
PB.Size = new System.Drawing.Size(924, 736);
PB.SizeMode = PictureBoxSizeMode.StretchImage;
PB.ImageLocation = "http://www.taloreal.com/Earth%20Rotation/Rotating.gif";
PB.Visible = true;
}
private void Form1_Load(object sender, EventArgs e)
{
Load_Submenus();
}
public void MML_Multiplayer_Click(object sender, EventArgs e)
{
Submenus[Submenu_Index].Visible = false;
if (Current == At.Left)
Go_to = At.Right;
if (Current == At.Right)
Go_to = At.Left;
ShowHideMenus.Enabled = true;
Submenu_Index = 0;
}
private void ShowHideMenus_Tick(object sender, EventArgs e)
{
Point P = new Point(MainMenu.Location.X, MainMenu.Location.Y);
Size S = new Size(MainMenu.Size.Width, MainMenu.Size.Height);
if (Go_to == At.Left)
{
P = new Point(P.X - 30, P.Y);
S = new Size(S.Width + 30, S.Height);
if (P.X == 0)
{
Submenus[Submenu_Index].Visible = true;
ShowHideMenus.Enabled = false;
Current = Go_to;
}
}
if (Go_to == At.Right)
{
P = new Point(P.X + 30, P.Y);
S = new Size(S.Width - 30, S.Height);
if (P.X == 930)
{
ShowHideMenus.Enabled = false;
Current = Go_to;
}
}
Reposition_Menu(P, S);
}
void Reposition_Menu(Point P, Size S)
{
MainMenu.Location = P;
MainMenu.Size = S;
}

How to add one form into another form winform project

i tried to create a form instance with in another form and then add that form into main form. but the form which i added that is not showing. i want to show that form at center at top of all controls.
here is my code
BBA.Controls.ExecludeSpecialist ucExecludeSpecialist = null;
Form frmContainer = null;
private void btnExclude_Click(object sender, EventArgs e)
{
if (ucExecludeSpecialist != null)
{
if (frmContainer != null)
{
frmContainer.Controls.Remove(ucExecludeSpecialist);
ucExecludeSpecialist = null;
}
}
if (frmContainer != null)
{
this.Controls.Remove(frmContainer);
frmContainer = null;
}
frmContainer = new Form();
frmContainer.ControlBox = false;
frmContainer.StartPosition = FormStartPosition.Manual;
frmContainer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
ucExecludeSpecialist = new BBA.Controls.ExecludeSpecialist();
ucExecludeSpecialist.SaveClicked +=
new BBA.Controls.ExecludeSpecialist.SaveComplete(OnSaveClicked);
ucExecludeSpecialist.CloseClicked +=
new BBA.Controls.ExecludeSpecialist.CloseComplete(OnCloseClicked);
ucExecludeSpecialist.BringToFront();
frmContainer.Height = ucExecludeSpecialist.Height;
frmContainer.Width = ucExecludeSpecialist.Width;
//frmContainer.Top = this.Height - frmContainer.Height / 2;
//frmContainer.Left = this.Height - frmContainer.Height / 2;
frmContainer.BringToFront();
frmContainer.TopLevel = false;
frmContainer.Controls.Add(ucExecludeSpecialist);
this.Controls.Add(frmContainer);
}
please guide me how to show that form on top of all control of another form at center. thanks
If I understand your comment correct, your problem is that a DataGrid overlays your recently added form? Try :
After you have add
frmContainer.Show();
your Form shoul be visible. After that you should solve your problem, if you call ucExecludeSpecialist.BringToFront(); after calling frmContainer.Show();
Example :
private void button1_Click(object sender, EventArgs e)
{
frmContainer = new Form();
frmContainer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmContainer.Height = this.Height / 2;
frmContainer.Width = this.Width / 2;
frmContainer.BackColor = Color.Red;
frmContainer.TopLevel = false;
this.Controls.Add(frmContainer);
frmContainer.Show();
frmContainer.BringToFront();
}

Accessing control from a different function in Winforms

I have a hopefully simple question, for which I could not google up any solution:
I would like to add labels buttons textboxes at runtime, which i can in the constructor of my Form, but I cannot access them outside of the constructor.
Something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
//changeMe.Name = "changeMe";
this.Controls.Add(changeMe);
}
private void btn_changeLabelText_Click(object sender, EventArgs e)
{
//Would like to achieve this:
//changeMe.Text = "You changed me !! ";
//But I found only this solution:
//Label l; l = (Label)this.Controls.Find("changeMe", true)[0]; l.Text = "You changed Me";
}
}
The solution I commented out is the only one I found, but I can't believe there isn't any better one then that. Is there a way to make my controls public for example? Whats a good way of solving this problem?
(The number of controls vary on every time I call my Dialogbox I am trying to design)
Thanks
EDIT --------------------------
After accepting Adil's answer, I stayed with the following solution, which I only find better as the originally outcommented this.Control.Find way, because I also want to have "n" Textboxes, and in thie way I can easily loop through them and read inputs.
public partial class Form1 : Form
{
public struct labels { public Label lbl; public int id; }
List<labels> lbls = new List<labels>();
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
this.Controls.Add(changeMe);
labels newlabel = new labels();
newlabel.id = 137; newlabel.lbl = changeMe;
lbls.Add(newlabel);
}
private void btn_changeLabelText_Click(object sender, EventArgs e)
{
lbls.Find(i => i.id == 137).lbl.Text = "You changed me";
}
}
You declared the label inside constructor that makes it accessible only in constructor, ceclare label out side constructor at class scope as class member.
Label changeMe = new Label();
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
//changeMe.Name = "changeMe";
this.Controls.Add(changeMe);
}

Displaying tooltip over a disabled control

I'm trying to display a tooltip when mouse hovers over a disabled control. Since a disabled control does not handle any events, I have to do that in the parent form. I chose to do this by handling the MouseMove event in the parent form. Here's the code that does the job:
void Form1_MouseMove(object sender, MouseEventArgs e)
{
m_toolTips.SetToolTip(this, "testing tooltip on " + DateTime.Now.ToString());
string tipText = this.m_toolTips.GetToolTip(this);
if ((tipText != null) && (tipText.Length > 0))
{
Point clientLoc = this.PointToClient(Cursor.Position);
Control child = this.GetChildAtPoint(clientLoc);
if (child != null && child.Enabled == false)
{
m_toolTips.ToolTipTitle = "MouseHover On Disabled Control";
m_toolTips.Show(tipText, this, 10000);
}
else
{
m_toolTips.ToolTipTitle = "MouseHover Triggerd";
m_toolTips.Show(tipText, this, 3000);
}
}
}
The code does handles the tooltip display for the disabled control. The problem is that when mouse hovers over a disabled control, the tooltip keeps closing and redisplay again. From the display time I added in the tooltip, when mouse is above the parent form, the MouseMove event gets called roughly every 3 seconds, so the tooltip gets updated every 3 seconds. But when mouse is over a disabled control, the tooltip refreshes every 1 second. Also, when tooltip refreshes above form, only the text gets updated with a brief flash. But when tooltip refreshes above a disabled control, the tooltip windows closes as if mouse is moving into a enabled control and the tooltip is supposed to be closed. but then the tooltip reappears right away.
Can someone tell me why is this? Thanks.
you can show the tooltip only once when mouse hits the disbled control and then hide it when mouse leaves it. Pls, take a look at the code below, it should be showing a tooltip message for all the disabled controls on the form
private ToolTip _toolTip = new ToolTip();
private Control _currentToolTipControl = null;
public Form1()
{
InitializeComponent();
_toolTip.SetToolTip(this.button1, "My button1");
_toolTip.SetToolTip(this.button2, "My button2");
_toolTip.SetToolTip(this.textBox1, "My text box");
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Control control = GetChildAtPoint(e.Location);
if (control != null)
{
if (!control.Enabled && _currentToolTipControl == null)
{
string toolTipString = _toolTip.GetToolTip(control);
// trigger the tooltip with no delay and some basic positioning just to give you an idea
_toolTip.Show(toolTipString, control, control.Width/2, control.Height/2);
_currentToolTipControl = control;
}
}
else
{
if (_currentToolTipControl != null) _toolTip.Hide(_currentToolTipControl);
_currentToolTipControl = null;
}
}
hope this helps, regards
The answer turned out to be a bit simpler, but needed to be applied at all times.
void OrderSummaryDetails_MouseMove(object sender, MouseEventArgs e)
{
Control control = GetChildAtPoint(e.Location);
if (control != null)
{
string toolTipString = mFormTips.GetToolTip(control);
this.mFormTips.ShowAlways = true;
// trigger the tooltip with no delay and some basic positioning just to give you an idea
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height / 2);
}
}
In case of TextBox control, making it as readonly solved the issue.
I tried many but ended up using this simple trick which I think it is more effective.
Create a subclass(CustomControl with just base control in it) which extends UserControl
then instead of setting "Enabled" property to false create a Method which disables just basecontrol in it instead of whole CustomControl.
Set the tool tip on CustomControl still will be able to fire eventhandlers setting the basecontrol disabled. This works wherever CustomControl is in use rather than coding on every form you use with.
Here is the hint.. :)
public partial class MyTextBox : UserControl
{
...
...
...
public void DisableMyTextBox()
{
this.txt.Enabled = false; //txt is the name of Winform-Textbox from my designer
this.Enabled = true;
}
public void EnableMyTextBox()
{
this.txt.Enabled = true;
this.Enabled = true;
}
//set the tooltip from properties tab in designer or wherever
}
Since no one ever pointed this out, this works for any control that exposes ToolTipService:
ToolTipService.ShowOnDisabled="True"
As in this example:
<Button Content="OK"
ToolTipService.ShowOnDisabled="True" />
/*
Inspired by the suggestions above in this post, i wrapped it up as an extended ToolTip control specially works for disabled control.
// Reference example
var td = new ToolTipOnDisabledControl();
this.checkEdit3.Enabled = false;
td.SetTooltip(this.checkEdit3, "tooltip for disabled 3333333333333");
*/
using System;
using System.Windows.Forms;
namespace TestApp1
{
public class ToolTipOnDisabledControl
{
#region Fields and Properties
private Control enabledParentControl;
private bool isShown;
public Control TargetControl { get; private set; }
public string TooltipText { get; private set; }
public ToolTip ToolTip { get; }
#endregion
#region Public Methods
public ToolTipOnDisabledControl()
{
this.ToolTip = new ToolTip();
}
public void SetToolTip(Control targetControl, string tooltipText = null)
{
this.TargetControl = targetControl;
if (string.IsNullOrEmpty(tooltipText))
{
this.TooltipText = this.ToolTip.GetToolTip(targetControl);
}
else
{
this.TooltipText = tooltipText;
}
if (targetControl.Enabled)
{
this.enabledParentControl = null;
this.isShown = false;
this.ToolTip.SetToolTip(this.TargetControl, this.TooltipText);
return;
}
this.enabledParentControl = targetControl.Parent;
while (!this.enabledParentControl.Enabled && this.enabledParentControl.Parent != null)
{
this.enabledParentControl = this.enabledParentControl.Parent;
}
if (!this.enabledParentControl.Enabled)
{
throw new Exception("Failed to set tool tip because failed to find an enabled parent control.");
}
this.enabledParentControl.MouseMove += this.EnabledParentControl_MouseMove;
this.TargetControl.EnabledChanged += this.TargetControl_EnabledChanged;
}
public void Reset()
{
if (this.TargetControl != null)
{
this.ToolTip.Hide(this.TargetControl);
this.TargetControl.EnabledChanged -= this.TargetControl_EnabledChanged;
this.TargetControl = null;
}
if (this.enabledParentControl != null)
{
this.enabledParentControl.MouseMove -= this.EnabledParentControl_MouseMove;
this.enabledParentControl = null;
}
this.isShown = false;
}
#endregion
#region Private Methods
private void EnabledParentControl_MouseMove(object sender, MouseEventArgs e)
{
if (e.Location.X >= this.TargetControl.Left &&
e.Location.X <= this.TargetControl.Right &&
e.Location.Y >= this.TargetControl.Top &&
e.Location.Y <= this.TargetControl.Bottom)
{
if (!this.isShown)
{
this.ToolTip.Show(this.TooltipText, this.TargetControl, this.TargetControl.Width / 2, this.TargetControl.Height / 2, this.ToolTip.AutoPopDelay);
this.isShown = true;
}
}
else
{
this.ToolTip.Hide(this.TargetControl);
this.isShown = false;
}
}
private void TargetControl_EnabledChanged(object sender, EventArgs e)
{
if (TargetControl.Enabled)
{
TargetControl.EnabledChanged -= TargetControl_EnabledChanged;
enabledParentControl.MouseMove -= EnabledParentControl_MouseMove;
}
}
#endregion
}
}
Here is how I solved this problem
I have an application that generates code automatically for a PIC32MX.
The application has 3 Tab Pages text = PWM, ADC and UART.
On each Tab Page I have one Check Box text = RPA0
The intention is, when a peripheral uses RPA0, the other peripheral is prevented
from using that pin, by disabling it on the other pages, and a tooltip text must pop up
on the disabled check boxs saying (example "Used by PWM")
what peripheral is using that pin.
The problem is that the tooltip text won't pop up on a disabled check box.
To solve the problem, I just removed the text of the check boxes and inserted labels with the text the check box should have.
When a check box is checked, the other check boxes are disabled and the label next to it takes a tool tip text.
As the label is enabled, the tooltip text pops up, even on a disabled check box.
Double the work, half the complexity.
Here is the code and the designer for C# 2010
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void cb_ADC_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_UART_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_PWM_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_PWM_RPA0, lbl_UART_RPA0, "ADC");
}
private void cb_PWM_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_UART_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_ADC_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_ADC_RPA0, lbl_UART_RPA0, "PWM");
}
private void cb_UART_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_ADC_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_PWM_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_ADC_RPA0, lbl_PWM_RPA0, "UART");
}
void SetTootTip(CheckBox sender, Label lbl1, Label lbl2, string text)
{
/* Update tooltip on the other labels */
if (sender.Checked)
{
toolTip1.SetToolTip(lbl1, "Used by " + text);
toolTip1.SetToolTip(lbl2, "Used by " + text);
}
else
{
toolTip1.SetToolTip(lbl1, "");
toolTip1.SetToolTip(lbl2, "");
}
}
}
}
namespace WindowsFormsApplication1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tpPWM = new System.Windows.Forms.TabPage();
this.tpUART = new System.Windows.Forms.TabPage();
this.tpADC = new System.Windows.Forms.TabPage();
this.cb_PWM_RPA0 = new System.Windows.Forms.CheckBox();
this.cb_ADC_RPA0 = new System.Windows.Forms.CheckBox();
this.lbl_PWM_RPA0 = new System.Windows.Forms.Label();
this.lbl_ADC_RPA0 = new System.Windows.Forms.Label();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.lbl_UART_RPA0 = new System.Windows.Forms.Label();
this.cb_UART_RPA0 = new System.Windows.Forms.CheckBox();
this.tabControl1.SuspendLayout();
this.tpPWM.SuspendLayout();
this.tpUART.SuspendLayout();
this.tpADC.SuspendLayout();
this.SuspendLayout();
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tpPWM);
this.tabControl1.Controls.Add(this.tpUART);
this.tabControl1.Controls.Add(this.tpADC);
this.tabControl1.Location = new System.Drawing.Point(12, 12);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(629, 296);
this.tabControl1.TabIndex = 0;
//
// tpPWM
//
this.tpPWM.Controls.Add(this.lbl_PWM_RPA0);
this.tpPWM.Controls.Add(this.cb_PWM_RPA0);
this.tpPWM.Location = new System.Drawing.Point(4, 22);
this.tpPWM.Name = "tpPWM";
this.tpPWM.Padding = new System.Windows.Forms.Padding(3);
this.tpPWM.Size = new System.Drawing.Size(621, 270);
this.tpPWM.TabIndex = 0;
this.tpPWM.Text = "PWM";
this.tpPWM.UseVisualStyleBackColor = true;
//
// tpUART
//
this.tpUART.Controls.Add(this.cb_UART_RPA0);
this.tpUART.Controls.Add(this.lbl_UART_RPA0);
this.tpUART.Location = new System.Drawing.Point(4, 22);
this.tpUART.Name = "tpUART";
this.tpUART.Padding = new System.Windows.Forms.Padding(3);
this.tpUART.Size = new System.Drawing.Size(621, 270);
this.tpUART.TabIndex = 1;
this.tpUART.Text = "UART";
this.tpUART.UseVisualStyleBackColor = true;
//
// tpADC
//
this.tpADC.Controls.Add(this.lbl_ADC_RPA0);
this.tpADC.Controls.Add(this.cb_ADC_RPA0);
this.tpADC.Location = new System.Drawing.Point(4, 22);
this.tpADC.Name = "tpADC";
this.tpADC.Padding = new System.Windows.Forms.Padding(3);
this.tpADC.Size = new System.Drawing.Size(621, 270);
this.tpADC.TabIndex = 2;
this.tpADC.Text = "ADC";
this.tpADC.UseVisualStyleBackColor = true;
//
// cb_PWM_RPA0
//
this.cb_PWM_RPA0.AutoSize = true;
this.cb_PWM_RPA0.Location = new System.Drawing.Point(17, 65);
this.cb_PWM_RPA0.Name = "cb_PWM_RPA0";
this.cb_PWM_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_PWM_RPA0.TabIndex = 0;
this.cb_PWM_RPA0.UseVisualStyleBackColor = true;
this.cb_PWM_RPA0.CheckedChanged += new System.EventHandler(this.cb_PWM_RPA0_CheckedChanged);
//
// cb_ADC_RPA0
//
this.cb_ADC_RPA0.AutoSize = true;
this.cb_ADC_RPA0.Location = new System.Drawing.Point(17, 65);
this.cb_ADC_RPA0.Name = "cb_ADC_RPA0";
this.cb_ADC_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_ADC_RPA0.TabIndex = 1;
this.cb_ADC_RPA0.UseVisualStyleBackColor = true;
this.cb_ADC_RPA0.CheckedChanged += new System.EventHandler(this.cb_ADC_RPA0_CheckedChanged);
//
// lbl_PWM_RPA0
//
this.lbl_PWM_RPA0.AutoSize = true;
this.lbl_PWM_RPA0.Location = new System.Drawing.Point(38, 65);
this.lbl_PWM_RPA0.Name = "lbl_PWM_RPA0";
this.lbl_PWM_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_PWM_RPA0.TabIndex = 1;
this.lbl_PWM_RPA0.Text = "RPA0";
//
// lbl_ADC_RPA0
//
this.lbl_ADC_RPA0.AutoSize = true;
this.lbl_ADC_RPA0.Location = new System.Drawing.Point(38, 66);
this.lbl_ADC_RPA0.Name = "lbl_ADC_RPA0";
this.lbl_ADC_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_ADC_RPA0.TabIndex = 2;
this.lbl_ADC_RPA0.Text = "RPA0";
//
// lbl_UART_RPA0
//
this.lbl_UART_RPA0.AutoSize = true;
this.lbl_UART_RPA0.Location = new System.Drawing.Point(37, 65);
this.lbl_UART_RPA0.Name = "lbl_UART_RPA0";
this.lbl_UART_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_UART_RPA0.TabIndex = 4;
this.lbl_UART_RPA0.Text = "RPA0";
//
// cb_UART_RPA0
//
this.cb_UART_RPA0.AutoSize = true;
this.cb_UART_RPA0.Location = new System.Drawing.Point(16, 65);
this.cb_UART_RPA0.Name = "cb_UART_RPA0";
this.cb_UART_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_UART_RPA0.TabIndex = 5;
this.cb_UART_RPA0.UseVisualStyleBackColor = true;
this.cb_UART_RPA0.CheckedChanged += new System.EventHandler(this.cb_UART_RPA0_CheckedChanged);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(758, 429);
this.Controls.Add(this.tabControl1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.tabControl1.ResumeLayout(false);
this.tpPWM.ResumeLayout(false);
this.tpPWM.PerformLayout();
this.tpUART.ResumeLayout(false);
this.tpUART.PerformLayout();
this.tpADC.ResumeLayout(false);
this.tpADC.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tpPWM;
private System.Windows.Forms.Label lbl_PWM_RPA0;
private System.Windows.Forms.CheckBox cb_PWM_RPA0;
private System.Windows.Forms.TabPage tpUART;
private System.Windows.Forms.TabPage tpADC;
private System.Windows.Forms.Label lbl_ADC_RPA0;
private System.Windows.Forms.CheckBox cb_ADC_RPA0;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.CheckBox cb_UART_RPA0;
private System.Windows.Forms.Label lbl_UART_RPA0;
}
}
I created a new UserControl which only contains a button.
public partial class TooltipButton : UserControl
{
public TooltipButton()
{
InitializeComponent();
}
public new bool Enabled
{
get { return button.Enabled; }
set { button.Enabled = value; }
}
[Category("Appearance")]
[Description("The text displayed by the button.")]
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public override string Text
{
get { return button.Text; }
set { button.Text = value; }
}
[Category("Action")]
[Description("Occurs when the button is clicked.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new event EventHandler Click;
private void button_Click(object sender, EventArgs e)
{
// Bubble event up to parent
Click?.Invoke(this, e);
}
}
I found Serge_Yubenko's code worked on disabled buttons , but in order to stop the flashing make sure the tooltip pops up away from the button - just don't position it half way down the control but do this:
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height);
instead of
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height / 2);
This seems to follow the usual tooltip placement too...
So, I came across this post in my efforts to do the same thing, being the top result on Google. I had already considered the mouse move event and while the answers here did help, they didn't provide me with exactly what I wanted - that being a perfect recreation of the original show tooltip event.
The problem I discovered was this: For whatever reason in the API, ToolTip.Show turns the Mouse Move Event into effectively a Mouse Hover Event. Which is why the tooltip keeps flashing.
The workaround as suggested was to keep the tooltip on always show, or to display the tooltip away from the control, but that wouldn't be a faithful recreation, from the show to the timed fade. The answer would suggest that a block to prevent further execution of the code is needed - the reality was 2 blocks in the event code (One of which has no earthly reason existing and yet without it a timed event fires twice ***), a double delclaration of the control location, one inside the event, one class wide, and another class wide to check if the mouse is over a control, a class wide timer, and a Mouse Leave event to clean up due to too fast mouse movement away from the panel housing the control.
As you will see there are two events on the timer, both functions for them are in the event code as they need to reference variables get/set in the code. They can be moved out, but would then need class wide declarations on the variables, and they cause no harm where they are. FYI: "ToolTips" in the code is referencing the ToolTip control I have on the form.
*** Just to expand. If you look at the code you'll see that IsTipReset could be replaced with IsShown - after all they end up at the same value as each other. The reason for IsTipRest is this: If IsShown is used then while moving the mouse inside the control while the tootip is showing will cause a slight hiccup when the tooltip fades and very very very briefly another tooltip will popup. Using IsTipReset stops that. I have no idea why and maybe someone will spot it because I sure can't! Lol.
This is my first post here, and I realise it is an old thread, but I just wanted to share the fruits of my labour. As I said, my goal was a faithful recreation of tooltip and I think I achieved it. Enjoy!
using Timer = System.Windows.Forms.Timer;
private readonly Timer MouseTimer = new();
private Control? Ctrl;
private bool IsControl = false;
private void TopMenuMouseMove (object sender, MouseEventArgs e) {
Panel Pnl = (Panel)sender;
Control Area = Pnl.GetChildAtPoint (e.Location);
bool IsShown = false;
bool IsTipReset = false;
if (Area != null && Area.Enabled == false && Area.Visible == true) {
Ctrl = Pnl.GetChildAtPoint (e.Location);
Point Position = e.Location;
if (IsControl) { IsShown = true; } else if (!IsControl) { IsControl = true; IsShown = false; }
if (!IsShown) {
MouseTimer.Interval = ToolTips.InitialDelay;
MouseTimer.Tick += new EventHandler (TimerToolTipShow!);
MouseTimer.Start ();
}
void TimerToolTipShow (object sender, EventArgs e) {
if (!IsTipReset) {
MouseTimer.Dispose ();
string Txt = ToolTips.GetToolTip (Ctrl) + " (Disabled)";
Position.Offset (-Ctrl.Left, 16);
ToolTips.Show (Txt, Ctrl, Position);
MouseTimer.Interval = ToolTips.AutoPopDelay;
MouseTimer.Tick += new EventHandler (TimerToolTipReset!);
MouseTimer.Start ();
IsShown = true;
IsTipReset = true;
}
}
void TimerToolTipReset (object sender, EventArgs e) {
if (IsShown) {
MouseTimer.Dispose ();
IsShown = false;
ToolTips.Hide (Ctrl);
}
}
}
else if (Area == null) {
if (Ctrl != null) {
MouseTimer.Dispose ();
IsShown = false;
IsControl = false;
ToolTips.Hide (Ctrl);
Ctrl = null;
}
}
}
private void TopMenuMouseLeave (object sender, EventArgs e) {
if (Ctrl != null) {
MouseTimer.Dispose ();
IsControl = false;
ToolTips.Hide (Ctrl);
Ctrl = null;
}
}

Categories