notifyicon not raising click event and contextmenustrip not showing - c#

I have a problem where the notifyicon is showing up fine, and displaying its bubble, but it does not raise its click event when clicked.
It should show its contextmenustrip, but if i add contextmenustrip.show(); into the code, it just shows the shadows of the menu but not the menu itself.
the function is part of a WPF application and is called via a named pipe from a WCF service application.
Code, in case you need it:
in the service app:
public partial class Service1 : ServiceBase
{
ChannelFactory<ILicenseWatchingServiceUIHost> pipeFactory;
ILicenseWatchingServiceUIHost LWSProxy;
public Service1()
{
InitializeComponent();
}
#region service states
protected override void OnStart(string[] args)
{
pipeFactory = new ChannelFactory<ILicenseWatchingServiceUIHost>(
new NetNamedPipeBinding(),
new EndpointAddress("net.pipe://localhost/LWSPipe"));
LWSProxy = pipeFactory.CreateChannel();
Run();
}
//...
private void Run()
{
//...
LWSProxy.Execute();
}
}
server creation in WPF app:
public partial class App : Application
{
ServiceHost host = new ServiceHost(typeof(LicenseWatchingServiceUserInterface), new Uri[] { new Uri("net.pipe://localhost") });
public App()
{
StartServer();
}
private void StartServer()
{
host.AddServiceEndpoint(typeof(ILicenseWatchingServiceUIHost), new NetNamedPipeBinding(), "LWSPipe");
host.Open();
BackgroundWorker worker = new BackgroundWorker();
System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher;
}
}
and finally:
public class LicenseWatchingServiceUserInterface : ILicenseWatchingServiceUIHost
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
void Execute(){
//...
contextmenustrip.show(); //does not work
}
//does not get raised
private void notifyIcon_Click(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
contextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
}
else if (e.Button == MouseButtons.Left)
{
Execute();
}
}
}
void Init()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LicenseWatchingServiceUserInterface));
this.notifyIcon = new System.Windows.Forms.NotifyIcon();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
//
// notifyIcon
//
this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.notifyIcon.ContextMenuStrip = this.contextMenuStrip;
this.notifyIcon.Icon = iconLoading;
this.notifyIcon.Visible = true;
//clickhandler is in fact wired up
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon_Click);
//
// contextMenuStrip
//
this.contextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.settingsToolStripMenuItem,
this.openLicenseManagerToolStripMenuItem,
this.closeToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(234, 128);
//
// contextmenustrip items...
//
}
//...
}

Figured it out:
The LWSProxy.Execute(); was creating an instance of the LicenseWatchingServiceUserInterface class in a background thread, wich was causing problems. The notifyicon has to be created in the main thread, otherwise the eventhandlers won't work. My solution is a helper class (just put it below the class App) :
public class LicenseWatchingServiceUICreator : ILicenseWatchingServiceUIHost
{
public void Execute(List<LicenseInfoContainerExpiring> elcs, List<LicenseInfoContainerUntrusted> ulcs)
{
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
LicenseWatchingServiceUserInterface LWSUI = new LicenseWatchingServiceUserInterface(elcs, ulcs);
}));
}
}
with minor tweaking, this classes execute method will get called through the pipe, and it will create an instance of my class in the main thread. Now my UI works as usual.

Related

Threading lock in WinForms

