Autor Beitrag
manuall
Hält's aus hier
Beiträge: 1



BeitragVerfasst: Sa 23.01.16 16:54 
Hallo zusammen,

ich bin noch Anfänger in Sachen C# und komme bei einem Problem nicht weiter.
Hier mal der Code:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
                void Button7Click(object sender, EventArgs e)
    {
      
    schleife:
      string a1=label12.Text, b1=label11.Text, a2=label14.Text, b2=label13.Text, z1=textBox3.Text, z2=textBox4.Text;
      string k1=label6.Text, k2=label8.Text, l1=label7.Text, l2=label9.Text;
      string rot = textBox5.Text, gruen = textBox6.Text, blau = textBox7.Text, angabe;
      int x1=0, y1=0, x2=0, y2=0, s1, s2;
      int m1,  m2,  n1,  n2,  rest1, rest2, x, y;
      int treffer = 0;
      
      Int32.TryParse(z1, out s1);  
      Int32.TryParse(z2, out s2);
      Int32.TryParse(a1, out x1);
      Int32.TryParse(b1, out y1);
      this.Cursor = new Cursor(Cursor.Current.Handle);
      Cursor.Position = new Point(x1, y1);
      LeftClick(x1,y1);
      Thread.Sleep(s1*1000);
      Int32.TryParse(a2, out x2);
      Int32.TryParse(b2, out y2);
      LeftClick(x2,y2);
      this.Cursor = new Cursor(Cursor.Current.Handle);
      Cursor.Position = new Point(x2, y2);
      
      Int32.TryParse(k1, out m1);  
      Int32.TryParse(k2, out m2);
      Int32.TryParse(l1, out n1);
      Int32.TryParse(l2, out n2);      
      x = m2;
      y = n2;      
      rest1 = m2-m1+1;
      rest2 = n2-n1+1;      
      angabe="Color [A=255, R=" + rot + ", G=" + gruen + ", B=" + blau + "]";
      
      Thread.Sleep(s2*1000);
      bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format16bppRgb555);
                        gfx = Graphics.FromImage(bmp);
                        gfx.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 00, Screen.PrimaryScreen.Bounds.Size);
                        bmp.Save("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");
      Bitmap myBitmap2 = new Bitmap("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");
      
                        do
      {
            
      do
      {
        Color pixelColor = myBitmap2.GetPixel(x, y);
        
        if(pixelColor.ToString() == angabe)
        { 
          treffer = 1;
        }
         x--;
      }while (x >= m1);
        
        y--;
        x = m2;
      }while (y >= n1);
      
       if(treffer == 1)
      {
        MessageBox.Show("Farbe vorhanden");
      }
      else
      {
        MessageBox.Show("Farbe nicht vorhanden");
      }
               
                        Thread.Sleep(500);
      if (checkBox1.Checked == true){
          
        goto schleife;
      
      }
      
    }


Hier soll nachdem der Button geklickt wurde ein bestimmter Bereich des Desktops auf eine angegebene Farbe überprüft werden.
Bei erstmaligem Ausführen funtkioniert auch alles, wie es soll, nur wenn ich dann das zweite mal auf den Button klicke kommt ein Fehler.

