Windows Form - High CPU usage - c#

newbie here, my form is monitoring Caps Lock status but is using around 50% of CPU, I think this is related to Application.Idle += Application_Idle and Application.Idle -= Application_Idle. Once I've removed those my form is not monitoring Caps Lock state, any suggestions?
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;
namespace CapsLockChecker
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Application.Idle += Application_Idle;
}
private void Form1_Load(object sender, EventArgs e)
{
}
void Application_Idle(object sender, EventArgs e)
{
if (Control.IsKeyLocked(Keys.CapsLock))
{
label1.Text = "CapsLock is On";
pictureBox1.ImageLocation = "C:\\Users\\user\\source\\repos\\CapsLockChecker\\CapsLockChecker\\if_Circle_Green_34211.png";
}
else
{
label1.Text = "CapsLock if Off";
pictureBox1.ImageLocation = "C:\\Users\\user\\source\\repos\\CapsLockChecker\\CapsLockChecker\\if_Circle_Red_34214.png";
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
Application.Idle -= Application_Idle;
base.OnFormClosed(e);
}
}
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.KeyDown += CapsLockMonitor;
this.KeyPreview = true;
}
private void CapsLockMonitor(object sender, KeyEventArgs e)
{
if (Control.IsKeyLocked(Keys.CapsLock))
{
this.label1.Text = "Caps lock enabled!";
}
else
{
this.label1.Text = "Caps lock disabled!";
}
}
}
This appears to not chew up all my CPU, I subscribe to the KeyDown event with my custom delegate.

Honestly, keeping the CapsLock status constantly monitored, even when the application is idle, looks like an overkill to me. I mean, I don't doubt it's a nice feature, but I don't know if it's worth the effort for implementing it.
If your application has to warn the user whenever he is typing something while his CapsLock is turned on, the best (and simpler) approach would be showing a tooltip or a little warning box somewhere as soon as the user focuses a Control that allows text editing. Even if the code is based on WPF framework, you have an excellent example of what I'm talking about here.
In order to perform what you are looking for, you need to set up a very complex system based on Global Keyboard Hook. Following this link you can find a very nice and detailed article ("Processing Global Mouse and Keyboard Hooks in C#") describing how to accomplish this task. The link also contains a demo code written in C# that you can deploy and try.
A little excerpt:
This class allows you to tap keyboard and mouse and/or to detect their
activity even when an application runs in the background or does not
have any user interface at all. This class raises common .NET events
with KeyEventArgs and MouseEventArgs, so you can easily retrieve any
information you need.

Related

How do I start C# program without the window being active?

