.net webbrowser control - c#

I am using the webbrowser control in visual studio. I think it is a wrapper around internet explorer. Anyway all is going well I am using it in edit mode however I can't get he document's keydown event to fire (in order to catch ctrl+v) anyone had similar problems with it?
Anyone have a solution?

Indeed the webbrowser control is just a wrapper of the IE browser control.
Is your problem that the controls PreviewKeyDown not working? Seems to be working for me as long as the control has focus.
webBrowser1.PreviewKeyDown += new PreviewKeyDownEventHandler(webBrowser1_PreviewKeyDown);
....
private void webBrowser1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
Console.WriteLine(e.KeyCode.ToString() + " " + e.Modifiers.ToString());
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V) {
MessageBox.Show("ctrl-v pressed");
}
}
but perhaps I am not completely understanding?

You should override a "WndProc()" method in derived class from WebBrowser control or in form, which contains a webbrowser. Or you can catch the keys with custom message filter ( Application.AddMessageFilter ). With this way you can also filter a mouse actions.
I had same problems years ago, but I don't remember which way i used.

You mentioned the KeyDown event of the 'document'. If you are referring to the WebBrowser control's Document property (type HtmlDocument) it only has events for MouseUp, MouseDown, etc but not keyboard events. You want to register your event handler with the WebBrowser control's PreviewKeyDown delegate. You may also want to set the value of the WebBrowser control's WebBrowserShortcutsEnabled property to false if you don't want standard Internet Explorer shortcuts to have their usual effect. You should also make sure that the WebBrowser control is in focus by manually calling its Focus() method and setting the TabStop property of other controls on the form to false. If this is not possible because you have other controls on the form that need to accept focus, you also might want to add an event handler for the KeyDown event of the Form itself.

How to trap keystrokes in controls by using Visual C#
e.g.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;
if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
switch(keyData)
{
case Keys.Down:
this.Parent.Text="Down Arrow Captured";
break;
...
}
}
return base.ProcessCmdKey(ref msg,keyData);
}

Related

Arrow key events not arriving

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.

Forms not responding to KeyDown events

