html element's attribute in c# web browser by using threading - c#

i am making web browser in windows form by using c# where i can set values of loaded html's input fields automatically by clicking on button. when i simply put code in click event of button its work fine`
private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Document.GetElementById("username").SetAttribute("value","admin");
webBrowser1.Document.GetElementById("password").SetAttribute("value","12345");
}`
but when i try to this via threading it gives me error
Specified cast is not valid?
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ThreadStart(setvalues));
thread1.Start();
}
void setvalues()
{
webBrowser1.Document.GetElementById("username").SetAttribute("value","admin");
webBrowser1.Document.GetElementById("password").SetAttribute("value","12345");
Thread.Sleep(8000);
}
}
where i am doing mistake in code ? any error? am beginner i need help

You can't access forms controls in a separate thread. Try this in setvalues():
Invoke((Action)(() => {
webBrowser1.Document.GetElementById("username").SetAttribute("value","admin");
webBrowser1.Document.GetElementById("password").SetAttribute("value","12345");
}));

Related

How to trigger DrillThrough with Report Viewer

I'm using ReportViewer with my WPF application.
I'm trying to trigger a function within my c# code and the button will be on the ReportViewer.
I'm wondering how do I trigger the DrillThrough?
void DemoDrillThroughEventHandler(object sender, DrillthroughEventArgs e)
{
MessageBox.Show("Drillthrough worked");
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
this._reportViewer.Drillthrough += new DrillthroughEventHandler(DemoDrillThroughEventHandler);
this._reportViewer.Reset();
....
this._reportViewer.LocalReport.Refresh();
this._reportViewer.RefreshReport();
}
}
Sometimes there is a method what rises event (OnSomething, to example, in winforms there is Button.PerformClick). Otherwise you can put code from event handler in separate function and call it directly.
Simplest solution to call it
DemoDrillThroughEventHandler(this._reportViewer, new DrillthroughEventArgs());
or even (depends on what is going on inside)
DemoDrillThroughEventHandler(null, null);

How to close a form on a new thread from a form which is in another thread?

I've been trying to figure this out for the past day or so.
I have a program which has Form1, and a button that spawns Form2 in a new thread.
I also have another button on Form1 that should close Form2, but since Form2 is in another thread, I cannot touch that object directly.
I could do t.Abort() but that throws an exception.
How can I gracefully touch the other thread? Do stuff to it?
For example, how do I close the form from within Form1?
I've searched google for "how to close a form from within another thread" and found several links hinting at Invoke and Delegate, but after trying some things, I obviously can't figure out how to use it properly.
Can anyone help me to understand how it would apply to the code I have, so that I can understand how they can be used? in which context, etc?
I've uploaded the project to github for your convenience: https://github.com/powercat/WindowsFormsApplication7/archive/master.zip
--
Code:
[Form1.cs]
public void FormThread()
{
Application.Run(new Form2());
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(FormThread));
t.Start();
}
private void button2_Click(object sender, EventArgs e)
{
//Need to close Form2 from here.
}
[Form2.cs]
has the other form code.
In general, having two threads for two forms is not a good idea. It's almost always a better idea to have all of your forms on the main, UI thread, and move your logic and work onto background threads instead.
That being said, if the Form is being run in the separate thread, you should be able to use BeginInvoke to close it:
otherForm.BeginInvoke(new Action(() => otherForm.Close()));
Edit:
In your case, you'd need to save the instance:
Form2 otherForm;
public void FormThread()
{
otherForm = new Form2();
Application.Run(otherForm);
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(FormThread));
t.SetApartmentState(ApartmentState.STA); // THIS IS REQUIRED!
t.Start();
}
private void button2_Click(object sender, EventArgs e)
{
//Need to close Form2 from here.
if (otherForm != null)
{
otherForm.BeginInvoke(new Action( () => otherForm.Close() ));
otherForm = null;
}
}

Some events dont work in Winform in C#

I am using YoutubeExtractor's dll.. videoDownloader_ProgressChanged and videoDownloader_DownloadFinished events are working in console application but in winform, it doesnt work.. I dont understand why..
private void btnStart_Click(object sender, EventArgs e)
{
string link = textBox1.Text;
start(link);
}
static void start(string link)
{
IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link);
DownloadVideo(videoInfos);
}
private static void DownloadVideo(IEnumerable<VideoInfo> videoInfos)
{
VideoInfo video = videoInfos
.First(info => info.VideoFormat == VideoFormat.Standard360);
var videoDownloader = new VideoDownloader(video, Path.Combine("C:/Downloads", video.Title + video.VideoExtension));
videoDownloader.DownloadFinished += new EventHandler(videoDownloader_DownloadFinished);
videoDownloader.ProgressChanged += new EventHandler<ProgressEventArgs>(videoDownloader_ProgressChanged);
videoDownloader.Execute();
}
static void videoDownloader_ProgressChanged(object sender, ProgressEventArgs e)
{
//some code..
}
static void videoDownloader_DownloadFinished(object sender, EventArgs e)
{
//some code..
}
my second question is, I want to access a form control in a static videoDownloader_ProgressChanged event. e.ProgressPercentage paramter gives me percent of video downloaded. I want to show it in label. But I cant access label because of static event.. I tried to use delegate but nothing changed..
Please modify both Start() and DownloadVideo() routines to instance methods. Remove 'static' keyword from them and event handlers as well.
Thread off 'videoDownloader.Execute()' and BeginInvoke() in the changed/finished handlers.
Don't call methods that take forever, (in computer terms), in GUI event handlers. If it takes more than about 50ms, thread it off. Any net thingy, eg. something with 'YouTube' in it, will take longer than that just to establish a connection!

logout the main form and show the login form

i know this problem may sound stupid, but sad case, i've been searched online to get solution but still cannot get it correct. My problem now is = Logout button so to exit the main form, then show up the login form again.
The code below will NOT show the login form after i click the logout button, it straight away exit the whole application.
void logoutbtn_Click(object sender, EventArgs e)
{
CloseSockets();
this.Close();
serverlogin login = new serverlogin();
login.Show();
}
So, i try to replace this.Hide() instead of this.Close();. But, something even dumb happen. Yes, the login page show after i click the logout button, but when i click the Cancel button at my login form, it didnt exit the whole application where it suppose to exit the whole application. i guess is because the main form is just hiding and not yet close??? Plus, when i try to login again, the login button is also, NOT functioning, cannot login to main page.
i apologize upon my explanation and please tell me if it is very unclear.
Please kindly help me. Thank you so much.
You need to define 2 event in your form which will be fired on butttons click and handle it in the main form:
MainForm.cs
void logoutbtn_Click(object sender, EventArgs e)
{
CloseSockets();
this.Hide();
serverlogin login = new serverlogin();
login.Login += new EventHandler(serverlogin_Login);
login.Cancel += new EventHandler(serverlogin_Cancel);
login.Show();
}
private void serverlogin_Login(object sender, EventArgs args)
{
this.Show();
// do login
}
private void serverlogin_Cancel(object sender, EventArgs args)
{
Application.Exit();
// do exit
}
LoginForm.cs
public event EventHandler Login;
public event EventHandler Cancel;
private void OnLogin()
{
if (Login != null)
Login(this, EventArgs.Empty);
}
private void OnCancel()
{
if (Login != null)
Login(this, EventArgs.Empty);
}
private void btnLogin_Click(object sender, EventArgs e)
{
this.OnLogin();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.OnCancel();
}
You might just want to start a new instance of your application, then exit the old one, when "logout" is selected. This cleans up any resources still in use, and makes it much more difficult to leak data from one user session to the next.
The disadvantage, of course, is that it will be slower, but there's ngen.exe to reduce the cost of restarting the app.
I reviewed the first answer, and I found out that there is something wrong. In the code, he closes the form after creating the new thread. I tested it, but it always closed my form. So I switched the this.Close(); with t.Start(); and it worked. Below you have the explanation of the code.
You create a new thread then you close the form you are in (for exemple the menu), and finally you start your new thread. You create a new method where you run your new form. I commented it line by line.
private void btnLogout_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(OpenLoginForm)); //you create a new thread
this.Close(); //you close your current form (for example a menu)
t.Start(); //you start the thread
}
public static void OpenLoginForm()
{
Application.Run(new LoginForm()); //run your new form
}
private void btnLogout_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(OpenLoginForm));
t.Start();
this.Close();
}
public static void OpenLoginForm()
{
Application.Run(new LoginForm());
}

Print on a background thread

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();});

Categories

Resources