Meiner Meinung nach muss folgender Bereich für den Fehler verantwortlich sein:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
155:                    bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format16bppRgb555);
156:                    gfx = Graphics.FromImage(bmp);
157:                    gfx.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 00, Screen.PrimaryScreen.Bounds.Size);
158:                    bmp.Save("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");
159:
160:                    Bitmap myBitmap2 = new Bitmap("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");
161:
162:                    do
163:                    {
164:
165:          do
166:          {
167:        Color pixelColor = myBitmap2.GetPixel(x, y);


Als Fehlermeldung kommt folgendes:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
System.Runtime.InteropServices.ExternalException: Allgemeiner Fehler in GDI+.

   bei System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
   bei System.Drawing.Image.Save(String filename, ImageFormat format)
   bei System.Drawing.Image.Save(String filename)
   bei Testprogramm_001.MainForm.Button7Click(Object sender, EventArgs e) in c:\Users\Timo\Documents\SharpDevelop Projects\Testprogramm_001\Testprogramm_001\MainForm.cs:Zeile 158.
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
   bei System.Windows.Forms.Button.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.Run(Form mainForm)
   bei Testprogramm_001.Program.Main(String[] args) in c:\Users\Timo\Documents\SharpDevelop Projects\Testprogramm_001\Testprogramm_001\Program.cs:Zeile 27.

Ich hoffe das war jetzt nicht zu viel Text und bedanke mich schonmal im Voraus für die Antworten.
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: So 24.01.16 12:51 
Moin user profile iconmanuall und :welcome:,

user profile iconmanuall hat folgendes geschrieben Zum zitierten Posting springen:
Hallo zusammen,
ich bin noch Anfänger in Sachen C# und komme bei einem Problem nicht weiter.


Dann bist du hier hoffentlich richtig :)

Ich habe gestern Abend schon mal in deinen Code geguckt und ich muss sagen, der ist tatsächlich etwas unorthodox. Aber ich denke, wir kriegen das hin.
Der Ausschnitt, den du da gepostet hast, ist für mich leider etwas unverständlich. Ich bin ehrlich gesagt auch nicht sicher, ob er überhaupt funktionieren kann. Aber ich versuche mich mal an einem Review. Ich werde dabei recht viele Sachen anmerken, aber lass dich davon nicht entmutigen, du musst theoretisch nicht alle Ratschläge befolgen (auch wenn ich natürlich ausschließlich gute Ratschläge gebe ;-))

Ich glaube das Kernproblem deines Codes ist, dass du (noch) recht schleifenorientiert und nicht eventbasiert denkst. Das hat dich vermutlich auch bewegt, eine goto-Anweisung zu verwenden. Das und die Tatsache, dass du fuß- statt kopfgesteuerten Schleifen verwendest sorgt dafür, dass man den Code nicht flüssig lesen kann, sondern immer erst bis zum Ende scrollen muss, damit man wissen kann, was passiert. Klar, das erhöht die Spannung etwas, aber das ist vermutlich nicht das Hauptziel deiner Software ;-). Ein weiteres Problem ist, dass die meisten Programmierer weinen müssen, wenn sie ein goto sehen.

Mein Tipp hier: Dein goto lässt sich erstmal ohne jegliche Hinterfragung in ein
ausblenden C#-Quelltext
1:
2:
3:
while (checkbox1.Checked){
  //...
}

verwandeln. Das gilt analog auch für die beiden do /*...*/ while()-Schleifen. Fun Fact am Rande: Der Zustand der Checkbox wird sich während das Programm läuft vermutlich nicht ändern können, da dein Code im gleichen Thread ausgeführt wird, wie dein User Interface. Demzufolge hast du eine garantierte Endlosschleife, wenn beim starten des Codes die Checkbox angehakt ist.

Ein weiteres Problem sehe ich in der Benamung deiner Variablen. Ich kann leider überhaupt nicht folgen. Die Verwendung des ,-Operators ist meiner Meinung nach auch nur bedingt sinnvoll, gerade wenn nicht zusammenhängende Werte in einer Zeile gesetzt werden. Ich würde an deiner Stelle versuchen, den Code der die Daten aus deinem Formular entnimmt im Button7Click-Eventhandler zu behalten und alle Logik die den tatsächlichen Zweck deines Programms beinhaltet in irgendeiner Form (zunächst z.B. als Methode) auszulagern. Dann kann man da schon signifikant besser folgen.

Weiterhin rufst du mehrmals Thread.Sleep mit potentiell ewigen Wartezeiten auf. Den Nutzen davon habe ich noch gar nicht erkannt. Kannst du das erläutern?

Weiterer Tipp am Rande: Das Problem mit den escapeten Backslashes lässt sich so lösen: @"C:\Users\Timo\Screenshot.bmp". Das @"..." vor dem String übernimmt das für dich.

