Show "Spinning Wheel” over my Windows Forms application [duplicate] - c#

This question already has answers here:
How can I make the cursor turn to the wait cursor?
(11 answers)
Closed 9 years ago.
I have a Windows Forms application, in my application i load files into a list box and sometimes this could take few seconds so in this time i want to show "Spinning Wheel” and i found this Gif: http://www.ajaxload.info/
is it possible to add it to my application while my application is busy over the controllers ?

Yes
Found some old code from a project where I had it.
Edited out a few things, you should be able to get it working easily.
Invoke it:
GuiCursor.WaitCursor(() => { yourclass.DoSomething(); });
The class
internal class GuiCursor
{
private static GuiCursor instance = new GuiCursor();
private GuiCursor() { }
static GuiCursor() { }
internal static void WaitCursor(MethodInvoker oper)
{
if (Form.ActiveForm != null && !Thread.CurrentThread.IsBackground)
{
Form myform = Form.ActiveForm;
myform.Cursor = Cursors.WaitCursor;
try
{
oper();
}
finally
{
myform.Cursor = Cursors.Default;
}
}
else
{
oper();
}
}
internal static void ToggleWaitCursor(Form form, bool wait)
{
if (form != null)
{
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(() => { form.Cursor = wait? Cursors.WaitCursor : Cursors.Default; }));
}
else
{
form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default;
}
}
}
internal static void Run(Form form)
{
try
{
Application.Run(form);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
As by request, an example. Create a new winform project to test it out.
As default you get a Form1. Add a button to it, double click on it so you get a autogenerated method to it.
Replace the class Form1 with this.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
GuiCursor.WaitCursor(() => { DoSomething(); });
}
private void DoSomething()
{
Thread.Sleep(3000);
}
}
internal class GuiCursor
{
private static GuiCursor instance = new GuiCursor();
private GuiCursor() { }
static GuiCursor() { }
internal static void WaitCursor(MethodInvoker oper)
{
if (Form.ActiveForm != null && !Thread.CurrentThread.IsBackground)
{
Form myform = Form.ActiveForm;
myform.Cursor = Cursors.WaitCursor;
try
{
oper();
}
finally
{
myform.Cursor = Cursors.Default;
}
}
else
{
oper();
}
}
internal static void ToggleWaitCursor(Form form, bool wait)
{
if (form != null)
{
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(() => { form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default; }));
}
else
{
form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default;
}
}
}
internal static void Run(Form form)
{
try
{
Application.Run(form);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}

A little trick to do this could be to use a PictureBox with image in it. On button click, make the PictureBox visible and hide it again after click operation is completed.

Related

How can I activate the previously opened microsoft access instance of an app using C#?

I'm using this code to open an access database :
public partial class Start_Baseet : System.Windows.Forms.Form
{
string MyFile = Environment.CurrentDirectory + "\\Baseet.accde";
Microsoft.Office.Interop.Access.Application AccApp = new Microsoft.Office.Interop.Access.Application();
public Start_Baseet()
{
InitializeComponent();
}
public void OpenDb()
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
private void Start_Basset_Load(object sender, EventArgs e)
{
try
{
OpenDb();
}
catch
{
AccApp.Quit();
MessageBox.Show("Something is missing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
this.Close();
System.Windows.Forms.Application.Exit();
System.Windows.Forms.Application.ExitThread();
// Process.GetCurrentProcess().CloseMainWindow();
}
The problem is the MSACCESS process is piling up in the running processes so I tried this :
//var prc = Process.GetProcessesByName("MSACCESS.EXE*32");
var prc = Process.GetProcessesByName("Microsoft Access");
if (prc.Length > 0)
{
MessageBox.Show("Access Found");
SetForegroundWindow(prc[0].MainWindowHandle);
}
else
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
But still with every time I use the code another MSACCESS process starts.
How can I fix this ?
Other point if I ran my app second time it will open a new instance of the same database can I activate the database if it is opened otherwise open a new instance of it ?
Thanks
Try this. This should catch users closing out Access as well through error catching. I'm sure it can be improved on but, I don't get a bunch of MSAccess.exe in the background from this code I wrote a while ago.
public partial class Form1 : Form
{
Microsoft.Office.Interop.Access.Application accApp = new Microsoft.Office.Interop.Access.Application();
private bool isFormClosed = false;
public Form1()
{
InitializeComponent();
OpenMicrosoftAccessFile(#"FileName");
Thread t = new Thread(new ThreadStart(CheckIfMSAccessExeIsRunning));
t.Start();
}
/// <summary>
/// The User Closed Out Access Cleanup.
/// </summary>
public void CheckIfMSAccessExeIsRunning()
{
int secondsToWait = 5*1000;
while(!isFormClosed)
{
if (accApp != null &&
accApp.Visible == false)
CloseMicrosoftAccessFile();
Thread.Sleep(secondsToWait);
}
CloseMicrosoftAccessFile();
}
private bool OpenMicrosoftAccessFile(string accessFileName)
{
try
{
if (accApp != null &&
!accApp.Visible)
{
CloseMicrosoftAccessFile();
}
if (accApp == null)
{
accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(accessFileName);
accApp.Visible = true;
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
CloseMicrosoftAccessFile();
return false;
}
}
private void CloseMicrosoftAccessFile()
{
try
{
if (accApp != null)
{
accApp.CloseCurrentDatabase();
accApp.Quit();
}
}
catch (Exception ex)
{
//Good chance there never was an Access exe.
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(accApp);
accApp = null;
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
isFormClosed = true;
}
}
Also, if you still have processes running the Debugger or Visual Studio is probably holding onto it still. It would be good to test this from the release exe. If OpenMicrosoftAccessFile returns false you can try opening it up again but, this way ignores the error it caught.

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
{
}
}
}

Closing a WPF Application through ActiveX - Does not close properly

I have a WPF Project "ActiveX" that is registered for COM Visibility.It has a class "ActiveX".I am trying to create an object of another WPF Project's "MainApplication" MainWindow
The ActiveX class has two methods 1)Initialize 2)Close
1)Initialize API -- initializes and launches the mainwindow of the "MainApplication"
2)Close API -- Tries to close the instance created by the Initialize API
The problem is:
When the Close API is called the application is not closed completely. That is the Window is getting closed,Yet the thread is running in the background.
Could anyone suggest the proper exit of the Application called as ActiveX
using MainApplication;
//This interface is registered for COM
public interface IActiveX
{
[DispId(1)]
bool Initialize();
[DispId(2)]
bool Close();
}
//This class is registered for COM
public class ActiveX: IActiveX
{
MainWindow mainwindow;
Thread thread;
[STAThread]
public bool Initialize()
{
try
{
ThreadStart exeFunc = new ThreadStart(() =>
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
try
{
mainwindow = new MainWindow();
mainwindow.OpenWindow(); //OpenWindow() is the API of the MainApplication
}
catch()
{}
}));
});
thread = new Thread(exeFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
System.Threading.Thread.Sleep(5000);
return true;
}
catch (Exception e)
{
return false;
}
}
public bool Close()
{
try
{
//Application.Current.Shutdown();
//Environment.Exit(0);
success = form.CloseWindow(); //CloseWindow() is the API of the MainApplication
Thread.Sleep(2000);
//thread.Join(15000);
//thread.Abort();
//thread = null;
//mainwindow = null;
GC.Collect();
Thread.Sleep(5000);
return success;
}
catch (Exception exp)
{
return false;
}
}
MainApplication APIs:
public bool OpenWindow()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
try
{
this.ShowDialog();
}
catch()
{}
}));
return true;
}
public bool CloseWindow()
{
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
try
{
this.Close();
Application.Current.Shutdown();
}
catch
{}
}));
return true;
}

