Setting Control.Capture = true hides the cursor - c#

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.

Related

Show a MessageBox when the Help Button is pressed

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

Using MouseHover event and ToolTip

To show the relevant information(in monopoly game, the property belongs which player, current market price etc.), I put a Label on the top of a panel, and used a ToolTip object to display the information. This is the image of my current setup.
Here are the steps I have done:
1.Added MouseHover event handler (The Label name is MEDITERANEAN)
this.MEDITERANEAN.MouseHover += new System.EventHandler(this.MEDITERANEAN_MouseHover);
2.Initialized Tooltip
private void InitializeToolTip()
{
toolTipLabel.ToolTipIcon = ToolTipIcon.Info;
toolTipLabel.IsBalloon = true;
toolTipLabel.ShowAlways = true;
}
3.Call setToolTip() in MouseHover call back function
private void MEDITERANEAN_MouseHover(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(MEDITERANEAN, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
But when I start application and move my cursor over the label, there is no text from toolTipLabel. What part did I make mistakes?
Interestingly, i made other function and it works.
private void panelBoard_MouseOver(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(panelBoard, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
I think you just need to bring your lable control in front of image. Try something like this .
MEDITERANEAN.BringToFront();
I found the solution, first I should set Panel's property "Enable" to true, then set label's property "visible" to true as well.

In WPF, how do you tell if the left mouse button is currently down without using any events?

I have an app where I want to be able to move a slider. However, the slider is automatically updated by the program every 30 seconds. When I try to change the slider position with my mouse, the program is still updating the slider position, so I cannot move it manually with the mouse.
Somehow, I want the app to NOT update the slider if the user is in the process of changing its position. How can I tell if the left mouse button is down without using the left button down event? I just want to be able to access the mouse, and check the button state of the left mouse button. How do I access it without being inside of a mouse event?
bool mouseIsDown = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;
There are some rare cases, where System.Windows.Input.Mouse.LeftButton does not work. For example during Resize.
Then you can use GetKeyState:
public enum VirtualKeyCodes : short
{
LeftButton = 0x01
}
[DllImport("user32.dll")]
private static extern short GetKeyState(VirtualKeyCodes code);
public static bool CheckKey(VirtualKeyCodes code) => (GetKeyState(code) & 0xFF00) == 0xFF00;
Ok,
I figured it out. The Slider control in WPF does NOT fire the MouseDown, LeftMouseDown, or LeftMouseUp events. This is because it uses them internally to adjust the value as the user is manipulating the slider. However, the Slider control in WPF DOES fire the PreviewLeftMouseDown and the PreviewLeftMouseUp events. In addition, when you click the Left Mouse button, the Slider Control automatically captures the mouse and holds on to it until you release the Left Mouse button.
I was able to solve my problem with the following 3 events:
private void _sliderVideoPosition_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_adjustingVideoPositionSlider = true;
_mediaElement.Pause();
}
private void _sliderVideoPosition_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_adjustingVideoPositionSlider = false;
_mediaElement.Play();
}
private void _sliderVideoPosition_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_adjustingVideoPositionSlider)
{
_mediaElement.Position = TimeSpan.FromMilliseconds((int)e.NewValue);
}
}
You may consider, in your case, using Mouse Class.
If I'm not mistaken it doesn't track the state of the button when the mouse
goes out of the UI of the application, so to be sure that you have always correct information,
you may need to capture mouse.
Repeat, you need to check this by yourself.
As I understand it, you want to keep an MVVM pattern to accomplish this task.
So first I would start by designing what I want in my ViewModel
public class ViewModel
{
public ICommand EditingSliderCommand { get; set; } // actually set the command
public ICommand DoneEditingCommand { get; set; } // actually set the command
public bool IsEditing { get; set; }
...
private void AutomaticUpdate
{
if (IsEditing)
return;
Update();
}
}
then you could use the Blend Interactivity library to do the UI side in xaml.
The following is an example. I don't know if the event name is correct. You could also do the same with mouse up and done editing.
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cmd:EventToCommand Command="{Binding Mode=OneWay,
Path=EditingSliderCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Accepted answer didn't work for me, but this did:
if ((System.Windows.Forms.Control.MouseButtons & System.Windows.Forms.MouseButtons.Left) == System.Windows.Forms.MouseButtons.Left)
{
System.Diagnostics.Debug.WriteLine("Left mouse down");
}

Hiding form when are other controls focus

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;
}
}

How to disable cursor in textbox?

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.

Categories