Detecting the user pressing F10 in WPF - wpf

My WPF application has behaviour triggered by the functions keys (F1-F12).
My code is along these lines:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.F1:
...
case Key.F2:
...
}
}
This works for all F-keys except F10. Debugging, I find that e.Key == Key.System when the user presses F10.
In the enum definition, F10 = 99 and System = 156, so I can rule out it being a duplicate enum value (like PageDown = Next = 20).
So, how do I tell when the user presses F10?
Is it safe to check for Key.System instead? This feels a little dirty - might it be possible that Key.System would ever result from some other key being pressed? Or is there some setting somewhere that will make F10 report as Key.F10?

In addition to Yacoder's response, use the following to check for the F10 key:
case Key.System:
if (e.SystemKey == Key.F10)
{
// logic...
}
The SystemKey property will tell you which System key was pressed.

F10 launches the window menu. It's the same in all Windows apps.
It seems that Key.System is the expected value for the F10 key.

Answer with DataContext:
public partial class BankView : UserControl
{
public BankView()
{
InitializeComponent();
this.KeyDown += new KeyEventHandler(BankView_KeyDown);
}
private void BankView_KeyDown(object sender, KeyEventArgs e)
{
try
{
switch (e.Key)
{
case Key.F4:
((BankViewModel)DataContext).OpenAccount();
break;
}
}
catch (Exception ex)
{
...
}
}

This worked for me, for F1
Private Sub Window_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If (e.Key = Key.F1) Then
ShowHelp()
End If
End Sub

Related

if Right button pressed on console

Good morning,
I would like to know if my right mouse button is held down.
For this I thought of System.Windows.Input.Mouse but I get this error if I execute the following code:
while (true)
{
if (Mouse.RightButton == MouseButtonState.Pressed)
{
}
}
Error : Unmanaged exception: System.InvalidOperationException: The calling thread must be in STA mode, as required by the name
Is there an alternative or something that would work as a console?
Thanks
Try using it inside a function like this :
private void PressLeftButton(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
MessageBox.Show("The Left Mouse Button is pressed");
}
}

Windows Form - Override Enter with an other key

