This is my first question so please go easy :)
I am new to WPF and Desktop based applications and I am studying Event Handling. Going through Bubbling and Tunneling I can not find an example anywhere that explains how to use tunneling on a Button_Click.
Basically when I click a button I need the parent control (in this case a grid) to handle the event first and do some checks before allowing the Button_Click to take place. The problem I am having is I can use the Grid_PreviewMouseDown to capture the event but this is ambiguous! It does not tell me (at least i think it doesnt) what control caused the handler to trigger.
What can i do to determine the PreviewMouseDown was triggered by a Button Click? Or:
Is there an alternative/better was to tunnel a Button_Click?
Thanks
In your handler, you should inspect the Source of the event to get the control which initiated it. Just note that it is not readonly and could be changed so the Source refers to a different control.
You'll probably have better luck registering with the PreviewMouseLeftButtonDown event to get left clicks and not just any click.
If your handler is meant to only look for the left mouse click, you could use this code:
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Button button = e.Source as Button;
if (button != null)
{
// button is being clicked, handle it
}
}
Related
I'm using Mapsui as a mapping control in a C# application.
By default, panning is initiated by dragging using the left mouse button.
I want to change this to the middle mouse button.
Does anyone know how to do this?
Mapsui has an object called PanMode, you can create an instance as follows, however, I believe it is just an enum for centering the map when panning:
Mapsui.UI.PanMode panMode = new PanMode();
EDIT:
Based on what 'pauldendulk's' answer (thank you for your support) I think I need to do something like this:
First, catch the middle button click and relay it to the mapsui left button method. Unfortuantly MapControlMouseLeftButtonDown() is a private method so this will not work.
MyMapControl.MouseDown += MapControlOnMouseButtonDown;
private void MapControlOnMouseButtonDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton == MouseButton.Middle)
{
Mapsui.UI.Wpf.MapControl.MapControlMouseLeftButtonDown(sender, e);
}
}
Secondly I need to stop the origional left button click from firing.
MyMapControl.MouseLeftButtonDown += null;
Again, this is not correct syntax as it throws an exception (cannot be null).
Does anyone know how to solve these issues?
Mapsui was not designed with this in mind. Perhaps it is possible if you assign an event handler to WPFs mouse down event, set the viewport in there. Also, you need to suppress the regular mouse event. Perhaps this is possible by setting the MouseLeftButtonDown event handler to null.
PanMode is not relevant. It is meant to limit the area where users can pan/zoom.
How can I check that whether mouse pointer is pointing a button or some other control?
I want to perform a particular task when mouse hover/move a button.
I know I can set event on individual button. But isn't it possible to check the pointed/hover control is button?
The sender argument in an event method should have the information you need...
private void MyEventHandler(object sender, EventArgs args) {
if(sender is Button) {
//Do some stuff
}
}
I'm not sure if you mean: can I do this without event handlers for MouseHover in individual controls. If so, the answer is no.
But you can attach each contol's MouseHover event to just one event handler that could look like the one in Chris's answer. For convenience you could even do that programmatically by looping through the controls in the form's load event. (assuming this is winforms)
How to capture mouse wheel on panel in C#?
I'm using WinForms
EDIT:
I try to do it on PictureBox now.
My code:
this.pictureBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseClick);
this.pictureBox1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseClick);
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("Click");
}
Clicking works. Wheelling doesn't.
Why?
If you can't see the "MouseWheel" event on a component, then you need to create it manually. Also, we need to focus that component, otherwise the "MouseWheel" event will not work for that component. I will show you how to create a "MouseWheel" event for "pictureBox1" and how it works.
INSIDE THE CONSTRUCTOR, create a mousewheel event on that component.
InitializeComponent();
this.pictureBox1.MouseWheel += pictureBox1_MouseWheel;
CREATE THE FUNCTION manually. According to my example, call it "pictureBox1_MouseWheel"
private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
{
//you can do anything here
}
CREATE a MouseHover event on that component (Go to properties in PicureBox1, select event, locate "MouseHover" and double-click the "MouseHover" event).
CALL "Focus()"; method inside that MouseHover event.
pictureBox1.Focus();
Now run the program.
Windows sends the WM_MOUSEWHEEL message to the control that has the focus. That won't be Panel, it is not a control that can get the focus. As soon as you put a control on the panel, say a button, then the button gets the focus and the message.
The button however has no use for the message, it's got nothing to scroll. Windows notices this and sends the message to the parent. That's the panel, now it will scroll.
You'll find code for a custom panel that can get the focus in this answer.
UPDATE: note that this behavior has changed in Windows 10. The new "Scroll inactive windows when I hover over them" option is turned on by default. The makes the mouse wheel behavior more consistent with the way it works in a browser or, say, an Office program. In this specific case the picturebox now will get the event. Watch out for this.
To wire it up manually...
this.panel1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseWheel);
private void panel1_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
{
///process mouse event
}
Easier method is in visual studio click on panel, goto properties viewpanel, select events, locate and double click the "mousewheel" event.
In Winforms, this is achieved using the Control.MouseWheel event
Getting mousewheel events is tricky. The easiest way is using
this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseWheel);
instead of
this.panel1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseWheel);
This way the form gets the event instead of control. This way is easy but has one problem: you can use only one mousewheel event in your form.
If you have more than one control to get mousewheel event the best way is This answer by "Shehan Silva - weltZ"
I'm currently developing a custom control and realize that my code is being run twice. It is not really a huge issue (it is only a Focus method call). However, I would like to understand it.
From reading the MSDN description for click | onclick event, it states that:
Fires when the user clicks the left mouse button on the object.
So I added the OnClick event and the MouseClick events to handle both left and right clicking. But after debugging the code I found that the OnClick handles both left and right click events.
Why is OnClick handling both and do I need to keep both events in my code for some reason I'm overlooking?
protected override void OnClick(EventArgs e)
{
this.Focus();
base.OnClick(e);
}
private void CustomControl_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
rightClickMenu(e);
}
}
According to MSDN, the Click event is called not only when the mouse is clicked, but also when the Enter button is pressed. If you only need to handle mouse clicks, I'd move all of your code in the MouseClick event. You can't do it the other way around because the Click event doesn't tell you which mouse button (if any) was clicked.
First of all, your link is incorrect, it links to HTML and DHTML Reference, not WinForms :)
Correct link is Control.MouseClick event
You need to override only one method. If you want to handle only mouse clicks - override OnMouseClick() and don't handle MouseClick event, otherwise - override OnClick() and don't override OnMouseClick().
You shouldn't need to have both events... Just keep the OnClick.
Also, I haven't done Windows Forms in quite a while, but I think there's a better way to accept focus than manually setting it on the click event, but I can't tell you specifically what it is... I think there's a property for it or something.
In Winforms, the Click event is raised when either mouse key is clicked.
If my memory serves me right, click does both mouseclick and the 'Enter' key or even setting focus on the control using the 'Tab' key and then using 'Space' or 'Enter' to "click" it.
If such behaviour is acceptable/desired, you may do the following.
I had this workaround for a DoubleClick event...
void ControlClick(object sender, EventArgs e)
{
MouseEventArgs mEvt=e as MouseEventArgs; // or (MouseEventArgs)e;
// now mEvt has the same properties as 'e' in MouseClick event
}
Hope this helps.
-Nurchi
The OnClick and CustomControl_MouseClick is the same event
You can have how many methods you want attached to an event ( this.Click += ...)
I have a bunch of controls (textbox and combobox) on a form with toolstripcontainer and toolstripbuttons for save, cancel etc for edits. We are using .Net 3.5 SP1
There is bunch of logic written in control.lostfocus and control.leave events. These events are not being called when clicked on the toolstrip buttons. Is there a way to call these events manually when any of these buttons are pressed.
Thanks.
Kishore
[Edit]
This is how I solved the problem. Thanks Chris Marasti-Georg for the pointer. In the button click event I calling focus on the toolstrip instead of the button as the toolstripbutton does not have a focus event. We can access the toolstrip on which the button is placed using
((ToolStripButton)sender).Owner.Focus()
-Kishore
You could listen to the click events on the buttons, and in the handler call their focus method. That would (hopefully) cause the previously focused control to respond correctly. Add the following handler to each button's click event:
private void ButtonClick(object sender, EventArgs e) {
if(sender != null) {
sender.Focus();
}
}
You can extend those controls and then call the OnLostFocus and OnLeave protected methods of the base class...
I'd suggest moving the login to a method outside the event handler and calling that method...