I have a button. On Button.MouseRightButtonDown, I'm calling Mouse.Capture(button), because I want to detect if someone releases right-click outside of the Button.
I also have a Button.MouseLeave event registered. If someone right-click-drags the mouse off the button, I want this event to trigger.
Unfortunately, it seems like Mouse.Capture somehow blocks MouseLeave from occuring.
Does anyone know a workaround, or maybe can point out where I'm going wrong?
(By the way, if anyone's curious what I'm doing this for, see my other question.)
When mouse is captured, you can use MouseMove and hit-testing to determine whether the mouse within your element or another.
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (this.IsMouseCaptured)
{
HitTestResult ht = VisualTreeHelper.HitTest(this, e.GetPosition(this));
if (ht != null)
{
DependencyObject current = ht.VisualHit;
while (current != this && current != null)
{
current = VisualTreeHelper.GetParent(current);
}
if (current == this)
{
Debug.WriteLine("Inside");
return;
}
}
Debug.WriteLine("Outside");
}
}
The following code can be used to avoid tree walk:
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (this.IsMouseCaptured)
{
bool isInside = false;
VisualTreeHelper.HitTest(
this,
d =>
{
if (d == this)
{
isInside = true;
}
return HitTestFilterBehavior.Stop;
},
ht => HitTestResultBehavior.Stop,
new PointHitTestParameters(e.GetPosition(this)));
if (isInside)
{
Debug.WriteLine("Inside");
}
else
{
Debug.WriteLine("Outside");
}
}
}
Following on from my answer to your related question, if you use CaptureMouse() from UIElement in place of Mouse.Capture(...) then you will see the correct behaviour.
public class MyButton : Button
{
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
base.OnMouseRightButtonDown(e);
CaptureMouse();
}
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonUp(e);
ReleaseMouseCapture();
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
Debug.WriteLine("Mouse enter");
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
Debug.WriteLine("Mouse leave");
}
}
Related
Under certain conditions I'd like to cancel the ValueChanged event of a NumericUpDown control in Winforms (e.g. when the value set in the control is too high in relation to another value in a TextBox).
However, the EventArgs passed as argument into the event handler for the NumericUpDown control doesn't offer anything like "Cancel", so how can I do it?
private void nudMyControl_ValueChanged(object sender, EventArgs e)
{
// Do some stuff, but only if the value is within a certain range.
// Otherwise, cancel without doing anything.
}
You probably can handle this situation by using Minimum & maximum Properties, yet there are some solutions.
One way to do it is by creating a custom control, although it is nasty in my idea.
public partial class CustomNumericUpDown : NumericUpDown
{
public CustomNumericUpDown()
{
InitializeComponent();
}
protected override void OnTextBoxKeyDown(object source, KeyEventArgs e)
{
if (MyCustomCondition())
{
e.Handled = true;
}
base.OnTextBoxKeyDown(source, e);
}
private bool MyCustomCondition()
{
var checkOut = false;
//if (something == foo)
//{
checkOut = true;
//}
return checkOut;
}
}
You also can do stuff for ValueChanged:
This is some dummy sample, yet you can change it in your way:
public virtual decimal CurrentEditValue { get; internal set; } = 0M;
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (decimal.TryParse(Text, out decimal v))
{
CurrentEditValue = v;
OnValueChanged(e);
}
}
protected override void OnValueChanged(EventArgs e)
{
// if(CurrentEditValue == foo) Do_stuff.
base.OnValueChanged(e);
}
IDE: C# .net, WINFORMS, .net 4.0
Hi have created a userControl, and I want to make a property that if user control enabled is false than change the back Image to imgDisabled.jpg else imgEnabled.jpg
Please tell me how to override the Enabled Property of usercontrol and add this function to it.
private void onPropertyChanged()
{
if (this.Enabled)
this.BackgroundImage = Properties.Resources.imgEnabled;
else
this.BackgroundImage = Properties.Resources.imgDisabled;
}
Override virtual OnEnabledChanged method of base Control class:
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
if (this.Enabled)
this.BackgroundImage = Properties.Resources.imgEnabled;
else
this.BackgroundImage = Properties.Resources.imgDisabled;
}
Kindly use an event litner like this
class CustomProperty : Property
{
public event EventHandler SelectionChanged;
private int _selectionStart;
private int _selectionLength;
protected override void OnMouseDown(MouseEventArgs e)
{
_selectionStart = SelectionStart;
_selectionLength = SelectionLength;
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (null != SelectionChanged && (_selectionStart != SelectionStart || _selectionLength != SelectionLength))
SelectionChanged(this, EventArgs.Empty);
base.OnMouseUp(e);
}
}
I have a user control that has the following overridden event:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Left )
DoSomething();
}
When I place the user control on my Main Form, this event is not fired.
How can I access this event from Parent form?
protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
if (e.KeyCode == Keys.Left)
Move(pt.X,pt.Y);//Move is a function within the usercontrol
else if (e.KeyCode == Keys.Right)
Move(pt.X,pt.Y);
//other conditions
e.Handled = false;
}
I need the parent to be notified on this event
If I understand correctly, you are trying to invoke the OnKeyDown method of the user control from within the parent form.
This is the main form class:
public class Form1 : Form
{
private UserControl1 myControl;
public Form1()
{
myControl = new UserControl1();
Controls.Add(myControl);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
myControl.InvokeOnKeyDown(e);
}
}
And this is the User Control:
public class UserControl1 : UserControl
{
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
MessageBox.Show("Key Down Fired!");
}
public void InvokeOnKeyDown(KeyEventArgs e)
{
OnKeyDown(e);
}
}
Edit regarding arrow keys: the arrow keys are not normally considered to be input keys and therefore are not passed on to the key methods. To change this you must override the IsInputKey method as such:
protected override bool IsInputKey(Keys e)
{
if (e == Keys.Up || e == Keys.Down ||
e == Keys.Left || e == Keys.Right) return true;
return base.IsInputKey(e);
}
Following your updated question and code example posted, if you want the parent Form to be notified that a move operation took place, you need to create an event in the UserControl and subscribe to it in the parent form. This could be achieved in the following example. Please let me know if this solves your problem, else please post further detail.
Best regards
// Define custom EventArgs to pass into the Move event
public class MoveEventArgs : EventArgs
{
private Point _movePoint;
public MoveEventArgs(Point movePoint)
{
_movePoint = _movePoint;
}
public Point MovePoint { get { return _movePoint; } }
}
// Define a custom user control that raises an event to subscribers on move
public class MyUserControl : UserControl
{
public event EventHandler<MoveEventArgs> Moved;
protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
if (e.KeyCode == Keys.Left)
{
Move(pt.X,pt.Y);//Move is a function within the usercontrol
OnMoved(pt);
}
else if (e.KeyCode == Keys.Right)
{
Move(pt.X,pt.Y);
OnMoved(pt);
}
//other conditions
e.Handled = false;
}
// Raises a custom event, Moved
protected void OnMoved(Point movePoint)
{
var handler = Moved;
if (handler != null)
{
handler(this, new MoveEventArgs(movePoint);
}
}
}
// How to subscribe to the event (and be notified of move)
public class MyParentForm : Form
{
public MyParentForm()
{
InitializeComponent();
_myUserControl.Moved += new EventHandler<MoveEventArgs>(MyUserControl_Moved);
}
private void MyUserControl_Moved(object sender, MoveEventArgs e)
{
// e.MovePoint now contains the point that the usercontrol was moved to
// this event will fire whenever the user presses Left or Right arrow
}
}
I need Button.click from another class but doesn't work pickButton.PerformClick()?
[Category("Özel")]
[DefaultValue(null)]
public Button pickButton { get; set; }
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (e.Key == Key.F10)
{
if (pickButton != null)
{
//pickButton.PerformClick() ??
}
}
}
PerformClick isn't available in Silverlight.
Why don't you extract the code from the pickButton click event and call that from both places:
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (e.Key == Key.F10)
{
if (pickButton != null)
{
DoStuff();
}
}
}
and:
private void pickButton_OnClick(object sender, RoutedEventArgs e)
{
DoStuff();
}
Obviously DoStuff() is a placeholder to illustrate the concept.
Silverlight does not support that operation. Call the click event directly i.e
pickButton.pickButton_Click(this, null);
or
button2_Click(this, null);
I inherited KryptonToolkit ListBox control to get SelectedItemChanging event.
public class CPListBox : KryptonListBox
{
public event CancelEventHandler SelectedIndexChanging;
protected virtual void OnSelectedIndexChanging(CancelEventArgs e)
{
SelectedIndexChanging(this, e);
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
CancelEventArgs cArgs = new CancelEventArgs();
OnSelectedIndexChanged(cArgs);
if(!cArgs.Cancel)
{
base.OnSelectedIndexChanged(e);
}
}
}
In form I handle event with code:
void UsersListBoxSelectedIndexChanging(object sender, CancelEventArgs e)
{
if(_presenter.CurrentUser.IsModified)
{
MessageBox.Show("Nie zapisales zmian!");
e.Cancel = true;
}
}
And I got stackOverflow ;) Exception. Maybe someone now what is wron with this code?
You're recursively calling the method in itself forever. There's no terminating condition for these recursive calls. It'll result in Stack Overflow.
protected override void OnSelectedIndexChanged(EventArgs e)
{
CancelEventArgs cArgs = new CancelEventArgs();
OnSelectedIndexChanged(cArgs); // Clearly calling yourself indefinitely.
//...
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
CancelEventArgs cArgs = new CancelEventArgs();
//Next line!!
OnSelectedIndexChanged(cArgs);
if(!cArgs.Cancel)
{
base.OnSelectedIndexChanged(e);
}
}
You're calling yourself. Hence the StackOVerflow exception.
You have OnSelectedIndexChanged call within OnSelectedIndexChanged, it's an endless recursive call.