Laden...

Scrollen in den negativer Bereich der Form

Erstellt von Gumba vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.021 Views
G
Gumba Themenstarter:in
28 Beiträge seit 2010
vor 12 Jahren
Scrollen in den negativer Bereich der Form

hallo ihr lieben 😉

ich hab mal wieder ein kleines Problem, welches ich unter der suche nicht gefunden habe.
Und zwar ist es so, dass ich eine Art Karte von Webseiten erstellen möchte, wobei die aktuelle Webseite immer in der Mitte der Form angezeigt werden soll. So weit kein Problem. Da Problem kommt jedoch, wenn Webseiten links der aktuellen gezeichnet werden. Dabei gehen diese über die Form hinaus (in den negativen Bereich jenseits von 0 😄) und ich konnte noch keine Möglichkeit finden, welche es mir erlaubt in diesen Bereich zu scrollen. AutoScroll ist natürlich auf true 😉
Ich hab mir schon gedanken darüber gemacht, dann "einfach" alle Pictureboxen entsprechend nach rechts zu verschieben, so dass es passt, nur leider weiß ich nicht, wie ich die aktuelle dann in der Mitte halten soll...

Hier noch ein bisschen Code, wie die Pictureboxen erstellt werden:


for(i = 0; i < brlist.Count; i++)
{
   pb.Add(new PictureBox());
   map.Controls.Add(pb[i]);
   pb[i].Size = new Size(aufx / 7, aufy / 7);
   pb[i].SizeMode = PictureBoxSizeMode.StretchImage;
   pb[i].Image = image;

   if (i < weblist.IndexOf(aktweb))
      pb[i].Location = new Point(map.ClientSize.Width / 2 - pb[i].Width / 2 - (weblist.IndexOf(aktbr) - i) * aufx / 6, map.ClientSize.Height / 2 - pb[i].Height / 2);
   else if (i > weblist.IndexOf(aktweb))
      pb[i].Location = new Point(map.ClientSize.Width / 2 - pb[i].Width / 2 + (i - weblist.IndexOf(aktbr)) * aufx / 6, map.ClientSize.Height / 2 - pb[i].Height / 2);
   else
      pb[i].Location = new Point(map.ClientSize.Width / 2 - pb[i].Width / 2, map.ClientSize.Height / 2 - pb[i].Height / 2);
}

weblist ist eine Liste mit allen Webseiten,
pb ist eine Liste mit entsprechender Anzahln an Pictureboxen,
map ist meine Form,
aufx ist die Bildschrimauflösung in x Richtung (dementsprechend werden die Pictureboxen proportional angepasst)
aufy ist die Bildschirmauflösung in y Richtung
Bei Fragen einfach melden 😉

Mfg
Gumba

Ach so hier noch ein Bild, welches die Situation beschreibt

5.742 Beiträge seit 2007
vor 12 Jahren

Hallo Gumba,

mit Pictureboxen kommst du da nicht weit - zeichne lieber wie in [Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox) beschrieben in OnPaint (nebenbei geht das so auch deutlich performanter).

Dann kannst du mittels einer TranslateTransform einfach alles verschieben.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Gumba,

ermittle die kleinste vorkommende Koordinate (also die negative Koordinate, mit dem größten Absolutwert). Addiere diesen Absolutwert auf alle vorkommenden Koordinaten. Anschließend ist die kleinste vorkommende Koordinate 0 und damit sollte wieder alles passen. Wenn sich dadurch die Scrollposition verschiebt, kannst du ja AutoScrollPosition anschließend so setzen, dass wieder alles stimmt.

Das beschreibt nur das Prinzip. Die praktische Umsetzung von winSharp ist vermutlich einfacher.

herbivore

G
Gumba Themenstarter:in
28 Beiträge seit 2010
vor 12 Jahren

@winSharp93 ich weiß auch nicht warum ich pictureboxen genommen hab, wo ich den rahmen ja schon via graphics zeichne 🤔

@herbivore danke für die herleitung 🙂 damit konnte ich winsharps ansatz optimal umsetzen. 👍

hier noch mal der finale code:


private void map_Paint(object sender, PaintEventArgs e)
        {
            if (weblist.IndexOf(aktweb) * aufx / 6 + aufx / 14 >= map.ClientSize.Width / 2)
            {
                int add = weblist.IndexOf(aktweb) * aufx / 6  + aufx / 14 - map.ClientSize.Width / 2;
                e.Graphics.TranslateTransform(add, 0);
            }

            for (i = 0; i < weblist.Count; i++)
            {
                if (i < weblist.IndexOf(aktweb))
                    e.Graphics.DrawImage(GenerateScreenshot(weblist[i]),
                                         map.ClientSize.Width / 2 - aufx / 14 - (weblist.IndexOf(aktweb) - i) * aufx / 6,
                                         map.ClientSize.Height / 2 - aufy / 14,
                                         aufx / 7, aufy / 7);
                else if (i > weblist.IndexOf(aktweb))
                    e.Graphics.DrawImage(GenerateScreenshot(weblist[i]),
                                         map.ClientSize.Width / 2 - aufx / 14 + (i - weblist.IndexOf(aktweb)) * aufx / 6,
                                         map.ClientSize.Height / 2 - aufy / 14,
                                         aufx / 7, aufy / 7);
                else
                    e.Graphics.DrawImage(GenerateScreenshot(weblist[i]),
                                         map.ClientSize.Width / 2 - aufx / 14,
                                         map.ClientSize.Height / 2 - aufy / 14,
                                         aufx / 7, aufy / 7);

                Pen pen = new Pen(Color.Lime, 5);
                e.Graphics.DrawRectangle(pen,
                                         map.ClientSize.Width / 2 - aufx / 14 - 5,
                                         map.ClientSize.Height / 2 - aufy / 14 - 5,
                                         aufx / 7 + 9,
                                         aufy / 7 + 9);
            }
        }