Deine Variable int treffer wird zur Speicherung eines Wahrheitswertes verwendet. Dann sollte man als Typ der Variable auch bool nehmen.

user profile iconmanuall hat folgendes geschrieben Zum zitierten Posting springen:
Hier mal der Code:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
      bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format16bppRgb555);
                        gfx = Graphics.FromImage(bmp);
                        gfx.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 00, Screen.PrimaryScreen.Bounds.Size);
                        bmp.Save("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");
      Bitmap myBitmap2 = new Bitmap("C:\\Users\\Timo\\Documents\\SharpDevelop Projects\\Testprogramm_001\\screenshot.bmp");



An dieser Stelle speicherst du das Bitmap in eine Datei und lädst sofort wieder das identische Bitmap aus der Datei. Das ist irgendwie nicht nötig. Du könntest direkt mit bmp weiterarbeiten.

Als spontane Handlungsempfehlung - um dem Fehler vernünftig auf die Schliche zu kommen - empfehle ich zusammenfassend erstmal, deinen Code ein wenig aufzuräumen. Ich schlage folgende Struktur vor:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
struct Rectangle {
  int x1;
  int x2;
  int y1;
  int y2;
}
//... Form Klasse
private bool IsColorInArea(Bitmap bmp, Color color, Rectangle area) {
  //...
}

void Button7Click(object sender, EventArgs e) {
  //Eingabewerte setzen
  //...
  
  //Einmal checken:
  if (IsColorInArea(bmp, myColor, myArea)) {
    // Ausgabe
  } else {
    // andere Ausgabe
  }
}


Wenn das ganze so funktioniert, würde ich mir Gedanken darüber machen, wie man das vernünftig in zeitlichen Abständen erneut prüft. Ich wiederhole: Versuche erstmal das ganze zuverlässig für einen Check pro Click zum Laufen zu kriegen. Danach sehen wir weiter.

Ich hoffe ich konnte irgendwie helfen. Sonst frag doch nochmal nach ;-)

Gruß
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 24.01.16 12:54 
Hallo und :welcome:

der Fehler kommt daher, daß du nach dem Abspeichern wieder diese Datei sofort lädst (erst Save, dann new Bitmap), bzw. beim 2. Klick dann wieder die Bitmap abspeichern willst, obwohl die Datei noch geöffnet ist.
Das Stichwort zum korrekten Behandeln lautet "Dispose" bzw. "IDisposable", s. z.B. C#: Dispose() a Bitmap object after call Bitmap.save()? (gleiches gilt für das Laden!).

Dein ganzer Code ist aber voller weiterer Fehler und "No-Gos" (also Code, den man so nicht programmieren sollte), z.B.
- mittels Thread.Sleep blockierst du die GUI (d.h. dein Programm ist währenddessen unbedienbar -> Windows meldet dann "die Anwendung reagiert nicht mehr")
- erst recht durch die Endlosschleife mittels goto schleife
- du solltest den Code besser aufteilen, d.h. eigene Methoden für die Funktionalität bereitstellen (Trennung von GUI und Logik)
- du solltest die Namen deiner Steuerelemente (Label, TextBox, Button) von Anfang an gleich richtig benennen
- du wertest den Fehlerfall bei TryParse nicht aus, d.h. der Wert wird dann immer als 0 zurückgegeben
- der Pixel-Vergleich mittels string ist völlig ineffizient! Du kannst Color-Werte direkt vergleichen.
- aber auch GetPixel ist bei so etwas (d.h. den ganzen Bildschirm zu überprüfen) nicht zu empfehlen, da gibt es bessere Alternativen z.B. GetPixel und SetPixel um Längen geschlagen. 800 mal schneller.
- dein Schleife kansnt du abbrechen, sobald du den ersten Treffer gefunden hast

Darf ich fragen, nach welchem Lehrmittel (Buch, Tutorial, etc.) du C# lernst?