I'm trying to create a C# program, but I don't want the window to be active when I open it. I'd like it to open in the background, and the window to show up on top of my other programs, except I want my active window to stay the same. It's because I'm using full screen programs, and I don't want my little popup to take my out of the full screen mode.
Program Use (might help in understanding what I need): I'm creating a set of macros that turn a spare mouse into a media controller. The scroll wheel controls volume, left button controls play/pause, etc. I use Spotify for music, and I want to be able to change the volume of Spotify independently from my computer's global volume. I already have this figured out using code here. I want a popup to display telling me that when I use the scroll wheel, I'm changing the volume of Spotify opposed to global volume. I want to be able to activate the macro, display the popup, change the volume as I wish, and then deactivate the macro without exiting my full screen applications. Hopefully this helps, thank you!
Program Use Edit: Here's just an explanation video, should be easier than trying to explain. To clarify, I want the program to not change activated window when it starts and to always be top most, without me having to activate it first. Thank you!!! https://streamable.com/2pewz
I'm using a program called QuickMacros to open the popup and I've tried a few different settings in there but haven't had any luck. I don't have any experience with C#, so I haven't tried anything inside C#.
My code is unrelated to the issue, but here it is just in case. All this does is give me the ability to move the popup.
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;
namespace SpotifyPopup
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Left += e.X - lastPoint.X;
this.Top += e.Y - lastPoint.Y;
}
}
Point lastPoint;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
lastPoint = new Point(e.X, e.Y);
}
private void label1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Left += e.X - lastPoint2.X;
this.Top += e.Y - lastPoint2.Y;
}
}
Point lastPoint2;
private void label1_MouseDown(object sender, MouseEventArgs e)
{
lastPoint2 = new Point(e.X, e.Y);
}
}
}
Thank you for your help!
Your question is a little bit unclear but if I am right what you want is to start your application in minimized state, to do that simply use code below in your form constructor
this.WindowState = FormWindowState.Minimized;
And when your event is fired and you want your app to be on top just use
this.TopMost = true;
this.WindowState = FormWindowState.Normal;
and for proper positioning of your form you can use this answer
Edit
Ok, now your needs are more clear, this a demo of what i think you want, in this example the form starts minimized and comes to top on mouse wheel, and then goes to background when idle, u can add more events to code and adapt it for your needs,
I used global hooks for this demo thanks to this link, so dont forget to add the proper nuget package based on the provided link.
here is the code:
using Gma.System.MouseKeyHook;
using System;
using System.Drawing;
using System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form
{
private Timer timer;
private IKeyboardMouseEvents m_GlobalHook;
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
Subscribe();
timer = new Timer();
timer.Interval = 1000;
timer.Tick += Timer_Tick;
// Set up how the form should be displayed.
ClientSize = new System.Drawing.Size(292, 266);
Text = "Notify Icon Example";
WindowState = FormWindowState.Minimized;
Rectangle workingArea = Screen.GetWorkingArea(this);
Location = new Point(workingArea.Right - Size.Width - 100,
workingArea.Bottom - Size.Height - 100);
}
private void Timer_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
TopMost = false;
}
public void Subscribe()
{
// Note: for the application hook, use the Hook.AppEvents() instead
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.MouseWheel += M_GlobalHook_MouseWheel;
}
private void M_GlobalHook_MouseWheel(object sender, MouseEventArgs e)
{
WindowState = FormWindowState.Normal;
TopMost = true;
timer.Stop();
timer.Start();
}
public void Unsubscribe()
{
m_GlobalHook.MouseDownExt -= M_GlobalHook_MouseWheel;
//It is recommened to dispose it
m_GlobalHook.Dispose();
}
}
Have a look here: Bring a window to the front in WPF
This thread discusses the general mechanism of presenting, activating and showing windows with WPF.

Stop a video playing upon closing a form

I have created a form that will play a video upon loading. However I cannot figure out how to get the video to stop playing when the user exits the form. I have tried some other solutions that people have used but they don't seem to work.
When I say the video doesn't stop playing I mean that the audio from the video can still be heard even after the form containing the video has been closed.
Any suggestions?
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;
namespace RRAS
{
public partial class frmVideoTutorial : Form
{
formRRAS _main;
public frmVideoTutorial(formRRAS main)
{
InitializeComponent();
_main = main;
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void frmVideoTutorial_Load(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = #"F:\Group Project\RRAS\RRAS\RRAS\Tutorial.mp4";
}
private void frm_close(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
axWindowsMediaPlayer1.close();
}
else
{
e.Cancel = true;
}
}
}
}
You can go to the form properties and go to the events. Click on FormClosed event. From there just add the code to make the player stop, upon form exit.
I was having a similar issue, and that's what I done to fix it. I had asked the same question, except it was for bringing another form up.
This should do the trick. Be sure to do it on each form that has a video. That you want stopped upon exiting.
Use the .Stop();

button in c# not firing

