In this example I'm using 1 button and web browser in VB using C#
I simply want to hit the button once then have it go to bing, wait 2 seconds, then go to google. Every method I've seen when I try it always has the pause or pauses at the beginning and not between navigation. Here's what I have. Thanks in advance.
public void button1_Click(object sender, EventArgs e)
{
WebBrowser1.Navigate("http://www.bing.com");
Thread.sleep(2000);
WebBrowser1.Navigate("http://www.google.com");
}
Subscribe to the DocumentCompleted event and navigate to the second page there:
private void LoadPages()
{
WebBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser1_DocumentCompleted);
WebBrowser1.Navigate("http://www.bing.com");
}
void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser1.Navigate("http://www.google.com");
// Might want to dispose of the webbrowser instance or else
// this event will fire again for the above call to `Navigate()`
// and you'll end up in a loop.
((WebBrowser)sender).Dispose();
// Or you could unsubscribe to the event if you still need the browser instance
WebBrowser1.DocumentCompleted -= WebBrowser1_DocumentCompleted;
}
Related
I try to record some internet activity through mouse hook in webbrowser control in winform application. Vary rare happens to click to a link and to not record that click just because everything happens too quickly and my code in
public void WebBrowser1Document_Click(object sender, HtmlElementEventArgs e)
{
tempHtmlElement = webBrowser1.Document.ActiveElement;
...
method couldn't reach to the end. In 90% record happens but some time it passes webBrowser1_Navigating event after that as I said passes WebBrowser1Document_Click just the beginning and webBrowser1.Document.ActiveElement breaks. It doesn't matter I have variable for the ActiveElement this variable looses access to some properties as Name for example. So my question is how to pause webbrowser1 activity until record is made. It's a STA application.
Assuming that Navigation occurs before Click method completes, You can pause by a tricky method. Use a global variable CanNavigate.
bool canNavigate;
public void WebBrowser1Document_Click(object sender, HtmlElementEventArgs e)
{
canNavigate=false;
tempHtmlElement = webBrowser1.Document.ActiveElement;
...
...
//At the End
canNavigate=true;
}
void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
do
{
Application.DoEvents(); Thread.Sleep(100);
} while (!canNavigate);
}
private void AddMyScrollEventHandlers()
{
VScrollBar vScrollBar1 = new VScrollBar();
}
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
break;
}
System.Threading.Thread.Sleep(200);
}
}
private void button2_Click(object sender, EventArgs e)
{
// vScrollBar1.Scroll
}
I am new in C#. I was working on scroll. What I wanted here is, if anyone click button1 then scroll automatically move to the end and I wanted to show gradual value in label1. Also when someone click button2 scrolling stop.
Now the problem is label1 do not show gradual change in value. It shows value once when the scrolling stop.
Also when scrolling continue i,e when while loop is working I can not click on button2. Actually I can not click on the form even.
Someone please give me some idea how to do this.
This happens because the thread that is performing the task is busy, and it's the same thread that updates the UI. You can use a multithreading solution. Take a look at
BackgroundWorker
All the UI events run in the main thread of the application, so the application can only process one event at a time. When the application is processing an event, no other event will be processed.
Since you are doing a UI related work periodically, the best option is to use the Timer class:
Drop Timer from the toolbox into the form.
In the properties window, set the interval to 200.
Double click the timer object to create the Tick event handler.
Put this code in the newly created timer1_Tick method:
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
timer1.Stop();
}
Change your methods as below:
private void AddMyScrollEventHandlers()
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
Now you're done.
I would recommend using BackgroundWorker control, as suggested by Agustin Meriles. However, one more important thing to note is that You should use Control.Invoke(...) method to update controls from another thread.
I've modified Your code, tested it in a sample application and it seems to work correctly.
First, add a new BackgroundWorker control to Your form and assign backgroundWorker1_DoWork to its DoWork event.
Then, You can use the code below:
private void button1_Click(object sender, EventArgs e)
{
//code from here is moved to BackgroundWorker control
backgroundWorker1.RunWorkerAsync();
}
private void button2_Click(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//while (true)
//the condition directly in the while looks more clear to me
while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
//update controls using Invoke method and anonymous functions
vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });
label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });
//when called inside BackgroundWorker, this sleeps the background thread,
//so UI should be responsive now
System.Threading.Thread.Sleep(200);
}
}
If You have any problems when using this code, please let me know.
Update
As mentioned in the comments, You could also use ProgressChanged event of the BackgroundWorker. It requires some more changes in the code, but is more suitable in this case. You can find some information about it here: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx.
If You are not going to add any other code with more processing in the while loop, You can also use Timer control, as suggested by MD.Unicorn in his answer.
Currently I'm moving from java to c# and I'm full of crazy questions.
I'm trying new things on a windows form application and now,I would like to create a loop wich is executing a code every 1 minute,the problem is that I have no idea where to put this code.
For example,the form structure is like:
using System;
namespace Tray_Icon
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
notifyIcon1.ShowBalloonTip(5000);
}
private void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
{
label1.Text = "Baloon clicked!";
}
private void notifyIcon1_BalloonTipClosed(object sender, EventArgs e)
{
label1.Text = "baloon closed!";
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
}
private void option1ToolStripMenuItem_Click(object sender, EventArgs e)
{
//some code here
}
private void option2ToolStripMenuItem_Click(object sender, EventArgs e)
{
//some code here
}
private void option3ToolStripMenuItem_Click(object sender, EventArgs e)
{
label1.Text = "Option 3 clicked!";
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
option1ToolStripMenuItem_Click(this, null);
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnWrite_Click(object sender, EventArgs e)
{
//code here
}
}
}
Where should I put the loop code? :(
Thanks in advance for ANY replay!!!
Add a Timer to your form:
set its Interval property to 60000 (one minute in milliseconds) and Enabled to True:
and attach an event handler to the Timer.Tick event, e.g. by double-clicking the timer in the Forms designer:
private void timer1_Tick(object sender, EventArgs e)
{
// do something here. It will be executed every 60 seconds
}
You would have to add a timer, and set the interval to 1000 miliseconds, and in the OnTick event you add the code with your loop
Timer tmr = null;
private void StartTimer()
{
tmr = new Timer();
tmr.Interval = 1000;
tmr.Tick += new EventHandler<EventArgs>(tmr_Tick);
tmr.Enabled = true;
}
void tmr_Tick(object sender, EventArgs e)
{
// Code with your loop here
}
You can't put any loop code in here.
In your designer look for the Timer control. When you have that, configure it to run every minute and place your code in the Timer_Tick event.
Or create a timer manually in code and respond to the event :) But for starters, doing it by the designer is easier!
Drag a Timer component on the Form and doubleclick it. There you go with the code.
The Timer component runs in the main thread so you can modify UI components without worrying.
Alternatively You could create a System.Timers.Timer, which has it's own thread and has some advantages, but possible caveats when modifying UI components. See http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
Try to use Background Worker and put the code in the backgroundWorker.DoWork or use a Timer
Use System.Timers.Timer:
System.Timers.Timer aTimer;
{
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 60000;
aTimer.Enabled = true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
for using Timer see this tutorial: C# Timer
How you do it in Java platform?
I think Java should be the same with .net.
In fact, a form program is just normal program which contains a event dispatcher. The event dispatcher listen to the UI events and dispatch them to the event handlers. I think all the UI mode should like this, no matter Java or .net platform.
So generally speaking, you have 2 options:
Start the loop at beginning. In this case, you should insert your
code in the constructor of the Form.
Start the loop when user
click the button. In this case, you should insert your code in the
event handler function.
Yes, as others mentioned, you should use the timer. But this should after you know where your code should locate. You also can use a endless loop with a sleep call. But timer is a better solution.
Idea of timer is more better. But If you want to use threads. Then Follow this
Let me assume that You want to do it right from the start of program
You can write in body of function (event in fact) named Form1_Load as
Your actual code is just within while loop other code only to guide
I can guide if you don't know the use of threads in C#
bool button2Clicked = false;
private void Form1_Load(object sender, EventArgs e)
{
// A good Way to call Thread
System.Threading.Thread t1 = new System.Threading.Thread(delegate()
{
while (!button2Clicked)
{
// Do Any Stuff;
System.Threading.Thread.Sleep(60000); //60000 Millieconds=1M
}
});
t1.IsBackground = true; // With above statement Thread Will automatically
// be Aborted on Application Exit
t1.Start();
}
I use the webbrowser control of .NET to open piles of urls,and the loop is called in the DocumentCompleted event.
Now I want to control the timeout.So I use a timer,and when timeout it will stop the webbrowser using the stop() function.
The question is: it seems that the stop function fires the DocumentCompleted event sometimes.So if the timer calls the next loop after stop the webbrowser,error happens.And if it doesn't call the next loop,sometimes the loop will be stopped in the middle.
The procedure like this(codes not related are deleted):
private string[] urls;//urls are stored here
private int index = 0;//next url index
private void loopFunc()
{
timer.Enabled = true;
wb.navigate(urls[index]);
index++;
return;
}
private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
loopFunc();
}
private void timer1_Tick(object sender, EventArgs e)
{
wb.stop();
//loopFunc() or not?
}
I don't know for sure whether it fires the event or not,and I found nothing via google.
If I have understood your situation clearly this could solve your problem:
Timer On ---> loopFunc() --> goto url --> oncomplete -> start timer again -->
|
|---> Stop timer so it doesn't call loopFunc again
So stop the timer after loopFunc, when the download completes, loopFunc is called again:
private void loopFunc()
{
timer.Enabled = true;
wb.navigate(urls[index]);
index++;
timer.stop(); //<<<<<
return;
}
And your tick should be:
private void timer1_Tick(object sender, EventArgs e)
{
loopFunc();
}
Then start your timer again on document complete:
private void wb_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
wb.Stop();
timer.Start();
}
I want to print a html page from c# application but on a back ground thread because if I print the doc on main thread UI freezes for few seconds and I dont want that.
I have tried WebBrowser control but it need to be hosted on some form to get it work. Hosting this control is still acceptable but Print method needs to be called from same thread the control was created on. I tried calling Print method of WebBrowser from other thread but it neither work nor it give any error/exception. I have also tried InternetExplorerClass but it start iexplorer.exe and takes too much time.
Is there any other way in which I can print html page on a diffrent (non UI) thread?
I'd use a backgroundworker for this purpose - since you've already got a winform and everthing.
Drag a background worker and a webbrowser to your form and you can use the following code (UI freezes for milliseconds when the print is actually spooled);
I've used a test button (2) for the call;
using System.Threading;
private void button2_Click(object sender, EventArgs e)
{
if (!this.backgroundWorker1.IsBusy)
{
this.backgroundWorker1.RunWorkerAsync("http://www.stackoverflow.com/");
}
else
{
MessageBox.Show("Already working on that piece of paper!");
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
this.webBrowser1.Navigate((string)e.Argument);
//-- only when you need to read very bulky pages: Thread.Sleep(1000);
e.Result = true;
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
this.webBrowser1.Print();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.webBrowser1.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
Does something like this not work?
webBrowser1.BeginInvoke((MethodInvoker)delegate{webBrowser1.Print();});