I have created two buttons in c#. Is there any way to deactivate a button if anything goes wrong in the other button's function. I am giving a sample code fragment. There are two buttons. one is for connect and other is for browse files. I want to disable the browse button if the connectivity fails in the connect button. How to do this?
Sample code fragment:
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
class Client:Form
{
public Client()
{
Size = new Size(400, 380);
Button connect = new Button();
connect.Parent = this;
connect.Text = "Connect";
connect.Location = new Point(295, 20);
connect.Size = new Size(6 * Font.Height, 2 * Font.Height);
connect.Click += new EventHandler(ButtonConnectOnClick);
Button browse = new Button();
browse.Parent = this;
browse.Text = "Browse";
browse.Location = new Point(220, 20);
browse.Size = new Size(6 * Font.Height, 2 * Font.Height);
browse.Click += new EventHandler(ButtonbrowseOnClick);
}
void ButtonConnectOnClick(object obj, EventArgs ea)
{
tcpClient = new TcpClient("127.0.0.1", 1234);
}
[STAThread]
public static void Main()
{
Application.Run(new Client());
}
}
Another Question:
Is there any way to reset the button (say, the browse button) activity at a certain time and wait for clicking again?
You can just use a global flag:
bool connectButtonBroken = false;
private void ButtonbrowseOnClick(object sender, EventArgs e)
{
if(!connectButtonBroken)
{
//do code
}
}
Just wrap your connect call in a Try/Catch block and disable the other button in the Catch:
catch (Exception)
{
ButtonConnect.Enabled = false;
}
You should probably re-enable it just before the end of the Try with this:
ButtonConnect.Enabled = true;
You will need to store a reference to your dynamically created Connect button in a variable called ButtonConnect in a form level variable instead of a local one in the constructor for this to work.
Related
I am at a loss after looking at relevant posts and documentation, many others seem to have had similar problems, but none of the existing solutions results in any keypresses actually being recognized by the browser.
All my code is below, just an empty form trying to type in a username/password on a website that currently doesn't have an API but it is coming. So this is just a bandaid fix until their API is fleshed out. Mostly just need to login and send keypresses to the website, but nothing seems to be working.
I have also tried: https://ourcodeworld.com/articles/read/520/simulating-keypress-in-the-right-way-using-inputsimulator-with-csharp-in-winforms
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
namespace Hydros_tmp_api
{
public partial class Form1 : Form
{
public ChromiumWebBrowser chromeBrowser;
string CurrentAddress = "";
public void InitializeChromium()
{
CefSettings settings = new CefSettings();
// Initialize cef with the provided settings
Cef.Initialize(settings);
// Create a browser component
chromeBrowser = new ChromiumWebBrowser("https://www.coralvuehydros.com/app/#/status");
// Add it to the form and fill it to the form window.
Controls.Add(chromeBrowser);
chromeBrowser.Dock = DockStyle.Fill;
(chromeBrowser).LoadingStateChanged += Browser_FrameLoadEnd;
chromeBrowser.AddressChanged += Browser_AddressChanged;
}
public Form1()
{
InitializeComponent();
InitializeChromium();
}
private void Form1_Load(object sender, EventArgs e)
{
}
async void Browser_FrameLoadEnd(object sender, LoadingStateChangedEventArgs e)
{ // Jumps in here when the page is fully loaded:
if (e.IsLoading == false)
{
if (CurrentAddress.Contains("login"))
{
timer_login.Enabled = true;
}
}
}
private void Browser_AddressChanged(object sender, AddressChangedEventArgs e)
{
CurrentAddress = e.Address;
}
private void timer_login_Tick(object sender, EventArgs e)
{
timer_login.Enabled = false;
chromeBrowser.GetBrowserHost().SetFocus(true);
Random rnd = new Random();
chromeBrowser.GetBrowser().GetHost().SendKeyEvent(new KeyEvent
{
WindowsKeyCode = (int)Keys.Tab, // Enter
FocusOnEditableField = true,
IsSystemKey = false,
Type = KeyEventType.KeyDown
});
System.Threading.Thread.Sleep(rnd.Next(20, 120));
chromeBrowser.GetBrowser().GetHost().SendKeyEvent(new KeyEvent
{
WindowsKeyCode = (int)Keys.Tab, // Enter
FocusOnEditableField = true,
IsSystemKey = false,
Type = KeyEventType.KeyUp
});
System.Threading.Thread.Sleep(rnd.Next(20, 120));
chromeBrowser.GetBrowser().GetHost().SendKeyEvent(new KeyEvent
{
WindowsKeyCode = (int)Keys.T, // Enter
FocusOnEditableField = true,
IsSystemKey = false,
Type = KeyEventType.KeyDown
});
System.Threading.Thread.Sleep(rnd.Next(20, 120));
chromeBrowser.GetBrowser().GetHost().SendKeyEvent(new KeyEvent
{
WindowsKeyCode = (int)Keys.T, // Enter
FocusOnEditableField = true,
IsSystemKey = false,
Type = KeyEventType.KeyUp
});
System.Threading.Thread.Sleep(rnd.Next(20, 120));
}
}
}
Edit: It appears to be a specific oddity with their website that is not accepting simulated input because it works fine on other sites? So idk where to go from here.
I am hoping someone can help me in getting an issue of mine to work, I feel as if it is an easy one, however not having any luck in fixing what I am trying to do. I want to be able to pause a video which I am playing using vlc.dotnet below is a brief summary of the structure of my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using Vlc.DotNet.Forms;
using System.Threading;
using Vlc.DotNet.Core;
using System.Diagnostics;
namespace TS1_C
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
button8.Click += new EventHandler(this.button8_Click);
}
void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string chosen = listBox1.SelectedItem.ToString();
string final = selectedpath2 + "\\" + chosen; //Path
playfile(final);
}
void playfile(string final)
{
var control = new VlcControl();
var currentAssembly = Assembly.GetEntryAssembly();
var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
// Default installation path of VideoLAN.LibVLC.Windows
var libDirectory = new DirectoryInfo(Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
control.BeginInit();
control.VlcLibDirectory = libDirectory;
control.Dock = DockStyle.Fill;
control.EndInit();
panel1.Controls.Add(control);
control.Play();
}
private void button8_Click(object sender, EventArgs e)
{
}
}
}
As you can see I have one method which takes a double click from an item in a list box and plays it using the method playfile. However I want to be able to pause the video using my button known as button8. I have tried many things even this
control.Paused += new System.EventHandler<VlcMediaPlayerPausedEventArgs>(button8_Click);
Which I put into the playfile method, however nothing seems to work. I am wondering if my whole method in which I play a file using playfile(); is completely wrong. I am hoping someone can help me in trying to achieve what I need
Thank you
Your control should be initialized only once:
private VlcControl control;
public Form1()
{
InitializeComponent();
control = new VlcControl();
var currentAssembly = Assembly.GetEntryAssembly();
var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
// Default installation path of VideoLAN.LibVLC.Windows
var libDirectory = new DirectoryInfo(Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
control.BeginInit();
control.VlcLibDirectory = libDirectory;
control.Dock = DockStyle.Fill;
control.EndInit();
panel1.Controls.Add(control);
}
then, your play method could be simplified:
void playfile(string url)
{
control.Play(url);
}
And for your pause method:
private void button8_Click(object sender, EventArgs e)
{
control.Pause();
}
using System;
using System.Data.SQLite;
using System.Drawing;
using System.Timers;
using System.Windows.Forms;
using Tulpep.NotificationWindow;
public partial class Form1 : Form
{
System.Timers.Timer timer = null;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
if (timer == null)
{
timer = new System.Timers.Timer();
timer.Elapsed += new System.Timers.ElapsedEventHandler(ObjTimer_Elapsed);
timer.Interval = 10000;
timer.Start();
}
}
private void ObjTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
PopupNotifier pop = new PopupNotifier();
pop.TitleText = "Test";
pop.ContentText = "Hello World";
pop.Popup();
//MessageBox.Show(""); !!! here is problem !!!
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Here i am using Tulpep notification for create desktop notification. I have one start button in my form. When start button clicked, timer start to pop desktop notification. But it is shows notification only when i not comment on MessageBox.Show("");. and if i remove or comment MessageBox.Show(""); it is not showing notification. I debug in both case, there is no error or exception in both case.
Is any one have idea why is this happening?
I am using .net framework 4.5.2,visual studio 2015, windows 8.
PopupNotifier needs to be called out of the UI-Thread. Since the handler of your timer runs in a different thread you need to invoke your form to solve the problem.
this.Invoke((MethodInvoker)delegate
{
PopupNotifier pop = new PopupNotifier();
pop.TitleText = "Test";
pop.ContentText = "Hello World";
pop.Popup();
});
Create a static class ControlExtensions:
public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
{
if (control.InvokeRequired)
{
control.BeginInvoke(action);
}
else
{
action.Invoke();
}
}
After that go again at the line where you call the Tulpep.NotificationWindow. and assign the main form to a variable like this:
//popup var is the notificationwindow inside form1
Form1 ff = (Form1)Application.OpenForms["Form1"];
ff.InvokeOnUiThreadIfRequired(() =>
{
ff.popup.Image = Properties.Resources.info_icon; //icon from resources
ff.popup.TitleText = title; // some text here
ff.popup.ContentText = contentMessage; // some text here
ff.popup.Popup();
});
Now you invoke the main form and show the NotificationWindow
I had the same problem but with Task.Run(), I tried calling Popup inside SomeMethod with no luck. Solved using Invoke. Hope this helps someone.
Task.Run(() => {
SomeMethod(); //Some method that executes in background
//Popup when SomeMethod is finished using Fruchtzwerg answer
this.Invoke((MethodInvoker)delegate
{
PopupNotifier pop = new PopupNotifier();
pop.TitleText = "Test";
pop.ContentText = "Hello World";
pop.Popup();
});
});
This program is used to display the data and store the data into a txt file using the input from the pic18f4550.
when the GUI received the input data is '1 ', the GUI should display the data and store the data into a txt file. data can be saved, but the data are keep repeating itself without stopping if the input is still in a state of '1 '.
how should i do, if i want to store the data just once even the input still '1'?
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Monitoring_System
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
// Create the USB reference device object (passing VID and PID)
theUsbDemoDevice = new usbDemoDevice(0x04D8, 0x003F);
// Add a listener for usb events
theUsbDemoDevice.usbEvent += new usbDemoDevice.usbEventsHandler(usbEvent_receiver);
// Perform an initial search for the target device
theUsbDemoDevice.findTargetDevice();
}
// Create an instance of the USB reference device
private usbDemoDevice theUsbDemoDevice;
// Listener for USB events
private void usbEvent_receiver(object o, EventArgs e)
{
// Check the status of the USB device and update the form accordingly
if (theUsbDemoDevice.isDeviceAttached)
{
// Device is currently attached
// Update the status label
usb_status.Text = "Status : USB Device Connected";
}
else
{
// Device is currently unattached
// Update the status label
usb_status.Text = "Status : USB Device Unplugged";
cr1v.Visible = false;
cr1i.Visible = false;
cr2v.Visible = false;
cr2i.Visible = false;
cr3v.Visible = false;
cr3i.Visible = false;
tr1v.Visible = false;
tr1i.Visible = false;
tr2v.Visible = false;
tr2i.Visible = false;
tr3v.Visible = false;
tr3i.Visible = false;
}
}
private void button_exit_Click(object sender, EventArgs e)
{
this.Hide();
Form4 f2 = new Form4();
f2.ShowDialog();
}
private void timer1_Tick_1(object sender, EventArgs e)
{
if(theUsbDemoDevice.isDeviceAttached)
{
// Read the push button state
bool sw1 = theUsbDemoDevice.sw1();
if (sw1 == true)
{
cr1i.Visible = false;
cr1v.Visible = true;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"D:\Desktop\log data.txt", true))
{
file.WriteLine("Class Room 1 in use");
file.Close();
}
}
else if (sw1 == false)
{
cr1i.Visible = true;
cr1v.Visible = false;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"D:\Desktop\log data.txt", true))
{
file.WriteLine("Class Room 1 vacant");
file.Close();
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
this.Hide();
Form5 f2 = new Form5();
f2.ShowDialog();
}
}
}
It looks like you are using a timer. Every tick your timer is writing to a file. You need to re-work your logic to either not include a timer. Or, disable it after a write, and re-enable it on another event.
Alright so basicly I have this simple application running in system tray that has one timer. Every tick it performs a check to see if a given directory and file exists, and based on the result it changes its icon.
The problem is every single timer tick the memory for the application raises ~100kb. I currently have it running for about 5 mins and it already uses 40MB of memory, which is unacceptable for such "micro" application.
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace Tray
{
public partial class Main : Form
{
string drive = "C:\\";
string file = "test.txt";
System.Drawing.Image imgRed = Image.FromFile("res\\icon-red.png");
System.Drawing.Image imgOrange = Image.FromFile("res\\icon-orange.png");
System.Drawing.Image imgGreen = Image.FromFile("res\\icon-green.png");
System.Drawing.Icon icoRed = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-red.ico");
System.Drawing.Icon icoOrange = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-orange.ico");
System.Drawing.Icon icoGreen = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-green.ico");
public Main()
{
InitializeComponent();
}
public static string ShowPrompt(string text, string caption)
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
return textBox.Text;
}
public void updateInfo(){
this.statusDrive.Text = "Drive [" + drive + "]";
this.statusFile.Text = "File [" + drive + file + "]";
}
public void exec(){
int status = 0;
this.trayIcon.Text = "[Drive - ";
if (Directory.Exists(drive)){
this.statusDrive.Text += " - OK";
this.statusDrive.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
} else{
this.statusDrive.Text += " - FAIL";
this.statusDrive.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
this.trayIcon.Text += "[File - ";
if (File.Exists(drive + file))
{
this.statusFile.Text += " - OK";
this.statusFile.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
}
else
{
this.statusFile.Text += " - FAIL";
this.statusFile.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
switch (status)
{
case 2:
this.Icon = icoGreen;
this.trayIcon.Icon = icoGreen;
this.status.Image = imgGreen;
break;
case 1:
this.Icon = icoOrange;
this.trayIcon.Icon = icoOrange;
this.status.Image = imgOrange;
break;
case 0:
default:
this.Icon = icoRed;
this.trayIcon.Icon = icoRed;
this.status.Image = imgRed;
break;
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
private void timer1_Tick(object sender, EventArgs e)
{
updateInfo();
exec();
}
private void chDrive_Click(object sender, EventArgs e)
{
this.drive = ShowPrompt("Enter drive path", "Change drive");
}
private void chFile_Click(object sender, EventArgs e)
{
this.file = ShowPrompt("Enter new file path:", "Change file");
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
I already tried to optimize the app by preloading the icons and images into variables and assigning those to the appropriate properties, however this didn't solve my problem.
Also, note that I managed to hide my main window by doing this (in Program.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Tray
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Main mForm = new Main();
Application.Run();
}
}
}
UPDATE
I just noticed that the memory usage climbs up to 50MB and drops to 20MB afterwards (and goes up again). Is this something I can possibly address or is it a windows "issue"?
I'm going to take a stab at it being the string concatenations happening once a second. Consider using a StringBuilder. 40MB is nothing though really.
RE: Your update. The Garbage Collector is reclaiming the memory as it sees fit.
You never appear to be disposing your form correctly in ShowPrompt, so I'd imagine this is your problem.
Because a form displayed as a dialog box is not closed, you must call the Dispose method of the form when the form is no longer needed by your application.
ShowDialog
Some points that could cut down on memory usage:
Try to prebuild all those strings you're building in exec(). It looks like they're all runtime constants, but you build them every tick instead of building them once when the application starts. If this isn't possible, use StringBuilder instead of +=.
Only change properties on controls (icon, trayText, etc) if there has been a change. I.E. if tray text is already "[Drive C:\ - OK]", don't set its value again to "[Drive C:\ - OK]" next tick.
Garbage Collector does all the work of memory management for you. Temporary rise in memory doesn't always mean that there is a memory leak. It may come down when the GC collects memory. In case you suspect that there are memory leaks you need to do memory profiling which is no easy job. You need to read into this article for steps that you can take to find out the problem in your code. Alternatively, there are multiple tools avaiable in the market to do this job for you. You can use Ants Profiler of Red Gate, memprofiler amongst others.
One thing you might consider is rather than using a timer why not use the FileSystemWatcher and attach to events:
var watcher = new FileSystemWatcher("somepath");
watcher.Deleted += (sender, eventArgs) => { };
watcher.Changed += (sender, eventArgs) => { };
watcher.Error += (sender, eventArgs) => { };
watcher.Renamed += (sender, eventArgs) => { };
I also agree that you should be disposing of the forms once you're done with them.