C# ChromiumWebBrowser: Prevent control from stealing focus - c#

I'm making a program that has a Form with a ChromiumWebBrowser in it. The navigation is done automatically. When webbrowser complete it's task, I'll dispose it, create a new webbrowser, add it to form, and load a new address.
But, when the new webbrowser was created and added to form, the program jumps in front of what ever other program is in the top with focus. Example: I start my program, press the button to start its task, open notepad to type some text and my program jumps in front of it when navigating to a new site.
Even when the window is minimized, it still steals focus from other open programs.
How do I prevent it stealing focus after it is created?

As #amaitland said, this looks like a bug.
Workarounds I've used are:
1) disable the browser. This will prevent the browser from receiving mouse/keyboard input, but it won't "grey-out" the control.
Browser1 = New CefSharp.WinForms.ChromiumWebBrowser(url)
Browser1.Enabled = False
2) Pass a callback .net function for when the page loads where you simply put the focus back to winforms by focusing on a label of your choice.
Label1.Focus()

Your Form need set: this.Topmost = false;
AND just set: this.BringToFront();
Add new browser to the form just like the function as follow:
private ChromiumWebBrowser AddNewBrowser(FATabStripItem tabStrip, String url)
{
if (url == "")
{
url = OpenUrl;
txtUrl.Select();
txtUrl.Focus();
}
else
{
tabStrip.Select();
tabStrip.Focus();
}
// ...
}
Hope has help to you. Thanks !

Related

C# window Form , that run two forms

