Laden...

Imagemap in WindowsFormsApplication in c# (keine Webapplication!)

Erstellt von vandadito vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.292 Views
Thema geschlossen
V
vandadito Themenstarter:in
5 Beiträge seit 2012
vor 12 Jahren
Imagemap in WindowsFormsApplication in c# (keine Webapplication!)

ich möchte gerne ne WFA schreiben doch ich weis nicht wie das mit dem imagemap funktioniert? hab schon lange im Internet durchsucht.

ich möchte dies in c# machen und es ist KEINE web-application, da wüsste ich wies geht

ich verwende Microsoft Visual Studio 10, das controll seh ich zwar unter "standart" aber es ist gräulich? das heisst man kann es nicht drauf ziehen.

wie geht jetzt das mit dem imagemap genau? eigentlich müsst ich wenn dies geht nur wissen wie ich das imagemapcontroll verwenden kann, dann solllte es selbsterklärend sein, bisschen erfahrung in c# hab ich nähmlich schon

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo vandadito,

Imagemap ist ein Control aus System.Web.UI.WebControls. Das kannst du in Windows Forms Anwendungen gar nicht verwenden. In Windows Forms gibt es standardmäßig auch nichts vergleichbares.

Entweder du schaust mal auf www.codeproject.com und ähnlichen Seiten, oder du musst es selbst programmieren. MouseClick-Ereignis abonnieren und dann prüfen, wohin geklickt wurde und in welchem Bereich der Klick liegt. Dabei hilft die GraphicsPath-Klasse und die IsVisible-Methode.

herbivore

V
vandadito Themenstarter:in
5 Beiträge seit 2012
vor 12 Jahren

hmm, ok. dann ist es schonmal klar warums nicht ersichtlich war

nun das problem ist einfach es sind so um die 400 klicks dann auf einem bild, und dann muss es zusätzlich noch ziemlich genau sein

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo vandadito,

wenn man es einmal korrekt implementiert hat, macht es keinen Unterschied, ob man später zwei oder 400 Bereiche hat.

Mehr als pixelgenau kann man es eh nicht implementieren. Und dafür, eine geringere Genauigkeit zu implementieren, besteht kein Anlass.

