Rekursion.

Du brauchst eine eigene Methode, die einen Ordnerpfad als Parameter entgegennimmt und die Anzahl der enthaltenen Dateien zurückgibt. Sollte der Pfad weitere Ordner enthalten, lässt du die gleiche Methode mit dem neuen Ordner aufrufen. Das umschließt du mit einen try-Block und fängst die Ausnahme ab, damit solche System-Ordner übersprungen werden.

Du findest sicherlich genug Beispiele dazu im Internet.

...zur Antwort

Das ToolStripMenuItem in der obersten Ebene (also das Stammelement des MenuStrip, häufig "Datei", "Bearbeiten", "Hilfe", etc.) kann zwar auch "Checked" sein, wird allerdings nicht durch einen Haken visuell dargestellt. Möglicherweise hast du dadurch den Eindruck, dass nichts passiert.

Versuche, ob das Problem bei einem untergeordneten ToolStripMenuItem ebenfalls auftritt.

...zur Antwort

Was hat dir an meiner Antwort in der vorherigen Frage nicht gepasst? Du hättest es ja auch kommentieren können, wenn es nicht deiner Erwartung entspricht.

So genau habe ich die Verbindung zur Datenbank nicht verstanden. Aber wenn du für jede Zeile die 5. Spalte anpassen willst, dann geht das mit folgendem Code:

For Each row As ListViewItem In ListView1.Items
' Für jede Zeile wird der Text aus der fünften
' Spalte mit "Neuer Text" ersetzt.
row.SubItems(4).Text = "Neuer Text"
Next

Vielleicht kannst du das Problem aber nochmal genauer erläutern. Wann kommen welche Daten? Wann soll unter welcher Vorraussetzung was geändert werden?

...zur Antwort

C# Focus bei UserControl?

Hallo,

ich hab ein Problem mit dem Focus eines UserControls. Und zwar bekommt das UserControl trotzdem den Focus obwohl alle seine ChildControls nicht focusierbar sind. Ich hab hier mal ein kleines Beispiel erstellt, zum testen einfach ein neues Windows Forms Project anlegen und den Code in den Source Code der Form kopieren.

using System.Windows.Forms;

namespace testUserControl
{
  using System.Diagnostics.Eventing.Reader;

  public partial class Form1 : Form
  {
    private testControl testControl1;
    private testControl testControl2;
    private testControl testControl3;
    
    public Form1()
    {
      InitializeComponent();

      this.testControl1 = new testUserControl.testControl();
      this.testControl2 = new testUserControl.testControl();
      this.testControl3 = new testUserControl.testControl();

      this.testControl1.Location = new System.Drawing.Point(24, 27);
      this.testControl1.Name = "testControl1";
      this.testControl1.Size = new System.Drawing.Size(150, 37);
      this.testControl1.TabIndex = 0;


      this.testControl2.Location = new System.Drawing.Point(24, 71);
      this.testControl2.Name = "testControl2";
      this.testControl2.Size = new System.Drawing.Size(150, 45);
      this.testControl2.TabIndex = 1;


      this.testControl3.Location = new System.Drawing.Point(24, 136);
      this.testControl3.Name = "testControl3";
      this.testControl3.Size = new System.Drawing.Size(150, 47);
      this.testControl3.TabIndex = 2;

      this.Controls.Add(this.testControl3);
      this.Controls.Add(this.testControl2);
      this.Controls.Add(this.testControl1);

      testControl2.Disable();
    }
  }

  public class testControl : UserControl
  {
    private TextBox test;

    private Label TestLabel;

    public testControl()
    {
      this.test = new TextBox();
      this.test.Name = "TextBox";
      this.test.Location = new System.Drawing.Point(100, 5);
      this.test.Size = new System.Drawing.Size(80, 17);

      this.TestLabel = new Label();
      this.TestLabel.Name = "Label";
      this.TestLabel.Text = "Test";
      this.TestLabel.Location = new System.Drawing.Point(10, 5);
      this.TestLabel.Size = new System.Drawing.Size(50, 17);

      this.Controls.Add(this.test);
      this.Controls.Add(this.TestLabel);
    }