Is there a way in Windows Form to activate the currently focused button/control with the Q key? Or override the Enter, so that pressing Q activates the currently focused control like Enter does? I want the user to be able to control the application with just the left hand on Tab and Q to cycle controls and activate them.
private void Form2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Q)
{
e.Handled = true;
}
I already have this, but what do I need after the e.Handled to activate the current focus?
As an option you can override ProcessCmdKey and check if the key is Q then send Enter using SendKeys.Send and return true to indicate you that you processed the key:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Q)
{
SendKeys.Send("{Enter}");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
You can limit the behavior to buttons by checking this.ActiveControl is Button if you need.

Restrict button click on telerik radgridview cellValidating event - winforms

I was testing its cellValidating event which has some problem or may be i am missing something. When the radgridview cell in in edit mode i cannot click anywhere on the form thats fine here. But when i click on button, code executes and my form hangs. So my question is how can i disable code execution on button click when radgridview cell is in edit mode during cellValidating event. Note: When i debug code and insert breakpoints on cellValidating event and button. Code works well and button code does not executes. Following is the code that i am using.If anyone can immediate answer i shall be very thankful to him.
Private Sub rgv_CellValidating(sender As System.Object, e As Telerik.WinControls.UI.CellValidatingEventArgs) Handles rgv.CellValidating
Dim column As GridViewDataColumn = TryCast(e.Column, GridViewDataColumn)
If TypeOf e.Row Is GridViewDataRowInfo AndAlso column IsNot Nothing AndAlso column.Name = "ProductId" Then
If String.IsNullOrEmpty(DirectCast(e.Value, String)) OrElse DirectCast(e.Value, String).Trim() = String.Empty Then
e.Cancel = True
DirectCast(e.Row, GridViewDataRowInfo).ErrorText = "Validation error!"
Else
DirectCast(e.Row, GridViewDataRowInfo).ErrorText = String.Empty
End If
End If
The phenomnenon you describe about buttoncode still executing also is true for ribbonmenu buttons and ribbonmenutabs. The hanging up problem I couldn't reproduce so I guess it has to do with the code of your executed buttons there.
For a possible workaround you could put a private variable into your form and in the cellvalidation code set it to true if an error occurs and false if no error occurs (and naturally set it fo false in the form initialization code).
Then within the buttons code you test for the variables value if its true no code is executed.
Thus if you have a ribbonform (or any other form) as class:
public partial class MF : RadRibbonForm
{
private bool _hasValidationError;
public MF()
{
...//Normal construction handler code
_hasValidationError = false;
}
void MF_CellValidating(objec sender, CellValidatingEventArgs e)
{
.....//Do validation and set e.Cancel true if the validation fails.
if (e.Cancel)
{
hasValidationError = true;
}
else
{
hasValidationError = false;
}
}
private void MyButton_Click(object sender, EventArgs e)
{
if (_hasValidationError)
{
// Before return you could put in a messagebox that there are cell errors that need to be looked at first
return;
}
else
{
.......//Button code execution occurs here
}
}
With this code you can make sure that the code of the buttons you don't want to be executed won't get executed on an Cell validation error.
The Code is in C# but should work similar for VB winforms.
This seems to be a known issue with the grid issue link.
There is also work around for the issue provided:
bool validating = false;
void radGridView1_CellValidating(object sender, Telerik.WinControls.UI.CellValidatingEventArgs e)
{
if (e.Value.ToString().Length < 5)
{
e.Cancel = true;
validating = true;
e.Row.ErrorText = "Validation error!";
}
else
{
validating = false;
}
}
private void radButton1_Click(object sender, EventArgs e)
{
if (!validating)
{
Debug.WriteLine("Executed");
}
}

WinForms - Capturing the combination of key presses using ProcessCmdKey VS KeyDown

My goal is to implement a custom Control + S key press handler to wire up to a custom save method in a winforms app.
There are several ways to accomplish this based on my R&D. First, I tried the obvious KeyPress event handler. This wasn't powerful enough to capture the key presses I need (it wasn't called on the Editor level, which is what I needed).
The second option which looks better is the protected override bool ProcessCmdKey(ref Message msg, Keys keyData) override. This works - it intercepts the CTRL key click, but apparently I need to write extra code to persist the fact the CTRL key is pressed and intercept the next key press (which would be S in my case) and then perform the custom action.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.S | Keys.Control))
{
// This is never called
}
else if (keyData == (Keys.Menu | Keys.Alt))
{
// this is called each time I hit CTRL
}
return true;
}
ProcessCmdKey seems to be called immediately after I hit the CTRL key.
This post suggests creating a KeyTracker class that will persist the keys pressed and do what it needs to do:
Capture Key Sequence via ProcessCmdKey
Which seems like a good option, but before I dig in an implement a memento tracking pattern, does anyone have input on how else to accomplish this seemingly common feature?
Another pattern uses the GetKeyboardState API function:
Capture multiple key downs in C#
This seems interesting, though I'm not sure it will suite my needs.
[DllImport ("user32.dll")]
public static extern int GetKeyboardState( byte[] keystate );
private void Form1_KeyDown( object sender, KeyEventArgs e )
{
byte[] keys = new byte[255];
GetKeyboardState (keys);
if( keys[(int)Keys.Up] == 129 && keys[(int)Keys.Right] == 129 )
{
Console.WriteLine ("Up Arrow key and Right Arrow key down.");
}
}
Thank you for taking a look at my problem.
UPDATE
I've added three events for key handling to my DataPanel. None of these events are being picked up by VS when I set breakpoints in the events, so this is what leads me to believe that ProcessCmdKey is my best option.
If I could get these Events to work, that would be good as well:
// Ctrl + S: Save Support
this.ParentForm.KeyPreview = true;
this.KeyPress += new KeyPressEventHandler(DataPanel_KeyPress);
this.KeyDown += new KeyEventHandler(DataPanel_KeyDown);
this.PreviewKeyDown += new PreviewKeyDownEventHandler(DataPanel_PreviewKeyDown);
None of these events seem to be caught when pressing any keys:
void DataPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == (Keys.S | Keys.Control))
{
SessionManager.Trace.AddTrace("You Hit Save!!");
}
}
void DataPanel_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == (Keys.S | Keys.Control))
{
SessionManager.Trace.AddTrace("You Hit Save!!");
}
}
void DataPanel_KeyPress(object sender, KeyPressEventArgs e)
{
var key = e.KeyChar;
}
UPDATE
I've solved the problem by using a simple KeyUp event and the KeyPreview flag:
void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
MessageBox.Show("Control + S Key Hit!");
}
}
Thank you.
Set the KeyPreview property of our form to true. The summary of this property says: "Gets or sets a value indicating whether the form will receive key events before the event is passed to the control that has focus.". Then use the KeyUp event. Unless KeyPressed it gives also information on special keys like control keys.
I solved this by doing,
if(e.KeyData==(Keys.S | Keys.Control))
Though this is a very old question, I still like to add my answer.
The OP writes that he could not use the ProcessCmdKey because it would fire as soon he hits the Control key and would not wait until he hits the S key also.
I don't have that problem, my code below works well and the Delete() method is only called when I first hit Ctrl and then S
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool bHandled = false;
// switch case is the easy way, a hash or map would be better, but more work to get set up.
switch (keyData)
{
case Keys.F5:
RefreshList("", "", false); // call my refresh method
bHandled = true;
break;
case Keys.S | Keys.Control: // call my delete method
Delete(false);
bHandled = true;
break;
default:
base.ProcessCmdKey(ref msg, keyData);
break;
}
return bHandled;
}
protected virtual void Delete(bool handled)
{
if (handled == false)
{
MessageBox.Show("delete");
}
}

