i have some user control and i want to disable Alt + F4 oportunity for the end user. When my User Control shows, there is opportunity to close it with Alt + F4, then program goes to base class in the method:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
//Content = null; // Remove child from logical parent - for reusing purposes
this.RemoveLogicalChild(Content); //this works faster
base.OnClosing(e);
{ GC.Collect(); };
}
What i must do here or somewhere else, to do disable my user control closing on Alt + F4?
To be sure, I would really question this as a Best Practice. However, if you really want to do this, then you need to prevent the window containing the UserControl from closing.
The easiest way to do this is to set a DependencyProperty on your UserControl that is simply a Boolean that flags whether the container can be closed. You would only set this to true when you want it to actually close (you probably already have a button or something that you are using now to close the control).
public Boolean AllowClose
{
get { return (Boolean)GetValue(AllowCloseProperty); }
set { SetValue(AllowCloseProperty, value); }
}
public static readonly DependencyProperty AllowCloseProperty =
DependencyProperty.Register("AllowClose", typeof(Boolean),
typeof(MyUserControl), new UIPropertyMetadata(false));
Then, in the windows Closing event, you would check for that property to be set to true. If it is not, then you would set e.Cancel = true;
Using your example:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (! myUserControl.AllowClose)
{
MessageBox.Show("Even though most Windows allow Alt-F4 to close, I'm not letting you!");
e.Cancel = true;
}
else
{
//Content = null; // Remove child from parent - for reuse
this.RemoveLogicalChild(Content); //this works faster
base.OnClosing(e);
{ GC.Collect(); };
}
}
On your custom control add the following handlers:
PreviewKeyDown="Window_PreviewKeyDown"
PreviewKeyUp="Window_PreviewKeyUp"
The implementation for the handlers:
bool AltDown = false;
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt)
{
AltDown = true;
}
else if (e.SystemKey == Key.F4 && AltDown)
{
e.Handled = true;
}
}
private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt)
{
AltDown = false;
}
}
you can override the OnPreviewkeyDown method and trap ALT and F4 keys.
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
if ((Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) && Keyboard.IsKeyDown(Key.F4))
e.Handled = true;
}
Another decent method is :
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
if (e.KeyboardDevice.Modifiers == ModifierKeys.Alt && e.SystemKey == Key.F4)
{
e.Handled = true;
}
}
The simplest way to block Alt+F4 is to block only F4.
So, when F4 doesn't need to be handled, blocking Alt is unnecessary.
Hope that's useful.
Related
I am trying to warn the user when they select and delete text in a wpf textbox.
I am able to trap the delete event using the previewkeydown event, but its is canceling out the delete event. Even when you press ok in the code below - deletion does not happen. I am missing something ...
private void TextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Delete)
{
var textbox = (TextBox)sender;
if (textbox.SelectionLength > 1)
{
var result = MessageBox.Show("Delete selected?", "MyApp", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.Cancel)
{
e.Handled = true;
}
}
}
}
This does not seem to be the proper usage of the PreviewKeyDown event handler. That handler seems to be meant to redirect non-standard input key events to do custom behavior. The delete key is not considered non-standard/special.
You've got the right idea with your current code otherwise, but now you just need to actually delete the text in the textbox.
private void TextBox_KeyDownHandler(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Keys.Delete:
if (sender is TextBox tb)
{
if(tb.SelectionLength > 1 && MessageBox.Show("Delete?", "MyApp", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
tb.SelectedText = "";
}
}
e.Handled = true;
break;
}
}
Lastly, make sure you're actually subscribing your handlers
public MainWindow()
{
InitializeComponent();
MyTextBox.KeyDown += new KeyEventHandler(TextBox_KeyDownHandler);
}
I'm working on a text editing UwP Desktop application that needs to add a line when the user presses ENTER, and perform another procedure when the user presses CTRL + ENTER. The problem is to delete the new line that is also created in the second case. How to prevent this from happening?
KeyEventHandler keyeventHandler = new KeyEventHandler(rtbText_KeyDown);
rtbText.AddHandler(TextBox.KeyDownEvent, keyeventHandler, true);
private static bool IsCtrlKeyPressed()
{
var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
}
private void rtbText_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (IsCtrlKeyPressed())
{
switch (e.Key)
{
case VirtualKey.Enter:
NviNew_Tapped(nviNew, null);
e.Handled = true;
break;
}
}
}
You can use PreviewKeyDown Event as keydown event will not fire for system handled keys
private void TextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down)&& e.Key == Windows.System.VirtualKey.Enter)
{
e.Handled = false;
}
}
As #Vignesh said, you can use PreviewKeyDown Event instead of keydown event and set the event as "handled" like e.Handled = true to prevent adding the new line.
KeyEventHandler keyeventHandler = new KeyEventHandler(rtbText_KeyDown);
rtbText.AddHandler(TextBox.PreviewKeyDownEvent, keyeventHandler, true);
Or based on this document, you can change how your TextBox reacts to key input by overriding Control.OnKeyDown. First, declare a custom class inherits from TextBox and override OnKeyDown event. Then you can continue to use keydown event to do something.
public class MyTextBox : TextBox
{
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down) && e.Key == VirtualKey.Enter)
{
e.Handled = true;
}
else
{
base.OnKeyDown(e);
}
}
}
.xaml:
<local:MyTextBox Width="400" AcceptsReturn="True" x:Name="rtbText"></local:MyTextBox>
How can i check if tabcontrol1 is null(no pages-tabs inside)??
I want this code for setting up my tab control when is null to visible=false;
and when its not null to visible=true;
I'm using this code in selection changed but nothing is happened.
private void TabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (TabControl==null)
{
TabControl.Visible = false;
}
else
{
TabControl.Visible = true;
}
But nothing it doesnt work.
I found this way which it works. But please check if it is the right way.
private void TabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (TabControl.SelectedTab == TabControl.TabPages[""])//
{
TabControl.Visible = false;
}
else
{
TabControl.Visible = true;
}
}
What you need to is to check the TabPages property or the TabCount of the TabControl:
this.tabControl.Visible = !this.tabControl.TabCount == 0;
This code will set the Visible property to false if there are no tab pages.
I have a handler for a C# panels VisibleChanged event. But how do I detect if the visibility is being set to true or false??
public void Parent_VisibleChanged(object sender, System.EventArgs e)
{
if(Visible = true)
{
// do what i want to do
}
}
You should use == and not =
if(Visible == true)
You should do something like this inside the event:
if (((Panel)sender).Visible)
MessageBox.Show("Visible.");
else
MessageBox.Show("Not Visible.");
Here are two ways:
private void panel1_VisibleChanged(object sender, EventArgs e)
{
// use sending object
Panel panel = sender as Panel;
if (panel.Visible == false)
;
// alternate use name of object
if (panel1.Visible == false)
;
}
I have a TextBox (multiline) and if I press Ctrl+Enter it just makes a new line. But I would also like to do this on Shift+Enter.
I tried:
messageTextBox_KeyDown(null, new KeyEventArgs(Keys.Control | Keys.Enter));
But this is not working.
I think that I can do this:
int lastSelectionStart = messageTextBox.SelectionStart;
messageTextBox.Text = messageTextBox.Text.Insert(messageTextBox.SelectionStart, Environment.NewLine);
messageTextBox.SelectionStart = lastSelectionStart;
But I don't like this.
How can I make it so that Shift+Enter will be the same as Ctrl+Enter?
My current code:
KeyDownEvent
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
if (e.Shift)
{
}
else if (!e.Control)
{
sendButton_Click(null, null);
}
}
In KeyPress event:
if (e.KeyChar == (char)13)
{
e.Handled = true;
return;
}
This is because I want to use the Enter key alone as Send button.
Sounds to me like the real problem you are fighting is the form's AcceptButton property. You cannot fix this with the KeyDown event handler, the keystroke is processed before it ever gets to the event.
This can be fixed by overriding the form's ProcessCmdKey() method but the cleanest way is to just create your own TextBox derived control. You can override its IsInputKey() method to tell Winforms that you want to see the Ctrl+Enter key. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox. Note how you can alter the class to your convenience to make it more adept at being a chat input box.
using System;
using System.Windows.Forms;
class ChatBox : TextBox {
public ChatBox() {
this.Multiline = true;
}
protected override bool IsInputKey(Keys keyData) {
if (keyData == (Keys.Shift | Keys.Enter)) return true;
return base.IsInputKey(keyData);
}
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyData == (Keys.Shift | Keys.Enter)) {
int pos = this.SelectionStart;
this.SelectedText = Environment.NewLine;
this.SelectionStart = pos;
e.Handled = e.SuppressKeyPress = true;
return;
}
base.OnKeyDown(e);
}
}