    public void Disable()
    {
      this.test.Enabled = false;
    }
  }
}

Ich weiß das das Design jetzt nicht schön aussieht aber das ist auch egal. Um was es mir jetzt geht ist, das wenn ich mit tab durchgehe das 2. Control trotzdem den Focus bekommt obwohl es aus einem lable und einer deaktivierten TextBox besteht. Warum ist das so? Und wie kann ich das umgehen?

Danke für alle Antworten.

...zur Frage

Das Usercontrol ist in Sachen Fokus eine seltsame Geschichte.

Am einfachsten wäre es, die Enabled-Eigenschaft auf False zu setzen. Dabei werden automatisch alle Child-Controls auch auf Enabled = False gesetzt und ist über den Tab nicht mehr zu erreichen.

this.SetStyle(ControlStyles.Selectable, false) wäre auch eine Möglichkeit, aber dann kannst du nicht mehr von einer TextBox des UserControls in eine andere TextBox eines anderen UserControls mit Tab springen.

Gibt sicher noch andere Möglichkeiten, da wird es dann aber etwas komplizierter.

...zur Antwort

Zahl1 ist der Inhalt, bevor du auf eine Rechenoperation klickst. Zahl2 ist der Inhalt, bevor zu auf das Gleichheitszeichen klickst. Das Ergebnis wird dann in Zahl1 zusammengefasst und angezeigt.

Wenn man programmieren möchte, hilft es häufig sich das Problem auf Papier klar zu machen - oder in einem Textverarbeitungsprogramm am PC - oder ... je nachdem, was einem lieber ist.

...zur Antwort

Zuerst zu deinem Problem: Application.DoEvents steht an der falschen Stelle. Wenn dich die Erklärung für das Verhalten interessiert, dann lies weiter, ansonsten springe zum nächsten Absatz nach der Liste. Schritt für Schritt sieht der Ablauf so aus:

  • Erster Durchlauf: Du setzt den Wert auf 10 und weist diesen Wert dem Label zu. Das Label hat nun von Windows eine Anforderung zum Neuzeichnen erhalten und wird diese ausführen, sobald die MessageQueue verarbeitet wird. (Das passiert noch nicht, weil der aktuelle Thread noch in der For-Schleife arbeitet.)
  • Im zweiten Durchlauf setzt du den Wert auf 10 und erlaubst die Abarbeitung der MessageQueue durch Application.DoEvents. Das Label darf nun seinen Inhalt aktualisieren und zeigt den Wert 10 an. Erst dann weist du dem Label den neuen Wert 20 zu. Gleiches Spiel: die Anforderung zum Neuzeichnen landet in der MessageQueue und wird bei der nächsten Abarbeitung ausgeführt. Aber auch das passiert erst im nächsten Durchlauf.
  • Im vorletzten Durchlauf ist der Wert der ProgressBar 90 und das Label darf dann erst seine 80 aus der vorherigen Anforderung zeichnen.
  • Im letzten Durchlauf passiert das gleiche. Allerdings ist der Thread danach frei (kein Thread.Sleep) und kann sofort die MessageQueue erneut abarbeiten und somit die 100 anzeigen. Die 90 wird also vorher angezeigt, aber nur für den Bruchteil einer Sekunde (wenn überhaupt).

Wenn du Application.DoEvents nach der Wertzuweisung des Labels schreibst, funktioniert es wie gewollt.

Nun zum anderen Problem: Nichts ist nerviger als ein simulierter Fortschritt. Eine ProgressBar, die ihren Wert in Abhängigkeit einer (zur Entwurfszeit) definierten Zeit verändert hält den gesamten Programmablauf auf und hat ohne Multithreading wenig Sinn.

...zur Antwort

Typischerweise (sofern nichts geändert wurde) wird die Anwendung beendet, wenn die Startform geschlossen wird.

Es kann sein, dass das Startformular versteckt wurde (Hide) und somit nicht geschlossen werden kann. Dadurch bleibt die Anwendung aktiv.

Du könntest zum Test einfach mal schauen, was dir "My.Application.OpenForms" so ausgibt, wenn dein Fenster geschlossen wird. Damit lässt du dir alle geöffneten Fenster anzeigen.

