C# Spaßprogramm optimieren. (ANFÄNGER)

Blackhawk50000

Erfahrenes Mitglied
Einen schönen guten Tag.
Ich sitze seit gestern an einem Programm das Beeptöne in form von kleines Liedern ausgeben soll. Ich habe 3 radioButton

radioEntchen
radioBells
radioElise

und 2 buttons

button1
button2

dazu noch ein Progressbar

progressBar1

und ein Label

label1


Nach dem Klick auf den button1 wird eine if else struktur durchsucht und bestimmt welcher radioButton angeklickt wurde. Dann wird der jeweilige Methodenaufruf für das Lied aktiviert und in die Methode Bsp.: PlayEntchen gesprungen. in der Methode PlayEntchen befinden sich viele Methodenaufrufe die pro Aufruf eine Note mit Frequenz und Tonlänge übergeben Bsp.: Beep(200, 300). Der Aufruf startet die Methode Beep in der der Beepton ausgegeben wird. Der Quellcode sieht so aus.
Während das Lied spielt, wird der Wert für den progrssBar1 um eins erhöt. Am ende wird die Anzahl der Töhne in dem Label angezeigt.

Das Programm ist nicht anhaltbar. Der Stopbutton geht nicht (weil ich noch keinen code dafür habe) und während das Lied spielt, ist das ganze Programm lahmgelegt, d.h. das sich nicht mal das Fenster verschieben lässt.

