Unable To Write to a text box from a method - c#

Im currently trying to create a messaging application from client to server. When the server sends the client a message it will open up an new form and add the text to a text box inside the form.
However the client is defiantly reviving the message, I tested this with a message box displaying the message before trying to update the text box. The text box is displaying the message perfectly.
However, when i try to edit the textboxt nothing happens. However my other method on a button click works perfectly. really unsure why this is happening.
I've also written an invoke method to check if the textbox need's to be invoked as i am using differen't threads for some methods.
Below is an example of my code with some screenshots the method below is being opened from another form "MAIN" i have reference to it in the code. Not sure if that is causing an issue perhaps?
public ChatWindow()
{
InitializeComponent();
Thread timerThread = new Thread(Main.ReceiveLoop);
timerThread.Start();
}
private void txtChatLog_TextChanged(object sender, EventArgs e)
{
}
private void btnSendMessage_Click(object sender, EventArgs e)
{
string clientReply = txtReply.Text;
string Message = "ClientMsg§" + clientReply;
var time = DateTime.Now;
txtChatWindow.AppendText($"{time} client: {clientReply}");
txtChatWindow.AppendText(Environment.NewLine);
Main main = new Main();
main.ChatResponse(Message);
txtReply.Text = "";
}
delegate void setTextCallBack(string message);
public void UpdateChatLog(string message)
{
if (txtChatWindow.InvokeRequired)
{
setTextCallBack d = new setTextCallBack(UpdateChatLog);
this.Invoke(d, new object[] { message });
}
else
{
var time = DateTime.Now;
string newMessage = message.Split('$')[1];
string messageToDisplay = $"{time} Server: {newMessage}";
MessageBox.Show(messageToDisplay);
this.txtChatWindow.AppendText(messageToDisplay);
this.txtChatWindow.AppendText(Environment.NewLine);
}
}
Below are some images of my server and the code running on the client:
as you can see the server is recieving what the client replies with, the textbox is also being appended for when the client presses the SEND button. However it isn't being changed when the method is called. You know the method is being called because the MessageBox.Show is being called and displaying what should be in the text box.
Really unsure what the issue is here. If anyone could help me It would be very appreciated! This is a project for my university degree that is due in soon!
Thankyou in advance!

Related

Chatbox not working c#,Visual Studio ,Winforms,Bunifu UI

I have a problem that i dont understand at all , i need your help...
I am working in a chat , i will do it with sockets , but the problem isnot this ,
I created a control user to my chat box... and another to my bubbles i am trying to use this control users from my main form
private void button1_Click_1(object sender, EventArgs e)
{
chatbox a = new bunifchat.chatbox();
a.send2message("ABC");
}
chatbox is the name of my controlUser and i am trying to use his method send2message, i know that it works but not correctly.
public void send2message(String message)
{
bubble bbl = new bunifchat.bubble(message);
bbl.Location = bubble1.Location; bbl.Left += 100; //add intent
bbl.Size = bubble1.Size;
bbl.Anchor = bubble1.Anchor;
bbl.Top = bbl_old.Bottom + 20;
panel2.Controls.Add(bbl);
//bottom.Top = bbl.Bottom + 50;
bbl_old = bbl; //safe the last added object
}
this method receive the string and create the bubble entering to other controlUser, it works when i run it from the ControlUser Chatbox with the next code:
private void buttonx_Click(object sender, EventArgs e)
{
//panel1.VerticalScroll.Value = panel1.VerticalScroll.Maximum;
String respuesta = txtbox.Text;
sendmessage("hola mundo");
send2message(respuesta);
panel2.VerticalScroll.Value = panel2.VerticalScroll.Maximum;
}
but if i run it from my main form , nothing happens,the code of my bubble is this:
public bubble(String message)
{
InitializeComponent();
label1.Text = message;
Setheight();
}
if i am not explicit, please ask , i need help
enter image description here
when i press the button green , it create more bubbles(blue rectangules) , but i want to send the content from my main form and not from my chat box.
i will do it with sockets
Does that mean you use a socket to receive data on a different thread than the UI-thread?
If so, you need to check, if oyu need to invoke before accessing / creating a new object.
private bool AddMessage(string msg)
{
if (this.InvokeRequired)
return (bool)this.Invoke((Func<string,bool>)AddMessage, msg);
//DO stuff here
send2message(msg);
return false;
}

Webkit.Net wait for page to be fully loaded

