Umrechnung Pixel Koordinate

  • C#

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Umrechnung Pixel Koordinate

    Guten Morgen,

    ich habe mittels for-Schleifen ein Schachbrett erstellt.

    C#-Quellcode

    1. for (byte file = 0; file < 8; ++file)
    2. {
    3. for (byte rank = 0; rank < 8; ++rank)
    4. {
    5. bool isLightSquare = (file + rank) % 2 == 0;
    6. var squareColor = isLightSquare ? lightSquareColor : darkSquareColor;
    7. DrawSquare(new Point(boardLocation.X + rank * squareSize, boardLocation.Y + file * squareSize), squareColor);
    8. }
    9. }


    DIe Schachfiguren stelle ich mittels PictureBoxen dar. Nun habe ich aber bei der Ermittlung der korrekten Koordinaten meiner Schachfigur-PictureBoxen ein kleines Problemchen. Die Koordinaten für die PictureBox.Location sind new Point(boardLocation.X + rank * squareSize, boardLocation.Y + file * squareSize), wobei boardLocation den Abstand vom Fensterrand angibt. rank ist die Spalte, file ist die Zeile. Die squareSize ist 113, mit dieser Zahl wurden auch mittels Graphics.FillRectangle(...) die einzelnen Quadrate erstellt.

    Allerdings habe ich die Vermutung, dass eine Umrechnung zwischen Pixel, die Einheit also, mit der das Bitmap gezeichnet wurde, und Koordinate, die Einheit, mit der die Location der PictureBox angegeben wird, erforderlich ist.

    Ich finde aber keinen erfolgreichen Ansatz, wie ich das machen kann. Das mündet irgendwie alles dahin, dass das alles sehr unsauber aussieht.

    Hätte vielleicht einer eine Idee? Bin ich mit dem jetzigen Vorgehen auf dem Holzweg?

    Viele Grüße,
    Michael


    Dieses Bild zeigt, was schief läuft. Die PictureBox hat eine Size von 113, wie die Quadrate eigentlich auch, aber trotzdem wird diese kleiner als das "a8"-Qaudrat dargestellt. Außerdem sind der linke und obere Rand der PictureBox überhaupt nicht gleich mit dem linken und oberen Rand des "a8"-Quarats.
    Aus Gründen der besseren Erkennbarkeit hat die PictureBox einen pinken Hintergrund, dieser wird, wenn ich das Problem lösen konnte, auf transparent gestellt.


    Dieses Bild zeigt eine weitere Schachfigur, die allerdings exakt genau mit der Location Point(9, 9) und der Size(170, 174) in das Quadrat passt. Die eigentlichen "Koordinaten" des "a8"-Quadrats sind Point(6, 6) und Size(113, 113), zumindest wurde es mit diesen Zahlen gezeichnet.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „rwCapt“ ()

    @rwCapt ((PixelImFeld - Rand) / FeldBreite) ist der 0-basierte Index Deines Feldes.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, richtig, so weiß man, welches Feld man z.B. mit der Maus getroffen hat.

    Ich habe noch etwas mehr ausprobiert und bin zu dem Ergebnis gekommen, dass ich die x-Werte mal 1,5 nehmen muss, damit es zu 100 % passt. Die y-Werte wiederum muss ich mal 1,5395 nehmen. Wie kommen diese Zahlenwerte zustande? Mit der Bildschirmauflösung scheint das nichts zutun zu haben.

    Nochmal vereinfacht erklärt: Zeichne ich ein Quadrat mit Graphics.FillRectangle(...), sind die Werte für Größe und Position um den Faktor 1,5 für x-Werte und um den Faktor 1,5395 für die y-Werte geringer, als die Werte für Größe und Position bei einer PictureBox.

    rwCapt schrieb:

    Wie kommen diese Zahlenwerte zustande?
    Haben Deine Bilder solch ein Seitenverhältnis?
    Bereinige Dein Projekt, zippe es ohne obj,bin,.vs-Ordner und hänge es an:
    Erweiterte Antwort => Dateianhänge => Hochladen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bloß eine Vermutung, aber hast du in Windows das Scaling aktiv?
    Das müsste die Pixels Per Inch beeinflussen und dementsprechend sind die Werte verschoben, wobei ich mir die 1,5395 nicht erklären kann.
    Ich habe es versucht nachzustellen, bei mir passt es aber. Auch mit Skalierung (125 %) und einer Bildschirmauflösungsänderung passt es weiterhin.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class Form1
    2. Private ReadOnly DarkRectangles As New List(Of Rectangle)
    3. Private ReadOnly LightRectangles As New List(Of Rectangle)
    4. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    5. e.Graphics.FillRectangles(Brushes.Peru, LightRectangles.ToArray)
    6. e.Graphics.FillRectangles(Brushes.SandyBrown, DarkRectangles.ToArray)
    7. End Sub
    8. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    9. For x = 0 To 7
    10. For y = 0 To 7
    11. Dim NewRectangle As New Rectangle With {.Height = 113, .Width = 113, .X = x * 113, .Y = y * 113}
    12. If x Mod 2 = 0 Xor y Mod 2 = 0 Then
    13. LightRectangles.Add(NewRectangle)
    14. Else
    15. DarkRectangles.Add(NewRectangle)
    16. End If
    17. Next
    18. Next
    19. End Sub
    20. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    21. PictureBox1.Left = 113
    22. PictureBox1.Top = 113
    23. PictureBox1.Width = 113
    24. PictureBox1.Height = 113
    25. End Sub
    26. End Class

    Bilder
    • Result.png

      35,51 kB, 993×971, 45 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @rwCapt Mit einem 8*8-TableLayoutPanel hast Du alle Probleme vom Tisch, wenn Du in jedes Element ein entsprechendes UserControl packst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    rwCapt schrieb:

    Nachträglich etwas zu ändern
    Besser ist es, sich vorher über das Design Gedanken zu machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Absolut richtig. Ich bin mir darüber im Klaren, dass ich mehrere Anläufe brauchen werde, um das ganze für mich zufriedenstellend sauber und ordentlich auf die Reihe zu kriegen. Also erst mal mehr oder weniger alles aufs Reißbrett und dann nach und nach mal schauen, wie das alles zusammen passt.

    Ich hätte noch eine Frage. Kennt ihr chess.com? Die haben ein wunderbares Analysetool. chess.com/analysis?tab=analysis Nimmt man die Figuren per linkem Mausklick auf, hält die Maus gedrückt und verschiebt sie dann, so verschiebt man die Figur mit. Könnte man so eine Darstellung auch mit WinForms umsetzen? Ich hatte ja ursprünglich die Idee, das mit einem Bitmap auf der Form und dann mit PictureBoxen für die Schachfiguren zu machen. Allerdings überlappen sich die PictureBoxen, sobald man sie auf die Art und Weise während der Runtime verschiebt und außerdem sieht das irgendwie nicht wirklich schön aus.

    Es ginge auch, die Schachfiguren ebenfalls mittels DrawToBitmap als Bild darzustellen und die PictureBoxen dann unsichtbar zu machen. Sobald dann eine PictureBox verschoben werden soll, wird die entsprechende Figur auf dem Bitmap gelöscht, das Bitmap an der einen Stelle neu gezeichnet, die PictureBox wieder sichtbar gemacht. Damit überlappen die PictureBoxen nicht mehr, aber trotzdem wird das Bild in der PictureBox beim schnellen Verschieben gar nicht mehr angezeigt und der Rand der PictureBox wird auf dem Schachbrett-Bitmap sichtbar, da das System wahrscheinlich nicht mit dem Redraw hinterher kommt. Oder würde man, wenn man sowas umsetzen wollen würde, eher Richtung Direct2D gehen?

    rwCapt schrieb:

    Könnte man so eine Darstellung auch mit WinForms umsetzen?
    Klar. Mit transparentem Um-Bild geht das alles.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie genau? Was ist unter transparentem Um-Bild zu verstehen?

    Also, wie gesagt, das Bewegen von PictureBoxen währen der Laufzeit sieht nicht "smooth" aus, teilweise sind Ränder zu sehen oder eine PictureBox überdeckt die andere, auch wenn sie einen transparenten Hintergrund hat.

    Könnte das direkte Aufrufen von InvokePaint nach dem Verschieben einer PictureBox während der Runtime solche visuellen "Fehler" verhindern?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „rwCapt“ ()

    @rwCapt Q&D aber getestet:
    Neues Projekt, Form mit einem Button
    Form2, leer.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ' Button in Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Dim dlg = New Form2()
    4. dlg.Show(Me)
    5. End Sub
    6. '#################################
    7. Public Class Form2
    8. Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    9. Me.FormBorderStyle = FormBorderStyle.None
    10. Me.BackColor = Color.Aqua
    11. Me.TransparencyKey = Color.Aqua
    12. Dim bmp = New Bitmap("D:\Temp\_Test\Linien.png") ' ein Bild mit Rand. der transparent wird
    13. bmp.MakeTransparent(bmp.GetPixel(0, 0))
    14. Me.BackgroundImage = bmp
    15. End Sub
    16. End Class
    Da kannst Du die Form1 unter der transparenten Form2 bewegen.
    Das Bild musst Du natürlich bereitstellen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!