Meine Frage an euch ist nun, Wie mach ich das ganze mit dem Stop Button, und wie kann die häufigen Methodenaufrufe minimieren, oder gar in eine eigene Datei zu packen, die dann die Methodenaufrufe als C# code enthällt und von dem Programm gelesen und verwendet werden kann. ich dachte da an eine *.txt oder eine *.cs Datei.


Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Liedabspielprogramm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                progressBar1.Visible = true;
                if (radioEntchen.Checked == true)
                {
                    progressBar1.Maximum = 27;
                    progressBar1.Value = 0;
                    PlayEntchen();
                    label1.Visible = true;
                    label1.Text = (progressBar1.Value + " Töne");
                }
                else if (radioBells.Checked == true)
                {
                    progressBar1.Maximum = 11;
                    progressBar1.Value = 0;
                    PlayBells();
                    label1.Visible = true;
                    label1.Text = (progressBar1.Value + " Töne");
                }
                else if (radioElise.Checked == true)
                {
                    //progressBar1.Maximum = 11;
                    //progressBar1.Value = 0;
                    PlayElise();
                    label1.Visible = true;
                    label1.Text = (progressBar1.Value + " Töne");
                }
                else MessageBox.Show("Dieses Lied ist noch nicht Vorhanden");
            }

            catch (Exception ex)
            {
                label1.Visible = true;
                MessageBox.Show(""+ ex);
            }
        }




        #region Alle meine Entchen
        private void PlayEntchen()
        {
            Beep(262, 250);
            progressBar1.Value += 1;
            Beep(294, 250);
            progressBar1.Value += 1;
            Beep(330, 250);
            progressBar1.Value += 1;
            Beep(349, 250);
            progressBar1.Value += 1;
            Beep(392, 500);
            progressBar1.Value += 1;
            Beep(392, 500);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(392, 700);
            progressBar1.Value += 1;
            System.Threading.Thread.Sleep(70);
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(440, 250);
            progressBar1.Value += 1;
            Beep(392, 700);
            progressBar1.Value += 1;
            System.Threading.Thread.Sleep(70);
            Beep(349, 250);
            progressBar1.Value += 1;
            Beep(349, 250);
            progressBar1.Value += 1;
            Beep(349, 250);
            progressBar1.Value += 1;
            Beep(349, 250);
            progressBar1.Value += 1;
            Beep(330, 500);
            progressBar1.Value += 1;
            Beep(330, 500);
            progressBar1.Value += 1;
            Beep(392, 250);
            progressBar1.Value += 1;
            Beep(392, 250);
            progressBar1.Value += 1;
            Beep(392, 250);
            progressBar1.Value += 1;
            Beep(392, 250);
            progressBar1.Value += 1;
            Beep(262, 500);
            progressBar1.Value += 1;
        }
        #endregion

        #region Jingle Bells
        private void PlayBells()
        {
            Beep(330, 250); // Quarter E
            progressBar1.Value += 1;
            Beep(330, 250); // Quarter E
            progressBar1.Value += 1;
            Beep(330, 500); // Half E
            progressBar1.Value += 1;
            Beep(330, 250); // Quarter E
            progressBar1.Value += 1;
            Beep(330, 250); // Quarter E
            progressBar1.Value += 1;
            Beep(330, 500); // Half E
            progressBar1.Value += 1;
            Beep(330, 250); // Quarter E
            progressBar1.Value += 1;
            Beep(392, 250); // Quarter G
            progressBar1.Value += 1;
            Beep(262, 250); // Eigth C
            progressBar1.Value += 1;
            Beep(294, 250); // Eigth D
            progressBar1.Value += 1;
            Beep(330, 500); // Quarter E
            progressBar1.Value += 1;
        }
        #endregion

        #region Für Elise
        private void PlayElise()
        {
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(622, 120);  //  Treble D#
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(622, 120);  //  Treble D#
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(120);
            Beep(587, 120);  //  Treble D
            System.Threading.Thread.Sleep(120);
            Beep(523, 120);  //  Treble C
            System.Threading.Thread.Sleep(120);
            Beep(440, 120);  //  Treble A
            System.Threading.Thread.Sleep(140);
            Beep(262, 120);  //  Middle C
            System.Threading.Thread.Sleep(120);
            Beep(330, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(440, 120);  //  Treble A
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(140);
            Beep(330, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(415, 120);  //  Treble G#
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(120);
            Beep(523, 120);  //  Treble C
            System.Threading.Thread.Sleep(140);
            Beep(330, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(622, 120);  //  Treble D#
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(622, 120);  //  Treble D#
            System.Threading.Thread.Sleep(120);
            Beep(659, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(120);
            Beep(587, 120);  //  Treble D
            System.Threading.Thread.Sleep(120);
            Beep(523, 120);  //  Treble C
            System.Threading.Thread.Sleep(120);
            Beep(440, 120);  //  Treble A
            System.Threading.Thread.Sleep(140);
            Beep(262, 120);  //  Middle C
            System.Threading.Thread.Sleep(120);
            Beep(330, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(440, 120);  //  Treble A
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(140);
            Beep(330, 120);  //  Treble E
            System.Threading.Thread.Sleep(120);
            Beep(523, 120);  //  Treble C
            System.Threading.Thread.Sleep(120);
            Beep(494, 120);  //  Treble B
            System.Threading.Thread.Sleep(140);
            Beep(44, 120);   //  Treble A
        }
        #endregion

        #region Tonausgabe
        [DllImport("kernel32.dll")]
        private static extern bool Beep(int frequenz, int dauer);
        #endregion

        private void button2_Click(object sender, EventArgs e)
        {
            
        }


        
    }
}
 
Ich bin zwar mit sicherheit kein Profi, was Programmierung angeht, aber wäre nicht die Verwendung verschiedener Arrays, in denen die Zahlenpaare für die Töne gespeichert sind (eventuell als Point oder eigenem Type), eine Möglichkeit? Je nach Radiobutton könntest du ein anderes Array aufrufen das du vorher schon gefüllt hast.

Und dann sowas ähnliches wie
Code:
private void PlaySong()
{
  foreach (Type _ton in _tonArray)
  {
    Beep(_ton.frequenz, _ton.laenge);
    progressBar1.Value += 1;
  } 
}

Es ruft die Methode Beep zwar immernoch x-Mal auf, aber dafür etwas elleganter.
 
hier ist dann nur das kleine problem, wie lege ich ein array an, wie sieht so ein array aus?.. wie wird das verwendet? und und und..... gib mal ein KURZES beispiel mit zwei tönen
 
Wie gesagt, ich bin selber kein Profi, und habe oft meine liebe Müh mit den Codes daher werde ich einfach so versuchen zu erklären, wie "ich" es evtl machen würde (aber ohne großes Code Beispiel).

Ich würde die Noten jedes Liedes in eine Textdatei packen (also Entchen.txt, JingleBells.txt etc.). Über einen Button könnte man dann einen FileDialog aufrufen und das zu spielende Lied auswählen indem man die Datei wählt (oder natürlich über die Radiobuttons).

Wenn eine Datei ausgewählt wurde, wird ein 2-dimensionales Array erzeigt (Array[tonnummer, tondaten]). Den Inhalt würde ich dann aus der ausgewählten Datei via einem FileStream zeilenweise auslesen und in das jeweilige Feld des Arrays schreiben.
Code:
Also Pseudo-Code:
while-Schleife über die Zeilen der ausgewählten Datei solandge der zeileninhalt nuchzt "null" ist
  Lese eine Zeile aus der Datei
  Trenne den Inhalt der Zeile an einem bestimmten Zeichen auf (z.B Leerzeichen oder komma)
  Erzeuge ein Objekt vom Typ Point, in dem die beiden Zahlen gespeichert sind
  Füge dieses Point-Objekt in das Array an der Stelle "n" ein.
  Arrayzähler um eins hoch
Schleifenende

Einen guten Artikel zu Arrays kannst du HIER finden.
Tut mir leid wenn ich keine große Hilfe bin
 
Du kannst einen Thread erstellen um die beeptöne abzuspielen, dieser blockiert deine Anwendung nicht durch die Sleep-befehle

System.Threading.Thread thread = new System.Threading.Thread(prozedurname);
thread.Start();

Bei dem Prozedurnamen kommt der Name der Prozedur hin, die ausgeführt wird (mit dem Commandbutton)

um ihn zu stoppen, geht ein einfaches

thread.Abort();

Dabei wird er vom zurzeítigen Befehl aus sofort beendet.
Da müsstest du halt jetzt 3 Threads machen, die du in der Klasse und nicht in der Prozedur deklarierst, damit sie auch für den Stop-Knopf noch zur verfügung steht. Den rest überlass ich dir ;)
 
Obwohl thread.Abort(); immer wieder eine ThreadAbortException wirft. Besser wäre es eine boolsche Statusvariable einzuführen, die bei jedem Schleifendurchlauf abgefragt wird. Ein Klick auf den Stop-Button verändert diesen Wert. Ist der Wert dann false bzw. true (je nachdem was du als Abbruch ansiehst), wird ein break; für die Schleife ausgeführt, sodass die Methode, welche vom ThreadStart des Threads ausgeführt wird, ausläuft, also als beendet gilt, was automatisch bedeutet, dass der Thread beendet ist.

Natürlich kannst Du auch Thread.Abort verwenden, musst dann aber natürlich die ThreadAbortException abfangen und nach der Behandlung ein "return;" einfügen, da sonst die ThreadAbortException immer wieder ausgelöst wird.


Gruß
Andreas
 
Au ja, das hab ich vergessen. Mist..


Man muss oben in der Klasse NUR "dim klingeling as thread" schreiben!
dann im "Startknopf" "klingeling = new system.threading.thread(AdressOf *PROZEDUR*)"

Das war der Fehler, dann wird keine ThreadAbortException mehr geworfen, wenn du ihn jedes mal neu definierst, nach dem du ihn abgebrochen hast.
 
Zurück