Escape TabStop within a WebBrowser control - c#

I'm building a email client in c# that allows users to send HTML emails. I have some general formatting capabilities including the option to insert bulleted and numbered lists. I want to allow users to tab through the controls, but also use the tab key to indent the bullets or numbers in their list. Is there a way to escape TabStop within a certain control, a webBrowser control in particular?

David sparked the idea, but I'd like to give a little more detail. I used mshtml to actually insert the indent and outdent. Just that still moved to the next control, so adding e.IsInputKey = true actually kept the cursor in the webBrowser control so the user can continue typing.
private void webBrowser_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyData == Keys.Tab)
{
webBrowser.Document.ExecCommand("Indent", false, null);
e.IsInputKey = true; //prevents going to next control
}
else if (e.KeyData == (Keys.Shift | Keys.Tab))
{
webBrowser.Document.ExecCommand("Outdent", false, null);
e.IsInputKey = true;
}
}

For a multiline TextBox you can use the AcceptsTab property.
For a WebBrowser control I think you have to use the KeyPress event and insert a tab character \t yourself.

Related

How to PgUp/PgDn with SendKeys to a foreground textbox

I am trying to page up/down the contents of a simple textbox control in a simple Windows Form on NET 6.0, but something is wrong. Textbox shortcuts are enabled (probably why SendKeys.SendWait("^a"); works) and readonly is false.
I have a method (not on the UI thread) that I call to SendKeys.SendWait("{PgUp}"); to the foreground app (which is both the key sender and textbox (with focus) receiver.
If I type PgUp on the keyboard, the textbox pages up as expected.
If I SendKeys.SendWait("^a");, the textbox selects all text as expected.
If I Sendkeys.SendWait("{PgUp}");, the textbox adds a blank line to the bottom of the text.
From this I conclude that my code is working because it sends "^a" and the textbox receives it and selects all text. But somehow the textbox does not handle the "{PgUp}" key, even though it does when the PgUp key is sent by the keyboard.
I've read easily a dozen articles and posts on the web and SO that talk about paging using scrolling events, positioning the caret and then scrolling to the caret, and so on. But none of them say anything about why SendKeys(^a) and keyboard PgUp would work but SendKeys.SendWait("{PgUp}") would fail.
Can anyone tell me what I'm doing wrong and maybe what I need to do (or read) to fix it? Thank you
UPDATE: Jimi asked for some code, so here is the code that I use to send the ^a and the {PgUp} keys. I know this is not on the UI thread because it is executed from a voice-driven recognizer thread. The app is a voice-driven app that displays content in the textbox by textbox.AppendLines calls. I was trying to PgUp and PgDn the multi-line textbox by voice as well.
When I tried to use Send (I normally use .SendWait for everything in other programs), I received the following error message:
System.InvalidOperationException: 'SendKeys cannot run inside this
application because the application is not handling Windows messages.
Either change the application to handle messages, or use the
SendKeys.SendWait method.'
It is true that my app does not intercept Windows messages. I can't figure out why the app can receive and properly process my keyboard keys, and my "^a' shortcut keys, but not the SendWait("{PgUp}") key.
internal static void
HelperPageUp() {
var keys = "{PgUp}";
keys = "^a";
SendKeys.SendWait(keys);
}
I'm starting to think that {PgUp} is never handled by a textbox or control. Instead, probably {PgUp} must be handled by logic in a case statement that converts PgUp "orders" into sets of actions that implement whatever PgUp means to the app that receives the PgUp key. So maybe I will have to add a keystroke handler to the form. Maybe something like this:
textBox1_KeyUp(object sender, KeyEventArgs e) {
// identify the special key and implement what it means
if (e.KeyCode == Keys.PageDown) {
...
e.Handled = true;
}
Yes, my thought at the end of the question was correct. The ^a was handled by the textbox because I had textbox.EnableShortcuts=true;, so the textbox handled the popular ^a shortcut. But keys like {PgUp} are a different matter; they are not included in shortcuts.
The solution was to write code to handle the {PgUp} key explicitly in the form. Here is my code that worked.
void
textBox1_KeyUp(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.PageUp) {
// page the viewport up; watch for end of content
var charIndex = textBox1.SelectionStart;
var lineIndex = textBox1.GetLineFromCharIndex(charIndex);
// move 20 lines up, but not past zero
var newLine = lineIndex - 20;
var newIndex = Math.Max(0, newLine);
// set the new anchor and scroll to it
var newAnchor = textBox1.GetFirstCharIndexFromLine(newIndex);
textBox1.Select(newAnchor,0);
textBox1.ScrollToCaret();
e.Handled = true;
}

How to change the panel visibility with richtextbox input

For some reason, this one will not work:
if (richTextBox2.Text == "settings")
panel5.Visible = true;
The other inputs work like "close", inputting close will close the form.
What i want to happen is when "settings" is typed into the text box, i want the panel to become visible.
You could try comparing in this way:
if (richTextBox2.Text.ToUpper() == "SETTINGS")
panel5.Visible = true;
Other way to try, is debug "if" line, and check the content of Text property. Maybe, richTextBox2.Text contains some hidden characters.
I hope this could help you.

SendKeys.Send function not working

I want to press Shift + Tab on some event , I am using System.Windows.Forms.SendKeys.Send for that purpose but it is not working , I tried below ways to call the function.
System.Windows.Forms.Application.DoEvents();
SendKeys.Send("{+(Tab)}");
System.Windows.Forms.Application.DoEvents();
SendKeys.Send("+{Tab}");
System.Windows.Forms.Application.DoEvents();
SendKeys.Send("{+}{Tab}");
System.Windows.Forms.Application.DoEvents();
SendKeys.Send("+{Tab 1}");
Can someone tell me what is the right way ?
The proper syntax is:
SendKeys.Send("+{Tab}");
In light of your comment that you are trying to implement pressing Shift+Tab to cycle between control fields, note that this can be done more reliably without emulating keys. This avoids issues where, for instance, another window has focus.
The following method will emulate the behavior of Shift_Tab, cycling through tab stops in reverse order:
void EmulateShiftTab()
{
// get all form elements that can be focused
var tabcontrols = this.Controls.Cast<Control>()
.Where(a => a.CanFocus)
.OrderBy(a => a.TabIndex);
// get the last control before the current focused element
var lastcontrol =
tabcontrols
.TakeWhile(a => !a.Focused)
.LastOrDefault(a => a.TabStop);
// if no control or the first control on the page is focused,
// select the last control on the page
if (lastcontrol == null)
lastcontrol = tabcontrols.LastOrDefault();
// change focus to the proper control
if (lastcontrol != null)
lastcontrol.Focus();
}
Edit
The deleted text will cycle through controls in reverse order (emulating shift+Tab), but this is more properly done with with the built-in Form.SelectNextControl method. The following method will emulate the behavior of Shift_Tab, cycling through tab stops in reverse order.
void EmulateShiftTab()
{
this.SelectNextControl(
ActiveControl,
forward: false,
tabStopOnly:true,
nested: true,
wrap:true);
}
Is it does nothing or sends input into control you don't want to be edited? Check if this code is called first, and dont't forget to focus on target control manually before SendKeys to make sure that it will receive your keys.

Why are some textboxes not accepting Control + A shortcut to select all by default

I have found a few textboxes here and there in my program that accepts Control+A shortcut to select the entire text "by default" with "no coding".
I don't know what additional information I have to give here to enable it for all of them, as I find absolutely no difference between these textboxes. They are all simple dragged and dropped textboxes.
Note: I'm not talking about this piece of code:
if (e.Control && e.KeyCode == Keys.A)
{
textBox1.SelectAll();
}
I want selection by default... or is there anyway to change textbox property so that textboxes accept all default windows shortcuts?
Everything else (Control + Z, Control + X, Control + C, Control + V) works by default! Why not Control + A?
Update: The text boxes that accepted Ctrl+A by default were masked textboxes, not the regular one. And at that point I was with .NET 2.0. But I guess the original problem was something else, as I can see Ctrl+A working fine by default in .NET 2.0 code.
You might be looking for the ShortcutsEnabled property. Setting it to true would allow your text boxes to implement the Ctrl+A shortcut (among others). From the documentation:
Use the ShortcutsEnabled property to
enable or disable the following
shortcut key combinations:
CTRL+Z
CTRL+E
CTRL+C
CTRL+Y
CTRL+X
CTRL+BACKSPACE
CTRL+V
CTRL+DELETE
CTRL+A
SHIFT+DELETE
CTRL+L
SHIFT+INSERT
CTRL+R
However, the documentation states:
The TextBox control does not support the CTRL+A shortcut key when the Multiline property value is true.
You will probably have to use another subclass of TextBoxBase, such as RichTextBox, for that to work.
Indeed CTRL + A will not work unless you add something like this:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && (e.KeyCode == Keys.A))
{
if (sender != null)
((TextBox)sender).SelectAll();
e.Handled = true;
}
}
This answer worked for me in a similar question (which isn't marked as accepted)
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
var keyCode = (Keys) (msg.WParam.ToInt32() &
Convert.ToInt32(Keys.KeyCode));
if ((msg.Msg == WM_KEYDOWN && keyCode == Keys.A)
&& (ModifierKeys == Keys.Control)
&& txtYourTextBox.Focused)
{
txtYourTextBox.SelectAll();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Original Post: How can I allow ctrl+a with TextBox in winform?
Make sure that
Application.EnableVisualStyles();
is not commented out in
static void Main()
That can disable Ctrl+A
This question wants an answer that cannot be given in the form of code avoidance, as the Win32 API at the core of the other methods doesn't allow it. If other methods DO allow it, they are just writing the code for you. :)
So the real question is: What is the smallest, neatest way to do it? This worked for me:
First, there is no need to handle WM_KEYDOWN! And no need to test for the Ctrl key already down either. I know that most examples here (and CodeProject and many other places) all say there is, but it does not cure the beep that results whenever a WM_CHAR arises that is not handled.
Instead, try handling WM_CHAR and doing the Ctrl+A selection there:
LRESULT CALLBACK Edit_Prc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
if(msg==WM_CHAR&&wParam==1){SendMessage(hwnd,EM_SETSEL,0,-1); return 1;}
else return CallWindowProc((void*)WPA,hwnd,msg,wParam,lParam);
}
Remember to subclass the EDIT control to this Edit_Prc() using WPA=SetWindowLong(...) where WPA is the window procedure address for CallWindowProc(...)

C# textbox deletion question

I am working on a project that I use textbox as telnet terminal.
The terminal has "->" as the command prompt in the textbox.
Is there a way to disable the delete or backspace once it reach the "->" prompt?
I don't want to delete the command prompt.
Thanks
Dave is right.
The best way to do this is to make a label on the left side of the textbox that says ->.
You can remove the textbox's border and put them both in a white (or non-white) box to make it look real.
This will be much easier for you to develop and maintain, and will also be more user-friendly. (For example, the Home key will behave better)
Two options:
Make the prompt ("->") an image or label, instead of being part of the textbox.
If it's a web app, handle the textchanged event in javascript and cancel the textchanged if it represents a deletion of the prompt. If its not a web app, do the same thing in c# rather than JS.
You could always make sure that when deleting, the index of the character you're deleting is > 1 (since -> would occupy positions 0 & 1)
This is a naive example, but you should be able to figure it out from here. You can peak at the keydown event and cancel it, when desired.
private void testTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back && testTextBox.SelectionStart == 2)
{
e.SuppressKeyPress = true;
}
}

Categories