I've been working for a while on my Windows Forms project, and I decided to experiment with keyboard shortcuts. After a bit of reading, I figured I had to just write an event handler and bind it to the form's KeyDown event:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.Alt && e.KeyCode == Keys.O)
{
MessageBox.Show("Ctrl+Alt+O: magic!");
}
}
I did that the good ol' way of opening the Properties panel of the Visual Studio designer, then double-clicking on the KeyDown event of my form to generate the Form1_KeyDown event handler. But on testing my application, the form doesn't respond at all to the Ctrl+Alt+O keyboard shortcut. The Visual Studio designer did generate the code to bind the event handler to the form though:
private void InitializeComponent()
{
// ...
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
// ...
}
So I tried adding a Console.WriteLine() call to the handler to check that it was being called at all, but no luck on that either.
Also, I tried to set a breakpoint on the event binding call (shown just above) and found that the program reaches that breakpoint just fine. But any breakpoints I set within the method definition itself are never reached.
To make sure I was doing the first few steps correctly, I tried repeating them with:
A new form in the same solution.
Same issue: the form doesn't respond when I press my Ctrl+Alt+O keyboard shortcut and the debugger isn't even stepping into the event handler. Tried this again and it works.
A brand new WinForms solution.
It works perfectly: the message dialog appears (the Console.WriteLine() call also works).
So I'm quite lost here. What's preventing all the forms in this one project from receiving KeyDown events?
Does your form have KeyPreview property set to true?
Form.KeyPreview Property
Gets or sets a value indicating whether the form will receive key
events before the event is passed to the control that has focus.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx
The most common piece of advice for this problem on StackOverflow and the MSDN1, 2 (including the accepted answer here) is quick and easy:
KeyDown events are triggered on a Form as long as its KeyPreview property is set to true
That's adequate for most purposes, but it's risky for two reasons:
KeyDown handlers do not see all keys. Specifically, "you can't see the kind of keystrokes that are used for navigation. Like the cursor keys and Tab, Escape and Enter for a dialog."
There are a few different ways to intercept key events, and they all happen in sequence. KeyDown is handled last. Hence, KeyPreview isn't much of a preview, and the event could be silenced at a few stops on the way.
(Credit to #HansPassant for those points.)
Instead, override ProcessCmdKey in your Form:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == Keys.Up)
{
// Handle key at form level.
// Do not send event to focused control by returning true.
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
That way, all keys are visible to the method, and the method is first in line to see the event.
Note that you still have control over whether or not focused controls see the KeyDown event. Just return true to block the subsequent KeyDown event, rather than setting KeyPressEventArgs.Handled to true as you would in a KeyDown event handler. Here is an article with more details.
Try setting the KeyPreview property on your form to true. This worked for me for registering key presses.

How to pass messages from a child user-control to the parent

This is a Windows Forms / .Net C# question.
I have a borderless windows whose transparency key and background color make it completely transparent. Inside the window are a couple of user controls.
I want to be able to move the window. I know how to do this on the parent window, but my problem is that the child controls are the only thing visible and thus the only thing click-able.
The question is: how can I pass certain messages up to the Parent so the Parent can move when the right mouse button is down and the mouse is moving on any one of the child controls?
Or maybe you can suggest another way?
Thanks for the help.
Mark
You can achieve your goal even without SendMessage using System.Windows.Forms.Message class. If you have done dragging I guess you are familiar with WM_NCLBUTTONDOWN message. Send it to you parent from your control's MouseDown event.
Here is an example for moving the form clicking on control label1. Note the first line where sender is used to release the capture from clicked control. This way you can set this handler to all controls intended to move your form.
This is complete code to move the form. Nothing else is needed.
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
private void label1_MouseDown(object sender, MouseEventArgs e)
{
(sender as Control).Capture = false;
Message msg = Message.Create(Handle, WM_NCLBUTTONDOWN, (IntPtr)HT_CAPTION, IntPtr.Zero);
base.WndProc(ref msg);
}
Hope this helps.
I think the easiest way is to add this event to your child controls:
/// <summary>
/// The event that you will throw when the mouse hover the control while being clicked
/// </summary>
public event EventHandler MouseRightClickedAndHoverChildControl;
After, all the parent have to do is to subscribe to those events and make the operations to move the Parent:
ChildControl.MouseRightClickedAndHoverChildControl += OnMouseHoverChildControl;
private void OnMouseHoverChildControl(object sender, EventArgs e)
{
//do foo...
}
You need to call the SendMessage API function to send mouse messages to your parent control.
It would probably be easiest to do this by overriding your control's WndProc method.
I had exactly this question... but came up with a different answer.
If you have the Message in your WndProc, you can just change the handle to your Parent's handle and then pass it along.
I needed to do this in our derived TextBox... TextBox eats scroll wheel events even when its ScrollBars are set to None. I wanted those to propagate on up to the Form. So, I simply put this inside the WndProc for my derived TextBox:
case 0x020A: // WM_MOUSEWHEEL
case 0x020E: // WM_MOUSEHWHEEL
if (this.ScrollBars == ScrollBars.None && this.Parent != null)
m.HWnd = this.Parent.Handle; // forward this to your parent
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;

Press Escape key to call method

Is there a way to start a method in C# if a key is pressed? For example, Esc?
use the OnKeyPress Event of your textbox and in the event
if(e.KeyCode==Keys.Escape)
{
yourTextBox.Text = string.Empty;
}
As others have mentioned, handle the KeyDown or KeyUp event of the appropriate control. The KeyPress event would work for the Escape key as well, though it will not trigger for some keys, such as Shift, Ctrl or ALt.
If you want to execute this function anytime the user presses the Escape key, then you probably want to handle the event on the Form. If you do this, you will probably also want to set the Form's KeyPreview property to true. This will allow the Form control to receive the event even if the focus is currently inside of one of the child controls.
If you want the behavior to be specific to a control, such as clearing the text within a textbox that currently has focus, then you should handle the KeyDown or KeyUp event of the TextBox control. This way, your event handler will not be triggered if the user presses the escape key outside of the textbox.
In some situations you might want to prevent child controls from handling the same event that you've just handled. You can use the SuppressKeyPress property on the KeyEventArgs class to control this behavior:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("Escape key pressed");
// prevent child controls from handling this event as well
e.SuppressKeyPress = true;
}
}
In case someone is looking for how to do this in a console application
if (Console.ReadKey().Key == ConsoleKey.Escape)
{
return;
}
I am writing WinForms application. User fills the textbox and if he wants to delete everything, he just clicks esc key on keyboard
I think you need to handle the KeyDown event.
You have to switch the form property "KeyPreview" to true or your events will not be fired. Handling these events alone will not do anything even though the events are correct. It will look to you like nothing really happens even though you have subscribed the proper event handlers.
First in Properties do > KeyPreview : True
Then :
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
//call your method here
}
}
Are you writing a Console application, a WinForms application or something else? Are you trying to capture the ESC key at all times (regardless of the focused window/application) or something else?
More context required.
If you're writing a Console app, then you should start looking at things like Console.ReadKey...
http://msdn.microsoft.com/en-us/library/system.console.readkey.aspx
With Event KeyPress...
//Escape
if (e.KeyChar == '')
{
this.DialogResult = DialogResult.Cancel;
e.Handled = true;
}
You can use KeyUp event too. I prefer it though.
private void Window_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) {
if (e.Key == Key.Escape) {
//WHAT WILL HAPPEN INSERT HERE
}
}
The basic answer is listed here several time
Implement Form_KeyDown
Private Sub frmCustomerSearch_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Try
If e.KeyCode = Keys.Escape Then
ClearFindForm()
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Set form.keyPreview
form.KeyPreview = true
The additional thing you need to check is whether you have a button capturing ESC so it can be the form.cancelButton
to be sure ...
form.CancelButton = nothing
This is sneaky. If you have set that and forgot about it, the Escape key will not trigger the KeyDown event.
I was led to this because a button set to be the form.CancelButton does not seem to fire if it is invisible or on a non visible tab,so KEYDOWN is your only option.

Capture MouseDown event for .NET TextBox