I have a class that generates images in a thread and invokes an event on every frame. A Form subscribes to this event and displays the image in a PictureBox using Invoke.
If the image generation process is allowed to finish, all is good. However, if the Form is closed while the thread is running, the Form tries to stop the thread but ends up in some sort of a deadlock.
When I try to use the threaded class in without a Form or in a Console app, start the process, wait for a second, then Cancel it, everything works fine.
The question is, something must be wrong with either the Form_Closing method of the Form or the Stop method of the threaded class.
I have kept the code to a minimum and it can be pasted into LinqPad, etc.
An auxiliary question: Should the Process method invoke the Stop method to clean up?
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
namespace VideoMask.WinFormsAppApp
{
internal static class Program
{
[STAThread]
private static void Main ()
{
Program.TestWithoutForm(); // Runs fine.
Program.TestWithForm(); // Deadlocks.
}
private static void TestWithForm ()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
private static void TestWithoutForm ()
{
new TestWithoutForm().Run();
}
}
public class TestWithoutForm
{
private VideoProcessor VideoProcessor = new VideoProcessor();
public TestWithoutForm ()
{
this.VideoProcessor.SourceFrameRead += this.VideoProcessor_SourceFrameRead;
}
public void Run ()
{
this.VideoProcessor.Start();
Thread.Sleep(1000);
this.VideoProcessor.Stop();
MessageBox.Show("Done");
}
private void VideoProcessor_SourceFrameRead (object sender, VideoProcessorEventArgs e)
{
var filename = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Sample.png");
e.Bitmap.Save(filename, ImageFormat.Png);
}
}
public class FormMain: Form
{
private PictureBox PictureBox = new PictureBox();
private VideoProcessor VideoProcessor = new VideoProcessor();
public FormMain ()
{
this.Controls.Add(this.PictureBox);
this.PictureBox.Dock = DockStyle.Fill;
this.Shown += this.FormMain_Shown;
this.FormClosing += this.FormMain_FormClosing;
this.WindowState = FormWindowState.Maximized;
}
private void FormMain_Shown (object sender, EventArgs e)
{
this.VideoProcessor.SourceFrameRead += this.VideoProcessor_SourceFrameRead;
this.VideoProcessor.Start();
}
private void FormMain_FormClosing (object sender, FormClosingEventArgs e)
{
this.VideoProcessor.Stop();
this.VideoProcessor.Dispose();
this.VideoProcessor = null;
}
private void VideoProcessor_SourceFrameRead (object sender, VideoProcessorEventArgs e)
{
this.Invoke
(
new Action
(
() =>
{
using (var bitmap = this.PictureBox.Image)
{
this.PictureBox.Image = new Bitmap(e.Bitmap);
}
}
)
);
}
}
public sealed class VideoProcessor: IDisposable
{
public event EventHandler<ErrorEventArgs> ConversionError = null;
public event EventHandler<VideoProcessorEventArgs> SourceFrameRead = null;
private Font Font = null;
private Bitmap Bitmap = null;
private Thread Thread = null;
private Graphics Graphics = null;
private readonly object SyncRoot = new object();
private CancellationTokenSource CancellationTokenSource = null;
public VideoProcessor ()
{
this.Bitmap = new Bitmap(800, 600, PixelFormat.Format32bppArgb);
this.Graphics = Graphics.FromImage(this.Bitmap);
this.Font = new Font(FontFamily.GenericSansSerif, 48, GraphicsUnit.Point);
}
public bool IsRunning { get; private set; }
public void Start ()
{
lock (this.SyncRoot)
{
if (this.IsRunning) { throw (new Exception("A video conversion process is already running.")); }
this.Stop();
this.CancellationTokenSource = new CancellationTokenSource();
this.Thread = new Thread(new ParameterizedThreadStart(this.Process));
this.Thread.Start(this.CancellationTokenSource);
}
}
public void Stop ()
{
lock (this.SyncRoot)
{
if (!this.IsRunning) { return; }
this.CancellationTokenSource?.Cancel();
this.Thread.Join();
this.Thread = null;
this.CancellationTokenSource?.Dispose();
this.CancellationTokenSource = null;
}
}
private void Process (object cancellationTokenSource)
{
var source = (CancellationTokenSource) cancellationTokenSource ?? throw (new ArgumentNullException(nameof(cancellationTokenSource)));
lock (this.SyncRoot) { if (this.IsRunning) { throw (new Exception("A conversion process is already running.")); } }
this.IsRunning = true;
for (var i = 1; i <= int.MaxValue; i++)
{
if (source.IsCancellationRequested) { break; }
this.Graphics.Clear(Color.White);
this.Graphics.DrawString(i.ToString(), this.Font, Brushes.Black, 10, 10);
this.SourceFrameRead?.Invoke(this, new VideoProcessorEventArgs(this.Bitmap));
Thread.Sleep(33);
}
this.IsRunning = false;
}
public void Dispose () => this.Stop();
}
public class VideoProcessorEventArgs: EventArgs
{
public Bitmap Bitmap { get; private set; }
public VideoProcessorEventArgs (Bitmap bitmap) { this.Bitmap = bitmap; }
}
}

