I have a usercontrol2 (custom) on a form. I have defined a tooltip on the user control. The usercontrol2 has some child controls on it.
I want the tooltip to be shown when i click on a specific child control on usercontrol2. The tooltip should hide only if i click outside the child control.
The tooltip is shown when i click on the child control but is hidden once i move the mouse position. Also, when i click outside the child control and i click on the child control again, the tooltip is not shown.
The child control is named usercontrol1.
public partial class UserControl2 : UserControl
{
private Boolean IsToolTipShown;
public UserControl2()
{
InitializeComponent();
WireControl(userControl11);
InitiliseToolTip();
}
private void WireControl(Control cont)
{
cont.MouseClick += UserControlMouseClick;
foreach (Control ctl in cont.Controls)
{
ctl.MouseClick += UserControlMouseClick;
if (ctl.HasChildren) WireControl(ctl);
}
}
private void UserControlMouseClick(object sender, MouseEventArgs e)
{
if (!IsToolTipShown)
{
string s = null;
for (int i = 0; i < 5; i++)
{
s += string.Concat(i, Environment.NewLine);
}
toolTip1.Show(s, userControl11);
IsToolTipShown = true;
}
}
private void InitiliseToolTip()
{
IsToolTipShown = false;
toolTip1.AutomaticDelay = 0;
toolTip1.BackColor = Color.Chartreuse;
toolTip1.StripAmpersands = true;
toolTip1.ToolTipIcon = ToolTipIcon.Info;
toolTip1.UseFading = false;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (IsToolTipShown)
{
toolTip1.Hide(userControl11);
IsToolTipShown = false;
}
}
}
Related
I want to display message that button is unclickable (I have used Enabled option, button1.Enabled = false/true; ). Does anyone know how to detect if button is clicked, when it is unclickable in order to display error message "Button is unclickable...".
Windows forms, C#
Whenever a standard control doesn't behave in exactly the way that need it to, all we usually have to do is make our own version that inherits the standard control so that we can make it do whatever we want. Your question offers a great reason for doing that because a normally a disabled Button is not going to fire a Click or a MouseDown event.
Here is a guideline example for a custom Button that:
Intercepts the Enabled property by declaring it new.
Leaves the base class button always responsive because it's always enabled.
Paints the control as dimmed if disabled.
Suppresses the firing of the Click event if disabled, and fires DisabledClick instead.
Look in the Title Bar to see when the button is clicked.
ButtonWithDisabledOption class
class ButtonWithDisableOption : Button
{
bool _enabled = true;
public new bool Enabled
{
get => _enabled;
set
{
if (!Equals(_enabled, value))
{
_enabled = value;
OnEnabledChanged(EventArgs.Empty);
}
}
}
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
if(Enabled)
{
ForeColor = SystemColors.ControlText;
BackColor = SystemColors.Control;
FlatStyle = FlatStyle.Standard;
}
else
{
ForeColor = Color.FromArgb(191, 191, 191);
BackColor = Color.FromArgb(204, 204, 204);
FlatStyle = FlatStyle.Flat;
}
}
protected override void OnClick(EventArgs e)
{
if (Enabled)
{
base.OnClick(e);
}
else
{
DisabledClick?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler DisabledClick;
}
MainForm.Designer.cs
Be sure to replace Button references with ButtonWithDisabledOption.
private void InitializeComponent()
{
// this.buttonWithDisableOption = new System.Windows.Forms.Button();
this.buttonWithDisableOption = new button_with_disabled_option.ButtonWithDisableOption();
...
}
// private System.Windows.Forms.Button button1;
private button_with_disabled_option.ButtonWithDisableOption buttonWithDisableOption;
TEST
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
buttonWithDisableOption.Enabled = checkBoxButtonEnabled.Checked = true;
// Button events
buttonWithDisableOption.Click += buttonWithDisableOption_Click;
buttonWithDisableOption.DisabledClick += buttonWithDisableOption_DisabledClick;
// CheckBox events
checkBoxButtonEnabled.CheckedChanged += checkBoxButtonEnabled_CheckedChanged;
}
private void checkBoxButtonEnabled_CheckedChanged(object sender, EventArgs e)
{
buttonWithDisableOption.Enabled = checkBoxButtonEnabled.Checked;
}
private void buttonWithDisableOption_Click(object sender, EventArgs e)
{
// Title bar
Text = $"Button Click {_tstcount++} (Enabled)";
}
private void buttonWithDisableOption_DisabledClick(object sender, EventArgs e)
{
// Title bar
Text = $"Button Click {_tstcount++} (Disabled)";
MessageBox.Show("Button is unclickable");
}
int _tstcount = 1;
}
I am new to C#. I am using windows forms.
As shown in screenshot, I have form1 with 4 buttons and 4 user controls.
click show UserControl1 and UserControl1 shows up.
click show UserControl2 and UserControl2 shows up.
click show UserControl3 and UserControl3 shows up.
click show UserControl4 and UserControl4 shows up.
what I want to do is: when I click Show Previous UC (on User Control4) , the previous User Control shows up.
for example:
click show UserControl2 and UserControl2 shows up.
click show UserControl4 and UserControl4 shows up.
and now I want when I click Show Previous UC, UserControl2 shows up (the previous user control).
How Can I show the previous User Control ( the last one which was shown before the current one)?
Please help me, Thank you.
public partial class Form1 : Form
{
UserControl1 UC1 = new UserControl1();
UserControl2 UC2 = new UserControl2();
UserControl3 UC3 = new UserControl3();
UserControl4 UC4 = new UserControl4();
public Form1()
{
InitializeComponent();
Controls.Add(UC1);
Controls.Add(UC2);
Controls.Add(UC3);
Controls.Add(UC4);
}
private void ShowUserControl1_Click(object sender, EventArgs e)
{
UC1.Visible = true;
UC2.Visible = false;
UC3.Visible = false;
UC4.Visible = false;
}
private void ShowUserControl2_Click(object sender, EventArgs e)
{
UC2.Visible = true;
UC1.Visible = false;
UC3.Visible = false;
UC4.Visible = false;
}
private void ShowUserControl3_Click(object sender, EventArgs e)
{
UC3.Visible = true;
UC1.Visible = false;
UC2.Visible = false;
UC4.Visible = false;
}
private void ShowUserControl4_Click(object sender, EventArgs e)
{
UC4.Visible = true;
UC3.Visible = false;
UC2.Visible = false;
UC1.Visible = false;
}
}
You need to keep track of which user control was the previous in the page (and possible also the current, unless you want to iterate the UCs to find out). Use fields for this in the page.
public partial class Form1 : Form
{
UserControl[] userControls = new []{
new UserControl1(),
new UserControl2(),
new UserControl3(),
new UserControl4()
};
UserControl previous;
UserControl current;
public Form1()
{
InitializeComponent();
foreach(var uc in UserControls)
{
uc.Click += ShowPrevControl_Click;
Controls.Add(uc);
}
}
In the event (you only need one)
private void ShowUserControl_Click(object sender, EventArgs e)
{
foreach(UserControl uc in UserControls)
{
if(uc.Name == (string)((Control)sender).Tag)
{
previous = current;
uc.Visible = true;
current = uc;
}
else
{
uc.Visible = false;
}
}
}
private void ShowPrevControl_Click(object sender, EventArgs e)
{
if (previous != null)
{
foreach(var uc in UserControls)
{
uc.Visible = false;
}
var temp = current;
previous.Visible = true;
current = previous;
previous = temp;
}
}
Set the Tag property for each button to hold the name of the UserControl it should control (UserControl1, UserControl2, UserControl3 or UserControl4).
Let all the buttons click events be handled by ShowUserControl_Click.
Create a new public event in your user controls (if all should handle clicks), that that page can handle using your ShowPrevControl_Clickmethod:
public UserControlx : UserControl
{
public event EventHandler Click;
public UserControlx()
{
Button.Click += Button_Click;
}
private void Button_Click(object sender, EventArgs e)
{
if(Click != null)
Click(this, EventArgs.Empty);
}
}
An easy solution is to add a member variable to your class.
So your class would look like:
public partial class Form1 : Form
{
UserControl prevControl;
// Etc...
So when you click the button for, say, UC2, you can set prevControl to UC2.
private void ShowUserControl2_Click(object sender, EventArgs e)
{
UC2.Visible = true;
prevControl = UC2;
UC1.Visible = false;
UC3.Visible = false;
UC4.Visible = false;
}
And on an event handler for the "Show previous control" button:
private void ShowPrevControl_Click(object sender, EventArgs e)
{
if (prevControl != null) prevControl.Visible = true;
}
UserControl is a reference in C#, which makes this possible.
I have a UserControl that has someother controls:
I need to enable click on any item I click of the user control so I can set the UserControl borderstyle.
This works if I don't have any control added, but If I have for example a panel and I try to click on the panel my UserControl's click event doesn't get fired.
This is my code:
public partial class TestControl : UserControl
{
public TestControl()
{
InitializeComponent();
this.Click += Item_Click;
IsSelected = false;
}
public bool IsSelected { get; set; }
void Item_Click(object sender, EventArgs e)
{
if (!IsSelected)
{
IsSelected = true;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
}
else
{
IsSelected = false;
this.BorderStyle = System.Windows.Forms.BorderStyle.None;
}
}
}
Any clue on how to fire my UserControl click's event even if I click over other elements?
Actually it's really simple to achieve this, you can iterate through all the controls contained in your UserControl and register the Item_Click to their EventHandler which will invoke it when the Click event is fired:
public partial class TestControl : UserControl {
public TestControl( ) {
//...
for ( int i = 0; i < Controls.Count; i++ ) {
Controls[ i ].Click += Item_Click;
}
}
//...
}
I have a custom TabPage class:
class CustomTabPage : TabPage
{
TextBox tbCode = new TextBox();
public CustomTabPage()
{
}
public CustomTabPage(string title)
{
tbCode.Multiline = true;
tbCode.Size = this.Size;
}
//Something like this...
private void OnThisControlSizeChanged()
{
tbCode.Size = this.Size;
}
}
What I need for this class is to raise the OnSizeChanged event of the TabPage control when I resize it from where I create the control. The reason for this is when I resize the TabPage control, I want to adapt the TextBox size accordingly so that they stay the same.
class CustomTabPage : TabPage
{
TextBox tbCode = new TextBox();
public CustomTabPage()
{
SizeChanged += CustomTabPage_SizeChanged;
}
void CustomTabPage_SizeChanged(object sender, EventArgs e)
{
OnThisControlSizeChanged();
}
public CustomTabPage(string title)
{
tbCode.Multiline = true;
tbCode.Size = this.Size;
}
private void OnThisControlSizeChanged()
{
tbCode.Size = this.Size;
}
}
this.OnSizeChanged(new EventArgs());
I am trying to change the BackColor property of a User Control and ForeColor of a label inside it. Following is my code:
private void NRow_MouseLeave(object sender, EventArgs e)
{
BackColor = Color.White;
label1.ForeColor = Color.Black;
}
private void NRow_MouseEnter(object sender, EventArgs e)
{
BackColor = Color.Lime;
label1.ForeColor = Color.White;
}
But its not working. Even I tried to add breakpoint on BackColor changing line but control is not reaching there. I also checked the event binding, its ok. The user control is added to a panel like this:
notContainer.Controls.Add(new NRow());
I don't know what is happening. Please help.
UPDATE:
Event handlers are attached like this:
this.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
this.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);
If your label1 placed inside your user control (UC) NRow, you should be handle MouseEnter and MouseEvent of label1 too. Because, your label1 inside your UC can be handles your mouse events instead your UC when the mouse moves over it.
this.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
this.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);
label1.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
label1.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);
Note: all of above lines should be placed inside your UC NRow.
I was able to get it working by overriding the UserControl's OnMouseLeave and OnMouseEnter and using the PointToClient Method to determine if the mouse coordinates are still within the UserControl before reverting, see if something like this works for you.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
protected override void OnMouseEnter(EventArgs e)
{
BackColor = Color.Lime;
label1.ForeColor = Color.White;
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (! Bounds.Contains(PointToClient( MousePosition)))
{
BackColor = Color.White;
label1.ForeColor = Color.Black;
base.OnMouseLeave(e);
}
}
}
You can try this code to pass messages from child controls to your UserControl, in your case you need to pass the message WM_MOUSEMOVE plus some little code to make it work as expected:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
Dictionary<Control,NativeControl> controls = new Dictionary<Control,NativeControl>();
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
OnMouseLeave(e);
}
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.HandleCreated += ControlsHandleCreated;
base.OnControlAdded(e);
}
protected override void OnControlRemoved(ControlEventArgs e)
{
e.Control.HandleCreated -= ControlsHandleCreated;
base.OnControlRemoved(e);
}
private void ControlsHandleCreated(object sender, EventArgs e)
{
Control control = sender as Control;
NativeControl nc;
if(!controls.TryGetValue(control, out nc)) {
nc = new NativeControl(this);
controls[control] = nc;
}
nc.AssignHandle(control.Handle);
}
public class NativeControl : NativeWindow
{
public NativeControl(UserControl1 parent)
{
Parent = parent;
}
UserControl1 Parent;
bool entered;
protected override void WndProc(ref Message m)
{
//WM_MOUSEMOVE = 0x200
//WM_LBUTTONDOWN = 0x201
//WM_LBUTTONUP = 0x202
//WM_NCHITTEST = 0x84
if (m.Msg == 0x200 || m.Msg == 0x201 || m.Msg == 0x202 || m.Msg == 0x84){
//Check if Parent is not nul, pass these messages to the parent
if (Parent != null){
m.HWnd = Parent.Handle;
Parent.WndProc(ref m);
}
if (m.Msg == 0x200 && !entered){
entered = true;
Parent.OnMouseEnter(EventArgs.Empty);
}
else entered = false;
}
else if (entered) entered = false;
base.WndProc(ref m);
}
}
}