I created a custom form to show it as a ToolTip but to show data on it, the show will be display when the user hovers on a Button and disappear on mouse leave, everything works perfectly but how can I prevent the Form from display outside the screen area??
Here is the code I used to show the Form:
Info_Form tooltip = new Info_Form();
private void Button131_MouseHover(object sender, EventArgs e)
{
Button b = (Button)sender;
tooltip = new Info_Form();
tooltip.Height = tooltip.Height + 30;
tooltip.Location = new Point(
b.Right,
b.Top);
tooltip.Show();
}
private void Button131_MouseLeave(object sender, EventArgs e)
{
tooltip.Close();
}
I suggest to:
declare your ToolTip Form in Program.cs
add static Methods to show and hide it
Of course you can use a dedicated class that exposes static methods to handle your ToolTip Form
You can then reach your ToolTip Form from anywhere in your application, just call ShowToolTip() and HideToolTip() when the Mouse pointer enters or leaves a specific Control: the bounds of this Control, translated to Screen coordinates, are used as reference to position the ToolTip.
Here, I'm using a simplified method to determine whether the ToolTip should be shown to the right or left and to the top or bottom of the reference Control:
if the reference Control is positioned to the left half of the screen, then the left potion of the Form is: ToolTip.Left = [ref Control].Left
otherwise, ToolTip.Left = [ref Control].Right - ToolTip-Width
the same logic applies to the top position of the ToolTip
Adjust this simple calculation to position your ToolTip Form using a different logic, if needed.
▶ There's no need to dispose of the ToolTip Form: it's automatically disposed of when the Form instance passed to Application.Run() is closed.
Note: If the Application is not DpiAware and the Screen where the Application's Windows are shown is scaled, any measure relative to either the Screen or the Windows/Forms may be virtualized, so you receive wrong results and any calculation will be off.
See the notes here:
Using SetWindowPos with multiple monitors
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
public static frmToolTip tooltip = null;
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
tooltip = new frmToolTip();
Application.Run(new SomeForm());
}
public async static Task ShowToolTip(Control control, string title) {
await Task.Delay(400);
if (tooltip.Visible) return;
Rectangle refBounds = control.RectangleToScreen(control.ClientRectangle);
if (!refBounds.Contains(Cursor.Position)) {
HideToolTip();
}
else {
var screen = Screen.GetBounds(control);
var leftPos = refBounds.Left <= screen.Width / 2 ? refBounds.Left : refBounds.Right - tooltip.Width;
var topPos = refBounds.Top <= screen.Height / 2 ? refBounds.Bottom + 2: refBounds.Top - tooltip.Height - 2;
tooltip.Location = new Point(leftPos, topPos);
tooltip.Text = title;
tooltip.Show(control.FindForm());
}
}
public static void HideToolTip() => tooltip.Hide();
In any Form, use a Control's MouseEnter and MouseLeave events to show/hide your ToolTip.
Note: I'm using Task.Delay() to delay the presentation of the ToolTip, so it doesn't show up if you briefly move the Mouse Pointer over the Control that shows it.
It also verifies whether the Form ToolTip is already shown (you cannot show a Form twice) or the Mouse Pointer has moved outside the bounds of the reference Control in the meanwhile (the ToolTip is not shown in this case).
Change this behavior as required.
In ShowToolTip(), I'm passing a string, meant to be used as the Title of the ToolTip. It's just an example, to show that you may pass any other parameter to this method (a class object, maybe) to setup the ToolTip Form in a custom way, different based on the caller requirements.
using System.Threading.Tasks;
public partial class SomeForm : Form
{
// [...]
private async void SomeControl_MouseEnter(object sender, EventArgs e)
{
await Program.ShowToolTip(sender as Control, "Some Title Text");
}
private void SomeControl_MouseLeave(object sender, EventArgs e)
{
Program.HideToolTip();
}
}
Related
Visual Studio C #
I made a calculator, and now I have to make a calculator memory (event).
There are 4 components other than the calculator: one Textbox for the answer of the calculator, two Buttons for "M" and "M+", and one Lable to display the answer again.
When the user clicks the “M” button, the contents of the Answer TextBox should be copied to a memory variable. Also make it so that when the user moves the mouse over the label, the value in the memory variable will appear in this label, and then disappear, when the mouse moves away from the label. Also add one more button, an “M+” button. When the user clicks this button, the contents of the Results box will be added to Memory. You will need to use a Global Variable to store this data.
My problem is that the label doesn't appear when the mouse over the label, and also it doens't disappear when the mouse leave the label. How can I fix it?
And also, is this way the right way to use the Global variable?
Below is my code (I just put the code for "M" and "M+" buttons, not the code for the calculator).
private String ans;
private Double answer;
private Double answerPlus;
private void btnM_Click(object sender, EventArgs e)
{
ans = txtDisplay.Text;
answer = double.Parse(ans);
lblblank.Text = answer.ToString();
}
private void lblblank_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void lblblank_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
private void btnMplus_Click(object sender, EventArgs e)
{
answerPlus = answer + double.Parse(ans);
lblblank.Text = answerPlus.ToString();
}
Storing variables
The way you store your values is fine.
Events
Once you call .Hide() the next MouseEnter/MouseLeave-event will not be triggered anymore. What you could do is to take a panel, or any layout element as a wrapper/parent-element for the label and then adjust your event-callbacks to something like that:
private void panel_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void panel_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
Edit
~~~
What does it mean that any layout element as a parent-element for the
label? Could you explain more?
What I meant was to just create a new panel (or layout-element) and put the label into it as a child. See the picture below:
If you set that up correctly, the code snippet I posted above will work just fine. This solution does not prevent the MouseLeave event from triggering when your mouse enters the label. Therefore you could use an alternative solution using the MouseMove event.
Alternative
using System;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
this.InitializeComponent();
// Subscribe to the MouseMove event
this.panel.MouseMove += this.panel_MouseMove;
}
private void panel_MouseMove(object sender, MouseEventArgs e)
{
// Checks if current mouse position is within the panel
if (this.panel.Bounds.Contains(new Point(e.X, e.Y)))
{
// Current mouse position within the panel
this.label.Show();
return;
}
// Current mouse position outside the panel
this.label.Hide();
}
}
}
I've create a list of canvases in wpf, and I have a button click event. I want that when I press the button it will add to the list new canvas. but when I try to change the property of the canvas in another window, it says the index was out of bounds, which means the list didnt add the canvas. I've created a method to check that and indeed it says the index is 0.
I've this with an array also, same here, I change its value but its still wrote the value is 0. this is the code:
public partial class New_Paint : Window
{
public List<Canvas> paintsList = new List<Canvas>();
public Canvas painting = new Canvas();
private void ok_MouseUp(object sender, MouseButtonEventArgs e)
{
paintsList.Add(painting);
this.Close();
}
}
and this is the moethod to check its size:
public int getSize()
{
return paintsList.Count;
}
and here is the code in the main window:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = paint.getSize() + "";
}
the methos return 0 although i click "ok". the list just wont add the items.
I take it you're new at this? Your list of canvases belong to your instance of New_Paint, and you only add one canvas to that list before closing the window (at least in the code you've shown). I don't see why you would expect more than one. You need to have a master list of canvases that is owned by whatever is managing your child windows.
I registered Hotkey: Ctrl + Space. Hotkey message is sent to:
private void Hotkey_press()
{
... // I want to show tooltip "Hello" at current mouse location.
}
Is there any way to show this tooltip even the mouse doesnt point to any control and it is outside my Window.Form1?
Edit: That ToolTip can show even the form lost focus or hide
You want something like
ToolTip tt = new ToolTip();
IWin32Window win = this;
tt.Show("String", win, mousePosition);
Where the MousePosition can be obtained from the MouseEventArgs via
private SomeMouseEventHandler(object sender, MouseEventArgs e)
{
System.Drawing.Point mousePosition = e.Location;
...
}
or using
System.Drawing.Point mousePosition = Cursor.Position;
also, you may want to set a longer duration for which the ToolTip is displayed, well just use the overloads available for the Show method, tt.Show("String", win, mousePosition, 5000); will display the tool tip for 5 seconds.
I hope this helps.
Tooltip tip = new ToolTip();
tip.ShowAlways = true;
tip.Show("My tooltip",this,Cursor.Position.X,Cursor.Position.Y);
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.showalways.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.aspx
As this answer suggests, there is no managed way to accomplish this. If you want to show a tool tip control when your program is not in focus then the "right" way to do it is to PInvoke Win32 and use CreateWindowEx. The answer linked above given by gideon shows some pointers on how to do it, but nonetheless it is very complicated.
If you don't mind using thrid party libraries, AutoIt provides a way to create tool tips easily without having to deal with Win32 yourself.
Here is a very simple example demonstrating use:
//make sure AutoItX3.dll is referenced in your project
using AutoItX3Lib;
private AutoItX3 myAutoIt = new AutoItX3();
private async void ShowToolTipAtMouse(string message)
{
//default position is bottom right of mouse pointer,
//but you can set the x and y positions yourself
myAutoIt.ToolTip(message);
//call the function again with an empty argument to close
await Task.Delay(1000);
myAutoIt.ToolTip(String.Empty);
}
This will work as long as your program is running; doesn't matter if it is in/out of focus or even hidden. Downside is you don't get the regular fade out animation (it just vanishes). Also, if you need multiple tool tips at once you need to have multiple AutoItX3 objects.
You need Show/Hide it in the mouse events, also converting mouse location from Screen coordinate to your control coordinate. the little problem is if you put tooltip exactly on mous pointer location toolTip will catch mouseEnter event and unintended mouseLeave event on your control will be triggered so my solution was adding a little offset to final location.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Point p = pictureBox3.PointToClient(Cursor.Position);
p.X += 5;
p.Y += 5;
toolTip1.Show("My tooltip" ,
pictureBox1, p);
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
toolTip1.ShowAlways = false;
Text = ("Leave");
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
toolTip1.ShowAlways = true;
Text=("Enter");
}
It is a shame Winforms does not have a position property for tooltips.
The easiest thing I found is to add your own mouse-over and mouse-leave handlers and then use the Show() function to set the location (x and y), in pixels, relative to the upper left corner of the second argument of the Show() function.
The second argument can be any control, but probably makes most sense to use the control containing the tooltip itself (this), the parent the control, or a child control inside the control.
You can use a Point instead of two arguments (x and y) for the position, but remember Show() will take the point's x coordinate and y coordinate and add them to the x and y coordinates of the upper left corner of the control you chose as the second argument.
private void UserControl1_MouseHover(object sender, EventArgs e)
{
toolTip1.Show("this text is so new", this, 10, 10);
}
private void UserControl1_MouseLeave(object sender, EventArgs e)
{
toolTip1.Hide(this);
}
I want to be able to drag over a bunch of controls and select those of a certain type (TextBoxes).
Once the dragging action has been completed, I want to display an inputbox (yes, I'll have to reference/use the VB .dll) prompting the user for the value that will be entered in each selected TextBox.
Can this be done? (of course, but how?)
Or is there another way to accomplish the same thing (allow the user to quickly select multiple controls and then perform an action on all of them at once)?
Updated:
I've got this sort of working - the "caveat" or "gotcha" being that I have to pop up a MessageBox.Show() to the user for it to work. Essentially, I:
Set a boolean to true on the container's (FlowLayoutPanel, in my case) MouseDown event, if the right mouse button was selected.
Set that same boolean to false on the container's MouseUp event, if the right mouse button was selected.
I then have a shared MouseHover event handler for all of the TextBoxes on that form that, if the boolean is true, changes the BackColor (to Gainsboro, in my case, from Window).
In the container's MouseUp event, I also use an InputBox (referencing/importing/using the VB .dll) requesting the user enter the value that will be common for the "highlighted" TextBoxes. I then loop through them, looking for those with that BackColor, and assing the user-supplied value to their Text properties.
Voila!
Unfortunately, the TextBoxes' Modified property does not seem to be altered when you assign it values this way, so I had to work around that (explicitly setting the "Save" button to enabled), and I had to add more code to duplicate my KeyPressed code which limits the values entered by the user.
So, it is, of course, possible, albeit a little kludgy. I haven't decided if the MessageBox.Show() is a "bug" or a feature, though...
A related post is: Why does MouseHover event only get called if a messagebox.show() or breakpoint occurs before it?
This is actually very simple. I assume by drag you mean that you want to 'select' controls, like you would 'select' some pixels in a paint program for example. Here is an example I wrote you that does just this and only selects TextBox controls. It ignores other controls.
namespace WindowsFormsApplication5
{
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;
using System.Drawing.Drawing2D;
/// <summary>
/// Main application form
/// </summary>
public partial class Form1 : Form
{
/// <summary>
/// Initializes a new instance of the WindowsFormsApplication5.Form1 class
/// </summary>
public Form1() {
InitializeComponent();
DoubleBuffered = true;
}
private Point selectionStart;
private Point selectionEnd;
private Rectangle selection;
private bool mouseDown;
private void GetSelectedTextBoxes() {
List<TextBox> selected = new List<TextBox>();
foreach (Control c in Controls) {
if (c is TextBox) {
if (selection.IntersectsWith(c.Bounds)) {
selected.Add((TextBox)c);
}
}
}
// Replace with your input box
MessageBox.Show("You selected " + selected.Count + " textbox controls.");
}
protected override void OnMouseDown(MouseEventArgs e) {
selectionStart = PointToClient(MousePosition);
mouseDown = true;
}
protected override void OnMouseUp(MouseEventArgs e) {
mouseDown = false;
SetSelectionRect();
Invalidate();
GetSelectedTextBoxes();
}
protected override void OnMouseMove(MouseEventArgs e) {
if (!mouseDown) {
return;
}
selectionEnd = PointToClient(MousePosition);
SetSelectionRect();
Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
if (mouseDown) {
using (Pen pen = new Pen(Color.Black, 1F)) {
pen.DashStyle = DashStyle.Dash;
e.Graphics.DrawRectangle(pen, selection);
}
}
}
private void SetSelectionRect() {
int x, y;
int width, height;
x = selectionStart.X > selectionEnd.X ? selectionEnd.X : selectionStart.X;
y = selectionStart.Y > selectionEnd.Y ? selectionEnd.Y : selectionStart.Y;
width = selectionStart.X > selectionEnd.X ? selectionStart.X - selectionEnd.X : selectionEnd.X - selectionStart.X;
height = selectionStart.Y > selectionEnd.Y ? selectionStart.Y - selectionEnd.Y : selectionEnd.Y - selectionStart.Y;
selection = new Rectangle(x, y, width, height);
}
}
}
Now there are limitations with this currently. The obvious is that this will not select a TextBox within a nested container control (eg. a panel on your form containing a TextBox). If that were the case the selection would be drawn underneath the panel, and the TextBox would not be selected because the code I wrote does not check nested containers.
You can easily update the code to do all of this however, but this should give you a solid start.
I have been working with NotifyIcon in order to show an icon in the taskbar.
This program has no Windows Form. I perhaps could create one and make it invisible but I was hoping to avoid it. The ToolTip functions attached to NotifyIcon are somewhat lacking, and one of the gurus here suggested I look at the ToolTip functionality. It is possible to attach ToolTip to a form. Is is possible to attach it to just the NotifyIcon? I'm trying do this:
NotifyIcon CTicon = new NotifyIcon();
ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(CTicon, "Test");
And I get the error "cannot convert from 'System.Windows.Forms.NotifyIcon' to 'System.Windows.Forms.Control'. Is there a way to convert? I also tried:
toolTip.SetToolTip(CTicon.Container, "Test");
but a container is apparently not a valid control either.
I apologize for my total lack of understanding of how this may or may not work.
Thanks in advance.
A belated answer, but maybe useful for others .
NotifyIcon.Text = "ToolTipText";
Tray icons don't support square tool tips, only balloons. Kinda makes sense, the icons are usually quite close together so it would be hard to see what icon produced the tip without the "stem" on the balloon. Use the NotifyIcon.BalloonTipText property.
NotifyIcon is used for the system tray icon that you see on the bottom right hand corner of the screen, usage of ToolTip is only for controls such as textboxes, checkboxes and so on...for example, let's assume there's a TextBox instance called 'textBox1', on the form than this would work:
toolTip1.SetToolTip(textBox1, "Hello World");
Now, when you mouse-over the textbox, a tooltip is shown...
I'm not sure you can set a tooltip directly on a notify icon. It's the same thing as setting the text property on the notify icon itself. There are some limitations to the notify icon text. It's limited to 128 chars and will only stay up for a short amount of time. If you want to display more info for a longer amount of time you should look at the balloon text property of the notify icon. I highly suggest reading the MSDN page it's quite helpful.
http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx
You shouldn't.
NotifyIcon is used to show notifications, whereas ToolTip is used to show the information about the user's current activity, it should be used "in place".
Check the user interface guidelines:
Notifications
Balloons
All the tray icons on my computer have tooltips. You need to create your NotifyIcon using the constructor that accepts a Component as an argument. It displays the NotifyIcon.Text property.
I was able to create one using the example code here:
http://msdn.microsoft.com/en-us/library/1by05f8d.aspx
using System;
using System.Drawing;
using System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.ContextMenu contextMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.ComponentModel.IContainer components;
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
this.components = new System.ComponentModel.Container();
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
// Initialize contextMenu1
this.contextMenu1.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] {this.menuItem1});
// Initialize menuItem1
this.menuItem1.Index = 0;
this.menuItem1.Text = "E&xit";
this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);
// Set up how the form should be displayed.
this.ClientSize = new System.Drawing.Size(292, 266);
this.Text = "Notify Icon Example";
// Create the NotifyIcon.
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
// The Icon property sets the icon that will appear
// in the systray for this application.
notifyIcon1.Icon = new Icon("appicon.ico");
// The ContextMenu property sets the menu that will
// appear when the systray icon is right clicked.
notifyIcon1.ContextMenu = this.contextMenu1;
// The Text property sets the text that will be displayed,
// in a tooltip, when the mouse hovers over the systray icon.
notifyIcon1.Text = "Form1 (NotifyIcon example)";
notifyIcon1.Visible = true;
// Handle the DoubleClick event to activate the form.
notifyIcon1.DoubleClick += new System.EventHandler(this.notifyIcon1_DoubleClick);
}
protected override void Dispose( bool disposing )
{
// Clean up any components being used.
if( disposing )
if (components != null)
components.Dispose();
base.Dispose( disposing );
}
private void notifyIcon1_DoubleClick(object Sender, EventArgs e)
{
// Show the form when the user double clicks on the notify icon.
// Set the WindowState to normal if the form is minimized.
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal;
// Activate the form.
this.Activate();
}
private void menuItem1_Click(object Sender, EventArgs e) {
// Close the form, which closes the application.
this.Close();
}
}