I am writing a simple code it has 3 buttons 2 that will need to open up other forms and one to close the program. When i start the program the exit button will not work even though i have it coded the same as any other time i have wrote a program.
When i press any of the buttons nothing happens. Im not 100% sure how to use the buttons to open another form but i know the exit button should work as is.
Here is the 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;
namespace _3343_ParksJ_Lab02
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void workerButton_Click(object sender, EventArgs e)
{
WorkerForm workersForum = new WorkerForm();
}
private void suppervisorButton_Click(object sender, EventArgs e)
{
SupervisorForm workersForum = new SupervisorForm();
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
You have to subscribe your buttons' click events to the event methods before they'll fire correctly.
You can check the Designer.cs file to see if this has already been done, though I'm guessing it hasn't. You'll be looking for something like this:
this.workerButton.Click += new System.EventHandler(this.workerButton_Click);
One way to do so is directly in the constructor:
public MainForm()
{
InitializeComponent();
workerButton.Click += workerButton_Click;
suppervisorButton.Click += suppervisorButton_Click;
exitButton.Click += exitButton_Click;
}
Normally, I'd do this through the designer. Select each Button in turn, then open the properties panel and double-click on the event you wish to subscribe to, which will create the corresponding event method in the code-behind for you.
Look at .Designer.cs file and make sure your button is adding the correct delegate method. In your case it should exitButton_Click.
Sometimes when you change names of a button VS designer does not make the name change correctly in the .Designer file. Very rare but it happens.

How can I make a menu for notifyicon?

So.. i've googled around and everywhere i've seen different ways of creating this..
But so far, i haven't managed to make a single working menu.
So i wanted to ask, how does one create a notifyIcon menu?.. (prefered explained in details, as i'm rather new to this)
which way would be best and which should i use.. (so far people seemed to like contextmenu overally, but all i can find is contextmenustrip, not sure if it's the same.)
Currently i got a form, set to visible = false, windowstate minimized, showintaskbar = false.
that's about all it is for now. i wanted to have the menu before going wider.
Thank you for your time and effort for this (not sure if it's formulated properly)
EDIT: i've seemed to manage to make a menu, but how would i make it "appear" on my notify icon, it's a ContextMenu o_o
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;
namespace TrayTest.events
{
public partial class TrayMenu : Form
{
public TrayMenu()
{
InitializeComponent();
TrayMenuContext();
}
private void TrayMenuContext()
{
this.notify_icon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
this.notify_icon.ContextMenuStrip.Items.Add("Test1", null, this.MenuTest1_Click);
this.notify_icon.ContextMenuStrip.Items.Add("Test2", null, this.MenuTest2_Click);
this.notify_icon.ContextMenuStrip.Items.Add("Exit", null, this.MenuExit_Click);
}
void MenuTest1_Click(object sender, EventArgs e)
{
Application.Exit();
}
void MenuTest2_Click(object sender, EventArgs e)
{
Application.Exit();
}
void MenuExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
This worked fine for me. So i'll just leave it here, for other to take a peak at it.. (this is my Form1, just made 1 with a different name, and it's inside a folder named events (kinda why it has that .events))
"EDIT: i've seemed to manage to make a menu, but how would i make it "appear" on my notify icon, it's a ContextMenu o_o"
I believe you can only assign a ContextMenuStrip to the NotifyIcon using the IDE. For a ContextMenu, you'd have to wire it up via code. Double click your Form to get the Load() event, and wire it up in there:
private void Form1_Load(object sender, EventArgs e)
{
notifyIcon1.ContextMenu = contextMenu1;
}
notifyIcon1->ContextMenu = gcnew System::Windows::Forms::ContextMenu();
System::Windows::Forms::MenuItem^ nI_Open_Item = gcnew System::Windows::Forms::MenuItem("Open");
System::Windows::Forms::MenuItem^ nII_Close_item = gcnew System::Windows::Forms::MenuItem("Close");
notifyIcon1->ContextMenuStrip->Items->Add(status_Item);
notifyIcon1->ContextMenu->MenuItems->Add(nI_Open_Item);

Drag and drop from windows explorer to custom C# app that actually works with Windows 7

I've attempted (using dozens of examples) to create a simple WinForms app that will allow me to drag-and-drop a simple text file into an input box on a custom DotNet program.
Unfortunately, there appears to be no examples that actually work in Windows 7.
Here's a simple example (from another post that's been referenced all over the place) but it does not work at all.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace DragAndDropTestCSharp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.AllowDrop = true;
this.DragEnter += Form1_DragEnter;
this.DragDrop += Form1_DragDrop;
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] filePaths = (string[])(e.Data.GetData(DataFormats.FileDrop));
foreach (string fileLoc in filePaths)
{
// Code to read the contents of the text file
if (File.Exists(fileLoc))
{
using (TextReader tr = new StreamReader(fileLoc))
{
MessageBox.Show(tr.ReadToEnd());
}
}
}
}
}
}
}
Could this be a UAC issue? If so, why does every other app in the world seem to do this simple, yet elusive feat of drag and drop with UAC on?
Does someone have a real, working example of getting this to work in Windows 7?
I've tried your sample and it works fine.
Check if you have hook the Load event to the form object to the Form1_Load handler and your namespace is the same.
this.Load += new System.EventHandler(this.Form1_Load);
or via properties editor:
Ok, I discovered that running VS under Administrator (which I had to do for another project) was the culprit. Loading VS in normal user mode, it works fine with UAC on.
Thanks all for your input!

Categories