1

I would like for a program to play a beep as long as a specific key is pressed. Is there any way in which i can detect a key when it's released? and then abort a thread which plays that beep?

Consider the following example:

   class Program
        {
        public static void Play()
        {
            while (true)
            {
                Console.Beep(400, 10000);//play for a long length, will be interrupted as soon as the key is released
            }
        }
        public static void Main(string[] args)
        {
             while(true)
             {
             ConsoleKeyInfo cki=Console.ReadKey(true);
             if(cki.Key==ConsoleKey.G)
                  {
                    Thread p = new Thread(Play);
                    p.Start();
                  }

             }
        }

I considered using Thread.Abort(), However it should only abort the aforementioned thread p when the key G is released. Implementing a method which plays the beep for a short length while keeping the G key pressed wont work , since small intervals can be heard between each beep.

Therefore, using the following code will play short beeps with small intervals between them:

public static void Main()
    {

        ConsoleKeyInfo keyinfo;
        do
        {
            keyinfo = Console.ReadKey();

            Console.Beep(400, 10);
        }
        while (keyinfo.Key == ConsoleKey.G);
    }

Instead i would like to have one long beep, stopped as soon as a key is released.

  • Check this answer, and the link for hooks http://stackoverflow.com/a/8898251/752527 – Hanlet Escaño Jul 25 '14 at 18:06
  • try to make use of the KeyUp event handler – CularBytes Jul 25 '14 at 18:32
  • That will require me to use a Windows Forms Application... is there any way i could do it without it? – Shai Yehezkel Jul 25 '14 at 19:02
  • possible duplicate of [how to handle key press event in console application](http://stackoverflow.com/questions/8898182/how-to-handle-key-press-event-in-console-application) – Patrick Hofman Jul 25 '14 at 19:53
  • Doing so will make use of multiple console.beep commands which will be heard as many notes being stroked with really short intervals between them. Instead i would like to have one long Console.beep which will be heard as one long continuous beep, only stopped when a key is released – Shai Yehezkel Jul 25 '14 at 20:04

3 Answers3

0

It is because when you press and hold a key, the keyboard will generate at most about 31 "keystrokes" per second. That gives you a delay of about 32.25 ms between a keystroke and the next.

Now because the Console.ReadKey is blocking the thread, you will wait for this 32.25ms before invoking the next Beep which makes 22ms of silence for each 10ms Beep.

So back to code, you should increase the beep time to approximately match the delay between keystrokes. I spared myself the exact calculation based on SystemInformation.KeyboardSpeed. If you need that, I will add it.

ConsoleKeyInfo keyinfo;

do
{
    keyinfo = Console.ReadKey();

    Console.Beep(400, 33);
}
while (keyinfo.Key == ConsoleKey.G);
Alireza
  • 4,976
  • 1
  • 23
  • 36
  • The time between the first and second keypress will vary depending on the keyboard delay and repeat rate set in the control panel. – Moby Disk Jul 25 '14 at 20:37
  • I am afraid that it doesn't work... since Console.Beep() is blocking... so if you your system wil detect the key and then play 33 msec of beep and then stop for a while before sampling the new key... you can starting a thread for beeping asynchronously for 33 msec (or more) but I'll have to check the result... don't know what happens if two Console.Beep() calls overlap... – Morix Dev Jul 25 '14 at 20:44
  • @MobyDisk I've just simplified that part and mentioned it in the third paragraph, that is not the core part of the solution :) – Alireza Jul 25 '14 at 20:49
  • @MorixDev The thread will be blocked for 33ms on the `Beep` then will come back to `ReadKey` finding that the key press is now available. Just set your keyboard's rate at the highest and see if this works. Then I will add the calculations based on `SystemInformation.KeyboardSpeed` to make it work on any speed. – Alireza Jul 25 '14 at 20:54
  • @Alireza: maybe you won't hear it... but some silence will be there for sure using such an approach... – Morix Dev Jul 25 '14 at 20:57
  • @MorixDev My beeper is broken, so if it is not rude I will ask you to do this test on my behalf. It will clear the matter: `while (true) Console.Beep(33);` does this have silence in-between of the beeps? – Alireza Jul 25 '14 at 21:05
  • @Alireza: I've done the test... a lot of silence between beeps on my PC... sorry! – Morix Dev Jul 26 '14 at 08:04
  • If even this won't work, I think `Console.Beep()` is off the table and we must settle with your solution :) – Alireza Jul 26 '14 at 08:25
0

It is much more complex than the other suggestes solutions but I am afraid that the only option is to play the beep from a sound buffer whose content is filled up while pressing the key... I am speaking about using DirectSound API and things like that... maybe http://msdn.microsoft.com/en-us/library/windows/desktop/bb318673(v=vs.85).aspx can be a good starting point for investigating such possibility...

Morix Dev
  • 2,700
  • 1
  • 28
  • 49
-2

The Code you wrote works properly.

Use the Including :

using System.Threading;

I had run the code in Visual Studio 2010 Ultimate in Any CPU build mode.

It working properly.

Run the .exe file from the project output directory.

WhiteShadow
  • 303
  • 4
  • 18
Pratik Roy
  • 117
  • 1
  • 3