...zur Antwort

Ich habe so etwas vor längerer Zeit gelöst, in dem ich für jedes gezeichnete Objekt eine Klasse erstellt hatte (z.B. Line) mit Start- und Endkoordinate, Farbe und Zeichenstil. Davon einfach eine Instanz erzeugen und in einer Liste speichern

Im Paint-Ereignis kannst du dann durch die Liste iterieren und entsprechend der Koordinaten die Linie in gewünschter Farbe etc. zeichnen.

(Wird die Linie aus der Liste entfernt, wird sie dadurch nicht wieder gezeichnet.)

...zur Antwort

Rechtsklick auf die Toolbox und "Elemente auswählen" anklicken. Dann erscheint ein Fenster. Dort suchst du nach dem PowerPacks, wählst deine gewünschten Elemente aus und bestätigst das Fenster.

...zur Antwort

Selbst bei der Verwendung von Tabs brauchst du das ActiveX-Steuerelement nicht.

Du kannst ein TabControl verwenden, bei dem jede TabPage ein WebBrowser-Control enthält. Willst du einen neuen Tab erzeugen, dann brauchst du nur eine neue TabPage dem TabControl hinzufügen und platzierst ein WebBrowser-Control auf die neue TabPage.

Dann brauchst du dich nicht mit irgendwelchen Kompatibilitäten rumärgern.

...zur Antwort

Im Projektmappenexplorer alle Dateien anzeigen lassen (dort gibt es eine Schaltfläche dafür). Eine neue Form hinzufügen und den Inhalt deiner "Form8.Designer.vb" Datei in die "NeueForm.Designer.vb" Datei kopieren.

Der Programmcode, der in Form8 stande, wird allerdings verloren bleiben, denn die xxx.Designer.vb enthält nur die Initialisierungen für untergeordnete Steuerelemente.

PS: Wenn du Form8.vb über den Windowsexplorer gelöscht hast, dann sollte die Datei noch im Papierkorb sein (zumindest bei den standardmäßigen Windowseinstellungen).

...zur Antwort

Etwas mehr Programmcode wäre eventuell hilfreich.

Wie hast du denn deine Datenbindung realisiert? Normalerweise kannst du im Designer schon dem DataGridView eine Source übergeben. Dazu kannst du eine Projektdatenquelle anlegen, die eine Klasse als Grundlage verwendet. Dann fügt das DataGridView selbstständig die benötigten Spalten vom jeweiligen Datentyp hinzu.

Wahrscheinlich reicht es einfach aus, wenn du die Spalte, die die Variable "Frei" anzeigen soll, als DataGridViewCheckBoxColumn erzeugst.

...zur Antwort

Mit Hilfe einer Suchmaschine lässt sich herausfinden, dass Spotify eine API anbietet: https://developer.spotify.com/

Offensichtlich gibt es dafür auch schon vorhandene auf .NET basierende Wrapper: https://github.com/JohnnyCrazy/SpotifyAPI-NET

Das ist zwar in C# geschrieben, aber das interessiert bei einer kompilierten Bibliothek nicht mehr. Es ist höchstens für das Beispiel relevant, aber den Code kann man über diverse Webseiten konvertieren (z.B. http://converter.telerik.com/).

...zur Antwort

Du hast mit deiner Vermutung der "langsamen Animation" recht.

Seit Windows Vista ist das Redesign der Progressbar für ein solches Verhalten verantwortlich. Wird der Wert erhöht, dann wird durch Windows eine Animation ausgelöst, die diese Änderung progressiv anzeigt. Je schneller der Wert erhöht wird, desto mehr scheint die Animation hinterher zu hängen.

Eine Möglichkeit diese Animation zu umgehen wäre es beispielsweise den Wert nach dem Erhöhen wieder zu verringern. Zum Beispiel so:

if (progressBar1.Value == progressBar1.Maximum - 1)
{
progressBar1.Increment(1);
}
else
{
progressBar1.Increment(2);
progressBar1.Increment(-1);
}
...zur Antwort
Dim documentPath As String = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Dim deeperPath As String = System.IO.Path.Combine(documentPath, "Unterordner")

