Moskus Skrevet 22. september 2006 Skrevet 22. september 2006 Hei! Jeg skal snart i gang med et prosjekt som skal bruke en del grafikk. Og i den forbindelse hadde det vært kjekt om deler av grafikken er klikkbar som objekter. Med det mener jeg: Tegn en vegg fra punkt A til punkt B. Klikkes punkt A, kan du flytte dette. Tilsvarende for punkt B. Klikker du midt på "veggen" (dvs streken) kan du flytte denne. Er det noen som har gjort noe tilsvarende, og kan gi noen tips?
Gjakmarrja Skrevet 22. september 2006 Skrevet 22. september 2006 (endret) Du må bruke en array som holder orden på antall vegger og trykkpunktene til veggene. Innholde i arrayen kan være x og y til veggen. Også har du en egen funksjon som regner ut hvor trykkpunktene er. Det vil si ved punkt a eller ved punkt b. Om du velger å regne ut hvor trykkpunktene er samtidig som du lager veggene å ligge dette inn i arrayen med x og y ELLER regner dette ut ved clickevent kan du velge selv! Hver linje i arrayen må også inneholde lengde å bredde på veggen. Så kan du kalle funksjoner for dette: #MovePointA #MovePointB #MoveObject Du kan også ha et "object" som er heter "selectedObject", da blir det litt lettere med flytting av objektet. Når du holder på med grafikk har du vel en konstant loop, så når du skal flytte et punkt til et objekt setter du bare musens punkter hele tiden til det punkte du klikket på, så ved andre klikk lagrer du de nye verdiene. Når du klikker på selve formen må du loope igjennom arrayen og bruke en >/</if opplegg til å finne frem til hvilken vegg bite du holder musa over. Når du finner objektet, sletter du det fra arrayen og ligger det inn i et temp object for "ObjectSelected". Også kan du oppdatere arrayen når du er ferdig å flytte på det, eller et punkt. Den delen blir ikke så lett å implementere! Det stemmer at jeg har laget noe slikt før, men da baserte hele proskjektet seg på at formen var delt inn i et "virtuellt" rutenett. Det er nok ikke helt det samme som du er ute etter, en mer fleksibel løsning er nok det du er ute etter. Kanskje du kan "arve" et annet objekt sitt egenskaper? F.eks knapper? Jeg er ikke helt inne på hvordan arv fungerer i .Net, men i og med at formen vet hvilken knapper som trykkes på så burde det være mulig å trekke noe ut av det. Det er sikkert noen som har mer erfaring med dette en meg! Noen? Edit: Formen har jo et klikkevent? Som returnerer en pointer til objectet som ble klikket? (Tror jeg) Endret 22. september 2006 av chills
GeirGrusom Skrevet 22. september 2006 Skrevet 22. september 2006 (endret) using System; using System.Drawing; public enum SizeMode { None = 0, West = 1, North = 2, East = 4, South = 8, NorthWest = West | North, NorthEast = East | North, SouthWest = West | South, SouthEast = East | South, Move = 16 } public interface IGObject { Rectangle Rectangle { get; set; } void Resize(SizeMode grip_handle, Point increment); void Draw(Graphics g); } public class GObject : IGObject { protected Rectangle m_rect; public virtual void Draw(Graphics g) { ' Vi bruker g.TranslateTransform(m_rect.Left, m_rect.Top) ' For å gjøre tegning enklere, så (0, 0) vil være posisjonen til objektet ' på grafikk objektet Rectangle new_rect = new Rectangle(0, 0, m_rect.Width, m_rect.Height); g.FillRectangle(Brushes.Yellow, m_rect) g.DrawRectangle(Pens.Black, m_rect); } void Resize(SizeMode grip_handle, Point incr) { if( (grip_handle == SizeMode.Move) ) { m_rect.Offset(incr); } else if(grip_handle == SizeMode.None) { return; } else { if( (grip_handle & SizeMode.North) == SizeMode.North) { m_rect = new Rectangle(m_rect.Left, m_rect.Top - incr.Y, m_rect.Width, m_rect.Size.Height + incr.Y); } if( (grip_handle & SizeMode.South) == SizeMode.South) { m_rect = new Rectangle(m_rect.Left, m_rect.Top + incr.Y, m_rect.Width, m_rect.Size.Height - incr.Y); } if( (grip_handle & SizeMode.North) == SizeMode.West) { m_rect = new Rectangle(m_rect.Left - incr.X, m_rect.Top, m_rect.Width + incr.X, m_rect.Size.Height); } if( (grip_handle & SizeMode.East) == SizeMode.East) { m_rect = new Rectangle(m_rect.Left + incr.X, m_rect.Top, m_rect.Width - incr.X, m_rect.Size.Height); } } } } public IGObject GetObjectAtPoint(System.Collections.ObjectModel.Collection<IGObject> col, Point p, Point ScrollbarOffset) { p = new Point(p.X - ScrollbarOffset.X, p.Y - ScrollbarOffset.Y); foreach(IGObject obj in col) { if(obj.Rectangle.Contains(p) return obj; } } her er et eksempel Inherit GObject og override Draw funksjonen for å tegne noe annet Og slik tegner man alle: public void Draw(Graphics g, Collection<IGObject> col, Point scrollbaroffset) { System.Drawing.Drawing2D.Matrix mat; g.TranslateTransform(scrollbaroffset); mat = (System.Drawing.Drawing2D.Matrix)g.Transform.Clone(); foreach(IGObject obj in col) { g.TranslateTransform(obj.Rectangle.Left, obj.Rectangle.Top); obj.Draw(g); g.Transform = (System.Drawing.Drawing2D.Matrix)mat.Clone(); } } Endret 22. september 2006 av GeirGrusom
Moskus Skrevet 22. september 2006 Forfatter Skrevet 22. september 2006 Takk for mye fancy kode, Geir. Kan du nå forklare hvordan den brukes? Ved Public Class GObject Inherits IGObject får jeg at "Classes can inherit only from other classes".
GeirGrusom Skrevet 23. september 2006 Skrevet 23. september 2006 (endret) hmmm, du bruker Visual basic ja Bytt ut "Inherits" med "Implements" Jeg skal få laget et enkelt eksempel, må bare vaske badet Endret 23. september 2006 av GeirGrusom
GeirGrusom Skrevet 23. september 2006 Skrevet 23. september 2006 (endret) Her har du et eksempel, i fungerende form, skrevet i Visual Basic.NET Edit: fant en feil :S ObjectDrawApp.zip Endret 23. september 2006 av GeirGrusom
Moskus Skrevet 24. september 2006 Forfatter Skrevet 24. september 2006 Tusen hjertelig takk! Skal undersøke det så raskt som overhodet mulig!
GeirGrusom Skrevet 24. september 2006 Skrevet 24. september 2006 Aprikos så må man alltid tegne til en picturebox eller lignende inne i formen, hvis du tegner direkte på formen så begynner det å blinke (av en eller annen grunn)
Degeim Skrevet 24. september 2006 Skrevet 24. september 2006 "Blinkingen" din er vel "flickering", er det ikke? Jeg vet ikke hvorfor det er lurere å tegne på en form enn på en picturebox, men jeg mener likevel at jeg vet det er slik. Uansett: "Dont flicker; double buffer!" Degeim
GeirGrusom Skrevet 24. september 2006 Skrevet 24. september 2006 (endret) Ikke double buffer hvis du ikke trenger, det tar mer ram, og er mye tregere. Hold all tegning inne i OnPaint eller Paint event, og alt ser glimrende fantastisk ut, aldri bruk Control.CreateGraphics() (hvis du ikke trenger en hDC da, i såfall må du huske å kalle ReleaseDC() før du avslutter) Endret 24. september 2006 av GeirGrusom
Moskus Skrevet 25. september 2006 Forfatter Skrevet 25. september 2006 Geir, du er et jævla geni! Dette er glimrende å bygge videre på!
Moskus Skrevet 25. september 2006 Forfatter Skrevet 25. september 2006 (endret) Litt fikling og tukling med koden, kom jeg frem til denne klassen: Public Class Line Inherits GObject Protected m_pen As Pen Public Property Color() As Color Get Return m_pen.Color End Get Set(ByVal value As Color) m_pen.Color = value End Set End Property Public Overrides Sub Draw(ByVal g As System.Drawing.Graphics) g.DrawLine(m_pen, 0, 0, m_rect.Width, m_rect.Height) End Sub Public Overrides Sub New() m_pen = Pens.Black End Sub End Class Ekstremt simpelt! Men akkurat det jeg trenger! Men her er det noe som er litt merkelig. Ta en linje som vist over. Dra høyresiden mot venstre til den er på andre siden av "venstresiden". Linjen blir fremdeles tegnet, men er plutselig ikke klikkbar! Tipper det har noe med SeletionHelper -> Create å gjøre, men om du har noen gode tips før jeg herjer rundt, så tar jeg gladelig i mot dem! Endret 25. september 2006 av moskus
GeirGrusom Skrevet 25. september 2006 Skrevet 25. september 2006 Grunnen er at Rectangle ikke kan være negative i størrelse, jeg har ikke lagt inn noen sjekkrutiner på dette, men i .NET 1.1 fikk du exception hvis dette skjedde, men ikke nå lenger. Dette er faktisk en liten kødden rutine, fordi du må begynne å lage rektanglen fra Right til Left, og/eller Bottom til Top, men det er ikke uovervinnelig. Jeg har fikset problemet, jeg har lagt til 2 egenskaper på GObject, som er m_p1, og m_p2 som er (x1, y1)-(x2, y2) og en funksjon som heter CreateRectangle, og byttet ut GObject.Resize som følger: legg til dette i SelectionHelper.vb ' Denne ligger i SelectionHelper hos meg Public Shared Function CreateRectangle(ByVal p1 As Point, ByVal p2 As Point) As Rectangle Dim x As Integer, y As Integer Dim w As Integer, h As Integer w = p2.X - p1.X h = p2.Y - p1.Y x = p1.X y = p1.Y If (w < 0) Then x += w w = -w ' Bytt fortegn, vi vet det er negativt fra før End If If (h < 0) Then y += h h = -h ' Bytt fortegn, vi vet det er negativt fra før End If Return New Rectangle(x, y, w, h) End Function GObject ' Egenskaper Protected m_p1 As Point Protected m_p2 As Point Public Property Rectangle() As System.Drawing.Rectangle Implements IGObject.Rectangle Get Return SelectionHelper.CreateRectangle(m_p1, m_p2) End Get Set(ByVal value As System.Drawing.Rectangle) m_rect = value m_p1 = m_rect.Location m_p2 = New Point(m_rect.Right, m_rect.Bottom) End Set End Property ' GObject.Resize Public Sub Resize(ByVal grip_handle As SizeMode, ByVal incr As Point) Implements IGObject.Resize Dim x1 As Integer, y1 As Integer Dim x2 As Integer, y2 As Integer If grip_handle = SizeMode.None Then Exit Sub Else x1 = m_p1.X x2 = m_p2.X y1 = m_p1.Y y2 = m_p2.Y If grip_handle = SizeMode.Move Then x1 += incr.X x2 += incr.X y1 += incr.Y y2 += incr.Y Else If (grip_handle And SizeMode.North) = SizeMode.North Then y1 += incr.Y If (grip_handle And SizeMode.South) = SizeMode.South Then y2 += incr.Y If (grip_handle And SizeMode.East) = SizeMode.East Then x2 += incr.X If (grip_handle And SizeMode.West) = SizeMode.West Then x1 += incr.X End If m_p1 = New Point(x1, y1) m_p2 = New Point(x2, y2) m_rect = SelectionHelper.CreateRectangle(m_p1, m_p2) End If End Sub Det som skjer her nå er at jeg har lagt til m_p1 og m_p2 som er aboslutt verdier for størrelsen til objektet, men beholdt m_rect for at koden fortsatt skal fungere andre steder. Og CreateRectangle lager et Rectangle objekt som alltid er positivt i størrelse. Hyggelig å være til hjelp, moskus!
Moskus Skrevet 25. september 2006 Forfatter Skrevet 25. september 2006 Takk igjen! Det der forstod jeg faktisk! Hyggelig å være til hjelp, moskus! Ja visst faen er du det! Nå kan jeg gå tilbake til å "bare" bekymre meg om matematikken i programmet (foreløpig)...
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå