Capture MouseButtons.XButton1/2 for Forward/Backward navigation Windows 10 - c#

I want to capture the MouseButtons.XButton 1 and 2 and enable backward and forward navigation.
In Windows 10 I can capture mouse clicks using
this.PointerPressed += LevelsPage_PointerPressed;
private void LevelsPage_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
{
}
}
But how do I determine the pointer is MouseButtons.XButton or rather PointerRoutedEventArgs is of type MouseEventArgs? Once determined, I plan to handle the navigation using something like
if (pointer == MouseButton.XButton2 && this.Frame.CanGoBack)
{
this.Frame.GoBack();
e.Handled = true;
}
else if (pointer == MouseButton.XButton1 && this.Frame.CanGoForward)
{
this.Frame.GoForward();
e.Handled = true;
}

I figured it out. Here's how I do it
private void LevelsPage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
PointerPoint currentPoint = e.GetCurrentPoint(this);
if (currentPoint.PointerDevice.PointerDeviceType == PointerDeviceType.Mouse)
{
PointerPointProperties pointerProperties = currentPoint.Properties;
if (pointerProperties.IsXButton1Pressed && this.Frame.CanGoBack)
{
this.Frame.GoBack();
}
else if (pointerProperties.IsXButton2Pressed && this.Frame.CanGoForward)
{
this.Frame.GoForward();
}
}
}

Related

C# - txtbox.Undo() not working as expected for Del key

I'm making a Notepad variant in Visual Studio (Winform, C#). It has a toolstrip, with options such as Undo, Cut, Copy, Paste, Delete, etc. The shortcut keys are enabled and connected with the menu options (CTRL + Z, CTRL + C, etc).
The rest of the Notepad variant is filled with a multiline textbox.
The problem arises when I want to delete the text from the textbox via the Delete key, or the menu option - while that works (i.e. the characters to the right of the current caret position are deleted, selected characters are deleted, etc), I am unable to undo that specific action.
This is the relevant part of my code:
private void mnuCut_Click(object sender, EventArgs e)
{
if(txtbox.SelectedText != "")
{
txtbox.Cut();
}
}
private void mnuCopy_Click(object sender, EventArgs e)
{
if (txtbox.SelectedText != "")
{
txtbox.Copy();
}
}
private void mnuPaste_Click(object sender, EventArgs e)
{
if(Clipboard.GetDataObject().GetDataPresent(DataFormats.Text) == true)
{
if(txtbox.SelectionLength > 0)
{
txtbox.SelectionStart = txtbox.SelectionStart + txtbox.SelectionLength;
}
txtbox.Paste();
}
}
private void mnuUndo_Click(object sender, EventArgs e)
{
if(txtbox.CanUndo == true)
{
txtbox.Undo();
txtbox.ClearUndo();
}
}
private void txtbox_KeyUp(object sender, KeyEventArgs e)
{
// Delete
if(e.KeyCode == Keys.Delete)
{
if(txtbox.SelectionLength < 1)
{
txtbox.SelectionLength = 1;
}
txtbox.SelectedText = "";
}
// Select all
if(e.Modifiers == Keys.ControlKey && e.KeyCode == Keys.A)
{
txtbox.SelectAll();
}
}
private void mnuDelete_Click(object sender, EventArgs e)
{
if (txtbox.SelectionLength < 1)
{
txtbox.SelectionLength = 1;
}
txtbox.SelectedText = "";
}
private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
{
txtbox.SelectAll();
}
I think the problem may be in the way I'm deleting characters with the mnuDelete_Click and KeyUp event handlers. The same thing happens if I replace txtbox.SelectedText = "" with txtbox.SelectedText = String.Empty.
I know that I might be better off by using, say, txtbox.Cut(), like this:
private void txtbox_KeyUp(object sender, KeyEventArgs e)
{
// Delete
if(e.KeyCode == Keys.Delete)
{
if(txtbox.SelectionLength < 1)
{
txtbox.SelectionLength = 1;
}
//txtbox.SelectedText = "";
txtbox.Cut();
}
// Select all
if(e.Modifiers == Keys.ControlKey && e.KeyCode == Keys.A)
{
txtbox.SelectAll();
}
}
private void mnuDelete_Click(object sender, EventArgs e)
{
if (txtbox.SelectionLength < 1)
{
txtbox.SelectionLength = 1;
}
//txtbox.SelectedText = "";
txtbox.Cut();
}
But, even though this works, it'll replace the current contents of the clipboard with whatever was deleted / cut, which is something I don't want.
Finally, I ended up using SendKeys.Send("{BACKSPACE}"), and that gave the desired functionality. But the solution doesn't feel right - the original action was pressing the Delete key, not the Backspace key.
So, my question is this - how can delete characters via the Delete key, and obtain the ability to undo it, without resorting to hacky solutions? Or does it make no difference in the end, because it works as it is?

TextBox handled doesn't work in some case

I have textbox and when i create that form i pass some values and then i prevent user to input some things into textbox based on passed values with this code:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!brojevi && char.IsDigit(e.KeyChar))
{
e.Handled = true;
return;
}
if (!slova && char.IsLetter(e.KeyChar))
{
e.Handled = true;
return;
}
if (!znakovi && char.IsPunctuation(e.KeyChar) || !znakovi && char.IsSymbol(e.KeyChar))
{
e.Handled = true;
return;
}
if (!razmak && char.IsSeparator(e.KeyChar))
{
e.Handled = true;
return;
}
if (maxKaraktera != -1 && (textBox1.Text.Length + 1) > maxKaraktera)
{
e.Handled = true;
return;
}
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
}
Problem is that i enabled brojevi and set maxBroj to 10
Now when i try typing some char, it checks and see that slova is not true, set e.Handled = true and return and in my textbox that char is not imputed which is ok.
But when i try inserting number which is greater than 10 (let's say 12), it goes to if statement where it checks if(maxBroj != -1 && Convert.ToDoube(textBox1.Text) > maxBroj) and it enters it, set e.Handled = true and return but number is implemented in textbox.
Why this happens?
EDIT: Code from creating form and form that has textbox
Creating from:
MessageBoxWithValue msg = new MessageBoxWithValue("Unesite kolicinu", "Unesite zeljenu kolicinu. Maksimum: " + aa.maxKolicina.ToString());
msg.brojevi = true;
msg.maxBroj = aa.maxKolicina;
msg.ShowDialog();
if(msg.DialogResult == DialogResult.OK)
{
kol = Convert.ToDouble(msg.returnValue);
}
else
{
return;
}
Here is MessageBoxWithValue form:
public partial class MessageBoxWithValue : Form
{
public bool brojevi = false;
public bool slova = false;
public bool znakovi = false;
public bool razmak = false;
public double maxBroj = -1;
public int maxKaraktera = -1;
public string returnValue;
public MessageBoxWithValue(string naslov, string opis)
{
InitializeComponent();
this.Text = naslov;
label1.Text = opis;
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!brojevi && char.IsDigit(e.KeyChar))
{
e.Handled = true;
return;
}
if (!slova && char.IsLetter(e.KeyChar))
{
e.Handled = true;
return;
}
if (!znakovi && char.IsPunctuation(e.KeyChar) || !znakovi && char.IsSymbol(e.KeyChar))
{
e.Handled = true;
return;
}
if (!razmak && char.IsSeparator(e.KeyChar))
{
e.Handled = true;
return;
}
if (maxKaraktera != -1 && (textBox1.Text.Length + 1) > maxKaraktera)
{
e.Handled = true;
return;
}
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
}
private void button2_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
{
Uspesno();
}
}
private void button1_Click(object sender, EventArgs e)
{
Uspesno();
}
private void Uspesno()
{
this.DialogResult = DialogResult.OK;
returnValue = textBox1.Text;
}
}
But when i try inserting number which is greater than 10 (let's say 12), it goes to if statement where it checks if(maxBroj != -1 && Convert.ToDoube(textBox1.Text) > maxBroj) and it enters it, set e.Handled = true and return but number is implemented in textbox.
I hope I've got your issue right. You are trying to filter numbers by their values (e.g. maxBroj is set to 10) and you are expecting
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
not to allow entering a number >10. Unfortunately this will not work as intended, since textBox1.Text won't be set until the KeyPress event handler has finished.
Let's say you are entering 14. When the first KeyPress event is raised (1), textBox1.Text is empty. You are returning from
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
return;
}
Afterwards textBox1.Text is set to "1". Then the second KeyPress event is raised. textBox1.Text is "1", hence the method won't enter the block
if (maxBroj != -1 && Convert.ToDouble(textBox1.Text) > maxBroj)
{
e.Handled = true;
return;
}
Afterwards textBox1.Text will be set to "14", but this is too late for your validation.
You'll have to calculate the expected new value. Please see this question on how to insert the new character in the existing string.

Detecting simultaneous RMB and LMB presses on Raspberry Pi and Windows 10 IoT Core

Hello I am trying to detect if both the Left and Right buttons are being pressed at the same time in UWP. What is the best way to do this?
In UWP, there is no direct event indicated that LMB and RMB are both pressed. PointerUpdateKind specifies the types of pointer updates that are supported by an application.
You can detect only in an indirect method. Notice that, when pressing right mouse button meanwhile left mouse button is being pressed, it will invoke the PointerMoved event instead of PointerPressed.
private bool leftButtonPressed = false;
private bool rightButtonPressed = false;
//Scenario1OutputRoot is the ui element.
void Scenario1OutputRoot_PointerReleased(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(Scenario1OutputRoot);
if (pt.Properties.PointerUpdateKind != Windows.UI.Input.PointerUpdateKind.Other)
{
this.buttonPress.Text += (pt.Properties.PointerUpdateKind.ToString() + Environment.NewLine);
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.LeftButtonPressed)
{
leftButtonPressed = false;
}
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.RightButtonPressed)
{
rightButtonPressed = false;
}
}
}
void Scenario1OutputRoot_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(Scenario1OutputRoot);
if (pt.Properties.PointerUpdateKind != Windows.UI.Input.PointerUpdateKind.Other)
{
this.buttonPress.Text += (pt.Properties.PointerUpdateKind.ToString() + Environment.NewLine);
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.LeftButtonPressed)
{
leftButtonPressed = true;
}
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.RightButtonPressed)
{
rightButtonPressed = true;
}
}
if (leftButtonPressed && rightButtonPressed)
{
this.buttonPress.Text = "both the Left and Right buttons are being pressed ";
}
}
void Scenario1OutputRoot_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(Scenario1OutputRoot);
if(pt.Properties.PointerUpdateKind != Windows.UI.Input.PointerUpdateKind.Other)
{
this.buttonPress.Text += (pt.Properties.PointerUpdateKind.ToString() + Environment.NewLine);
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.LeftButtonPressed)
{
leftButtonPressed = true;
}
if (pt.Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.RightButtonPressed)
{
rightButtonPressed = true;
}
if (leftButtonPressed && rightButtonPressed)
{
this.buttonPress.Text = "both the Left and Right buttons are being pressed ";
}
}
e.Handled = true;
}

Detect two buttons clicked for touchscreen