Good day guys, I checked for previous question, yes i saw them, but it was not really solving my problems.
I am writing an application that has two forms, there is a mainForm and Password form.
The form is for scanning two code and match if they are equal. you scan the first code and then the second code. If they Match it pop-up the green lights to show that they match. If the code does not match it pop-up a red light and a Password form at the same time and locks the form textbox to ReadOnly for supervisor to verify what the user has scanned.
It is doing all this.
The problem is i want when the supervisor enter Password it must show the form again so that the user can continue scanning, it is doing this. But the thing is when it open a new form, the one at the back that was locked it does not disapear. i tried to reset the form, it does not work. Please help in this.
//object references of the Main Form
MainForm fm=new MainForm();
if ((txtPassword.Text =="This"
{
fm.BringToFront();
//Reset the form to a normal state
fm.lblResult.Visible = false;
fm.txtResult.Visible = false;
fm.chkMtn.Checked = false;
fm.chkVodacom.Checked = false;
//Clear the textBox of the form
fm.txtMainFormScan1.Text="";
fm.txtMainFormScan2.Text="";
set the focus on the fist Scan
fm.txtFirstScan.Focus();
}
The code above does not work. now i am using the one below.
if ((txtPassword.Text =="ThisPassword")
{
lblInstructPassword.Text = "Password correct";
txtPassword.Text = "";
fm.ControlBox = true;
//fm.Activate();
this.Hide(); //This Close the Password form
fm.Show();
fm.chkMtn.Checked = true;
}
Even when i use the //fm.ShowDialog, i cannot win. I also tried to use the Mutex to allow only one instance of an application to run. result are Zero. Thanks for your help in advance.
You're doing a lot of work that .Net should be doing for you.
All else being mutable details, your real problem is this:
You have a working form that compares two values.
If the comparison result is false, you need a modal window to appear to prompt for a password.
If the password is correct, you need the first form to be editable again and the password form to disappear.
You were on the right path using ShowDialog(), as this does disable the window that fires the command to show the dialog. You need your password logic to be a part of that dialog form, not the parent form. This will allow you to return a DialogResult enum value to the parent form (if any value at all) and get you around the needless Focus() tossing.
If you want the calling form to disappear and reappear when you do this, wrap the call to your form's ShowDialog() call in this.Hide() and this.Show()

c# second form closing after initialisation

I am trying to create a simple c# application (my first attempt at c# so please be kind). I've created a form with a textbox to capture an "auth code", which is then validated and then a webclient fetches an xml file passing this auth code in to the request. The data sent back is parsed e.c.t.
What i want to do is once the xml comes back and ive done my checks to valid it is all fine. I want to close the first form and load up a second form where i will programmatically add the form components needed to display the xml data in a pretty format.
My problem is that im unable to get the second form to stay open (im no doubt invoking the second form in the wrong manner). Here's what i have:
// close current form
this.Close();
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
I'm sure you've spotted the mistake im making by now. but just to state the obvious for the sake of completeness, it closes the first form, opens the second, and then immediately the program exits (the second form flashes up for a second obviously).
I've tried a few things but none of them work (including using Application.Run(new xmlViewForm()); instead of instantiating the class and using the show() method. Obviously you know that doesn't work, and now i do too, although i dont understand c# even remotely enough to work out why.
Thanks for any help :)
The first thing that came to mind is that you are closing the form that you opened by calling Application.Run(new MyForm()) or something similar. This form has special significance; it is the "main form" of the application, and when closed, it signals to the application that the user wants to close the entire program, no matter how many other windows are open.
There are two possible fixes. First, and easiest, is simply to Hide() the form you don't want visible instead of calling Close() on it. Though invisible, it's still running, so the application doesn't close.
The second solution is to define a custom "application context" that should be run instead of the "default context" that is created by specifying a main form to watch. You do this by deriving a custom class from System.Windows.Forms.ApplicationContext. With this context specified, you can use it to control termination of the application based on something other than closure of the main form. Example code that launches two "main forms" and keeps track of whether both are still active can be found at the MSDN page for the class. You can do something similar by specifying Load and Close handlers for the main form, then passing them to the child form when the main form instantiates it, thus keeping a count of "open" forms, and closing out the full application when that number is zero. Just make sure the child form loads before closing the main form by calling childForm.Show() before this.Close().
You can not open the second form after closing the main form.
Do this:
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
// hide current form
this.Hide();
Main form can not be closed because it's the parent form. The child form will never show up if you close the main form.
Or change the xmlViewForm to main form by editing Program.cs file
Application.Run(new XmlViewForm());
Then you can easily call the other form first at the time of loading and close it as you please:
private void XmlViewForm_Load(o, s)
{
// hide current form, and this will remain hidden until the other form is done with it's work
this.Hide();
//open the other form
TheOtherForm _theOtherForm = new TheOtherForm();
_theOtherForm.Show();
}
private void TheOtherForm_Closed(o, s)
{
// show current form
this.Show;
}

Alt keys and tab don't work in Windows Forms opened from a WPF application

I have lots of old Windows Forms applications that will eventually be ported to WPF (it is a large application so it can't be done in one sprint), and I have started the process by creating a main menu in WPF. The Windows Forms applications are separate windows opened from this menu.
The Windows Forms applications are opening and working without any problems except the issues I am having with the shortcut and Tab keys. The tab key is not moving focus to the next control, and the Alt key to trigger the &Search button no longer works.
What am I doing wrong?
A partial solution I discovered is to call this from your WPF constructor:
System.Windows.Forms.Integration.WindowsFormsHost.EnableWindowsFormsInterop();
(You need to reference the dll WindowsFormsIntegration.dll)
I say partial because not all key strokes function as expected. Eg, seems to work okay for simple forms.
See this:
http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.windowsformshost.enablewindowsformsinterop(v=vs.100).aspx
I finally managed to fix the issue by hosting the winform inside a WindowsFormsHost control inside a WPF form.
public partial class MyWindow : Window
{
public MyWindow()
{
InitializeComponent();
Form winform = new Form();
// to embed a winform using windowsFormsHost, you need to explicitly
// tell the form it is not the top level control or you will get
// a runtime error.
winform.TopLevel = false;
// hide border because it will already have the WPF window border
winform.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.windowsFormsHost.Child = winform;
}
}
Please note that you may also need to hook up the winform close event if you have a button to close the form.
This is by design. Shortcut keys are handled at the message loop level, detected before the Windows message gets dispatched to the window with the focus. That's the reason those keys can work regardless of the focus.
Problem is, you don't have the Winforms message loop pumping the messages. Application.Run() is implemented by WPF in your program, not Winforms. So any of the code in Winforms that processes keyboard messages to implement shortcut keystrokes won't run.
There's no good solution for this, it is pretty fundamentally the "can't get a little pregnant" problem. This code in Winforms is locked up heavily since it would allow CAS bypass. The only workaround is to display a Form derived class that contain Winforms controls with its ShowDialog() method. That method pumps a modal message loop, the Winforms one, good enough to revive the shortcut keystroke handling code. Restructure your approach by converting the main windows first, dialogs last.
Another solution I found to handle focus on the Tab key is to override OnKeyDown like this:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
HandleFocus(this, ActiveControl);
}
else
{
base.OnKeyDown(e);
}
}
internal static void HandleFocus(Control parent, Control current)
{
Keyboard keyboard = new Keyboard();
// Move to the first control that can receive focus, taking into account
// the possibility that the user pressed <Shift>+<Tab>, in which case we
// need to start at the end and work backwards.
System.Windows.Forms.Control ctl = parent.GetNextControl(current, !keyboard.ShiftKeyDown);
while (null != ctl)
{
if (ctl.Enabled && ctl.CanSelect)
{
ctl.Focus();
break;
}
else
{
ctl = parent.GetNextControl(ctl, !keyboard.ShiftKeyDown);
}
}
}
The advantage of this solution is that it doesn't require neither a WindowsFormsHost nor a message pump which can be a hassle to implement. But I don't know if it is possible to handle shortcuts keys like this because I didn't need it.
Check if IsTabStop="True" and TabIndex is assigned. For Alt + Key shortcut, try using the underscore (_) character instead of the ampersand (&).

C# WinForms Wait on form to proceed

I'm tired and hungry, so I might of missed it, but from what I can see no existing post covers this...
I'm writing a plugin for an application. My plugin loads a form to get some data specifically, it uses the webcam to scan for a barcode. Once it's found a barcode, the form hides itself (incase it's needed again later). This is how I currently call the form that does the barcode work:
string readData = null;
if (eye == null)
{
System.Windows.Forms.Application.EnableVisualStyles();
eye = new CamView();
}
eye.Show();
if (eye.found)
{
readData = eye.readData;
}
return readData;
So, my problem is that eye.show() doesn't block. It makes the form appear and carries right on before there's a chance for the barcode to appear. I imagine I need to use some form of threading or locking, but my crude attempts to do so have just frozen the interface completely.
The "eye" form is basically just a viewfinder for the webcam, and relies on the camera_OnImageCapture event to make it do it's image checks for the barcode.
Is there an elegant way to make the application calling the plugin wait for the form to finish? Or do I just need to add an accept button to the "eye form?"
Cheers. And humble apologies if this is in anyway a repost.
.ShowDialog();
http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx
"You can use this method to display a modal dialog box in your application. When this method is called, the code following it is not executed until after the dialog box is closed."
You are on the right track. You change the code to show CamView as a modal dialog but do no add an Accept button. Instead change camera_OnImageCapture to close the dialog.

Webbrowser steals focus

I'm using webbrowser control in my winforms app (c#). And when it is doing automation things, I'm losing focus control from the window I was working with. Webbrowsers' form doesn't show up also, I just lose focus from the contol. I now writing this message I have to click into textbox again and again...
How to disable such behaviour in webbrowser?
I create invisible webbrowser like that:
var br = new WebBrowser();
br.Visible = false;
br.ScriptErrorsSuppressed = true;
Please advise.
I had the same problem:
The Webbrowser Control stole focus from the application once the URL is loaded.
This worked for me:
Before Webbrowser.Navigate() method call, set the parent control of the Webbrowser to Enabled = false.
At the DocumentCompleted event of the Webbrowser, reset parent control of the Webbrowser to Enabled = true.
You can't do it directly on Webbrowser because WebBrowserBase.Enabled is not supported.
Let me know if it works for you.
You could try disabling it globally via the SystemParametersInfo api. Use SPI_SETFOREGROUNDLOCKTIMEOUT. Setting foreground lockout is a global settings, so you will want to clear this setting when you're done. A more permanent solution is to change HKCU\Control Panel\Desktop\ForegroundLockTimeout registry key. See also this discussion on social.msdn (specifically, billb08's answer).
I guess WebBrowser acquires the focus after a page is loaded by calling Navigate (or the Click method of an HtmlElement, which causes navigation). The focus could be given back to the control on the window (the TextBox) in the DocumentComplete event handler of the WebBrowser, but this is very difficult:
When would you determine which control owned the focus
originally? Before calling Navigate? This is not enough, because the
user can move to another control after calling Navigate, but before
handling DocumentComplete.
AFAIK setting the focus to a TextBox will select its whole
content, so you will have to put the cursor back to its original
position. But when would you store the original position? Same problem.
There can be more than one DocumentComplete event after a single
Navigate (or Click).
A possible solution would be to create a separate application for your hidden WebBrowser. This second application would be invisible, and could communicate with the original GUI application using some InterProcess Communication (IPC) technique. Because the WebBrowser in this case would run in a different process, you would have a better chance not to lose lose the focus and bother the user.
it's a very complex problem to fix, and should be revised by microsoft, an app just stealing the focus is not logical, it does depend on what the website is doing though. I had to resort to a CBT filter, see http://msdn.microsoft.com/en-us/magazine/cc188966.aspx, and filter out unwanted HCBT_ACTIVATE and HCBT_SETFOCUS (return 1;). You can use GetWindowClass(wParam) to see what's going on.
Even above didn't entirely work, the app window would still pop to the front temporarily so worked around that using SetWindowPos HWND_TOPMOST and HWND_NOTOPMOST on the window currently in foreground. The HCBT_SETFOCUS gets hit 2 or 3 times so on 1st set HWND_TOPMOST and last set HWND_NOTOPMOST. Count how many classname == "Internet Explorer_Server" which should be 2 (or possibly depends on website?), the other is "Shell Embedding" but doesn't always occur. Hope it helps.
I was looking at all the other answers to this question and they weren't working for me, but i saw the one about settings Browser.Parent.Enabled = false; i tried so and got an error, so i tried this instead it just came to mind.
Browser.Parent = new Control();
Browser.Parent.Enabled = false;
And now the problem is completely gone, it does not take away focus anymore.
I am using the web browser class as a variable, it is not on my form.
well this worked for me try it, this seemed to be a 100% solution.
Most of the methods won't work for me on more than one web browser. This method is work with any amount of web browsers;
1. Put web browser into a panel and set panel enabled to false, then navigate;
webBrowser.Parent = panelBottom;
panelWebBrowser.Enabled = false;
webBrowser.Navigate("http://www.google.com");
2. Define a navigated event to web browser and delay panels enabling for a second;
private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((obj) =>
{
panelWebBrowser.Enabled = true;
timer.Dispose();
},null, 1000, Timeout.Infinite);
}
My solution for sending the focus back to a form:
Private Sub Web_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles Web.DocumentCompleted
If Me.Visible = False Then
For Each f As Form In My.Application.OpenForms
If TypeOf f Is frmLogin Then
Dim fl As frmLogin = DirectCast(f, frmLogin)
If fl.Visible = True Then
fl.Focus()
Exit For
End If
End If
Next
End If
End Sub

Categories