Why doesn't the MaxLength property on a RichTextBox work in WPF?

I am trying to set the MaxLength property on a RichTextBox but it does not seem to work.
Any ideas what might be happening?
The fundamental problem is that the WPF RichTextBox doesn't have a MaxLength property - unlike the Windows.Forms one.
Here's an improvement on #jhony's anwser. If you catch the PreviewKeyDown event and check the length, you also need to allow the user to press Delete and BackSpace after hitting the limit.
// In constructor
this.RichTextBox.PreviewKeyDown += this.EditBox_KeyDown;
private void EditBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete && e.Key != Key.Back)
{
var range = new TextRange(this.RichTextBox.Document.ContentStart, this.RichTextBox.Document.ContentEnd);
if (range.Text.Length > this.MaxLength)
{
e.Handled = true;
return;
}
}
}
You should also allow the arrow keys, because you wouldn't expect them to be disabled.
To disable pasting, put this in the constructor DataObject.AddPastingHandler(this.RichTextBox, this.EditBox_Paste); and
private void EditBox_Paste(object sender, DataObjectPastingEventArgs e)
{
e.CancelCommand();
}
However, you might want to allow pasting unless it breaks the MaxLength, in which case you'll need to check the text being inserted, and the text it is replacing. At that point I decided not to implement a MaxLength in the control, but to handle it with the rest of the validation in the form.
Add this code in yout KeyDown Event.
private void rLetter_KeyDown(object sender, KeyEventArgs e)
{
TextRange tr= new TextRange(rLetter.Document.ContentStart, rLetter.Document.ContentEnd);
if (tr.Text.Length > 4000 || e.Key == Key.Space || e.Key == Key.Enter)
{
e.Handled = true;
return;
}
}
I have some problem, The bug is :
Test this code using copy and paste text max 4000.
Sorry for my English ..

Resources