pjsip c#, System.AccessViolationException on answering an incoming call on an separated thread

In the overrided void onIncomingCall I open a new Background thread which shows a new (Popup) Form.
I try to pickup or decline the Call in this Form but then I get an System.AccessViolationException.
it seems that the current call object is locked and cannot be accessed from another Form.
If I use the currentcall.answer(prm) in the onIncomingCall void then the call is established successfully (without another Form and thread).
public class myaccount : Account
{
public override void onIncomingCall(OnIncomingCallParam prm)
{
Call call = new Call(this, prm.callId);
CallOpParam param = new CallOpParam();
param.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
param.statusCode = pjsip_status_code.PJSIP_SC_OK;
pjsipfunctions.currentparam = param;
pjsipfunctions.currentcall = call;
var thread = new Thread(() =>
{
ShowPopup(call,prm.callId.ToString());
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
// Thread myCallingThread = new Thread(new ThreadStart(ShowPopup));
//myCallingThread.SetApartmentState(ApartmentState.STA);
//myCallingThread.IsBackground = true;
//myCallingThread.Start();
}
public void ShowPopup(Call myCall,string call_id)
{
IncommingCallPopup win = new IncommingCallPopup(ref myCall, call_id );
win.Show();
System.Windows.Threading.Dispatcher.Run();
}
}
#####################################
public IncommingCallPopup(ref Call info, string callid)
{
currentCall = info;
Callid = callid;
CurrentCall = currentCall;
Prm.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
InitializeComponent();
labelCallId.Content = callid;
}
private void rejectcall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_DECLINE;
CurrentCall.hangup(Prm);
}
private void transfercall(object sender, RoutedEventArgs e)
{
}
private void takecall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_OK;
try
{
CurrentCall.answer(Prm);
}
catch(Exception ex)
{
}
}
After crazy searching and trying some things i've figured it out.
Every Thread must registered in the Endpoint that you can hangup, pickup or transfer your call in another Class(Window).
All you need is to write this Method in a Public class and call this void everytime you call your void from another window ->
public void callpopup(String number) {
checkThread();
//answer, decline or something else
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void checkThread()
{
try
{
if (ep != null && !ep.libIsThreadRegistered())
ep.libRegisterThread(Thread.CurrentThread.Name);
}
catch (Exception e)
{
}
}

How to run in main thread from worker thread that start by Nancyfx? C#

I have a problem with using nancyfx in my winform application (I make a winform app and use a nancyfx inside the application) So i can use some API url to make change in the winform without additional server or services (because i attached the nancy in the winform apps)
Here is my Form1.cs
public partial class Form1 : Form
{
public Form1(bool test)
{
InitializeComponent();
textBox1.Text += "Apps Method "+ Environment.NewLine;
}
public bool startTestAPI()
{
textBox1.Text += "Api Worked" + Environment.NewLine);
}
private void button2_Click(object sender, EventArgs e)
{
HostingAPI s = new HostingAPI();
s.Start();
textBox1.Text += "Api Running" + Environment.NewLine);
}
}
public class ModuleCDM : NancyModule
{
public ModuleCDM()
{
try
{
Thread th2 = Thread.CurrentThread;
Get["/Start"] = parameters =>
{
Form1 form = new Form1(false);
Thread testthread = Form1.curthread;
bool res = form.startTestAPI();
if (res == true)
{
var feeds = new string[] { "Success" };
return Response.AsJson(feeds);
}
else
{
var feeds = new string[] { "Failed" };
return Response.AsJson(feeds);
}
};
}
}
}
and this is my HostingAPI.cs
public class HostingAPI
{
private NancyHost hostNancy;
private string hostUrl;
public void Start()
{
hostUrl = ConfigModule.ModuleAddress;
if (hostUrl == null) hostUrl = "http://localhost:5005";
hostNancy = new NancyHost(new Uri(hostUrl));
hostNancy.Start();
}
public void Stop()
{
hostNancy.Stop();
}
}
And it successfully run without error, but when i call api (localhost:5005/Start) the textbox in winform apps not add the text i wanted ("Api Worked"). I noticed it is because Nancyfx create another thread when there is API call, and i can use invoke/begininvoke because !invokerequired always comes with value false. So how can i access the main thread or maybe another solution to update the UI when i call the API.
Thanks
You have 2 issues in here.
You start host api service from Form1 instance then within Nancy Module you create a different Form1 instance which is invisible and you try to do access certain methods within that class
Cross thread issue as you rightfully guessed . You are trying to write from another thread context than the UI thread
Look at the code at below to achieve this. Bear in mind that you can create Singleton Form or find another way to access the instance of Form1
public class HostingAPI
{
private NancyHost hostNancy;
private string hostUrl;
public HostingAPI()
{
}
public void Start()
{
var hostConfig = new HostConfiguration
{
UrlReservations = new UrlReservations
{
CreateAutomatically = true
},
};
//hostUrl = ConfigModule.ModuleAddress;
if (hostUrl == null) hostUrl = "http://localhost:5005";
hostNancy = new NancyHost(hostConfig,new Uri(hostUrl));
hostNancy.Start();
}
public void Stop()
{
hostNancy.Stop();
}
}
public partial class Form1 : Form
{
delegate void SetTextCallback(string text);
public static Form1 Instance;
public Form1(bool test)
{
InitializeComponent();
textBox1.Text += "Apps Method " + Environment.NewLine;
Instance = this;
}
private void button1_Click(object sender, EventArgs e)
{
HostingAPI s = new HostingAPI();
s.Start();
textBox1.Text += "Api Running" + Environment.NewLine;
}
public void startTestAPI()
{
SetText("Api Worked" + Environment.NewLine);
}
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text += text;
}
}
}
public class ModuleCDM : NancyModule
{
public ModuleCDM()
{
try
{
Thread th2 = Thread.CurrentThread;
Get["/Start"] = parameters =>
{
var form1 = Form1.Instance;
form1.startTestAPI();
var feeds = new[] {"Success"};
return Response.AsJson(feeds);
};
}
catch
{
}
}
}