Bitte beachte vorsorglich [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

herbivore

V
vandadito Themenstarter:in
5 Beiträge seit 2012
vor 12 Jahren

giltet diese frage als grundlage? hätt ich jetzt nicht gedacht. möchte nämlich eine application sch reiben und das einzige was ich nicht weis wie implementieren ist halt dieses imagemap. da hier auch vorwiegend profis am werk sind dachte ich die chancen sind hier 10 mal höher als in anderen foren, weil ich es überhaupt nicht als eine grundlage ansehen würde.

auf deinen link bin ich auch schon über google gestossen, was hilfreiches hab ich jedoch noch nicht gefunden. kenn mich mit dem forum auch nicht aus oder so, wenn du mir einen hilfreichen link/nützlicher code schicken könntest wär ich dir dankbar, oder einfach ein bisschen genauer drauf ein gehen das ich mir ein wenig mehr vorstellen kann.

auf eine positive antwort würd ich mich freuen

Hinweis von herbivore vor 12 Jahren

Die Antwort auf diese Fragen gibt es am Ende des Threads.

S
4 Beiträge seit 2012
vor 12 Jahren

Hi

Es stellen sich dabei natürlich grundsätzliche Fragen, wie zB

  1. Als Hintergrund dient eine Bitmap (jpg, png, oder ähnliches), ja?
  2. Ist das Hintergrundbild fix oder gibt es verschiedene Bilder mit verschiedenen Bereichen?
  3. Sind die Bereiche rechteckig und regelmässig wie ein Raster angeordnet, sodass man diese berechnen könnte?

Falls du dich in die Thematik der WinForms-Control-Entwickung einlesen möchtest, empfehle ich hier das Kapitel Steuerelemente aus Visual C# 2008.

Darin findest du auch weitgehende Erläuterungen der WinForms und GDI+ Programmierung.

Als Lösungsansatz würde ich wohl mal ein Control erstellen, welches von ImageBox abgeleitet ist. Falls die Bereiche rastermässig angeordnet sind - also regelmässig - kannst du durch Überschreiben der OnMouseUp()-Methode die X/Y-Koordinaten auslesen und anhand der Bereichsgrösse die Zelle berechnen.

Falls es keine regelmässigen Bereiche sind, dann wirds etwas komplizierter: Erstelle dann eine Hilfsklasse für einen einzelnen Bereich, zB:

class ImageArea
{
    public string ID {get; set;}
    public int X {get; set;}
    public int Y {get; set;}
    public int Width {get; set;}
    public int Height {get; set;}
}

Im Control kannst du dann eine Eigenschaft zB 'ImageAreas' implementieren:

public List<ImageArea> ImageAreas {get; private set;} // Im Konstruktor initialisieren!

über diese kannst du dann manuell alle Bereiche hinzufügen, circa so:

this.ImageAreas.Add(new ImageArea() {ID="A1", X=1, Y=1, Width=10, Height=15});

etc.

In der OnMouseUp()-Überschreibung kannst du per Linq die entsprechende Area ermitteln, etwa so (e.X und e.Y sind EventArgumente von OnMouseUp):

var query = from ImageArea area in ImageAreas 
                  where 
                      e.X >= area.X && e.X <= area.X + area.Width &&
                      e.Y >= area.Y && e.Y <= area.Y + area.Height
                      select area;

if(query.Count() > 0) 
{
    MessageBox.Show(query.First().ID); 
}

Der Code ist jetzt nicht getestet, also einfach mal so rein gehackt. Ich hoffe du kannst damit was anfangen! Sonst frag einfach, wo es nicht verständlich ist.

Gruss syntagma

V
vandadito Themenstarter:in
5 Beiträge seit 2012
vor 12 Jahren
  1. ja, eine .jpg datei
  2. ist fix, fenstergrösse von der anwendung wird man nicht verstellen können, das heisst es wird auch nicht verschoben oder vergrössert
  3. ja es sind rechtecke, aber sie sind nicht immer regelmässig (bild im anhang) es sollen immer links über den zahlen enstehen, die sind nicht in einem raster

werde dein code etc noch genauer studieren heute oder morgen und dann nochmals melden obs funktionierte oder nicht

vielen dank!

vandadito

V
vandadito Themenstarter:in
5 Beiträge seit 2012
vor 12 Jahren

ich hab mich jetzt mal in das kapitel eingelesen. doch ich hab eigentlich eher einen "denkknopf". ich weis nicht genau wie ich das ganze implementieren muss um die mausdaten herauszulesen und was ich dann mit den daten mache. wie man UserControlls grundsätzlich mal erstellt ist mir klar, hab ich auch schon gemacht, aber wie gesagt ich weis nicht wie umsetzten. da ist mein grosser knopf

und ein weiteres "problem" ist auch noch das es halt über 400 einträge auf der WindowsForm sind. ist da der aufwand nicht extrem gross? würde sich das gar nicht bezahlt machen?

S
4 Beiträge seit 2012
vor 12 Jahren

Also das UserControl ist dafür nicht geeignet, deshalb eine Ableitung von ImageBox, obwohl du auch einfach von Control ableiten kannst und dabei das BackgroundImage als Bild-Eigenschaft verwenden kannst.

Das Control sähe in etwa so aus:

class ImageMapControl : Control
   {
      public event EventHandler<ImageMapEventArgs> AreaClicked; // Event für das Form

      public List<ImageMapArea> Areas { get; private set; } // Area Liste

      public ImageMapControl() // Konstruktor
      {
         Areas = new List<ImageMapArea>();
      }

      protected virtual void OnAreaClicked(ImageMapArea area) // Event feuern
      {
         if(AreaClicked != null)
            AreaClicked(this, new ImageMapEventArgs(area));
      }

      protected override void OnMouseUp(MouseEventArgs e) // Nach Klick
      {
         ImageMapArea area = HitTest(e.X, e.Y);
         if(area != null)
            OnAreaClicked(area);
         base.OnMouseUp(e);
      }

      private ImageMapArea HitTest(int X, int Y)
      {
         ImageMapArea result = null;
         var query = from ImageMapArea a in Areas
                     where
                     X >= a.X && X <= a.X + a.Width &&
                     Y >= a.Y && Y <= a.Y + a.Height
                     select a;
         
         if(query.Count() > 0)
            result = query.First();

         return result;
      }
   }

   class ImageMapArea
   {
      public string ID { get; set; }
      public int X { get; set; }
      public int Y { get; set; }
      public int Width { get; set; }
      public int Height { get; set; }
   }

   class ImageMapEventArgs : EventArgs
   {
      public ImageMapArea ImageMapArea { get; private set; }
      public ImageMapEventArgs(ImageMapArea area)
      {
         ImageMapArea = area;
      }
   }

Zur Kontrolle kannst du auch noch alle Areas visualisieren:

      protected override void OnPaint(PaintEventArgs e)
      {
         foreach(ImageMapArea a in Areas)
         {
            e.Graphics.DrawRectangle(System.Drawing.Pens.Black, new System.Drawing.Rectangle(
               a.X, a.Y, a.Width, a.Height));
         }
         base.OnPaint(e);
      }

Durch die HitTest Methode könntest du auch noch in OnMouseMove() prüfen ob darunter ein Link liegt und dann den Cursor als Händchen darstellen.

      protected override void OnMouseMove(MouseEventArgs e)
      {
         ImageMapArea area = HitTest(e.X, e.Y);
         Cursor = (area != null ? Cursors.Hand : Cursors.Default);
         base.OnMouseMove(e);
      }

Auf deiner Form hängst du nun dieses Control rauf, bestückst das Teil mit deinem Bild und hackst die Positionen der Links rein.

   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
         imageMap1.AreaClicked += new EventHandler<ImageMapEventArgs>(imageMap1_AreaClicked);
         imageMap1.Areas.Add(new ImageMapArea() { ID = "929", X = 30, Y = 95, Width = 30, Height = 18 });
      }

      void imageMap1_AreaClicked(object sender, ImageMapEventArgs e)
      {
         MessageBox.Show(e.ImageMapArea.ID);
      }
   }

Wenn die Bestimmung der Links zu aufwändig ist, könnte man eine Erfassung per Maus direkt im Control realisieren, zb mit CTRL+Maustaste und die Daten in ein File serialisieren. Aber etwas solltest du schon noch selber machen 😉

Hinweis von herbivore vor 12 Jahren

Die Frage selbst zählt nicht zu den Grundlagen, das habe ich auch nie behauptet. Aber nachdem du Stichpunkte bzw. sogar eine grobe Skizze genannt bekommen hast, zählen Nachfragen wie man Mausdaten herauslesen kann, unbedingt zu den Grundlagen. Die Art der Nachfragen hat also bestätigt, dass mein vorsorglicher Hinweis auf Punkt 1.1.1 angebracht war.

@syntagma: Statt sich eine eigene ImageMapArea-Klasse zu basteln, sollte man besser die schon genannte GraphicsPath-Klasse verwenden.

Thema geschlossen