With OpenFileDialog1
.InitialDirectory = deeperPath
.Title = "Wecktöne"
.ShowDialog()
End With

Verzeichnisnamen sollten bevorzugt über die Combine-Methode der System.IO.Path-Klasse zusammengefügt werden.

...zur Antwort

Was ist ein Picture-Button?

Wenn du mit Steuerelementen arbeitest, dann haben diese eine Location-Eigenschaft. Die gibt die Position von der oberen linken Ecke des übergeordneten Containers (bei dir möglicherweise die Form) zur oberen linken Ecke des Steuerelementes an.

Wenn es dir um die Logik der unterschiedlichen Programmzweige bei einem Klick geht, dann verwende eine zusätzliche Variable. Ist diese leer, dann wurde das erste mal geklickt und du kannst ihr einen Wert zuweisen (nämlich die Position). Ist diese nicht leer, dann wurde bereits einmal geklickt und sie hat einen Wert. Dann kannst du den Button auf diese Position setzen.

Oder wie auch immer; kann sein, dass ich dein Problem nicht ganz verstanden habe.

...zur Antwort

In einer deiner anderen Fragen gab ich dir ein Code-Beispiel, womit du das Problem lösen könntest - sowohl das alte als auch das aktuelle. Das Framework bietet genug Möglichkeiten, da muss man das Rad nicht nochmal erfinden. Daher bleibe ich dabei:

Du kannst aus deinen Kreisen ein Region-Objekt erzeugen, welches genug Methoden für deine Zwecke zur Verfügung stellt.

Public Function CreateRegion() As Region
Using p1 As New Drawing2D.GraphicsPath, p2 As New Drawing2D.GraphicsPath
' Kreis in p1 hinzufügen. Obere linke Ecke bei X=48; Y=77. Seite a=b=46.
p1.AddArc(New Rectangle(48, 77, 46, 46), 0, 360)
' Kreis in p2 hinzufügen. Obere linke Ecke bei X=52; Y=72. Seite a=b=132.
p2.AddArc(New Rectangle(52, 72, 132, 132), 0, 360)

' Region-Objekt von p1 erzeugen und mit p2 kombinieren.
Dim r As New Region(p1)
r.Union(p2)
Return r
End Using
End Function

Dann musst du nur noch das Region-Objekt darstellen:

Private Sub PictureBox1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
Using regionBrush As New SolidBrush(Color.FromArgb(178, 255, 0, 0))
e.Graphics.FillRegion(regionBrush, CreateRegion)
End Using
End Sub

Das Brush-Objekt kapselt hierfür die Farbe, die in diesem Fall im Alpha-Kanal einen Wert von 178 (entspricht 30% Transparenz) hat. Der Wert hierfür bleibt dir überlassen.

...zur Antwort

Du kannst deine Eingabe auch dynamisch kompilieren. Das heißt die Analyse übernimmt der Compiler, wodurch du selbst keinen Parser schreiben musst. (Ergibt das gleiche, als würdest du die Eingabe fest programmieren und das Programm kompilieren/starten.)

Public Function Parse(input As String) As Boolean
Dim provider As New VBCodeProvider
Dim parameters As New CodeDom.Compiler.CompilerParameters
parameters.GenerateInMemory = True
parameters.GenerateExecutable = True

' Programmcode erzeugen, der dynamisch kompiliert werden soll. Der übergebene Text wird dabei
' als Programmcode erkannt und entsprechend kompiliert.
Dim programCode As New System.Text.StringBuilder
programCode.AppendLine("Imports System.Windows.Forms")
programCode.AppendLine("Namespace RuntimeCompiled")
programCode.AppendLine(" Public Class RuntimeCompiledClass")
programCode.AppendLine(" Public Shared Sub Main()")
programCode.AppendLine(" End Sub")
programCode.AppendLine(" Public Shared Function Parse() As Boolean")
programCode.Append(" Return ")
programCode.AppendLine(input)
programCode.AppendLine(" End Function")
programCode.AppendLine(" End Class")
programCode.AppendLine("End Namespace")