Handling events after receiving a MSMQ message (thread issue?)

I created two separate Windows Forms applications in C# that use MSMQ for communicating. Here's how it works, it looked simple enough though:
App1 sends a details request to App2.
App2 creates an event to open the window.
App2 opens a "details" window.
The only problem I have is that when received the message, the "details" window freezes after appearing.
As I handle MSMQ messages handling in an object that uses threads, I suspect the problem comes from there... But I have no experience in handling MSMQ messages or specific events handling between parts of an application.
Here's part of the code I use for App2:
/*Class declared in the Core namespace*/
public class TaskMessageQueueHandler
{
public TaskMessageQueueHandler()
{
this.Start();
}
private Thread m_thread;
private ManualResetEvent m_signal;
public event System.EventHandler messageReceived;
public void Start()
{
m_signal = new ManualResetEvent(false);
m_thread = new Thread(MSMQReceiveLoop);
m_thread.Start();
}
public void Stop()
{
m_signal.Set();
}
protected virtual void SendEvent(object sender, EventArgs e)
{
if (messageReceived != null)
messageReceived(this.message, e);
}
public string message;
private void MSMQReceiveLoop()
{
bool running = true;
MessageQueue queue = new MessageQueue(#".\Private$\queue1");
while (running)
{
try
{
var message = queue.Receive();
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
this.message = message.Body.ToString();
string m = this.message;
SendEvent(m, System.EventArgs.Empty);
if (m_signal.WaitOne(10))
{
running = false;
}
}
catch
{
Console.WriteLine("ERROR");
running = false;
}
}
}
}
/*Main process, in the Program namespace*/
[...]
Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();
EventListener el = new EventListener();
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
[...]
/* Class in the Program namespace */
class EventListener
{
public void ShowDetails(object sender, EventArgs e)
{
int numero = int.Parse(sender as string);
Details details = new Details(numero);
details.Show();
}
}
Where did I go wrong? Where did I go right?
Thanks a lot,
Stephane.P
EDIT: if the MSMQ handler is stopped with Stop() anywhere around the event sending, the details window appears then disappears right away...
EDIT2: After the workaround given by Slugart, I managed to make this work:
class EventListener
{
Main control;
public EventListener(Main main)
{
control = main;
}
public void ShowDetails(object sender, EventArgs e)
{
int numero = int.Parse(sender as string);
control.Invoke((Action)(() => ShowDetails(numero)));
}
private void ShowDetails(int numero)
{
Details details = new Details(numero);
details.Show();
}
}
Which is used like:
Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();
EventListener el = new EventListener(this);
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
You're creating and displaying a form Details on a thread other than the main GUI thread and not an STA thread at that.
Your EventListener should have a reference to a running form (your main form perhaps) and then call form.Invoke() on it.
class EventListener
{
Control control; // A valid running winforms control/form created on an STA thread.
public void ShowDetails(object sender, string message)
{
int numero = int.Parse(message);
control.Invoke(() => ShowDetails(numero))
}
private void ShowDetails(int numero)
{
Details details = new Details(numero);
details.Show();
}
}
Also sending your event data as the sender is not really following the Event pattern that has been put in front of you. You want to use the EventArgs parameter for this, use the EventHandler delegate (EventHandler in your case).

Mainform.cs read routine more than twice

real problem:
Mainform read routine more than twice. and all components and objects inside of MainForm empty
Example:
button first run of excellent
add my code:
namespace CheckNet
{
/// <summary>
/// Description of MainForm.
/// </summary>
delegate void Function();
public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
Btn_Inicio.Click += new EventHandler (Btn_InicioClick);
// VerificationForm += new EventHandler (VerificationForm);
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
private DPFP.Template Template;
private DPFP.Template myTemplate;
//
void Btn_InicioClick(object sender, EventArgs e)
{
// call rutine ejecutar boton primera vez
//
if (this.panelContenedor.Controls.Count > 0)
this.panelContenedor.Controls.RemoveAt(0);
VerificationForm hijos = new VerificationForm();
hijos.TopLevel = false;
hijos.FormBorderStyle = FormBorderStyle.None;
hijos.Dock = DockStyle.Fill;
this.panelContenedor.Controls.Add(hijos);
this.panelContenedor.Tag = hijos;
hijos.Show();
}
void Button7Click(object sender, EventArgs e)
{
AddFormInPanel(new Hijo2());
}
private void AddFormInPanel(object formHijo)
{
if (this.panelContenedor.Controls.Count > 0)
this.panelContenedor.Controls.RemoveAt(0);
Form fh = formHijo as Form;
fh.TopLevel = false;
fh.FormBorderStyle = FormBorderStyle.None;
fh.Dock = DockStyle.Fill;
this.panelContenedor.Controls.Add(fh);
this.panelContenedor.Tag = fh;
fh.Show();
}
void Close_bottonClick(object sender, EventArgs e)
{
Close();
}
}
}
////////// call Form VerificationForm
namespace CheckNet
{
/* NOTE: This form is inherited from the CaptureForm,
so the VisualStudio Form Designer may not load it properly
(at least until you build the project).
If you want to make changes in the form layout - do it in the base CaptureForm.
All changes in the CaptureForm will be reflected in all derived forms
(i.e. in the EnrollmentForm and in the VerificationForm)
*/
public class VerificationForm : CaptureForm
{
public void Verify(DPFP.Template template)
{
Template = template;
ShowDialog();
}
protected override void Init()
{
base.Init();
base.Text = "Fingerprint Verification ";
Verificator = new DPFP.Verification.Verification(); // Create a fingerprint template verificator
UpdateStatus(0);
}
protected override void Process(DPFP.Sample Sample)
{
base.Process(Sample);
// Process the sample and create a feature set for the enrollment purpose.
DPFP.FeatureSet features = ExtractFeatures(Sample, DPFP.Processing.DataPurpose.Verification);
// Check quality of the sample and start verification if it's good
// TODO: move to a separate task
template= TomarHuellaBd();
Template=template;
if (features != null)
{
// Compare the feature set with our template
DPFP.Verification.Verification.Result result = new DPFP.Verification.Verification.Result();
Verificator.Verify(features, Template, ref result);
UpdateStatus(result.FARAchieved);
if (result.Verified)
{
MakeReport2(" ");
}
else
MakeReport("Huella no Identificado.");
}
}
private void UpdateStatus(int FAR)
{
// Show "False accept rate" value
SetStatus(String.Format("False Accept Rate (FAR) = {0}", FAR));
}
private DPFP.Template TomarHuellaBd()
{
// Verifica la Huella desde una base de Datos
bool Bandera=true;
try { // Validar Numero
int idEmpleado =int.Parse(Global_ip.Globalip.ToString());
} catch {
MessageBox.Show("Error Numero de Empleado ", Global_ip.Globalip.ToString());
Bandera=false;
//
return null;
//
}
try
{
int NumEmpleado=int.Parse(Global_ip.Globalip.ToString());
enlacedb db = new enlacedb();
FbConnection conexion2 = new FbConnection(db.connectionString);
conexion2.Open();
FbCommand Frda = new FbCommand("SELECT * FROM REGHUMAN WHERE ID_EMPLEADO=#ID_EMPLEADO", conexion2);
Frda.Parameters.Add("#ID_EMPLEADO",SqlDbType.VarChar).Value = NumEmpleado;
FbDataReader leerF = Frda.ExecuteReader();
bool fseek= leerF.Read();
if (fseek) {
Global_Nombre.GlobalNombre= leerF.GetValue(4).ToString();
Byte[] imageF = new Byte[Convert.ToInt32 ((leerF.GetBytes(2, 0,null, 0, Int32.MaxValue)))];
leerF.GetBytes(2, 0, imageF, 0, imageF.Length);
MemoryStream memfpt = new MemoryStream(imageF);
DPFP.Template template = new DPFP.Template(memfpt);
return template;
}
else
{
return null;
}
}
catch (Exception err2) {
MessageBox.Show(err2.ToString());
}
return null;
}
private DPFP.Template Template;
private DPFP.Template template;
private DPFP.Verification.Verification Verificator;
}
}
if the user requests running second time the same button
VerificationForm routines and residents are CaptureForm Digital Persona device and can not read the fingerprint
how to empty or reset the procedure or routine (MainForm, VerificationForm and CaptureForm)
Thank.
The Solution is:
modify the program.cs
private static void Main (string [] args)
{
Application.EnableVisualStyles ();
Application.SetCompatibleTextRenderingDefault (false);
Fm1 MainForm = new MainForm ();
Application.Run (fm1);
if (fm1.ToRestart)
Application.Restart ();
}
start
ToRestart public bool = false;
void Btn_InicioClick (object sender, EventArgs e)
{
ToRestart = true;
this.Close ();
}
to reset the fingerprint reader and winform controls
Thank

Categories

Resources