I am switching several TextBoxes out for RichTextBoxes to gain some of the cool features.
I had my TextBoxes configured to AcceptReturn so that the enter key will create a new line, rather than leave the control. The RichTextBox does not seem to have this feature.
Is there a simple way to do this, or do I have to capture all keypresses and handle them individually?
Note: This issue occurs only when you set the "AcceptButton" property of the form.
Set the RichTextBox.AcceptsTab to true. For some reason this works for both tabs and the enter key. If you only want the enter keys then you will have to write custom code.
Since Carter pointed out that this only applies if AcceptButton is set, and the other solution suggests deriving the RichTextBox class, I found another simple solution. Just unset AcceptButton for the time that the/a RichTextBox has the focus. Here's a sample code:
private void RichText_Enter(object sender, EventArgs e)
{
AcceptButton = null;
}
private void RichText_Leave(object sender, EventArgs e)
{
AcceptButton = OKActionButton;
}
This assumes that you only have a single AcceptButton and that is unlikely to change. Otherwise you would have to copy some AcceptButton finding logic here or just backup the previous AcceptButton value before setting it to null.
This solution also has the side effect of removing the default border from the actual accept button, indicating to the user that pressing the Enter key now will not activate that button.
The solution is to override IsInputKey:
protected override bool IsInputKey(Keys keyData)
{
if (
(keyData & ~Keys.Modifiers) == Keys.Tab &&
(keyData & (Keys.Control | Keys.Alt)) == 0
)
return false;
return base.IsInputKey(keyData);
}
After setting AcceptsTab to true, you ensure that the RichTextBox processes both the tab and return key. With the IsInputKey implementation above, we ensure that the Tab and Shift+Tab key never reach the RichTextBox so they are used for navigation instead.
The above override must be pasted in a class derived from RichTextBox.
Just change Accept option in Richtextbox Property turn to "true" it will work like a magic
Related
How can I totally disable tabbing on DataGridView so it won't go through cells at all?
I use DataGridView as music playlist in my application and I don't need that annoying windows default selection frame around cells. I want be able to select rows normally. I managed to hide selection border on buttons with SetStyle(ControlStyles.Selectable, false) but this does not disable tabbing on DataGridView.
Handle the KeyDown event of the DataGridView and call the parent (or grandparent) control's SelectNextControl method.
private void dataGridView1_KeyDown( object sender, KeyEventArgs e )
{
if ( e.KeyCode == Keys.Tab )
{
SelectNextControl( dataGridView1, true, true, true, true );
// or Parent.SelectNextControl() if the grid is an only child, etc.
e.Handled = true;
}
}
This will cause the whole grid to behave like tabbing among text boxes and buttons - you tab into the grid, and another press of the tab key will tab out and onto the next control. This retains navigation within the grid by the cursor keys. Refer to the linked MSDN documentation for options on the direction of tabbing, etc., which are what all those terrible Boolean parameters configure. The first parameter sets which control the "next" tab search begins from, so you can set that to a parent or sibling or grandparent.
if you want to DataGrid don't focus, you can set it's Enable property to false, this control on the form doesn't get focus, but in this way you must add or delete rows in DataGridView with specific button (it means a button for add and another for delete)
but if you want their cells don't focus, you should following this: in KeyDown event of your form, type this code
if (e.KeyCode == Keys.Tab)
{
dgvMain.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
[other component of your form like a textbox or a button].Focus();
}
with this, your DataGridView only highlight the whole selected row
OK. I've managed to do that. This ARTICLE helped me a lot. I used form's OnActivated and OnDeactivated events to disable and enable TAB key. Here you have sample code:
protected override void OnActivated(EventArgs e) {
ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
base.OnActivated(e);
}
protected override void OnDeactivate(EventArgs e) {
UnhookWindowsHookEx(ptrHook);
objKeyboardProcess = null;
ptrHook = IntPtr.Zero;
base.OnDeactivate(e);
}
There were a couple of problems that came up while i was trying to make it work but that's different story. Happy coding! :)
You can also set:
dataGridView.TabStop=false;
This will skip the grid when the tab button is hit.
I created a richTextBox and i noticed that when I press Tab key it is not doing anything.
It is suppose to do some space but it do not.
How can i access it?
By default pressing tab moves focus to the next control. Setting AcceptsTab property of the RichTextBox to true allows the RichTextBox to accept tab characters.
See this MSDN article on the AcceptsTab property.
First you need to set following properties of Richtextbox
richTextBox.Multiline = true;
richTextBox.AcceptsTab = true;
And in the keypress event of richtextbox you need to do following
if (e.KeyChar == 9)
{
e.Handled = false;
}
When a ContextMenuStrip is opened, if the user types the first letter of a possible selection - it's as if he clicked on it. I want to intercept that and get the character that he clicked.
The following code does that, but with hard-coding the possible character. I want a generic way to do this, either by disabling the automatic selection by key stroke (leaving only the mouse clicks) or some way to intercept the character.
The following simplified code assumes I want to have a winform's Text to be the character typed, and the ContextMenuStrip has one option which is "A".
public Form1()
{
InitializeComponent();
contextMenuStrip1.KeyDown += contextMenuStrip1_KeyDown;
}
private void button1_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show();
}
void contextMenuStrip1_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
if (e.KeyCode == Keys.A)
{
if (e.Shift) Text = "A";
else Text = "a";
}
}
Using the KeyPress event and checking e.KeyChar doesn't work because it doesn't get fired. (the "A" click-event gets fired instead.)
Using one of these: e.KeyCode, e.KeyData, or e.KeyValue doesn't work (without further hard-coding) because they accept a Shift as a Key.
As noted in the comment, you have to derive your own class from ContextMenuStrip so you can override the ProcessMnemonic() method.
Annotating this a bit, keyboard processing is very convoluted in Winforms. Shortcut keystrokes are processed very early, before they are dispatched to the control with the focus. Necessarily so, you would not want to implement the KeyDown event for every control so that you could make a shortcut keystroke work.
This works from the outside in and involves several protected methods, ProcessCmdKey, ProcessDialogChar and ProcessMnemonic. As well as OnKeyDown if the form's KeyPreview property is set, a VB6 compat feature. So the form gets a shot at it first, then it iterates controls from there, going from container to child controls.
The ToolStrip class (a base class for ContextMenuStrip) overrides the ProcessMnemonic() method to recognize key presses, mapping them to menu items. So in order to intercept this default processing, you have to override ProcessMnemonic() yourself to get a shot at the key press first.
I got a form with a number of buttons on it (assume 20). In the middle, I got a User Control which is completely empty. The question is: how can I make it so that when the User Control is clicked, it will get keyboard focus?
Reason: I paint shapes in that User Control, with my mouse. The shapes are actually other User Controls. What I want to do is be able to use the keyboard to move those shapes. But I cannot seem to correctly be able to grab the Keyboard focus. The Key_Down events just don't reach my main (drawing into) User Control.
So, in other words, how can we have keyboard focus in a control has no focusable items on it? How can one make an keyboard-unfocusable control, catch those events? Any way of grabbing these events window-wide, other than going raw-WIN32 API hardcore?
A UserControl was very much designed to be a container control for other controls. It abhors getting the focus and tries to pass it off first chance it gets. You should not be using a UserControl here, given that you don't put any controls inside of it. A Panel control will suffice. Which has the exact same problem, it doesn't want to get focus either.
Surgery is required to override its behavior. Everything you need is in this answer.
Add this to your user control code to capture keyboard input:
/// <summary>Keys which can generate OnKeyDown event.</summary>
private static readonly Keys[] InputKeys = new []
{ Keys.Left, Keys.Up, Keys.Right, Keys.Down, };
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
if(Array.IndexOf<Keys>(InputKeys, e.KeyCode) != -1)
{
e.IsInputKey = true;
}
base.OnPreviewKeyDown(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
// just to illustrate this works
MessageBox.Show("KeyDown: " + e.KeyCode);
}
See http://msdn.microsoft.com/en-us/library/aa969768.aspx. You can assign keyboard focus by
1. Set the usercontrol.Focusable=true;
2. Use Keyboard.Focus(usercontrol).
You need to set the CommandRouting flag on your control to true.
The command routing dependency property is defined in a public API (MS.VS.Editor.dll) and your adornment will want to use that API to indicate that it is handling its commands instead of allowing the containing text view handle them. You can do this with from your control’s initialization.
Microsoft.VisualStudio.Editor.CommandRouting.SetInterceptsCommandRouting(this, true);
Basically, I have a form with a custom control on it (and nothing else). The custom control is completely empty, and the form has KeyPreview set to true.
With this setup, I am not receiving any KeyDown events for any arrow keys or Tab. Every other key that I have on my keyboard works. I have KeyDown event handlers hooked up to everything that has such events, so I'm sure I'm not missing anything.
Also of note is that if I remove the (completely empty) custom control, I DO get the arrow key events.
What on earth is going on here?
EDIT:
I added this to both the form and the control, but I'm STILL not getting arrow keys:
protected override void WndProc(ref Message m) {
switch (m.Msg) {
case 0x100: //WM_KEYDOWN
//this is the control's version. In the form, it's this.Text
ParentForm.Text = ((Keys)m.WParam).ToString();
break;
}
base.WndProc(ref m);
}
I also checked with Spy++, and determined that the form itself is not getting any WM_KEYDOWN messages, they're all going to the control. However, that said, the control IS getting the arrow key WM_KEYDOWN messages. Sigh.
Edit 2: I've also updated the ZIP file with this version. Please look at it, if you want to help...
Edit 3:
I've figured this out, sort of. The form is eating the arrow keys, probably in an attempt to maintain focus amongst its children. This is proven by the fact that I DO get the events if the form is empty.
Anyway, if I add this code to the form, I start getting the events again:
public override bool PreProcessMessage(ref Message msg) {
switch (msg.Msg) {
case 0x100: //WM_KEYDOWN
return false;
}
return base.PreProcessMessage(ref msg);
}
When I override this, the form doesn't get a chance to do its dirty work, and so I get my KeyDown events as I expect. I assume that a side effect of this is that I can no longer use my keyboard to navigate the form (not a big deal in this case, as it's a game, and the entire purpose of this exercise is to implement keyboard navigation!)
The question still remains about how to disable this "properly", if there is a way...
I've done some extensive testing, and I've figured everything out. I wrote a blog post detailing the solution.
In short, you want to override the ProcessDialogKey method in the form:
protected override bool ProcessDialogKey(Keys keyData) {
return false;
}
This will cause the arrow keys (and tab) to be delivered as normal KeyDown events. HOWEVER! This will also cause the normal dialogue key functionality (using Tab to navigate controls, etc) to fail. If you want to retain that, but still get the KeyDown event, use this instead:
protected override bool ProcessDialogKey(Keys keyData) {
OnKeyDown(new KeyEventArgs(keyData));
return base.ProcessDialogKey(keyData);
}
This will deliver a KeyDown message, while still doing normal dialogue navigation.
If focus is your issue, and you can't get your user control to take a focus and keep it, a simple work-around solution would be to echo the event to your user control on the key event you are concerned about. Subscribe your forms keydown or keypress events and then have that event raise an event to your user control.
So essentially, Form1_KeyPress would Call UserControl1_KeyPress with the sender and event args from Form1_KeyPress e.g.
protected void Form1_KeyPress(object sender, KeyEventArgs e)
{
UserControl1_KeyPress(sender, e);
}
Otherwise, you may have to take the long route and override your WndProc events to get the functionality you desire.