' Programm kompilieren.
Dim compiledResult As CodeDom.Compiler.CompilerResults = provider.CompileAssemblyFromSource(parameters, programCode.ToString)
If compiledResult.Errors.HasErrors Then Throw New InvalidOperationException

' Methode mittels Reflection ermitteln, aufrufen und das Ergebnis zurückgeben.
Dim compiledAssembly As Reflection.Assembly = compiledResult.CompiledAssembly
Dim classType As Type = compiledAssembly.GetType("RuntimeCompiled.RuntimeCompiledClass")
Dim method As Reflection.MethodInfo = classType.GetMethod("Parse")
Return CBool(method.Invoke(Nothing, Nothing))
End Function

So würde die Methode aussehen. Der Aufruf wäre dann einfach:

Dim input As String = TextBox1.Text
input = input.Replace("1", "True")
input = input.Replace("0", "False")

Dim result As Boolean = Parse(input)
MessageBox.Show(result.ToString)

Der Vorteil ist, dass du damit komplizierte Anweisungen beliebig verschachteln kannst. Der Nachteil ist, dass damit jede Art von Code kompiliert wird. Es wäre daher möglich Schadcode auszuführen.

...zur Antwort

Die einfachste Möglichkeit wäre mit GraphicsPath und Region zu arbeiten, wenn du bei den einfachen GDI+ Methoden des Frameworks bleiben willst. Das könnte dann ungefähr so aussehen:

Dim intersection As Region

Private Sub PictureBox1_MouseClick(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseClick
If e.Button = Windows.Forms.MouseButtons.Left AndAlso intersection.IsVisible(e.Location) Then
Debug.WriteLine(e.Location.ToString & " ist eine Koordinate der Schnittmenge.")
End If
End Sub

Private Sub PictureBox1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality

Using p1 As New Drawing2D.GraphicsPath, p2 As New Drawing2D.GraphicsPath
p1.AddArc(New Rectangle(48, 77, 46, 46), 0, 360)
p2.AddArc(New Rectangle(52, 72, 132, 132), 0, 360)

e.Graphics.DrawPath(Pens.Red, p1)
e.Graphics.DrawPath(Pens.Red, p2)

intersection = New Region(p1)
intersection.Intersect(p2)
End Using
End Sub

Du erstellst zunächst für jedes Objekt (Kreis, Rechteck, ...) ein GraphicsPath-Objekt, dem du dann über diverse Add-Methoden unterschiedliche Geometrien hinzufügst. In dem einfachen Fall einen Kreisbogen über 360°. Danach kannst du ein Region-Objekt aus dem ersten Pfad erzeugen und über die Intersect-Methode die Schnittmenge aus diesem und den über den Parameter angegebenen Pfad ermitteln. In der MouseClick-Methode prüfst du dann mit der IsVisible-Methode, ob der Punkt enthalten ist.

Der Code sollte aber noch optimiert werden: im MouseClick sollte geprüft werden, ob "intersection" überhaupt vorhanden ist und das Erzeugen der GraphicPath-Objekte und von "intersection" sollte nicht im Paint-Ereignis geschehen, sondern in einer eigenständigen Methode, die nur einziges einmal aufgerufen wird - oder eben dann, wenn sich ein Pfad ändert.

...zur Antwort

Hat die Bilddatei den gleichen Namen wie die vorherige, gelöschte Datei?

Wenn ja, dann gehe ich bei Visual Studio 2010 immer wie folgt vor: Im Projektexplorer lösche ich die Datei aus dem Resources-Verzeichnis. Dann gehe ich in die Projekteigenschaften und lösche dort den Eintrag. Weil VS2010 irgendwie immernoch die Bilddaten im Speicher liegen hat, schließe und öffne ich die Projektmappe erneut und kann somit das Bild neu importieren.

Eventuell ist das Schließen und Öffnen in den neuen Versionen von VS nicht nötig. Wichtig für den Ressourcenkontext, wie du es nennst, ist es den Eintrag in den Projekteigenschaften unter "Ressourcen" zu entfernen (dort muss oben statt "Zeichenfolgen" "Bilder" stehen).

...zur Antwort