Odd object interaction with buttons, focusable property doing something strange - c#

private void Page_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Right)
{
if (shipPosition < right)
{
x = x + 10;
shipPosition = shipPosition + 10;
ship.Margin = new Thickness(shipPosition, y, 0, 0);
}
}
}
XAML - KeyDown="Page_KeyDown"
I have a rectangle named ship, and above is the function to move it, to be executed on right or left arrow key button press. For some reason, this doesn't work. The "KeyDown="Page_KeyDown"" is the xaml that links the button press with the event. There is another grid containing buttons that moves every time a timer ticks, and when I click on a button and highlight it, then press the arrow keys, the ship starts to move, with the highlighted button being changed as well. Does anyone have any idea what is going on?
Update: I removed the is focusable property on the buttons, and that then stopped ship movement all together. So I think it is something to do with the changing of focus on buttons.

Try this :
Keyboard.AddKeyDownHandler(this, Page_KeyDown);
Put it in the appropriate method of your control (constructor, initialized, ...)
public MainWindow()
{
InitializeComponent();
Keyboard.AddKeyDownHandler(this, Page_KeyDown);
}

Related

Annoying Border around button when pressing tab and clicking a button

I get this very annoying border when pressing tab and the clicking the button
I've tried
foreach (Control x in this.Controls)
{
if (x is Button)
{
Button newbut = (Button)x;
newbut.FlatStyle = FlatStyle.Flat;
newbut.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
newbut.FlatAppearance.BorderSize = 0;
newbut.TabStop = false;
}
}
And I've also tried doing adding an event on Keydown and not allowing to press the tab key but nothing has worked so far.
this is example of the border that keeps popping up
Fixed by generating own button class and editing the designer.cs file
If you do not want custom buttons, you can shift focus to another control once finished, this prevents the rectangle from showing. You could place a dummy control out of view and shift fucus to this.
private void btnDoSomething_Click(object sender, EventArgs e)
{
myDummyControl.Focus();
MessageBox.Show("This still executes even though we have lost focus");
// If you are decoupling your code from the UI, this becomes second nature quickly as it becomes part of your control handling.
}
Also you can stop the control from getting Tab focus my setting it's TabStop property tp false, do this in the buttons Paint event.
If you have many buttons, you can just point them to the same event handler (On_Paint).
private void On_Paint(object sender, PaintEventArgs e)
{
Button thisButton = sender as Button;
thisButton.TabStop = false;
}

Change button sprites in scrollview in Unity 5.2

I have a scroll view with lots of buttons on it. when i press one button, that button needs to change the sprite and stay like that. if any other button (or same one) is pressed previous button needs to revert back to original sprite..
here is some example
button 2 was pressed and changed sprite, it stays like that untill it is pressed again or any other (in this case button 3) is pressed
Here's a draft of a possible solution. Create a manager script for the "buttons group" and attach the script on the scrollview
public class ButtonsGroupController : MonoBehaviour
{
// List of all children buttons
private readonly List<Button> _buttons;
// Last pressed button index
private int _lastId = -1;
void Start(){
// Look for all buttons (children of this GO - scrollview)
_buttons = GetComponentsInChildren<Button>();
// Add event listener for buttons
for(var i = 0; i < _buttons.Count; i++){
var index = i;
_buttons[index].onClick.AddListener(() => ButtonPressed(index));
}
}
// Resolve buttons press event
private void ButtonPressed(int index){
// The same button has been pressed
if(_lastId == index)
return;
// Update the last selected button sprite - to normal state
// _buttons[_lastId]....
// Update the last id
_lastId = index;
// Update the sprite of newly pressed button
// _buttons[_lastId]....
}
}

Check time after a mousebuttondown before the mousebuttonup

I think that must be only a little problem, but I can't get a clear thought on that. Someone an idea?
I have some borders on a canvas (filled with images) and i want to click the border (i do this with the OnMouseLeftButtonDown) where the border gets red (so the user knows for sure which object he had clicked) and then, after 1 or 2 seconds, when the mousebutton is still pushed down, a drag'n'drop should start.
At first I had the borders inside buttons, but the clickevent seems to conflict with the dragevent. So I got rid of the buttons and did everything inside the borders directly, which works well also. But how can I start the drag after the mousebuttondown and stop it when the mousebuttonup happens before the time runs out.
Someone an idea for a clean solution?
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_source = sender as Border;
Mouse.Capture(_source);
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_source = null;
Mouse.Capture(null);
}
and in event OnMouseMove you can modify border margins depends on mouse position but after checking if _source is type of Border.
var position = e.GetPosition(Canvas);
EDIT:
For that time you can add property Stopwatch _watch, and inside OnMouseLeftButtonDown event handler you can do it:
_watch = Stopwatch.StartNew();
in OnMouseLeftButtonUp:
_watch.Stop();
and in OnMouseMove before your code:
while (_watch.ElapsedMilliseconds < 2000 && _watch.IsRunning)
{
Thread.Sleep(100);
}

Getting Position of mouse cursor when clicked out side the form's boundary