C# Close WPF Form from background Thread

I'm looking for a way to close a form from a background thread.
The scenario:
it's a chat application with a thread in background to manage the tcp client
now i want to close the first form from this thread
App.xaml.cs
public List<Window> dialogs = new List<Window>();
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Login loginDialog = new Login();
GUI.MainWindow mainDialog = new GUI.MainWindow();
dialogs.Add(loginDialog);
dialogs.Add(mainDialog);
client = new Klassen.TClient(dialogs);
if (loginDialog.ShowDialog() != true)
return;
}
the TClient class
public class TClient
{
public TSocket socket;
public TClient(List<Window> dialogs)
{
socket = new TSocket(dialogs);
}
}
the TSocket class, with the background thread
public class TSocket
{
/* Variables */
List<Window> dialogs;
public TSocket(List<Window> dialogs)
{
this.dialogs = dialogs;
clientThread = new Thread(connectionWorker);
clientThread.Start();
}
public bool connect()
{
/* Connect */
}
void connectionWorker()
{
connect();
while (isConnected)
{
/* if statment */
Login loginDialog = (Login)dialogs[0];
//dialogs[1].Close();
}
}
}
i already tried to work with a delagate and invoke , but it didn't worked properly
Windows programming allows only working with main UI thead for UI operations.
static class UiUtils
{
static UiUtils()
{
Dispatcher = Application.Current == null
? null
: Application.Current.Dispatcher;
}
public static Dispatcher Dispatcher { get; private set; }
public static void InvokeMainThread(this Action action)
{
try
{
if (Dispatcher != null && !Dispatcher.CheckAccess())
Dispatcher.Invoke(action);
else
action();
}
catch(Exception ex)
{
Debug.WriteLine("Error invoking main thread: {0}", ex);
}
}
}
And in your code you should call from any thread:
UiUtils.InvokeMainThread(()=>{loginDialog.Close();});`

How to make a SplashScreen in C# WindowsFormsApplication [duplicate]

This question already has answers here:
How to build splash screen in windows forms application?
(13 answers)
Closed 9 years ago.
I was wondering how to make a SplashScreen in C#. I looked around StackOverflow but found nothing useful, can you help me please? I already have 1 form filled with stuff, I just need some simple instructions on how to:
Make a new form appear before my main form
Make the SplashScreen disappear and the main form appear after a few seconds (maybe three)
I don't need an animated splashscreen.
Thanks in advance!
Just ask if you need any code samples from me :)
Here is an example of a splashscreen - I have used in one of my projects - that uses multithreading:
namespace WindowsForm1
{
public enum SplashTypeOfMessage
{ Success,
Warning,
Error
}
public partial class SplashForm : Form
{
static SplashForm _splashForm = null;
static Thread _splashThread = null;
public static object locker = new object();
public static bool WaitPlease = true;
private SplashForm()
{
InitializeComponent();
lblLoading.Text = "Please wait Loading";
}
public static void ShowSplashScreen()
{
if (_splashForm != null)
return;
_splashThread = new Thread(new ThreadStart(SplashForm.ShowSplash));
_splashThread.IsBackground = true;
_splashThread.SetApartmentState(ApartmentState.STA) ;
_splashThread.Start();
}
public static void ShowSplash()
{
if (_splashForm==null)
{
_splashForm = new SplashForm();
_splashForm.blueLoaderBar1.StartAnimation();
}
_splashForm.TopMost = true;
_splashForm.Show();
lock (SplashForm.locker)
{
WaitPlease = false;
}
Application.Run(_splashForm);
}
delegate void CloseSplashHandler(SplashTypeOfMessage typeOfMessage, string message,bool itWasRinvoked);
public static void CloseSplash(SplashTypeOfMessage typeOfMessage,string message,bool itWasrinvoked)
{
CloseSplashHandler closeSpalshHandler = new CloseSplashHandler(CloseSplash);
bool launched=false;
while (!launched && !itWasrinvoked)
{
lock (SplashForm.locker)
{
if (!SplashForm.WaitPlease)
{
launched = true;
}
}
}
if (_splashForm!=null && _splashThread!=null )
{
if (_splashForm.InvokeRequired)
{
_splashForm.Invoke(closeSpalshHandler,new object[] {typeOfMessage,message,true});
}
else
{
switch (typeOfMessage)
{
case SplashTypeOfMessage.Warning:
break;
case SplashTypeOfMessage.Error:
MessageBox.Show("Error");
break;
default:
break;
}
_splashForm.Close();
_splashThread = null;
}
}
}
}
}
Here is how you can call it:
SplashForm.ShowSplashScreen();
This is how you can close the splash screen:
SplashForm.CloseSplash(typeOfMessage ,string.Empty,false);

Categories

Resources