I need to display a Form as a ToolTip of an UserControl. When the mouse is over the UserControl, the Form have to be show, and when the mouse leave that UserControl, the Form have to be hide.
I've overrided these events, in my UserControl class :
public partial class TreatedMetricsDisplay : UserControl
{
private TreatedMetricsWindow _treatedMetricsWindow;
public TreatedMetricsDisplay()
{
InitializeComponent();
_treatedMetricsWindow = new TreatedMetricsWindow ();
}
protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover (e);
this._treatedMetricsWindow.Show();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave (e);
this._treatedMetricsWindow.Close ();
}
}
No exceptions, but events are not called.
Showing the Form will steal the Focus, It will get activated. So, it isn't a good idea to show Form as ToolTip. It will not behave as one would expect.
You need to use ToolStripDropDown combined with ToolStripControlHost. Which makes it possible to show any control as tooltip(not exactly).
public partial class MainForm : Form
{
private ToolStripDropDown dropDown = new ToolStripDropDown();
public MainForm()
{
InitializeComponent();
dropDown.Items.Add(new ToolStripControlHost(new ToolTipUserControl() { Size = new Size(200, 200) }));
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
dropDown.Show(MousePosition);
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
dropDown.Hide();
}
}
ToolTipUserControl could be any Control which you want to show as tooltip.
Here is a code sample that might help:
private void ToolTipControl_Load(object sender, EventArgs e)
{
AttachHandlers(this);
}
private void AttachHandlers(Control currentControl)
{
foreach (Control control in currentControl.Controls)
{
control.MouseHover += GenericMouseHover;
control.MouseLeave += GenericMouseLeave;
if (control.Controls.Count != 0)
{
AttachHandlers(control);
}
}
}
void GenericMouseLeave(object sender, EventArgs e)
{
// no need to hide it if there was no form created in first place
if(_form != null && _form.Visible)
Form.Hide();
}
private void GenericMouseHover(object sender, EventArgs e)
{
Form.Location = this.PointToClient(Cursor.Position);
Form.Show();
}
ToolTipForm _form;
private ToolTipForm Form
{
get
{
if (_form == null)
{
_form = new ToolTipForm();
}
return _form;
}
}
Related
I have two user controls usercontrol_1 and usercontrol_2, using a click event i am bring in usercontrol_1 to a panel called panel_screen on my main form.
private void btn_Click(object sender, EventArgs e)
{
if (!panel_screen.Controls.Contains(usercontrol_1.Instance))
{
panel_screen.Controls.Add(usercontrol_1.Instance);
usercontrol_1.Instance.Dock = DockStyle.Fill;
usercontrol_1.Instance.BringToFront();
}
else
usercontrol_1.Instance.BringToFront();
}
Similarly i wanna bring usercontrol_2 to the same panel on the main form using a button (click event) on usercontrol_1.
How do i do this? any help would be appreciated.
I'm not sure where you are having problem, I think the way you are using usercontrol_1.Instance might cause the issue.
I have working example here, you can try it.
private void btn_Click(object sender, EventArgs e)
{
bool userControlIsAlreadyInPanel = false;
//assuming you are cheking if usercontrol_1 is already there on panel
// you don't want to create new usercontrol, but just bring existing control to the front
foreach(UserControl control in panel_screen.Controls)
{
if (control.GetType() == typeof(usercontrol_1))
{
userControlIsAlreadyInPanel = true;
control.BringToFront();
}
}
if(!userControlIsAlreadyInPanel)
{
usercontrol_1 instane = new usercontrol_1();
panel_screen.Controls.Add(instane);
instane.Dock = DockStyle.Fill;
instane.BringToFront();
}
}
output
namespace WindowsFormsApp1
{
public delegate void MyEventDelegate(object sender, string name);
public partial class Form1 : Form
{
usercontrol_1 _ctrl1 = null;
usercontrol_2 _ctrl2 = null;
public Form1()
{
InitializeComponent();
_ctrl1 = new usercontrol_1();
_ctrl1.Dock = DockStyle.Fill;
_ctrl1.userControlButtonClicked += userControlButtonClicked;
_ctrl2 = new usercontrol_2();
_ctrl2.Dock = DockStyle.Fill;
_ctrl2.userControlButtonClicked += userControlButtonClicked;
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
userControlButtonClicked(_ctrl1, "1");
}
private void userControlButtonClicked(object sender, string name)
{
panel1.Controls.Clear();
if (sender.Equals(_ctrl1))
{
panel1.Controls.Add(_ctrl2);
}
else if (sender.Equals(_ctrl2))
{
panel1.Controls.Add(_ctrl1);
}
}
}
}
namespace WindowsFormsApp1
{
public partial class usercontrol_1 : UserControl
{
public event MyEventDelegate userControlButtonClicked;
public usercontrol_1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MyEventDelegate med = userControlButtonClicked;
if (med != null)
{
med(this, "1");
}
}
}
}
namespace WindowsFormsApp1
{
public partial class usercontrol_2 : UserControl
{
public event MyEventDelegate userControlButtonClicked;
public usercontrol_2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MyEventDelegate med = userControlButtonClicked;
if (med != null)
{
med(this, "2");
}
}
}
}
I've created a new form, in which I have a toolbox. When I press a button in that form, it should relay that information that has been entered by the user(toolboxbox value) to the main form, in which it should say that piece of information in a label.
Since the method to create that username from the toolbox is private, I cannot access it from any other way. Making it public does not seem to make a difference, neither does get,set (from the way I've been trying to atleast).
Picture that may help explaining it:
Code (in which to create user):
namespace WindowsFormsApplication3
{
public partial class Newuserform : Form
{
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
string uname = textboxUsername.ToString();
}
public void Unamecreate()
{
}
}
}
Form1 Code (To receive created user):
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
Aboutform form2 = new Aboutform();
form2.Show();
}
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.Show();
}
}
}
you have a lot of options.
One way is to create an event and handle it in the main form.
public partial class Newuserform : Form
{
//the public property
public event EventHandler<string> UnameChanged;
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
if (UnameChanged != null)
UnameChanged(textboxUsername.ToString()); //fire the event
}
}
Now, to "handle" the event, do the following in your main form:
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.UnameChanged += Handler;
formnewuser.Show();
}
private void Handler (object sender, string Uname)
{
// do something wit the new Uname.
}
note: recreating the Newuserform will require to cleanup previous attached resources.
I'm stuck with the following thing.
I want to change the panel color from another Form(ColorForm).
Is it possible?
Code From the MainForm:
public void upperpanel_Paint(object sender, PaintEventArgs e)
{
}
I don't know how to access that upperpanel_Paint in my ColorForm.
I'm opening ColorForm From SettingsForm
Mainform > SettingsForm > ColorForm
public partial class SettingsForm : Form
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
List<string> adreses;
List<string> bookmarki;
void SelectColour()
{
using (ColorForm colourForm = new ColorForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColor);
}
}
}
public SettingsForm(List<string> adr, List<string> s)
{
InitializeComponent();
adreses = adr;
bookmarki = s;
}
private void Historyb_Click(object sender, EventArgs e)
{
foreach (Form form in Application.OpenForms)
{
if (form.GetType() == typeof(HistoryForm))
{
form.Activate();
return;
}
}
HistoryForm hf1 = new HistoryForm(adreses);
hf1.Show();
}
private void Bookmarksb_Click(object sender, EventArgs e)
{
BookmarksForm booklist = new BookmarksForm();
booklist.SetAllBookmarks(bookmarki);
booklist.ShowDialog();
}
private void Colorb_Click(object sender, EventArgs e)
{
SelectColour();
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent != null)
ColourSettingsChangedEvent(color);
}
}
Code from ColorForm:
public partial class ColorForm : Form
{
public ColorForm()
{
InitializeComponent();
}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
upperpanel.BackColor = colorDlg.Color;
}
}
}
Thank you!
Perhaps it would be better to fire a global event when the settings change, or the particular form colour setting changes, and listen for that event on the form where you need to take action.
for example see this pseudo code:
ColourForm:
Form used just to pick a colour, and store the result in a property.
class ColourForm
{
public Color SelectedColor {get;set;}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
this.SelectedColor = colorDlg.Color;
}
}
void Cancel()
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
void Save()
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
SettingsForm:
The main form for updating settings, this creates a colour picker form and saved the settings and fires an event if the dialog result of the colour form is an 'ok' result.
class SettingsForm
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
void SelectColour()
{
using (ColourForm colourForm = new ColourForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColour);
}
}
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent!=null)
ColourSettingsChangedEvent(color);
}
}
On you Main Form:
The Main form listens for a settings / colour changed event and changes the panel colour to the colour specified in the event when it fires.
class MainForm()
{
//Constructor
MainForm()
{
SettingsForm.ColourSettingsChangedEvent += ColourSettingsChanged;
}
void ColourSettingsChanged(Color color)
{
upperpanel.BackColor = color;
}
}
it would be better to have some kind of settings manager class than have the event on the settings form itself but you should get the idea
I have a class that inherits from UserControl:
public partial class MyView : System.Windows.Forms.UserControl
I want to handle the event that occurs when the user clicks on the X in the upper right corner. Maybe it is Form.Closing? But I don't see that as an option in the designer. What event is it?
Edit:
class SomeControl : UserControl
{
Form _owner;
public SomeControl()
{
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
_owner = FindForm();
//_owner = ParentForm;
_owner.FormClosing += _owner_FormClosing;
_owner.FormClosed += _owner_FormClosed;
}
}
private void _owner_FormClosed(object sender, FormClosedEventArgs e)
{
throw new NotImplementedException();
}
private void _owner_FormClosing(object sender, FormClosingEventArgs e)
{
Hide();
_owner.FormClosing -= _owner_FormClosing;
_owner.FormClosed -= _owner_FormClosed;
Parent.Controls.Remove(this);
_owner = null;
}
}
I have a windows custom control with a picturebox and a button on it's default panel. This windows custom control will be added to a windows form. There is another windows form called form2. when the user double clicks on the custom control, it should load form2. in designer when i double clicked the custom control on the form, it creates a load() event for that custom control. But i need double click event, how this can be done?
here is the graphical view of what happens
Here is code in the control
[DefaultEvent("DoubleClick")]
public partial class cntrlImageLoader : UserControl
{
public cntrlImageLoader()
{
InitializeComponent();
}
private void btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = Environment.SpecialFolder.MyPictures.ToString();
if (ofd.ShowDialog() == DialogResult.OK)
{
pbImage.Image = Image.FromFile(ofd.FileName);
}
}
private void pbImage_Click(object sender, EventArgs e)
{
this.cntrlImageLoader_DoubleClick(pbImage, e);
}
private void cntrlImageLoader_Load(object sender, EventArgs e)
{
}
private void cntrlImageLoader_DoubleClick(object sender, EventArgs e)
{
}
}
Here is the calling code on form1
private void cntrImLdrFront_DoubleClick(object sender, EventArgs e)
{
//this.cntrImLdrFront.pbImage.DoubleClick += new EventHandler(pbImage_DoubleClick);
}
FrmImageViewer f; // this is form2
private void pbImage_DoubleClick(object sender, EventArgs e)
{
f= new FrmImageViewer();
f.MdiParent = this.MdiParent;
f.Show();
}
Assign the attribute [DefaultEvent("DoubleClick")] at the class declaration.
[DefaultEvent("DoubleClick")]
public partial class MyControl : UserControl
{
}
This will creates event which you have set by default on double click of control at design time where you have placed your user control.
EDITED:
[DefaultEvent("LoadPicture")]
public partial class cntrlImageLoader : UserControl
{
public delegate void LoadPictureEventHandler(object sender, LoadPictureEventArgs e);
public event LoadPictureEventHandler LoadPicture;
private void pbImage_DoubleClick(object sender, EventArgs e)
{
if (LoadPicture != null)
{
LoadPictureEventArgs ev = new LoadPictureEventArgs();
LoadPicture(this, ev);
if (ev.Picture != null)
{
pbImage.Image = ev.Picture;
}
}
}
}
Create another class and give that class name to LoadPictureEventArgs
public class LoadPictureEventArgs : EventArgs
{
public Image Picture {get; set;}
public LoadPictureEventArgs(Image _picture)
{
Picture = _picture
}
public LoadPictureEventArgs()
: base()
{
}
}
HOW TO USE IT?
//FORM1
private void cntrImLdrFron_LoadPicture(object sender, LoadPictureEventArgs e)
{
Image img = null;
//LOAD YOUR IMAGE HERE
e.Picture = img;
}