I have an application for kiosk machine that appears always on the top and fullscreen. Also, I have to turn off explorer.exe.
Therefore, I will not be able to access anything without a keyboard.
I'm thinking to make gestures or invincible buttons so that I can turn on explorer.exe without keyboard.
I would like to know if there is a way to detect if two buttons are clicked at the same time. I've tried using the following code but it is not working.
PS: I can't debug it line by line as my PC do not have touchscreen.
Therefore, I cannot find out which line causes the problem.
private bool button1WasClicked = false;
private bool button2WasClicked = false;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
button1WasClicked = true;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
button1WasClicked = false;
}
private void button2_MouseUp(object sender, MouseEventArgs e)
{
button2WasClicked = false;
}
private void button2_MouseDown(object sender, MouseEventArgs e)
{
if (button1WasClicked == true)
{
Process.Start(Path.Combine(Environment.GetEnvironmentVariable("windir"), "explorer.exe"));
Application.Exit();
button1WasClicked = false;
}
}
You can't click two buttons at once with a mouse or keyboard, and if you're talking about using a touchscreen, the WinForms framework doesn't support them (taps will simply be interpreted as individual mouse clicks at best). You'll want to look at using the Surface SDK or something else instead.
I've found a different solution where the buttons(panels) have to be clicked in a certain sequence to achieve what I wanted. I've also added a timer. Below is my code.
private bool panel1WasClicked = false;
private bool panel2WasClicked = false;
int second = 0;
private void panel1_Click(object sender, EventArgs e)
{
MaintenanceTimer.Interval = 500;
MaintenanceTimer.Start();
second = 0;
if (panel1WasClicked == false)
{
panel1WasClicked = true;
}
else
{
panel1WasClicked = false;
}
}
private void panel2_Click(object sender, EventArgs e)
{
if (panel2WasClicked == false && panel1WasClicked == true)
{
panel2WasClicked = true;
}
else
{
panel2WasClicked = false;
}
}
private void panel3_Click(object sender, EventArgs e)
{
if (panel1WasClicked && panel2WasClicked == true)
{
//Do something
}
panel1WasClicked = false;
panel2WasClicked = false;
MaintenanceTimer.Stop();
}
private void MaintenanceTimer_Tick(object sender, EventArgs e)
{
second += 1;
if (second >= 5)
{
MaintenanceTimer.Stop();
second = 0;
panel1WasClicked = false;
panel2WasClicked = false;
}
}

Capturing ctrl + multiple key downs

Is there an easy way to capture a ctrl+key1, key2 event in a winforms app similar to that in visual studio such as ctrl+e, c = comment out selected lines?
I am currently overriding my forms OnKeyDown event:
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Control && e.KeyCode.ToString() == "N")
{
//do something...
}
}
The article in the comment may have been for WPF but the idea in it can still be used
Construct a class such as
public class MultiKeyGesture
{
private List<Keys> _keys;
private Keys _modifiers;
public MultiKeyGesture(IEnumerable<Keys> keys, Keys modifiers)
{
_keys = new List<Keys>(keys);
_modifiers = modifiers;
if (_keys.Count == 0)
{
throw new ArgumentException("At least one key must be specified.", "keys");
}
}
private int currentindex;
public bool Matches(KeyEventArgs e)
{
if (e.Modifiers == _modifiers && _keys[currentindex] == e.KeyCode)
//at least a partial match
currentindex++;
else
//No Match
currentindex = 0;
if (currentindex + 1 > _keys.Count)
{
//Matched last key
currentindex = 0;
return true;
}
return false;
}
}
but ignore the inheritance.
to use it
private MultiKeyGesture Shortcut1 = new MultiKeyGesture(new List<Keys> { Keys.A, Keys.B }, Keys.Control);
private MultiKeyGesture Shortcut2 = new MultiKeyGesture(new List<Keys> { Keys.C, Keys.D }, Keys.Control);
private MultiKeyGesture Shortcut3 = new MultiKeyGesture(new List<Keys> { Keys.E, Keys.F }, Keys.Control);
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (Shortcut1.Matches(e))
BackColor = Color.Green;
if (Shortcut2.Matches(e))
BackColor = Color.Blue;
if (Shortcut3.Matches(e))
BackColor = Color.Red;
}
If you only have a two key shortcut, like VS does, you could store the last key pressed in a variable.
private Keys lastKeyPressed = null;
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if(e.Control && lastKeyPressed != null)
{
if(lastKeyPressed == Keys.firstKey && e.KeyCode == Keys.secondKey)
{
}
else if (...) // so on and so forth.
}
else if(e.Control)
lastKeyPressed = e.KeyCode;
}
protected override void OnKeyUp(KeyEventsArgs e)
{
if(!e.Control)
lastKeyPressed = null;
}
This would do a two key shortcut, and would reset it when the ctrl key is released. This is just untested pseudo code but its the concept of saving the last pressed key when Ctrl is being held then resetting it when ctrl is released that I'm trying to convey.
Call e.Modifiers for control key and e.KeyCode for the combined key.
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
// For Tow Key Shortcut.
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.B)
{}
// For Triple Key Shortcut.
if (e.Modifiers.ToString() == (Keys.Shift+", "+Keys.Control) && e.KeyCode == Keys.B)
{}
}
// For Form level Key events you must have to set KeyPreview to True;
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
}

Categories