EDIT.: Nachdem gescrollt wurde sind die Bilder verschwunden.. Sollte es aber nicht so sein, dass per Scroll die Paint-Methode aufgerufen wird? Es passiert auch, dass der Clientbereich plötzlich ein rotes X auf weißem grund zeigt. Ich kann dazu leider kein bild hochladen, dass ein screenshot daon nicht möglich ist. Außerdem kommt es mit teilweise so vor, dass er mit dem Zeichnen beim Scrollen nicht hinterher kommt 🙁
Vielen Dank für eure Hilfe 👍

Mfg
Gumba

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Gumba,

Sollte es aber nicht so sein, dass per Scroll die Paint-Methode aufgerufen wird?

beim Scrollen wird Paint normalerweise nur für den Bereich aufgerufen, der durch das Scrollen neu sichtbar geworden ist. Das ist üblicherweise ausreichend.

Es passiert auch, dass der Clientbereich plötzlich ein rotes X auf weißem grund zeigt.

Das ist normalerweise ein Anzeichen, dass der Paint-EventHandler eine Exception geworfen hat.

herbivore

5.299 Beiträge seit 2008
vor 12 Jahren

der code ist vmtl. sehr unperformant, weil alle Bilder in jedem Paint scheinbar neu generiert werden, bevor sie gezeichnet werden.

Dass alle Bilder gezeichnet werden, ist i.O. Denn da das Graphics geclipt ist, nehmen die Zeichnungen von Bereichen ausserhalb des Clips fast keine Zeit in Anspruch.

Aber wie gesagt: dass jedes Bild neu generiert wird...

Der frühe Apfel fängt den Wurm.

G
Gumba Themenstarter:in
28 Beiträge seit 2010
vor 12 Jahren

ok ich hab jetzt testweise nur ein rechteck zeichnen lassen. das rote X kommt nicht mehr, aber der rahmen ist beim langsamen hin und wieder zurück scrollen nicht zu sehen, beim schnellen scrollen entstehen grafikfehler 🙁


private void map_Paint(object sender, PaintEventArgs e)
{
     e.Graphics.DrawRectangle(pen, 100, 100, 200, 200);
}

mfg
Gumba

EDIT.: Wenn ich die Form Resize wird das rechteck wie gewünscht gezeichnet. Es scheint also nur beim scrollen probleme zu geben...

EDIT2.: Also manchmal könnt ich mich echt Ohrfeigen 😜 Wenn man die AutoscrollPosition weglässt is klar warums nich gescheit gezeichnet wird 😁
Also mit

e.Graphics.DrawRectangle(Pens.Red, 100 + map.AutoScrollPosition.X, 100 + map.AutoScrollPosition.Y, 200, 200);

klappts jez 👍

Das mit dem Generieren der Screenshots hab ich auf den Aufruf der Form gelegt. Wird also nur noch 1x zu Beginn ausgeführt 😉

Vielen Dank noch mal für eure Hilfe 😁

Mfg
Gumba

5.742 Beiträge seit 2007
vor 12 Jahren

Also manchmal könnt ich mich echt Ohrfeigen 😛 Wenn man die AutoscrollPosition weglässt is klar warums nich gescheit gezeichnet wird

Wie gesagt: Wenn du transformierst, brauchst du das nicht explizit einzurechnen.

Kürzlich habe ich ein fremdes Projekt genau um eine solche Autoscroll- (und sogar Zoom-) Funktionalität erweitert.
Der Code findet sich in der ScrollableZoomableControl.cs - man muss nur von dieser ableiten und Measure sowie PaintContent überschreiben und kriegt Scrolling und Zooming ohne weiteren Aufwand (bis, auf dass man in Eventhandlern ClientPointToContent verwenden muss).

G
Gumba Themenstarter:in
28 Beiträge seit 2010
vor 12 Jahren

Wie gesagt: Wenn du transformierst, brauchst du das nicht explizit einzurechnen.

Tu ich auch nicht und ich benutze ja dein transformieren 😉 Transformiert wird halt lediglich die AutoScrollPosition 😁

Dein Code ist sehr interessant! Der wird mit bestimmt bei etwaigen Zusatzfunktionen hilfreich sein 😁 Sollten Fragen dazu auftauchen, werd ich mich auf jeden Fall noch mal bei dir melden 😉

mfg
Gumba