Images horizontal in PictureBox "durchlaufen" lassen abhängig von mouseover ' machbar?

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Unwesen.

    Images horizontal in PictureBox "durchlaufen" lassen abhängig von mouseover ' machbar?

    Moin,

    hab nun schon ein paar Stunden im Netz rumgesucht und nicht so recht was passendes gefunden. Wie der Titel schon sagt, würde ich gerne den Effect den man von Handys etc her kennt in einem Vb.Net Projekt nutzen. Jpegs eines Ordners sollen in einer Picturebox natlos aneinandergereiht bei MouseOver in die jeweilige Richtung vom Benutzer gezogen verden können.

    Bin bei der Suche über folgende Stichwörter gestolpert: ListImage ListView Scrollbar

    Mir ist aber überhaupt nicht klar, wie ich es hinbekommen soll, dass die Bilder Aussenkante an Aussenkante durch eine PictureBox gezogen werden können. Ist das überhaupt machbar in VB.Net; mit nicht zuviel Code? Für Ideen und Vorschläge wär ich natürlich sehr dankbar. Ich meine nicht das Ziehen eines Bildes von einer PicturBox zur anderen (wen das interessiert dem wird hier geholfen dotnet-snippets.de/dns/bild-vi…u-picturebox-SID1176.aspx).
    Stichwort GDI!

    ImageList's kannst du generell verwenden, muss aber nicht.
    Von einer PB rate ich dir ab, soweit ich weiß kannst du zwar mit PB.Image.Location die Position des Bildes in der PB bestimmen/abrufen, jedoch kannst du nicht mehrere Bilder in einer PB haben. Ich würde dazu wirklich GDI in einem Panel verwenden.
    Ich würde dazu wirklich GDI in einem Panel verwenden.
    GDI hat ja durchaus gewisse vorteile gegenüber Picturboxen, aber das Drag&Drop des jeweiligen Bildes wird dadurch nicht unbedingt erleichtert, oder? Jedenfalls wird das etwas komplizierter, als wenn ich nun Beispielsweise ein Feld aus einzelnen Pictureboxen nahtlos aneinandersetze, wobei jedes ein anderes Bild enthält. Per MouseDown könnte man dann das Betreffende Bild in eine neue Picturebox (die dann über dem zu verschiebendem Bild erscheint) kopieren, und diese dann woanders hin verschieben. Wäre zumindest eine Möglichkeit. (Aber ich tu mich ja auch etwas schwer mit GDI).

    //Edit so in etwa sähe meine Idee dazu aus:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'In die Form: 10 Pictureboxen, PictureBox1 wäre der "Transporter"
    2. '2-10 sind die aneinandergereihten Bilder
    3. 'Zu Testzwecken mach nen BorderStyle=Fixed Single um die PictureBoxen
    4. Private isdown As Boolean
    5. Private clickPoint As Point
    6. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    7. End Sub
    8. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    9. clickPoint = New Point(e.Location.X, e.Location.Y)
    10. isdown = True
    11. End Sub
    12. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    13. If isdown = True Then
    14. PictureBox1.Location = New Point(PictureBox1.Location.X - (clickPoint.X - e.Location.X), PictureBox1.Location.Y - (clickPoint.Y - e.Location.Y))
    15. End If
    16. End Sub
    17. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    18. isdown = False
    19. pb.Visible = True
    20. End Sub
    21. Dim pb As PictureBox
    22. Private Sub PictureBox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseDown, PictureBox3.MouseDown, PictureBox4.MouseDown, PictureBox5.MouseDown, PictureBox6.MouseDown, PictureBox7.MouseDown, PictureBox8.MouseDown, PictureBox9.MouseDown, PictureBox10.MouseDown
    23. pb = DirectCast(sender, PictureBox)
    24. PictureBox1.Image = pb.Image
    25. PictureBox1.Location = pb.Location
    26. pb.Visible = False
    27. PictureBox1_MouseDown(sender, e)
    28. End Sub
    29. 'Wie gesagt, das ist nur so eine Idee. Ganz ausgereift ist sie zwar eh nicht, aber ich muss ja auch keine Komplettlösungen als Antwort bringen^^


    Hm, jetzt wo ich die Fragestellung nochmal durchlese, kommt mir der Verdacht, dass ich eventuell etwas falsch aufgefasst haben könnte.. Naja, is auch schon spät...

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

    Danke für die sehr freundliche Unterstüzung. Besonderen Dank an Unwesen für die Arbeit die in der Antwort steckt. Sieht so aus, als ob es nicht das ist was ich dachte, aber auf alle Fälle ne super Idee mit den "PictureBox in PictureBox", um meine Vorstellung umzusetzen.

    So hab in der Mittagspause gerade Zeit gehabt, um mal einen kurzen Blick drauf zu werfen. Also die Idee ist ja das man eine PixturBox als sozusagen Passpartout benutzt. Das wär bei mir Picturebox1 (natürlich ohne sichtbaren Inhalt) und dann wenn man die Mouse in PictureBox 1 drückt und zieht sich die Lage von einer Picturebox2 ändert, in der das anzuzeigende Foto ist. Hab es mit folgendem Code auch ganz gut hinbekommen; dank Unwesens Vorlage.

    Ein Probelm hab ich noch und zwar bekomm ich es nicht hin die Eigenschaft von PictureBox2 von Invisible zu Visible hin und her zu stellen (siehe Code PictureBox1_DragOver then PictureBox2.Visible = True). PicturBox2 muss immer Visible sein damit es geht, dass macht aber den ganzen Effect kaputt, da die PicturBox2 ja nur zu sehen sein soll wenn sie in der PictureBox1 ist.

    VB.NET-Quellcode

    1. Private isdown As Boolean
    2. Private clickPoint As Point
    3.  
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
    5. PictureBox2.Visible = False
    6. End Sub
    7.  Private Sub PictureBox1_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles PictureBox1.DragOver
    8. PictureBox2.Visible = True
    9. End Sub
    10. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    11. clickPoint = New Point(e.Location.X, e.Location.Y)
    12. isdown = True
    13. End Sub
    14. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    15. If isdown = True Then
    16. PictureBox2.Location = New Point(PictureBox1.Location.X + (e.Location.X), PictureBox1.Location.Y)
    17. End If
    18. End Sub
    19.  
    20. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    21. isdown = False
    22. End Sub


    P.S.: Man sollte unter Eigenschaften noch PicturBox2 auf "Enabled = False" stellen damit man immer einen MouseMove in PictureBox1 hinbekommt auch wenn diese von PictureBox2 komplett bedeckt ist.
    Irgendwelche Tips / Vorschläge wie man die PictureBox2 unsichtbar machen kann, solange sie ausserhalb PictureBox1 liegt.

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

    Hmja, das mit dem Invisible machen war eine Notlösung, damit dann die dorthin kopierte Picturebox1 draggen kann. Klar, dass der Code so nicht wirklich optimal ist. Ich denke, hier ließe sich auch gut GDI einsetzen. Das Bild aus der zu draggenden Picturbox in ein Image kopieren und es per gdi an die Position der pb Painten.

    VB.NET-Quellcode

    1. Dim g As Graphics
    2. Dim picc As Image
    3. picc = New System.Drawing.Bitmap(pb.image)
    4. g.DrawImage(picc, pb.top, pb.left, pb.width,pb.height)
    5. me.invalidate


    Auch nur grob umrissen, spiel einfach mal damit rum, solange keiner ne bessere Antwort gibt. ^^
    Falls du GDI und damit auch die ".DrawImage"-Funktion nutzen solltest, achte darauf, dass mit ".DrawImage" die Bilder gern kleiner angezeigt werden als sie sind.
    Um das zu verhindern kannst du ein neues Rectangle deklarieren und dies als "Point"-Parameter übergeben.

    MfG,
    X-Zat / Momo
    Moin VBler,

    hab eigendlich alles so hinbekommen wie ich es vor hatte. Dank der Hilfe von Unwesen. Das Problem, dass die zu bewegende PictureBox sichtbar ist und ich es nicht hinbekam sie unsichtbar zu schalten, habe ich über den zugegen sehr unschönen Trick hinbekommen, dass ich einfach die Bereiche in denen nichts zu sehen sein sollte mit Panels "verdeckt" habe. Ja ich kann mir denken, dass das nun wirklich nicht sauber ist, es macht aber was es soll. Leider wie schon von Anfang an vermutet, ist es wohl mit den PictureBoxen so, dass sie für diese Aufgabenstellung nicht wirklich geeignet sind (Hauptproblem ist hier, dass das Bild bei der Bewegung flackert und das schon wenn ich nur eine PictureBox bewege. Könnte mir vorstellen, wenn ich mehrere "in Reihe schalte" das das Problem noch schlimmer wird und schon mit einer PB ist es störend). Ich werde nun mal den Ansatz mit GDI versuchen. Dank an Unwesen und X-Zat für die Hinweise in diese Richtung.

    Das könnte nun ein bischen dauern, da ich damit so gut wie keine Erfahrung habe. Wenn jemand ne gute Netzseite kennt wo Grundlagen von GDI beschrieben stehen bitte posten. Die Aufgabe, die ich lösen will, ist immer noch die gleiche wie im OP, aber diesmal eben mit Hilfe von GDI. Bildbearbietung/Zeichnen und alles was man mit GDI etc. anstellen kann interessieren mich im Moment nicht.



    @toto: In meinem vorigen Posting steht der ganz Code, habe noch etwas veränder an folgenden Subs. Sonst ist das alles was man braucht.

    VB.NET-Quellcode

    1. Private PB2LocTmp As Point
    2. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox.MouseDown
    3. PB2LocTmp = PictureBox2.Location
    4. clickPoint = New Point(e.Location.X, e.Location.Y)
    5. isdown = True
    6. End
    7. SubPrivate Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox.MouseMove
    8. If isdown = True Then
    9. PictureBox2.Location = New Point(PB2LocTmp.X - (clickPoint.X - e.Location.X), PictureBox1.Location.Y)
    10. End If
    11. End Sub

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

    Das Bildflackern kannst du reduzieren, wenn du die Form DoubleBuffered=True stellst.

    So, ich lass mal einen code hier, just for Fun.
    Spoiler anzeigen

    Hat jetzt nicht besonders viel mit dem Thema zu tun, aber wer weiß, wozu es gut ist...

    Die FormSize ist 1024 x 786, wobei das auch relativ egal ist. Benötigt einen Timer.


    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Levelgröße As Integer = 230
    3. Dim bmp As Bitmap = New Bitmap(1024, 786)
    4. Dim gfx_item As Image
    5. Dim g As Graphics
    6. Dim xpos As Integer
    7. Dim ypos As Integer
    8. Dim fxx As Single
    9. Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
    10. Timer1.Start() 'Bei Klick in die Form Timer starten
    11. End Sub
    12. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    13. Me.BackgroundImageLayout = ImageLayout.None 'Backgroundimage bei 0,0 beginnen, nicht wiederholen, stretchen, zoomen oder sonstwas
    14. Timer1.Interval=1 'Etwas schnell vllt, aber ist ja nur zum gucken ...
    15. Timer1.Stop() 'Noch net starten
    16. End Sub
    17. Private Sub ErstelleBackground()
    18. g = Graphics.FromImage(bmp) 'Worauf soll gezeichnet werden?
    19. ' gfx_item = New System.Drawing.Bitmap(My.Resources.img1)
    20. xpos = 20 'Startkoordinate
    21. ypos = 20
    22. For i As Integer = 0 To Levelgröße
    23. 'g.DrawImage(gfx_item, xpos, ypos, 40, 40)
    24. g.DrawRectangle(Pens.Black, xpos, ypos, 40, 40) 'ein Quadrat zeichnen
    25. g.FillRectangle(Brushes.PaleVioletRed, xpos, ypos, 40, 40)
    26. g.RotateTransform(fxx) 'Muhaha
    27. xpos += 40 : If xpos > 820 Then xpos = 20 : ypos += 40
    28. Next
    29. Me.BackgroundImage = bmp 'Die bemalte bmp als Background benutzen
    30. End Sub
    31. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    32. fxx += 0.01 ' oO
    33. ErstelleBackground()
    34. Me.Invalidate()
    35. End Sub
    36. End Class


    //Edit:
    Galileo Openbook ist oft recht nützlich um die Grundlagen zu lernen.

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

    Erster Test leider fehlgeschlagen habs mal so versucht klein anzufangen.

    VB.NET-Quellcode

    1. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2. Dim Img As Image = Image.FromStream(New MemoryStream(File.ReadAllBytes("1.jpg")))
    3. Dim g As Graphics = Graphics.FromImage(Img)
    4. g.DrawImage(Img, 0, 0)
    5. Me.Invalidate()
    6. End sub

    Leider nicht mit dem von mir erwartetem Ergebnis.

    Ich dachte ich lade ich ein Bild 1.jpg in den Speicher, dann erstelle ich ein Graphics Objekt mit dem vorher geladenen Bild. Jetzt dachte ich, ich lass es mir in meiner Form1 anzeigen, in dem ich mit Drawimage(Img, 0, 0) den Befehl dazugebe und ich denke das Me.Invalidate() sorgt dafür, dass die Grafik sichtbar bleibt bei Refresh. Als Erbenis bekomm ich aber eine leere Form, nix zu sehen. Compilieren geht ohne Fehler, aber zur Laufzeit wird kein Bild angezeigt. Jemand ne Ahnung was da falsch ist? So gings auch nicht:

    VB.NET-Quellcode

    1. 'g.DrawImage(Img, Img.Width, Img.Height)
    2. 'g.DrawImage(Img, 0, 0, Img.Width, Img.Height)
    3. 'g.DrawImage(Img, PictureBox1.Top, PictureBox1.Left, PictureBox1.Width, PictureBox1.Height)




    So ein kleiner Erfolg. Ich habs mit Paint Event hinbekommen. Raff aber noch nicht so ganz warum das mit sub loadform nicht ging?

    VB.NET-Quellcode

    1. Private Sub form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles MyBase.Paint
    2. Dim Img As Image = Image.FromStream(New MemoryStream(File.ReadAllBytes("1.jpg")))
    3. 'Dim g As Graphics = Graphics.FromImage(Img)
    4. e.Graphics.DrawImage(Img, 0, 0, 100, 100)
    5. 'Me.Invalidate()
    6. End Sub


    Hier musste ich das Me.Invalide auskommentieren sonst flackerte es nur.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „nogood“ ()

    Im Loadform kann es so, wie du es gemacht hast nicht gehen:
    Stell dir das Graphics-Objekt als Papier vor, auf dem du zeichnen willst. das kann ein Bild sein (FromImage) oder z.B. deine Form (Me.Creategraphics, ist aber nich so schön)
    Du hast also in deinem Code lediglich dein bild auf das Bild gezeichnet, mehr nicht. Mit Invalidate hast du dann die grafik deiner Form für ungültig erklärt, so dass automatisch die Paint-Sub aufgerufen wird, um wieder alles neu zu zeichnen. da du nicht auf die Form gezeichnet hast, bleibt die leer.

    Somit hast du im 2. Beispiel im Grunde (fast) alles richtig gemacht, denn e.graphics ist das "Papier" der Form. du zeichnest also dein Bild direkt auf die Form und zwar immer dann, wenn sie neu gezeichnet werden muß (nach dem Verändern der Größe, dem verschieben aus dem Bildschirm, dem verlust des Focus usw.). Wenn du hier Invalidate aufrufst, hast du also eine Endlosschleife, daher das flackern.

    Lösungsmöglichkeit:
    Zeichne außerhalb von Paint auf ein Bild (leere Bitmap o.ä.) und zeichne im Paint das Bild an der gewünschten Position auf dein Fenster. Die Position bekommst du ja (für dein Vorhaben) aus dem MouseMove der Form. Entsprechend der sichtbaren Anzahl Bilder generierst du entweder eine entsprechende Anzahl Bitmaps oder zeichnest alle Bilder auf ein streifenförmiges Bitmap.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Bin wieder ein Stück weiter mit der Hilfe von Vatter und den anderen Postern. Mit dem Code geht es im Prinzip auch, aber es flackert sehr stark bei Mouse Move. Ich weiss nicht wie ich einen Refresh der Form "richtig" hinbekomme. Mit Me.Invalidate innerhalb des Mouse-Move Events jedenfalls ein schlechtes Ergebnis.

    VB.NET-Quellcode

    1. Dim Img As Image = Image.FromStream(New MemoryStream(File.ReadAllBytes("1.jpg")))
    2. Private isdown As Boolean
    3. Private x As Integer = 0
    4. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    5. isdown = True
    6. End Sub
    7. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    8. If isdown = True Then
    9. x = e.Location.X
    10. Me.Invalidate()
    11. End If
    12. End Sub
    13. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    14. isdown = False
    15. End Sub
    16. Private Sub form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles MyBase.Paint
    17. e.Graphics.DrawImage(Img, x, 200, 100, 100)
    18. End Sub



    1
    Wo muss/sollte Me.Invalidate stehen. Oder was mach ich mit Me.Invalidate. Gibt es eine "richtigerer" Lösung, um das Image bei Bewegung der Mouse an den neuen Ort zu zeichnen (ohne Flackern wenn sich das Bild bewegt)?

    2 oder hab ich Vatters Vorschlag falsch umgesetzt? Muss ich noch eine extra Bitmap erstellen in die ich das Image lade. Und verschiebe ich dann die Bitmap ,und so zu sagen das Image nur indirekt ?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „nogood“ ()

    Jo,

    hab mir unwesens Code in seiner letzen Post nochmal angesehen und daraus das mit dem timer abgeschaut; plus form1 auf doubleBuffered = true gestellt nun läufts schon recht flüssig. Werd ich noch ein wenig testen müssen, um zu sagen ob das nun "perfect" ist. Danke an all die netten Poster die mir sehr geholfen haben. Guten Rutsch...


    VB.NET-Quellcode

    1. Dim Img As Image = Image.FromStream(New MemoryStream(File.ReadAllBytes("1.jpg")))
    2. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    3. Timer1.Interval = 1
    4. Timer1.Start()
    5. End Sub
    6. Private isdown As Boolean
    7. Private x As Integer = 0
    8.  
    9. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    10. isdown = True
    11. End Sub
    12. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    13. If isdown = True Then
    14. x = e.Location.X
    15. End If
    16. End Sub
    17. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    18. isdown = False
    19. End Sub
    20. Private Sub form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles MyBase.Paint
    21. e.Graphics.DrawImage(Img, x, 200, 300, 300)
    22. End Sub
    23. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    24. Me.Invalidate()
    25. End Sub




    Bild läuft relativ flüssig, jedensfalls viel besse als mit der vorigen Lösung mit PictureBoxen. Jetzt versuchen ich, dass das Bild ab einer Grenze nichtmehr zu sehen sein soll. Im Moment noch planlos; klar könnte ich wieder alles mit Panels voll klatschen um so den Rest vom Bild zu verstecken aber so war das bestimmt nicht geplannt. Es soll halt so aussehen als ob Bilder hinter einem statischen Paspartout vorbeilaufen.

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

    X-Zat schrieb:

    Falls du GDI und damit auch die ".DrawImage"-Funktion nutzen solltest, achte darauf, dass mit ".DrawImage" die Bilder gern kleiner angezeigt werden als sie sind.
    Um das zu verhindern kannst du ein neues Rectangle deklarieren und dies als "Point"-Parameter übergeben.

    MfG,
    X-Zat / Momo

    Kannst du das bitte genauer erläutern? Bei mir werden die DrawImage Bilder 1-2 Pixel größer angezeigt.
    So mache ich das im Moment, wie kann ich da dann das New Rectangle benutzen?

    VB.NET-Quellcode

    1. g.DrawImage(dragObj, xpos, ypos, IconSizeX, IconSizeY)


    //Edit
    Also für 20x20 Px große Images muss ich derzeit bei Drawimage jeweils 4 Pixel bei IconSizeX und Y abziehen, damit sie die selbe Größe haben wie eine 20x20 Picturebox.
    Das ist eher unschön, vor allem da ich bei anderen Größen dann einen anderen Wert abziehen müsste. Versteh ich net, warum ist das so?

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

    Unwesen schrieb:

    Also für 20x20 Px große Images muss ich derzeit bei Drawimage jeweils 4 Pixel bei IconSizeX und Y abziehen, damit sie die selbe Größe haben wie eine 20x20 Picturebox.
    Vergleiche mal die Size mit der Clientsize-Eigenschaft eines Steuerelementes... ;) . Die Size-Eigenschaft beinhaltet den Rand.

    @nogood
    Ich habe mal eine Anwendung mit der "Schiebe-Funktion" für Bilders hingefummelt. Du brauchst eine Form mit 1 Button:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form2
    3. Private QuellRect, ZielRect As RectangleF 'Quell- und Zielrahmen
    4. Private Alt_Point As Single 'Zwischenspeicher für die Mausbewegung
    5. Private Move_Ein As Boolean 'Freigabe Verschieben
    6. Private Verschiebung As Single 'Verschiebeinkrement
    7. Private OPF As New OpenFileDialog 'Openfiledialog zur Bilderauswahl
    8. Private Film As Bitmap 'Das Filmbild beinhaltet die ausgewählten Bilder als Folge
    9. Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    10. Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.UserPaint Or _
    11. ControlStyles.AllPaintingInWmPaint Or _
    12. ControlStyles.SupportsTransparentBackColor Or _
    13. ControlStyles.ResizeRedraw, True)
    14. 'Setstyle zur Verhinderung von bösen Effekten :)
    15. 'Das hab ich als Standard in der Toolbox hängen
    16. End Sub
    17. ''' <summary>
    18. ''' Schieben des Quellrahmens
    19. ''' </summary>
    20. ''' <param name="sender"></param>
    21. ''' <param name="e"></param>
    22. ''' <remarks></remarks>
    23. Private Sub Form2_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
    24. If Move_Ein Then
    25. If Film IsNot Nothing Then
    26. Verschiebung = Alt_Point - e.X
    27. If Ausserhalb() Then
    28. Verschiebung = 0
    29. End If
    30. QuellRect.X += Verschiebung
    31. End If
    32. End If
    33. Alt_Point = e.X
    34. Invalidate()
    35. End Sub
    36. ''' <summary>
    37. ''' Schieben Starten/Freigeben
    38. ''' </summary>
    39. ''' <param name="sender"></param>
    40. ''' <param name="e"></param>
    41. ''' <remarks></remarks>
    42. Private Sub Form2_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
    43. Alt_Point = e.X
    44. Move_Ein = True
    45. End Sub
    46. ''' <summary>
    47. ''' Schieben anhalten
    48. ''' </summary>
    49. ''' <param name="sender"></param>
    50. ''' <param name="e"></param>
    51. ''' <remarks></remarks>
    52. Private Sub Form2_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
    53. Move_Ein = False
    54. 'Der Timer sorgt für ein sanftes Verzögern nach dem Loslassen der taste aus der Bewegung heraus
    55. Timer1.Interval = 20
    56. Timer1.Start()
    57. End Sub
    58. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    59. FileOpen()
    60. End Sub
    61. ''' <summary>
    62. ''' Bilder auswählen (evtl. Filter erweitern)
    63. ''' </summary>
    64. ''' <remarks></remarks>
    65. Private Sub FileOpen()
    66. OPF.Filter = "Fotos *.jpg|*.jpg"
    67. OPF.Multiselect = True
    68. If OPF.ShowDialog = Windows.Forms.DialogResult.OK Then
    69. Film_Laden()
    70. End If
    71. End Sub
    72. ''' <summary>
    73. ''' Laden der ausgewählten Bilder auf das Film-Bild
    74. ''' </summary>
    75. ''' <remarks></remarks>
    76. Sub Film_Laden()
    77. 'Diese Sub ggf. in anderen Thread auslagern um die Form nicht ins Stocken zu bringen
    78. Dim Hoehe As Single = CSng(Me.ClientSize.Height / 2)
    79. ZielRect.Y = Hoehe / 2
    80. 'Breite für Filmbild ermitteln
    81. Dim Breite As Single = 0
    82. Dim Faktor As Single 'Scalierung der Breite entsprechend Darstellungshöhe
    83. For Each Pfad As String In OPF.FileNames
    84. Faktor = Hoehe / Image.FromFile(Pfad).Height
    85. Breite += Image.FromFile(Pfad).Width * Faktor
    86. Next
    87. 'Leeres Bitmap erzeugen
    88. Film = New Bitmap(CInt(Breite), CInt(Hoehe))
    89. 'graphics-Objekt erzeugen
    90. Using g As Graphics = Graphics.FromImage(Film)
    91. For Each Pfad As String In OPF.FileNames
    92. Dim _bmp As Image = Image.FromFile(Pfad)
    93. Dim rect As New RectangleF(QuellRect.X, 0, _bmp.Width * Faktor, Hoehe)
    94. g.DrawImage(_bmp, rect)
    95. QuellRect.X += _bmp.Width * Faktor
    96. Next
    97. End Using
    98. QuellRect = New RectangleF(0, 0, Me.Width, Film.Height)
    99. ZielRect = New RectangleF(0, Hoehe / 2, Me.Width, Film.Height)
    100. 'Form neuzeichnen
    101. Invalidate()
    102. End Sub
    103. ''' <summary>
    104. ''' Paint-Event zeichnet den Quellausschnitt des Filmbildes in die Form
    105. ''' </summary>
    106. ''' <param name="sender"></param>
    107. ''' <param name="e"></param>
    108. ''' <remarks></remarks>
    109. Private Sub Form2_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    110. If Film IsNot Nothing Then
    111. e.Graphics.DrawImage(Film, ZielRect, QuellRect, GraphicsUnit.Pixel)
    112. End If
    113. End Sub
    114. ''' <summary>
    115. ''' Timer für Nachlauf nach dem Loslassen der Taste
    116. ''' </summary>
    117. ''' <param name="sender"></param>
    118. ''' <param name="e"></param>
    119. ''' <remarks></remarks>
    120. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    121. QuellRect.X += Verschiebung
    122. Verschiebung = Verschiebung * 0.98F
    123. If Verschiebung < 2 AndAlso Verschiebung > -2 Then
    124. Timer1.Stop()
    125. End If
    126. If Ausserhalb() Then
    127. Timer1.Stop()
    128. End If
    129. Invalidate()
    130. End Sub
    131. ''' <summary>
    132. ''' Überwacht, ob der Quellrahmen außerhalb des Filmbildes liegt
    133. ''' </summary>
    134. ''' <returns></returns>
    135. ''' <remarks></remarks>
    136. Private Function Ausserhalb() As Boolean
    137. If QuellRect.Right > Film.Width AndAlso Verschiebung > 0 OrElse _
    138. QuellRect.Left < 0 AndAlso Verschiebung < 0 Then
    139. Return True
    140. Else
    141. Return False
    142. End If
    143. End Function
    144. ''' <summary>
    145. ''' Zeichnet neu bei einer Änderung der Größe
    146. ''' </summary>
    147. ''' <param name="sender"></param>
    148. ''' <param name="e"></param>
    149. ''' <remarks></remarks>
    150. Private Sub Form2_SizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged
    151. ZielRect = New RectangleF(0, CSng(Me.Height / 4), Me.Width, CSng(Me.Height / 2))
    152. QuellRect.Width = Me.Width
    153. 'Es fehlt noch eine Größenänderung der Breite des Filmbildes, dadurch wird noch verzerrt dargestellt
    154. Invalidate()
    155. End Sub
    156. End Class

    Ich hoffe, die Kommentare helfen etwas. Das ganze ist so aufgebaut, dass man mit dem Button einen Openfiledialog öffnet und sich dort die anzuzeigenden Bilder auswählt. Nach OK werden die Bilder nebeneinander in ein Bitmap gezeichnet. Ein Quellrechteck bestimmt, welcher Teil des Streifens auf der Form angezeigt wird. Mit dem Mousemove wird also das Quellrechteck verschoben und jedesmal mit Invalidate() die Form neu gezeichnet.
    Der Timer is nur ein "Schnörkel", der nach dem Loslassen der Maustaste das Bild etwas nachgleiten lässt (sieht schön aus :D ).
    Zu guter Letzt wird überwacht, ob das Quellrechteck das Filmbild verlässt und damit wird das Verschieben angehalten.

    Fiel Fergnügen beim Probieren
    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Hallo ich bin platt, danke für die sehr nette Unterstüzung. Hab Vatters Code natürlich gleich mal ausprobiert. Klappt ja super. Ich bin wirklich erstaunt wie super das Forum ist. Ich hoffe, dass ich auch bei Zeiten dem ein oder anderen helfen kann. unwesen und vatter brauch ich mit meinem Bauern Code jedenfalls nicht kommen ;).

    @Vatter das mit dem langsam Auslaufen nach einer Bewegung hatte ich auch schon angedacht und hatte das auch umgesetzt. Ich hab "sogar" mit v=s/t die Geschwindigkeit der Mousebewegung einfliesen lassen bei ausfaden. Je länger und schneller gezogen wurde desto länger und weiter lief das Bildband weiter. Ist auch soweit ganz gut geglückt. Ein Prob. hab ich dadurch jedoch neu entwickelt. Wenn die Bilder noch am auslaufen waren und der User dann schon eine MouseDown ausführte und in die andere Richtung gezogen hat, wurde erst das Auslaufen in die andere Richtung bis zu Ende ausgeführt und dann erst die Bewegung in die neue Richtung. Das liegt daran, das ich das Auslaufen in der MouseUp Sub hab und dort die Schleife erst zuende laufen muss, bevor die anstehende MouseDown Sub abgearbeit wird. Weis einer wie man die Sub MouseUp sofort unterbrechen kann, wenn ein neues MouseDown ansteht. Ist hab in meinen anderen Progs schonmal mit Backgroundworker gearbeitet wär das so ein Fall wo man es damit lösen könnte oder gibts es einen einfachen Befehlt, um Prioritäten fest zu legen (MouseDown wichtiger als Sub MouseUp). So was wie exit if MouseDown ???

    Also noch mal viellen vielen Dank an Vatter und die anderen Poster. Nogood

    nogood schrieb:

    Wenn die Bilder noch am auslaufen waren und der User dann schon eine MouseDown ausführte und in die andere Richtung gezogen hat, wurde erst das Auslaufen in die andere Richtung bis zu Ende ausgeführt und dann erst die Bewegung in die neue Richtung.
    Bei meinem Code is das Auslaufen im Timer realisiert. Der Effekt von dir tritt aber bei mir auch auf :D.
    Das geht aber mit Timer.Stop im Mousedown ganz einfach zu unterbrechen.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Das liegt daran, das ich das Auslaufen in der MouseUp Sub hab und dort die Schleife erst zuende laufen muss, bevor die anstehende MouseDown Sub abgearbeit wird. Weis einer wie man die Sub MouseUp sofort unterbrechen kann, wenn ein neues MouseDown ansteht.
    Du könntest beispielsweise mal deine PN lesen, die seit dem 2.1. in deinem Postfach liegt? Da dürfte zumindest eine Möglichkeit beschrieben sein. Und falls du diese schon gelesen und verworfen hast, dann hast du zumindest vergessen eine rückmeldung zu geben.