I'm trying to make an C# windows form application, with an webbrowser.
I'm using the webkit browser: Link to the browser
The webbrowser did i put in an class file, so i can acces it through all the forms i'm going to use.
The code that's generate the webbrowser:
public static WebKit.WebKitBrowser mainBrowser = new WebKitBrowser();
I'm having this piece of code that give's some problems:
globalVars.mainBrowser.Navigate("http://www.somesite.com/");
while (globalVars.mainBrowser.IsBusy)
{
System.Threading.Thread.Sleep(500);
}
globalVars.mainBrowser.Document.GetElementById("user").TextContent = "User Name";
But it's not working. If i do an message box after the while, it shows up before it's possible to render the page...
So what is the best way to wait until the site is fully loaded?
UPDATE 1
In an standalone class file, am i making the webkit controll like this:
public static WebKit.WebKitBrowser mainBrowser = new WebKitBrowser();
And in an form, i've got now this code (thanks to Tearsdontfalls):
public void loginthen()
{
globalVars.mainBrowser.DocumentCompleted += mainBrowser_DocumentCompleted;
globalVars.mainBrowser.Navigate("http://www.somesite.com/");
}
void mainBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var send = sender as WebKit.WebKitBrowser;
if (send.Url == e.Url)
{
MessageBox.Show("Inloggen");
globalVars.mainBrowser.Document.GetElementById("user").TextContent = "User Name";
}
}
But no messagebox shows up. But if i use an local (on the same form) webkit browser, i'm getting te MessageBox. But then the user field isn't filled in.
Even an breakpoint in the documentCompleted event, isn't triggerd. So it looks like the event listner isn't working...
So why is it not working?
You can simply create an event listener on the Document Completed Event on your Webbrowser, or you can create it dynamically like that:
globalVars.mainbrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(mainbrowser_DocumentCompleted);
Where mainbrowser_DocumentCompleted is the name of the void where you can do sth like this(I used the names of your provided code):
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
var send = sender as WebKit.WebKitBrowser;
if (send.Url == e.Url) {
globalVars.mainBrowser.Document.GetElementById("user").TextContent = "User Name";
}
}
Adding the following piece of code let the events fire when the browser is in invisible mode.
using (Bitmap bmp = new Bitmap(webKitBrowser.Width, webKitBrowser.Height))
{
webKitBrowser.DrawToBitmap(
bmp,
new Rectangle(
webKitBrowser.Location.X,
webKitBrowser.Location.Y,
webKitBrowser.Width,
webKitBrowser.Height
)
);
}

Weather fetching is not working more than once

I have a problem with the Wunderground forecast that I am using to retrieve data in c# program.
When I click to retrieve data once everything is working correctly but when I hit the button once more I am getting this error:
Here is my code:
private void bweather_DoWork(object sender, DoWorkEventArgs e)
{
string lat = Math.Round(deciLat).ToString();
string lng = Math.Round(deciLon).ToString();
string latlong = String.Format("{0},{1}", lat.Replace(',', '.'), lng.Replace(',', '.'));
//Initialize Current as a new Day
dow.Current = new WeatherLib.WDay();
//Using Wunderground as the provider we populate the property with current data for the latlong entered into the textbox
try
{
dow = WeatherLib.WProvider.Wunderground(latlong);
writeToLogFile("Retrieve weather info successfully on: " + latlong);
}
catch (Exception ex)
{
writeToLogFile(ex.Message);
}
}
Here is the refresh button:
private void weather_refresh_Click(object sender, EventArgs e)
{
writeToLogFile("Weather button pressed");
weather_descripton.Clear();
weather_speed_textbox.Clear();
weather_tem_textbox.Clear();
weather_rain_text.Clear();
weather_wind_dir_textbox.Clear();
weather_descripton.AppendText("Searching.......");
if (!bweather.IsBusy)
{
bweather.CancelAsync();
}
bweather.RunWorkerAsync();
}
And here are the event handlers:
// Weather handlers
bweather.WorkerSupportsCancellation = true;
bweather.DoWork += bweather_DoWork;
bweather.RunWorkerCompleted += bweather_RunWorkerCompleted;
Any idea why is this not working as it should?
Thank you
Well the error message suggests that you're trying to use the same background worker more than once.
You're asking it to cancel if it's still busy, but that doesn't mean it'll cancel immediately. As far as I can tell, the BackgroundWorker code isn't even checking whether it's been cancelled, which means cancelling it won't really achieve anything useful.
I would suggest that if it's busy, you should instead just ignore the request. In fact, it might be better to disable the button completely when you start the operation, and only re-enable it when the operation completes.

C# WinForms cannot set focus

