How determine where a mouse is wherever it's clicked - c#

I'm making a chess game in C#, and I'm using 64 pictureBoxs to display the board. Now, I'm trying to figure out how to determine where the user clicks to allow the user to move pieces by clicking different tiles/pictureBoxes. I'm new to C#, but I'm trying to do it by detecting where the mouse is whenever it's clicked. I've been using:
void MainFormClick(object sender, EventArgs e){
Point mousePosition = pictureBox1.PointToClient(Cursor.Position); //pictureBox1 is in upper-left
int indexClicked = (mousePosition.X / tileSize) + (8 * (mousePosition.Y / tileSize));
if (indexClicked >= 0 && indexClicked <= 63){
//do code things?
}
this.Text = "Chess - " + indexClicked;
}
I assume this isn't working because the user isn't actually clicking on the form, but on the pictureBoxes. I'd rather not make 64 pictureBox*Click methods, so is there some other way I should be doing this or method I should be using?
EDIT: I just looked at How to get control under mouse cursor. My code needs to be changed a little to better determine which pictureBox the mouse is over when it's clicked, but my real problem is that it doesn't appear that clicking on the pictureBoxes runs the above method. I'm looking for a way to run a block of code whenever the mouse is clicked, regardless of what control or part of the form it's clicked on.

I would probably just use the normal Click event. Pictureboxes have a Click event that you can bind to. I'm not sure how you're adding them, but for 64 of them I'd probably add them dynamically in a loop. As you create each one, bind the Click event to a common handler. Name each control in a way that makes it easy to figure out where it is located. Then in the handler you get an object reference to the picturebox that was clicked and can figure out what to do from there.

What you can do is :
Create 64 pictureBoxes and name them something like squareA1, squareF4 and so on
Create Click event handler
Attach this event handler to all of your pictureboxes in designer
Use object sender to find out in what picturebox event was invoked
The code might look like:
private void square_Click(object sender, EventArgs e)
{
PictureBox target = sender as PictureBox;
MessageBox.Show(target.Name); // displays pictureBox name
}
Code that is added automatically by designer to each picturebox :
this.squareA2.Click += new System.EventHandler(this.square_Click);
Alternatively you can create all 64 pictureboxes in a loop, calculate their positions, and attach this event handler to each of them...

You are already calculating where the mouse cursor is, so you should really just change to use 1 large picture box for the entire board and wire the click event to your posted method.

Related

How to know which Image the MouseClick event occured?

I have 2 images for 2 players on my windows form. I have added a MouseClick event for both of them. Now when I mouse click, it activates both the events for both the players. I wanted to know only one player where I am clicking.
How do I do that?
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this._player1_MouseClick);
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this._player2_MouseClick);
Assume you have two PictureBox controls with images. Thus you have posted code from designer, I also assume that you are subscribing to events via designer.
Select one of PictureBox controls
In Events tab find Click property, type-in Player_Click as handler name and hit Enter. You have subscribed to Click event of first control.
Select second PictureBox
In Events tab find Click property, click on drop-down and select Player_Click as well. Hit Enter. You have used same event handler to subscribe to Click event of second control.
Now go to code view (you can double click any of those controls for that) and find Player_Click method
In order to find which control was clicked you need to cast sender argument to PictureBox type:
private void Player_Click(object sender, EventArgs e)
{
var pictureBox = (PictureBox)sender;
// use control which was clicked. e.g. get it's name
var name = pictureBox.Name;
}

C# mouse events on a panel don't apply to objects in panel

I am working on a simple C# program that allows the user to use the mouse to move simple controls (Buttons, textareas, etc), similar to a visual designer like visual studio. The controls are contained in a panel and they all work as expected. However, when I call MouseDown() on the panel the controls are contained in, the event only fires when clicking on an empty part of the panel, not when I click on a Control contained within the form.
Here is my MouseDown() Code:
private void splitContainer2_Panel2_MouseDown(object sender, MouseEventArgs e)
{
Console.WriteLine("MOUSE GRABBED");
...
//More code that uses the X and Y co-ords of the mouse to check which
//Control is selected
...
}
As you can see it is very straightforward. The writeLine() is not triggered when I click on a control.
I have looked at questions such as:
ignore mouse event on label inside panel
To no avail.
Any help would be appreciated, even a better method to do what I am trying to acomplish.
Instead of using a MouseDown() event for the panel, why not trying to use the same one for every object? Based on what you are trying to do, add the following code:
Where you create each form element:
nameOfElement.MouseDown += new System.Windows.Forms.MouseEventHandler(this.splitContainer2_Panel2_Objects_MouseDown);
The mouse down method:
Control ctrl = (Control)sender;
Console.WriteLine("Moused down on: " + ctrl.Name);
//Code to manipulate mouse down
Hope this helps!
Use PreviewMouseDown. The WPF hit testing engine will not raise events on parent elements if the child element absorbs the event.

Detecting a left button mouse click Winform

