I am trying to show a MessageBox (or something that I can put text into) when the context Help Button in the Form's Tile Bar is pressed.
This is the help button I want pressed:
Any help would be great! :)
A few additions to what has already been posted.
The Help Button is shown in the Caption of a Form.
To activate it, set HelpButton = true, MinimizeBox = false and MaximizeBox = false.
The HelpButtonClicked event is raised, for the Form only, when the Help Button is clicked.
The HelpRequested event is raised when you click on a Control after (when the Mouse Pointer has the shape of a question mark).
To show Help related to a Control, you can subscribe to the HelpRequested event of each Control that provides Help, or you can use just the Form's HelpRequested event for all Controls.
You need to get the child Control that was selected when the Mouse is clicked.
Here I'm using WindowFromPoint() to get the handle of the Control at the position specified by HelpEventArgs.
This function can get the handle of nested Controls.
A Dictionary<Control, string> is used to store and retrieve the Help text for all Controls that should provide a description of their functionality (or whatever else).
The Help text can of course come from localized Project Resources.
Note that the Help is not generated for ContainerControls (the Form itself, Panel, GroupBox etc.) and WindowFromPoint doesn't get the handle of disabled Controls.
using System.Runtime.InteropServices;
public partial class SomeForm : Form
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr WindowFromPoint(Point point);
Dictionary<Control, string> help = new Dictionary<Control, string>();
public SomeForm() {
InitializeComponent();
help.Add(someButton, "Help on someButton");
help.Add(someTextBox, "someTextBox gets help");
help.Add(someNestedControl, "someNestedControl needs clarifications");
}
private void SomeForm_HelpButtonClicked(object sender, CancelEventArgs e) {
// The Help Button has been clicked
}
private void SomeForm_HelpRequested(object sender, HelpEventArgs e) => ShowHelp(e);
public void ShowHelp(HelpEventArgs e) {
e.Handled = true;
var ctl = FromHandle(WindowFromPoint(e.MousePos));
if (ctl != null && help.ContainsKey(ctl)) {
MessageBox.Show(help[ctl]);
}
else {
MessageBox.Show("No help for this Control");
}
}
}
You need to wire up the HelpRequested or HelpButtonClicked events
Plus you need to get the button shown (off by default on a form) by setting
HelpButton = true
MinimizeBox = false
MaximizeBox = false
Sounds like you're new to C# so I'll give you the most simple rundown I can with examples:
In the InitializeComponent() function you need to add:
HelpRequested += new System.Windows.Forms.HelpEventHandler(this.form_helpRequested);
This will tell the form to run form_helpRequested once the help button is pressed. Then you can implement this event handler function with:
private void textBox_HelpRequested(object sender, System.Windows.Forms.HelpEventArgs hlpevent)
{
// Your code here
// Example of a popup with text:
MessageBox.Show("This is a help popup");
}
This all needs to be in your Form1.cs (or equivilent) script.
For reference on this event handler, I'd suggest giving this article a read: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.helprequested?view=windowsdesktop-6.0
Related
I have Windows Form TestForm, and in my Form I have several labels that are only used to display some text.
I need to display a MessageBox.Show anytime the Form is clicked. So I have an event handler for the click, which looks like this:
private void TestForm_Click(object sender, EventArgs e)
{
MessageBox.Show("The form has been clicked");
}
Unfortunately, the click event doesn't fire when I click over a label in the Form. Is there a way to fix this, besides consuming the click event for the labels?
Thanks.
To use the same click event for all labels:
In the properties for each label, go to the Events (lightning bolt tab).
You will see (probably near the top) a label for Click, click the dropdown for this event, and you will be shown a list of handlers that you could use for that label.
Here's the Properties > Events > Click handler (bottom right):
Because all of your labels are of the same type, and produce the same EventArgs, you are able to use the same handler for all of them.
Then, when you are adding more Labels, just choose the event handler from the Click event dropdown:
Hope this helps!
To flesh out LarsTech's comment, I have used something like this in the past when I was having problems with labels overlapping each other and lack of true transparency in WinForms. What I did was make the labels invisible on the Form, then iterate through them in the Form's paint event, pull the information out of them and then use Graphics.DrawString to draw the text. That way you you will still be able see them in design mode.
This is a quick example of what I mean.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (var temp in this.Controls)
{
if (temp is Label) //Verify that control is a label
{
Label lbl =(Label)temp;
e.Graphics.DrawString(lbl.Text, lbl.Font, new SolidBrush(lbl.ForeColor), new Rectangle(lbl.Location, lbl.Size));
}
}
}
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("The Form has been clicked");
}
}
When I set my control's Capture property to true, I receive the mouse events like I expect, but the cursor becomes invisible. Is this expected behavior, and if so, how can I make the cursor displayed when I am capturing it?
Sample Code:
This assumes you have a Form with a TextBox which has the TextChanged event linked appropriately.
Now, the sample code is really for the case of (Form).Capture to keep the sample code short, but I've tested it already and it also causes my mouse to disappear.
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
}
private void TextBox_TextChanged(object sender, EventArgs e)
{
this.Capture = true;
}
}
Type something in the text box and the mouse will disappear.
Mouse capture interrupts the normal flow of mouse processing which includes setting the cursor, so you should manually set the cursor.
This question is related to this my question. Now I have form in my class and when user click on button I show (or hide) form. That´s ok. But I want to hide form when I move with origin form or when I click somewhere in origin form. The new form is behind that origin form. I was trying events like lostfocus and others but It didn´t help. So I think I need some trick that check from my control if there was click in parrent form (origin form) or some other hack. I know the best would be that I put code but I have many lines so I think that best way will be if you help me in general way and then I try to applicate to my app.
You can do it with a global mouse and keyboard hook. In fact, its been wrapped up into well documented, well structured .NET API over at CodePlex
Go over there and download it. Then, set up a global mouse hook:
_mouseListener = new MouseHookListener(new GlobalHooker());
_mouseListener.MouseMove += HandleGlobalHookMouseMove;
_mouseListener.Start();
The key here is that you will receive the MouseMove event ANY time the mouse moves ANYWHERE on the desktop, not just within the bounds of your window.
private void HandleAppHookMouseMove(object sender, MouseEventArgs e)
{
if (this.Bounds.Contains(e.Location))
{
HandleEnter();
}
else
{
HandleLeave();
}
}
You can also setup one for MouseClick. The combination of the two will enable you to determine any time the mouse moves over your origin form, or the mouse is clicked when its over it. Unlike the LostFocus and other events you tried, focus is irrelevant.
Does below help?
public partial class Form1 : Form
{
Form f2 = new Form2();
public Form1()
{
InitializeComponent();
f2.Show();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (this.ClientRectangle.Contains(e.Location) && f2.Visible) { f2.Hide(); }
}
private void button1_Click(object sender, EventArgs e)
{
f2.Visible = !f2.Visible ? true : false;
}
}
Is there any way to disable cursor in textbox without setting property Enable to false?
I was trying to use ReadOnly property but despite the fact that I can't write in textbox, the cursor appears if I click the textbox. So is there any way to get rid of this cursor permamently?
In C#, you can use the following read-only textbox:
public class ReadOnlyTextBox : TextBox
{
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
public ReadOnlyTextBox()
{
this.ReadOnly = true;
this.BackColor = Color.White;
this.GotFocus += TextBoxGotFocus;
this.Cursor = Cursors.Arrow; // mouse cursor like in other controls
}
private void TextBoxGotFocus(object sender, EventArgs args)
{
HideCaret(this.Handle);
}
}
In C# you can disable the cursor in a textbox by temporarily disabling and then re-enabling the text box whenever it receives the focus. Note there is no need to make the textbox read only if using this method. For example:
private void TextBox_Enter(object sender, EventArgs e)
{
TextBox.Enabled = false;
TextBox.Enabled = true;
}
You could use a Label instead. When in the designer, you set BorderStyle = Fixed3D, BackColor = Window and AutoSize = False, it looks a lot like a TextBox.
However, the cursor in a TextBox is provided so that the user can scroll through the text when it is longer than the box. You'll lose that functionality with a Label, unless you are sure that it will always fit. Other than that, it is not possible to remove the cursor from a TextBox.
Putting the hideCaret function inside the TextChanged event will solve the problem:
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
private void textBox1_TextChanged(object sender, EventArgs e)
{
HideCaret(textBox1.Handle);
}
Easiest solution for me was to just override the on focus event and focus back to the parent. This prevents the cursor and any editing of the textbox by the user and basically disables the text box with out having to set the Enabled = false property.
private void Form1_load(object sender, EventArgs e) {
textBox1.ReadOnly = true;
textBox1.Cursor = Cursors.Arrow;
textBox1.GotFocus += textBox1_GotFocus;
}
private void textBox1_GotFocus(object sender, EventArgs e) {
((TextBox)sender).Parent.Focus();
}
Like #Mikhail Semenov 's solution, you can also use lambda express to quickly disable the cursor if you do not have many textboxes should do that:
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
textBox1.ReadOnly = true;
textBox1.BackColor = Color.White;
textBox1.GotFocus += (s1, e1) => { HideCaret(textBox1.Handle); };
textBox1.Cursor = Cursors.Arrow;
You can set it programatically.
textBox1.Cursor = Cursors.Arrow;
This is not strictly an answer to the question, but perhaps it can solve some similar problem(s). I use a textbox control which can look like a label for a control which displays a scale, but can be edited, when clicked. Start enabled = false and make an activation (enabled = true) in a mousehandler of the parent of the textbox control (which, when disabled, border None and backcolor = parent backcolor, looks like a label). E.g. when enter hit or other event, disable again in KeyDown handler.
(Of course the parent mouse click routine can check whether the mouseclick really occured in the label/textbox control).
If you need the textbox control to activate by tabbing, some more work is required (than I have done).
I use the form constructor to find the textbox parent at runtime and to apply the delegate mouse control. Perhaps you can do this as wel in compile time (Form header), but that seemed a little error-prone to me.
One way of doing it is using View + TabIndex, you can do indexing of some other controls on the dialog as first, let say for buttons if there any. Then as if the control tabIndex is not the first i.e 0, cursor won't get appear there.
To disable the edit and cursor in the TEXT BOX
this.textBox.ReadOnly = true;
this.textBox.Cursor = Cursors.No;//To show a red cross icon on hover
this.textBox.Cursor = Cursors.Arrow //To disable the cursor
you can use RightToLeft Property of Text Box, set it to true, you will not get rid of the Cursor, but it will get fixed at right corner and it will not appear automatically after every text you type in your text Box. I have used this to develop an application like Windows Calculator.
I have created a non-form c# program that uses the NotifyIcon class.
The text "(Click to Activate)" shows up when I hover the mouse.
So I am getting some events handled.
However, The "Click" event does not fire and the Context menu doesnt show up.
public class CTNotify
{
static NotifyIcon CTicon = new NotifyIcon();
static ContextMenu contextMenu = new ContextMenu();
static void Main()
{
//Add a notify Icon
CTicon.Icon = new Icon("CTicon.ico");
CTicon.Text = "(Click to Activate)";
CTicon.Visible = true;
CTicon.Click += new System.EventHandler(CTicon_Click);
//Create a context menu for the notify icon
contextMenu.MenuItems.Add("E&xit");
//Attach context menu to icon
CTicon.ContextMenu = contextMenu;
while (true) //Infinite Loop
{
Thread.Sleep(300); //wait
}
}
private static void CTicon_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Clicked!");
}
}
Take a look at the Shell_NotifyIcon() API method, the one that implements a NotifyIcon. Click through to the NOTIFYICONDATA structure. The second member of that structure is a window handle:
A handle to the window that receives
notifications associated with an icon
in the notification area
You don't have a window and can therefore not receive notifications. You must put the NotifyIcon on a Form. And use Application.Run() to get the notifications and activate the event handlers.
Keep your form hidden by pasting this code:
protected override void SetVisibleCore(bool value) {
if (!this.IsHandleCreated) {
this.CreateHandle();
value = false;
}
base.SetVisibleCore(value);
}
Why don't you create a form application, and upon initialization just hide the form? I've never had problems with notification icon using this approach
I have the same problem, when I use the .hide() event to hide the form or the SetVisibleCore that Hans provide, the click or any mouse events will not fire.
Does someone have another solution ?
P.S. While the form is visible, everything is working fine.