Is there any way to capture the MouseDown even from the .NET 2.0 TextBox control?
I know the inherited Control class has the event, but it's not exposed in TextBox.
Is there a way to override the event handler?
I also tried the OpenNETCF TextBox2 control which does have the MouseDown event exposed, but no matter what I do, it doesn't fire the handler.
Any suggestions?
What kind of crazy mobile device do
you have that has a mouse? :)
Yes, windows mobile does not have an actual mouse, but you are mistaken that Windows Mobile .NET do not support the Mouse events. A click or move on the screen is still considered a "Mouse" event. It was done this way so that code could port over from full Windows easily. And this is not a Windows Mobile specific issue. The TextBox control on Windows does not have native mouse events either. I just happened to be using Windows Mobile in this case.
Edit: And on a side note...as Windows Mobile is built of the WindowsCE core which is often used for embedded desktop systems and Slim Terminal Services clients or "WinTerms" it has support for a hardware mouse and has for a long time. Most devices just don't have the ports to plug one in.
According to the .Net Framework, the
MouseDown Event Handler on a TextBox
is supported. What happens when you
try to run the code?
Actually, that's only there because it inherits it from "Control", as does every other Form control. It is, however, overridden (and changed to private I believe) in the TextBox class. So it will not show up in IntelliSense in Visual Studio.
However, you actually can write the code:
textBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.textBox1_MouseDown);
and it will compile and run just fine, the only problem is that textBox1_MouseDown() will not be fired when you tap the TextBox control. I assume this is because of the Event being overridden internally. I don't even want to change what's happening on the event internally, I just want to add my own event handler to that event so I can fire some custom code as you could with any other event.
I know this answer is way late, but hopefully it ends up being useful for someone who finds this. Also, I didn't entirely come up with it myself. I believe I originally found most of the info on the OpenNETCF boards, but what is typed below is extracted from one of my applications.
You can get a mousedown event by implementing the OpenNETCF.Windows.Forms.IMessageFilter interface and attaching it to your application's message filter.
static class Program {
public static MouseUpDownFilter mudFilter = new MouseUpDownfilter();
public static void Main() {
Application2.AddMessageFilter(mudFilter);
Application2.Run(new MainForm());
}
}
This is how you could implement the MouseUpDownFilter:
public class MouseUpDownFilter : IMessageFilter {
List ControlList = new List();
public void WatchControl(Control buttonToWatch) {
ControlList.Add(buttonToWatch);
}
public event MouseEventHandler MouseUp;
public event MouseEventHandler MouseDown;
public bool PreFilterMessage(ref Microsoft.WindowsCE.Forms.Message m) {
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
// If the message code isn't one of the ones we're interested in
// then we can stop here
if (m.Msg != WM_LBUTTONDOWN && m.Msg != WM_LBUTTONDOWN) {
return false;
}
// see if the control is a watched button
foreach (Control c in ControlList) {
if (m.HWnd == c.Handle) {
int i = (int)m.LParam;
int x = i & 0xFFFF;
int y = (i >> 16) & 0xFFFF;
MouseEventArgs args = new MouseEventArgs(MouseButtons.Left, 1, x, y, 0);
if (m.Msg == WM_LBUTTONDOWN)
MouseDown(c, args);
else
MouseUp(c, args);
// returning true means we've processed this message
return true;
}
}
return false;
}
}
Now this MouseUpDownFilter will fire an MouseUp/MouseDown event when they occur on a watched control, for example your textbox. To use this filter you add some watched controls and assign to the events it might fire in your form's load event:
private void MainForm_Load(object sender, EventArgs e) {
Program.mudFilter.WatchControl(this.textBox1);
Program.mudFilter.MouseDown += new MouseEventHandler(mudFilter_MouseDown);
Program.mudFilter.MouseUp += new MouseEventHandler(mudFilter_MouseUp);
}
void mudFilter_MouseDown(object sender, MouseEventArgs e) {
if (sender == textBox1) {
// do what you want to do in the textBox1 mouse down event :)
}
}
Looks like you're right. Bummer. No MouseOver event.
One of the fallbacks that always works with .NET, though, is P/Invoke. Someone already took the time to do this for the .NET CF TextBox. I found this on CodeProject:
http://www.codeproject.com/KB/cs/TextBox_subclassing.aspx
Hope this helps
Fair enough. You probably know more than I do about Windows Mobile. :) I just started programming for it. But in regular WinForms, you can override the OnXxx event handler methods all you want. A quick look in Reflector with the CF shows that Control, TextBoxBase and TextBox don't prevent you from overriding the OnMouseDown event handler.
Have you tried this?:
public class MyTextBox : TextBox
{
public MyTextBox()
{
}
protected override void OnMouseDown(MouseEventArgs e)
{
//do something specific here
base.OnMouseDown(e);
}
}
is there an 'OnEnter' event that you could capture instead?
it'd presumably also capture when you tab into the textbox as well as enter the text box by tapping/clicking on it, but if that isn't a problem, then this may be a more straightforward work-around
According to the .Net Framework, the MouseDown Event Handler on a TextBox is supported. What happens when you try to run the code?

Categories

Resources