I'm trying to make a chat bot for twitch and i want to make it in a Form so its very user friendly, i got the twitch communication done but now my form wont initialize. Please help.
namespace TwitchBotForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
IrcClient irc = new IrcClient("irc.twitch.tv", 6667, "z_bot909", "oauth:dn2tixd1xd7krggyn49ztw08hmfjea");
irc.joingRoom("z_dog909");
irc.sendChatMessage("Startup Complete");
while (true)
{
string message = irc.readMessage();
string[] splitMessage = message.Split('#');
if (message.Contains("!info"))
{
irc.sendChatMessage("Please Keep all commands LowerCase I made this bot Myself and i think its pretty cool. do !Help for Commands");
}
if (message.Contains("!me"))
{
irc.sendChatMessage(splitMessage[1].Split(':')[0]); //Username
}
}
}
}
}
You should not put this infinite loop in constructor of your form.
Check this article on how to run background thread with windows forms.
Related
Im newbie to programming and now i have a problem with my new login window.
I created a new window for login to my server database,but in my mainwindow how do i call it? I don't know how to draw it up better.
In my login window:
using MyS_Database;
MyServer_Database server;
public void LoginButton_Click(object sender, RoutedEventArgs e)
{
server = new MyServer_Database("ClientName","ServerIP","","",UserID.Text,UserPassword.Password.ToString(),"01",MyServer_Database.LoginType.User,out serverresult)
swith(serverresult)
{
case 0:
Mainwindow.Show();
this.Close();
break;
default:
Environment.Exit(0);
}
}
But when I call a method on my MainWindow which is communicating with the server i have to call it like:
server.GetDataFromUserList();
But It doesn't recognize server,I tried something like Win1.server or similars but I failed.
How could i pass it? Thank you in advance!
The quick answer is to make server public like this:
public MyServer_Database Server { get; set; }
Then you can call it in MainWindow with:
Win1.Server.GetDataFromUserList();
But this is not a good approach. Better approach is to abstract away these kind of operations in different classes via MVVM. Read more about MVVM and you'll find great approaches.
Edit
You should also do one one of these two things:
Don't close Win1 instead do this.Hide();
Keep the instance of MyServer_Database in MainWindow by passing it to the constructor of Win1.
You should put this in MainWindow
public MyServer_Database Server { get; set; }
and When needed call this:
var Win1 = new LoginWindow(Server);
Then you have access to Server object in MainWindow
I am using SignalR to implement a notification system to exchange information between my application instances. I have the following hub class:
[HubName("OpenHub")]
public class OpenHub:Hub
{
public void DetermineLength(string message)
{
Clients.All.RecieveNewInfo(newMessage);
//How to use something like the following line?
//concerning that Form1 is loaded at application startup
//and I should not create a new instance
//Form1.lstMessages.Add(newMessage);
}
}
Yet, I have to update some UI controls including a label and a listbox to log whatever new information that has arrived. Besides defining my class in my form's code, how can I update Form object to show these new information when I have my hub defined in a different class?
You can use public static property in you Program class or you Form1 class to hold the reference for it.
For example in you Program before using Application.Run(new Form1());
You can do this:
public static Form1 MainForm { get; set; }
and then in the Main()
MainForm = new Form1();
Application.Run(MainForm);
From the hub you can access you form now:
[HubName("OpenHub")]
public class OpenHub:Hub
{
public void DetermineLength(string message)
{
Clients.All.RecieveNewInfo(newMessage);
Program.MainForm.lstMessages.Add(newMessage);
}
}
Of course, that lstMessages should be public. or better you expose in your form some public method to communicate with it.
If your app is winform you can register to the hub with something like this :
var Connection = new HubConnection("yourSignalRServerUrl");
var HubProxy = Connection.CreateHubProxy("OpenHub");
HubProxy.On<string>("RecieveNewInfo", (message) =>
this.Invoke((Action)(() =>
Form1.lstMessages.Add(message);
);
await Connection.Start();
The namespace needed to use HubProxy is Microsoft.AspNet.SignalR.Client
This example comes from : https://code.msdn.microsoft.com/windowsdesktop/Using-SignalR-in-WinForms-f1ec847b
Here is what I'm trying to achieve.
I have a login class. Once the user is authenticated, some post login operations are done in a thread. And the user gets to home page.
Now from home page I go to a different functionality, say class FindProduct. I need to check if post login operations in the login thread are completed. Only if post login operation is completed I allow to enter the functionality.
Do I have to put wait handles on PerformLoginAsyncThread as well as OnClickFindProduct?
Class Login
{
public bool Login(Userinfo)
{
// do tasks like authenticate
if(authenticationValid)
{
PerformLoginAsyncThread(UserInfo)
//continue to homepage
}
}
}
Class HomePage
{
public void OnClickFindProduct
{
if(finishedPostLoginThread)
// proceed to Find Product page
else
{
//If taking more than 8 seconds, throw message and exit app
}
}
}
Here is the general idea how to use EventWaitHandles. You need to Reset it before doing the work, and Set it when you are done.
In the example below I have made the ResetEvent property static, but I suggest you pass the instance somehow instead, I just could not do it without more details about your architecture.
class Login
{
private Thread performThread;
public static ManualResetEvent ResetEvent { get; set; }
public bool Login(Userinfo)
{
// do tasks like authenticate
if(authenticationValid)
{
PerformLoginAsyncThread(UserInfo);
//continue to homepage
}
}
private void PerformLoginAsyncThread(UserInfo)
{
ResetEvent.Reset();
performThread = new Thread(() =>
{
//do stuff
ResetEvent.Set();
});
performThread.Start();
}
}
class HomePage
{
public void OnClickFindProduct
{
bool finishedPostLoginThread = Login.ResetEvent.WaitOne(8000);
if(finishedPostLoginThread)
{
// proceed to Find Product page
}
else
{
//If taking more than 8 seconds, throw message and exit app
}
}
}
If you don't want to complicate your logic with await or raising an event the simplest solution would be inside the PerformLoginAsyncThread function just set a session variable to true on complete and in your OnClickFindProduct check for the session variable.
I have a requirement to send a signal from a Windows Service to a Windows console/Forms application using Named Events. I created a common NamedEvents class library which has the implementation to create events.
The issue is that my windows service is not creating the event. If I create another Windows Forms application (in place of the windows service) to create a event then it works fine. But with Windows Service it doesn't seem to work. Can someone please advise me if I am missing something in my code
public static class NamedEvents
{
public static EventWaitHandle OpenOrCreate(string name, bool initialState, EventResetMode mode)
{
EventWaitHandle ewh = null;
try
{
ewh = EventWaitHandle.OpenExisting(name);
}
catch (WaitHandleCannotBeOpenedException)
{
ewh = new EventWaitHandle(initialState, mode, name);
}
return ewh;
}
public static EventWaitHandle OpenOrWait(string name)
{
EventWaitHandle ewh = null;
while (null == ewh)
{
try
{
ewh = EventWaitHandle.OpenExisting(name);
}
catch (WaitHandleCannotBeOpenedException)
{
Thread.Sleep(50);
}
}
return ewh;
}
}
Windows Service Code:
public void SetSignalToClient()
{
EventWaitHandle completedA = NamedEvents.OpenOrCreate("CompletedA", false, EventResetMode.ManualReset);
completedA.Set();
completedA.Close();
}
Windows Forms Application:
public Form1()
{
InitializeComponent();
new Task((o) => SubscribeToAsyncEvents(),
new System.Threading.CancellationToken()).Start();
}
private void SubscribeToAsyncEvents()
{
while (true)
{
EventWaitHandle completedA = NamedEvents.OpenOrWait("CompletedA");
completedA.WaitOne();
if (textBox1.InvokeRequired)
{
textBox1.Invoke((MethodInvoker)delegate { textBox1.Text = "received"; });
}
completedA.Close();
}
}
This is documented in the MSDN article for CreateEvent. In order to use an event object across multiple Terminal Services sessions (also known as Remote Desktop sessions) you must create a global event object, which you can do by starting the name that with the prefix Global\, e.g., Global\MyEventName.
While the documentation does not mention it, to the best of my knowledge, the .NET EventWaitHandle class will pass the event name to CreateEvent unchanged. So the same mechanism should work.
Windows Services run in session 0, and user applications run in session 1 or higher. So for a service and a user application to communicate, they must use global objects.
Note that if the user application is not running as an administrator, the service will probably also need to explicitly set the permissions on the event object.
I have a dead simple example trying to get the CEF Browser to append on a Winforms Form. For some reason it won't display.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CefSharp.WinForms.ChromiumWebBrowser test = new CefSharp.WinForms.ChromiumWebBrowser("http://google.com");
this.Controls.Add(test);
}
}
Below is the VS Solution I am using. I added the package via Nuget
Your code above is a bit too dead simple :)
It's missing a call to Cef.Initialize()
See the Main() method of the CefSharp.MinimalExample.WinForms example for a working example and further details on how to use CefSharp.
You also need to give the control a DockStyle.Fill, like:
public Form1()
{
InitializeComponent();
var test = new CefSharp.WinForms.ChromiumWebBrowser("http://google.com")
{
Dock = DockStyle.Fill,
};
this.Controls.Add(test);
}