What I'm trying to do is get my winform to display a debug line when ever I click in my winform. However, when I do, nothing happens. I know how to get a button / other click event to happen. But what I need is to be able to click anywhere within my winform.
I've googled this for the past hour but can't see what I'm doing wrong. As far as I'm aware, this code should be correct in detecting a mouse click. This method is held withing the form1.cs class:
private void mouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
Trace.WriteLine("Mouse clicked");
}
I've tried setting brake points, but these don't get triggered either. What is it I'm doing wrong?
Sorry for the stupidly newbie question, but I am very new to winform programming.
How to add the EventHandler:
public Form1()
{
InitializeComponent();
// This line should you place in the InitializeComponent() method.
this.MouseClick += mouseClick;
}
Using the editor built-in to Visual Studio:
Go to the properties window (if you don't see it, press Alt + Enter).
Select the events icon (looks like lightning).
Double-click on the empty ComboBox to the right of Click.
You'll be taken to an empty method where you can put your code.
The method itself is correct. I think your actual problem is: you haven't added this method to MouseClick events.
In C# – and most other languages too – event is handled by an event handler. Windows forms and controls have events for all the events happening in your controls, such as OnClick or OnResize.
You can append methods to these events, and the methods will automatically get called when the actual event happens. Simply add the following line to your form's constructor, Form_Load-method, InitializeComponent-method, or such:
this.MouseClick += mouseClick;
Now when ever MouseClick event happens, your method mouseClick will be called automatically.
I would recommend reading Events C# Programming Guide. You need to add an event handler like so:
form1.MouseClick += mouseClick;

C# How to make webbrowser clickable

I was wonder how can I fire an event when the user double click on my webbrowser component. Since it has no such event how it could be possible...
Thanks in advance
Sounds like a WPF matter :-)
There you would go with an Behaviour attached to the browser. See this link for more information about this approach if you can alter your application (dependends on what you have done yet).
If you can't apply this solution, just bind a event handler to the click event and count click per time with respect to the mouse movement since the last click and if both conditions are true (two clicks in 0.2 secs, mouse hasn't moved more than 2px, for example) execute your double click code. The events you should use are previewMOUSEdown or MOUSEdown, not KEYdown.
// Call this where you want to create the event (let's say on the form load for example).
webBrowser1.DoubleClick += new EventHandler(webBrowser1_DoubleClick);
// This happens when the event is fired (so when you double click on the webbrowser control).
void webBrowser1_DoubleClick(object sender, EventArgs e)
{
// Code
}
Try this.
I don't know why you can't set this event via the designer :(, but this should work.

WPF create a list of controls that can be scrolled via the mouse but still remain functional

I have a list of controls that I am displaying via a WrapPanel and it horizontally oriented.
I have implemented a "Click and Drag" scrolling technique so that the user scrolls with the mouse via clicking and dragging.
Like so:
<Canvas x:Name="ParentCanvas" PreviewMouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove">
<WrapPanel>
<WrapPanel.RenderTransform>
<TranslateTransform />
</WrapPanel.RenderTransform>
<!-- controls are all in here ... -->
</WrapPanel>
</Canvas>
Then in the code behind:
private Point _mousePosition;
private Point _lastMousePosition;
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
_lastMousePosition = e.GetPosition(ParentCanvas);
e.Handled = true;
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
_mousePosition = e.GetPosition(ParentCanvas);
var delta = _mousePosition - _lastMousePosition;
if(e.LeftButton == MouseButtonState.Pressed && delta.X != 0)
{
var transform = ((TranslateTransform)_wrapPanel.RenderTransform).Clone();
transform.X += delta.X;
_wrapPanel.RenderTransform = transform;
_lastMousePosition = _mousePosition;
}
}
This all works fine
But what I want to do is make it so that when a users clicks to drag, the items within the WrapPanel dont respond (i.e. the user is only browsing), but when the user clicks (as in a full click) then they do respond to the click.
Just like how the iphone works, when you press and drag directly on an app, it does not open the app, but rather scrolls the screen, but when you tap the app, it starts...
I hope this makes sense.
Cheers,
Mark
I believe you'll need to capture the mouse. The problem is you'll be contending with the controls (such as Button) that will also be trying to capture the mouse.
In your MouseDown event (probably PreviewMouseDown actually) you can use e.MouseDevice.Capture(_wrapPanel, CaptureMode.Element). This should direct all mouse input to the _wrapPanel and not any subtree elements.
In your MouseUp event, you'll need to release the capture by calling e.Mousedevice.Capture(null). If no scrolling has taken place you'll want to send a "click" to the control that normally would have received the click which I'm not quite sure about. Perhaps you can use the Automation Peer classes to do this?
The trick is that certain controls will not work properly if you withhold mouse events from them. Consider a slider for example. How would the slider ever be usable inside a panel that works like this?
Another, and in my opinion better, solution is to:
Add a PreviewMouseDown handler in which you set Handled=true and record the parameters including the position and set a "maybeClick" flag (unless your "recursion" flag is set), and sets a timer.
Add a MouseMove handler that clears the "maybeClick" flag if the mouse moves more than an epsilon away from the position recorded for the PreviewMouseDown.
Add a PreviewMouseUp handler that checks the "maybeClick" flag - if true, it sets the "recursion" flag, does an InputManager.ProcessInput to re-raise the original PreviewMouseDown, and then clears the "recursion" flag.
In the timer, do the same thing as for PreviewMouseUp so the click will only be delayed a moment.
The net effect is to delay a PreviewMouseDown event until you have had time to check whether the mouse moved or not.
Some things to note about this solution:
Setting Handled=true on PreviewMouseDownEvent also stops the MouseDownEvent.
The recursive call is ignored in the PreviewMouseDown handler because the recursion flag is set

Categories

Resources