It is very easy to get the position of cursor out side the form's boundary by just dragaging the mouse it sends many values to the form when ever the position changes, form the following line of code.
MessageBox.Show(Cursor.Position.ToString());
But I need to get the mouse position when user clicked out side the forms boundary.
Not by just hovering the mouse. I used the following line of Code to do this:
private void Form1_Deactivate(object sender, EventArgs e)
{
MessageBox.Show(Cursor.Position.ToString());
}
I placed MessageBox.Show(Cursor.Position.ToString()); into forms Deactivate event. When user click outside the form this event definitely occures. But it also sends wrong values when user does not click outside but changes the program by using ALT + TAB key combination.
Actually I have to capture screen shot of the area starting from the position of first click. Therefore I need the position of the cursor when it is clicked outside the form.
like:
This might help some one.
Here I am using Windows.Forms.Timer and two text boxes for displaying [X and Y] cursor positions. On timer tick calling the API GetCursorPos and getting the cursor position.
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point lpPoint);
public Form1()
{
InitializeComponent();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
var pt = new Point();
GetCursorPos(ref pt);
textBox1.Text = pt.X.ToString();
textBox2.Text = pt.Y.ToString();
}
}
Regards,
Ranjeet.
You should use Global Mouse Hook logic to do this.
Here is a good article that will help you: Processing Global Mouse and Keyboard Hooks in C#
The solution to this problem is simple. All what you need is a System.Windows.Forms.Timer, and use System.Runtime.InteropService.DllImport to extern the method GetKeyState from user32.dll.
This function has one parameter of any type of integer, and it returns short (Int16). This function can tell you if some keys were pressed or not at every moment and everywhere, not depending on the form. While the Timer is Enabled, you can check if the mouse position is out of the form bounds. There are many ways to get the mouse position.
One way is Cursor.Position, or Control.MousePosition, or you can use the bool GetCursorPos(ref Point lpPoint), an extern method, that you can DllImport it from "user32.dll". form.Bounds or form.ClientRectangle, or form.Location and form.Size or form.Left and form.Top and form.Width and form.Height, all these bring you the form bounds. In the timer_Tick function event, you write the following code for example:
var mp = Cursor.Position;
var fb = form.ClientRectangle; // Or form.Bounds
if (mp.X < fb.X || mp.Y < fb.Y || mp.X > fb.X + fb.Width || mp.Y > fb.Y + fb.Height)
{
// Use GetKeyState from user32.dll to detect if at least 1 key is pressed
// (look at internet how to do it exactly)
// If yes MessageBox.Show("Clicked outside");
}
If at least 1 key was pressed, and then Show your message with the MessageBox. You can read on the Internet how to do all these stuff I was talking about before, and if you succeed, it will work!
Try this:
// Form1.cs
private Point pos1;
private Point pos2;
private bool b = true;
private double diffx;
private double diffy;
private double area;
private void Form1_Deactivate(object sender, EventArgs e)
{
if (b) (pos1, b) = (Cursor.Position, false);
else
{
pos2 = Cursor.Position;
if (pos1.x >= pos2.x) diffx = pos1.x - pos2.x;
else diffx = pos2.x - pos1.x;
if (pos1.y >= pos2.y) diffy = pos1.y - pos2.y;
else diffy = pos2.y - pos1.y;
area = diffx * diffy;
MessageBox.Show(area.ToString());
}
}
But you will have to click on the program again after clicking outside it in the start point and then click outside it in the end point to make the program work
Deactivate event notifies your form that it's not active any more. It could happen because of many reasons.
Usually a Window gets mouse events only when mouse is over this window. SetCapture function lets you grab all mouse events (I don't know .NET counterpart). Because only one window can capture mouse events, you should not capture mouse events when there's no need for it. The question does not have enough details on what you really want to do and why you need to know when user clicked outside your form.

C# Show/hide element on MouseHover/MouseLeave of the parent

In C#, we have the following:
A UserControl containing a PictureBox and an invisible FlowPanel.
What I want to achieve:
When the UserControl is hovered
(MouseHover), the invisible
FlowPanel will be set to visible =
true. When the mouse leaves the
UserControl or FlowPanel, the
FlowPanel should be set visible =
false.
Using MouseLeave on UserControl doesn't do the job, because this event is triggered when the mouse enters FlowPanel. Hiding the FlowPanel when the mouse leaves FlowPanel does it, but is buggy (sometimes MouseLeave is triggered, sometimes not).
What's the best way to fix this?
i did somthing similar on one of my forms
do a if(contorl.Opacity = 1.0) inside your first event
private void Form1_MouseLeave(object sender, EventArgs e)
{
if (this.ClientRectangle.Contains(this.PointToClient(Cursor.Position)))
{
this.Opacity = 1.0;
}
else
{
int loopctr = 0;
for (loopctr = 100; loopctr >= 5; loopctr -= 10)
{
this.Opacity = loopctr / 99.0;
this.Refresh();
Thread.Sleep(100);
}
}
}
In the case when FlowPanel.MouseLeave isn't triggered, isn't UserControl.MouseLeave triggered? I suppose that hiding on both events may do the trick.
This is a common UI problem. Mouse events come up as samples so it's possible that some pixel positions are missed and a control doesn't get the mouse up event.
A not so nice way that works is setting up some form of Timer when MouseHover is detected inside the Control and poll for the cursor in regular intervals (such as 342ms).

Categories