Im currently facing the problem that when i try to set focus on some control (textBox), nothing happens, maybe i just overlooked something.(somewhere i found that focus is "low-level" method and that select() should be used instead, however, it doesnt work as well)
From form Login, i launch new instance of EncryptPSW form
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
EncryptPSW ePSW = new EncryptPSW();
ePSW.setOsLog(false, this);
ePSW.ShowDialog();
}
On Button(which is located on EncryptPSW form ) click event i call fill method
public void fill()
{
if (textBoxPSW.Text.Length == 8)//psw has to be 8 chars long
{
if (save)//determinating whether save or fetch of data should be done
{ login.launchSave(textBoxPSW.Text,this); }
else { login.launchOpen(textBoxPSW.Text,this); }
}
else { MessageBox.Show("The password must contain 8 characters");}
}
Which launches either save or open method from Login (my problem is just with open, since during save i dont need to do anything with Focus)
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
setFocus();
}
After all the work is done, setFocus() should be called in order to set focus and other properties.
public void setFocus()
{
textBoxDatabase.Focus();
textBoxDatabase.SelectionStart = textBoxDatabase.TextLength - 1;
textBoxDatabase.SelectionLength = 0;
}
I tried so many different ways, like:
Calling setFocus() from within EncryptPSW_FormClosed
Calling whole open process after the EncryptPSW is closed (from within EncryptPSW_FormClosed)
and many more, however i dont remember it all.
In the case of Form_Closed the weird thing is, that when i tried to show a message box from there instead of setting focus (just to see where the problem might be), it's showed before the EncryptPSW form is closed.
My only guess about this is that the instance of EncryptPSW is somehow blocking Login form and it's controls
I hoped i described my problem well enough and that it makes at least a bit of sense ;]
Thanks in advance,
Regards,
Releis
Since the textbox is in the login form, and you are opening the EcryptPWS from it as a dialog (child), your login form will not be able to set focus to anything. You will need to set focus after it is closed. You can do this:
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
using(EncryptPSW ePSW = new EncryptPSW())
{
ePSW.setOsLog(false, this);
if (ePSW.ShowDialog() == DialogResult.OK)
{
textBoxDatabase.Focus();
}
}
}
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.DialogResult = DialogResult.OK;
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
}
OK this maybe the ugliest thing I saw round this but.
using
public void setFocus()
{
textBoxDatabase.Focus();
textBoxDatabase.SelectionStart = textBoxDatabase.TextLength - 1;
textBoxDatabase.SelectionLength = 0;
}
Change your code at
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
setFocus();
}
to
delegate void settingfocus();
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
settingfocus sf = new settingfocus(setFocus);
this.BeginInvoke(sf);
}
This worked for me
(Sorry for apparently thinking insert "this" before procedure, and change line x to this was legable)

How to update text in a label

I have here a long method that takes a little while to execute. I would like to keep the user entertained so I created a progress bar and a label. What I would like is for that label to change while the system executes the progress. Ive been looking at Application.DoEvents(), but it seems like thats the wrong way to go. This application is pretty simple and its just a project and nothing professional. All this app does is send a file to a client and insert the data into a database.
I have one label (besides a success and error label), that I would like to constantly update along side the progress bar. Any ideas or tips on how to do this? Would Application.DoEvents() be acceptable in this situation? Or is there a simple way to update the text. I am using C#, asp.net, and a System.Web.UI.Page. Any help or pointing me to the right direction would be greatly appreciated.
protected void Button_Click(object sender, EventArgs e)
{
PutFTPButton.Enabled = false;
Thread.Sleep(3000);
Button btn = (Button)sender;
KaplanFTP.BatchFiles bf = new KaplanFTP.BatchFiles();
KaplanFTP.Transmit transmit = new KaplanFTP.Transmit();
//label text change here
if (btn.ID == PutFTPButton.ID)
{
//bf.ReadyFilesForTransmission();
DirectoryInfo dir = new DirectoryInfo(#"C:\Kaplan");
FileInfo[] BatchFiles = bf.GetBatchFiles(dir);
bool result = transmit.UploadBatchFilesToFTP(BatchFiles);
//label text change here
if (!result)
{
ErrorLabel.Text += KaplanFTP.errorMsg;
return;
}
bf.InsertBatchDataIntoDatabase("CTL");
bf.InsertBatchDataIntoDatabase("HDR");
bf.InsertBatchDataIntoDatabase("DET");
bf.InsertBatchDataIntoDatabase("NTS");
List<FileInfo> allfiles = BatchFiles.ToList<FileInfo>();
allfiles.AddRange(dir.GetFiles("*.txt"));
bf.MoveFiles(allfiles);
//label text change here
foreach (string order in bf.OrdersSent)
{
OrdersSentDiv.Controls.Add(new LiteralControl(order + "<br />"));
}
//lblWait.Visible = false;
OrdersSentDiv.Visible = true;
OrdersInfoDiv.Visible = false;
SuccessLabel.Visible = true;
NoBatchesToProcessLbl.Visible = true;
BatchesToProcessLbl.Visible = false;
PutFTPButton.Enabled = false;
BatchesCreatedLbl.Text = int.Parse(NextBatchNum).ToString();
Thread.Sleep(20000);
if (KaplanFTP.errorMsg.Length != 0)
{
ErrorLabel.Visible = true;
SuccessLabel.Visible = false;
ErrorLabel.Text = KaplanFTP.errorMsg;
}
}
}
I think you can use an Ajax UpdateProgress control, check Progress Bar on File Upload ASP.NET.
EDIT: Another one Displaying Progress Bar For Long Running Processes using ASP.NET AJAX.
Application.DoEvents() is not available in an ASP.NET application, nor is it's use acceptable in a standard WinForms application with the advent of multicore processors and the .NET threading library.
A web application requires communication to/from a server. Therefore simply updating the text of a label does nothing unless you are sending that back to the client. In your case you would need an event which was signaled by this line (because it is a batch upload):
transmit.UploadBatchFilesToFTP(BatchFiles);
The event would update the value you want to display. You would then need some AJAX code (or an ASP.NET update panel around a ASP.NET label) on the web page in question to get and display the new value.
HTH
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.label1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else this.label1.Text = text;
}
void SomeMethod()
{
SetText(yourVariable.ToString());
}
if i understand you correctly this should work.

Categories