[vb6] 'verbindingslijnen' tussen objecten

Pagina: 1
Acties:

  • DukeMan
  • Registratie: Mei 2000
  • Niet online
Momenteel ben ik bezig een applicatie te maken waarin gebruikers server-objecten kunnen aanmaken. Elk object heeft een aantal eigenschappen zoals ip, naam ed.

Op het scherm kunnen zij deze objecten positioneren om dit een logische layout te geven.

Deze server-objecten heb ik gemaakt met usercontrols welke in een picturebox kunnen worden geplaatst (object-array) en middels dymanic loading getoond worden.

Nu wilde ik dat gebruikers 2 servers kunnen koppelen, zodat hier een verbindingslijn tussen verschijnt. (Je kan het zien als tabellen en de joins hiertussen zoals deze in de enterprise manager van ms SQL te zien zijn. )

Ook dit lukt allemaal wel en het lukt me met het (standaard) line-object van VB6 om deze verbindingslijnen te maken.
Nu wil ik alleen dat deze lijnen te selecteren zijn en zo eenvoudig bv te verwijderen zijn.
Ik wilde hier het Click event voor gebruiken, maar kwam erachter dat deze niet bestaat op het line-object.

Naar aanleiding hiervan had ik de volgende ideeen/oplossingen:

1- Maak een nieuw (transparante) usercontrol aan, plaatst hier een lijn in en zorg ervoor dat de usercontrol/lijn zo wordt weergegeven dat de servers verbonden zijn/lijken. Een nadeel hiervan is dat lijnen elkaar eventueel kunnen kruisen, waardoor er 2 usercontrols over elkaar heen kunnen liggen en dus niet altijd de juiste wordt aangeklikt (Click event ligt dan op de usercontrol).

2- Het zelf renderen van de lijnen. Op zich zal dit renderen niet zo'n probleem geven, maar om dan te achterhalen of deze worden aangeklikt lijkt me erg lastig te worden. Tevens denk ik niet dat dit de performce verbeterd.

Via google kan ik niet echt iets vinden wat ik kan gebruiken (buiten die transparante usercontrol).

Heeft iemand hier ervaring mee of dit ook gedaan? Misschien dat het toch heel eenvoudig is om te controleren of een getekende aangeklikt wordt.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
Het click event van het onderliggende object opvangen en controleren of daar een lijn zit.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Je lijnen mogen zeker niet alleen maar horizontaal en verticaal zijn? Anders kon je misschien mooi gebruik maken van een label met hoogte 1 en BorderStyle op FixedSingle.

Het controleren of er op een zelf gerenderde lijn geklikt is lijkt me trouwens niet heel moeilijk. Je weet de begin- en eindcoördinaten van alle lijnen en kan dus ook wel controleren of de klikpositie tussen een lijn valt (kan je 'm zelfs nog ff mooi dik tekenen ook).

rico = (lijn.y2 - lijn.y1) / (lijn.x2 - lijn.x1)
startpunt = y2 - rico * x2

if (rico * muisklik.x + startpunt == muisklik.y)
{
muisklik is op lijn...
}

Toch?

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • DukeMan
  • Registratie: Mei 2000
  • Niet online
De lijnen mogen idd niet alleen horizontaal of verticaal lopen. Deze kunnen 360 graden gedraaid worden. Ze bewegen mee als de gebruiker een serverobject verplaatst.
riezebosch schreef op 11 november 2004 @ 14:30:
rico = (lijn.y2 - lijn.y1) / (lijn.x2 - lijn.x1)
startpunt = y2 - rico * x2

if (rico * muisklik.x + startpunt == muisklik.y)
{
muisklik is op lijn...
}

Toch?
Gaat deze code werken? volgens mij niet... maar ik weet idd het begin en het eind punt.. met een beetje wiskunde is natuurlijk wel uit te rekenen op de click op de lijn valt...

Ik zal hier eens mee aan de slag gaan.

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 18:51

LauPro

Prof Mierenneuke®

Ik heb een hele tijd terug een programma in VB6 gemaakt waarmee je zegmaar een bouwtekening uit kon printen van een kubus, piramide, 'huis', cilinder etc. Hier werd het geheel helemaal zelf gerenderd en ook 'mouseovers' werden gedelecteerd. Dit deed ik op een P3 450 Mhz met 128 MB ram en dit ging als een trein zelfs met tientalle objecten die telkens werden hertekend als je iets verplaatst. Met een beetje efficient programma lukt het denk ik wel.

[ Voor 8% gewijzigd door LauPro op 12-11-2004 11:17 ]

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
riezebosch schreef op 11 november 2004 @ 14:30:
rico = (lijn.y2 - lijn.y1) / (lijn.x2 - lijn.x1)
startpunt = y2 - rico * x2

if (rico * muisklik.x + startpunt == muisklik.y)
{
muisklik is op lijn...
}
Toch?
Helaas werkt dit niet als de lijn vertikaal loopt. Je deelt dan door 0. Als je deze aanpak volgt dan moet je voor dat geval even onderscheid maken. Nu is het voor een verticale lijn niet echt moeilijk om je positie te bepalen, dus een echt probleem is dat niet.

Zou je iets kunnen doen met de projectie van de muiscoordinaten op een lijn in een 2D ruimte? Of nee, de afstand. Mmm dat is een tijd geleden...

[ Voor 13% gewijzigd door Infinitive op 11-11-2004 18:17 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Maak iedere lijn een object, en geef ze een method Hittest(x,y).
OnClick loop je door al je line objecten heen en roep je HitTest met de x en y van de muis aan. De hittest geeft True terug als de x en y (binnen een marge?) op de lijn vallen.

Het uitrekenen of de x en y op de lijn vallen lijkt me niet al te moeilijk... iets met sin/cos/pythagoras ofzo :Y) geen zin om daar nu over na te denken, want Robbie gaat een hapje eten :P

[ Voor 10% gewijzigd door RobIII op 11-11-2004 18:21 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 18:51

LauPro

Prof Mierenneuke®

Ik weet wel wat ik er gigantische berekeningen achter had zitten om de positie te bepalen. Dat is nogal verschillend omdat je idd niet door 0 kan delen bijvoorbeeld. Het is gewoon een kwestie van prutsen. Ben toch zeker wel een paar weken met dat programma intensief bezig geweest :) . Misschien dat ik eens een screenshot ergens online kan zetten voor de liefhebbers.

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • Haploid
  • Registratie: Maart 2002
  • Laatst online: 29-12-2021

Haploid

Doh!

Het lijkt me het makkelijkste als je de lijnen op het form tekent (of nog beter, een container control waar je de andere objecten op plaatst) en dan in de Paint handler van de container met de functie Line tekent.

Het enige dat je dan nog mist is een Click handler. Daarvoor kun je die van de container gebruiken. Dan moet je bij de klik berekenen op welke lijn er wordt geklikt. Dat kan vrij simpel met een functie die je op http://www.c-program.com/c-g-a-faq1.html#q7 kunt nalezen. In de Click event van de container loop je al je lijnen na om te kijken op welke er geklikt wordt (dit kost niet zoveel tijd). Je zou kunnen zeggen dat je op een lijn klikt als je afstand tussen het geklikte punt en de lijn minder dan pakweg 2 pixels is.

Hey, I came here to be drugged, electrocuted and probed, not insulted.


  • DukeMan
  • Registratie: Mei 2000
  • Niet online
RobIII schreef op 11 november 2004 @ 18:20:
Maak iedere lijn een object, en geef ze een method Hittest(x,y).
OnClick loop je door al je line objecten heen en roep je HitTest met de x en y van de muis aan. De hittest geeft True terug als de x en y (binnen een marge?) op de lijn vallen.

Het uitrekenen of de x en y op de lijn vallen lijkt me niet al te moeilijk... iets met sin/cos/pythagoras ofzo :Y) geen zin om daar nu over na te denken, want Robbie gaat een hapje eten :P
Aan wat voor object zat jij te denken? Het enige waar ik op kom is het standaard lijn object van VB (welke geen onclick heeft) en het incapselen van zo'n lijn in een usercontrol welke wel een onclick heeft, maar waarbij enkele controls over elkaar kunnen liggen.
LauPro schreef op 11 november 2004 @ 18:22:
Ik weet wel wat ik er gigantische berekeningen achter had zitten om de positie te bepalen. Dat is nogal verschillend omdat je idd niet door 0 kan delen bijvoorbeeld. Het is gewoon een kwestie van prutsen. Ben toch zeker wel een paar weken met dat programma intensief bezig geweest :) . Misschien dat ik eens een screenshot ergens online kan zetten voor de liefhebbers.
Misschien dat je dit zou willen doen? Ben wel benieuwd...
Haploid schreef op 11 november 2004 @ 19:13:
Het lijkt me het makkelijkste als je de lijnen op het form tekent (of nog beter, een container control waar je de andere objecten op plaatst) en dan in de Paint handler van de container met de functie Line tekent.

Het enige dat je dan nog mist is een Click handler. Daarvoor kun je die van de container gebruiken. Dan moet je bij de klik berekenen op welke lijn er wordt geklikt. Dat kan vrij simpel met een functie die je op http://www.c-program.com/c-g-a-faq1.html#q7 kunt nalezen. In de Click event van de container loop je al je lijnen na om te kijken op welke er geklikt wordt (dit kost niet zoveel tijd). Je zou kunnen zeggen dat je op een lijn klikt als je afstand tussen het geklikte punt en de lijn minder dan pakweg 2 pixels is.
Ik denk dat dit ook wel iets kan zijn. Ik zal hier eens mee gaan experimenteren. Het moet niet zo moeilijk zijn deze formule om te zetten in VB.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Die formule lijkt me nogal overkill, omdat je niet de afstand hoeft te weten maar alleen óf er op geklikt is. Of je moet natuurlijk willen dat er binnen een bepaalde afstand geklikt mag worden (om het makkelijk te maken). Heb mijn bovengenoemde formule getest in C# en werkt prima. Je moet alleen inderdaad wel rekening houden met een verticale lijn, omdat je anders gaat delen door 0. Maar de controle op zo'n lijn is dan ook wel weer supersimpel.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Point p1 = new Point(10,10);
Point p2 = new Point(100,100);

protected override void OnMouseDown(MouseEventArgs e)
{
    int rico = (p2.Y - p1.Y) / (p2.X - p1.X);
    int startpunt = p2.Y - rico * p2.X;

    if (rico * e.X + startpunt == e.Y)
        MessageBox.Show("click");
    else
        MessageBox.Show(e.X + ", " + e.Y);
    base.OnMouseDown (e);
}

[ Voor 7% gewijzigd door riezebosch op 11-11-2004 21:23 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • Haploid
  • Registratie: Maart 2002
  • Laatst online: 29-12-2021

Haploid

Doh!

riezebosch schreef op 11 november 2004 @ 21:14:
Die formule lijkt me nogal overkill, omdat je niet de afstand hoeft te weten maar alleen óf er op geklikt is. Of je moet natuurlijk willen dat er binnen een bepaalde afstand geklikt mag worden (om het makkelijk te maken).
Ach, dat valt wel mee. 3 Kwadraatjes, 1 worteltje, 7 aftrekkingen en 1 optelling. Meeste computers hebben daar nog geen microseconde voor nodig. Het is wel erg handig om niet precies op de lijn te hoeven klikken, maar een pixeltje speling hebt. Zeker als je op hoge resolutie werkt. En ik geloof dat het wat moeilijk is om in jouw algoritme in te bouwen.

Hey, I came here to be drugged, electrocuted and probed, not insulted.


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Dat is zeker waar, daarom zeg ik ook dat wanneer dat niet nodig is dat algoritme overkill is. Als je wel een marge in wilt bouwen is die formule wel een goede optie. Het gaat me ook niet om de rekenkracht van de computer, meer om de complexiteit van de code.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • DukeMan
  • Registratie: Mei 2000
  • Niet online
Voor de mensen die het interessant vinden, post ik hierbij de uiteindelijke code.

De input van de functie is het startpunt van de lijn (x1, y1) en het eindpunt (x2, y2). Tevens het punt waar geklikt is (PX, PY)

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Private Function IsLineClicked(X1 As Long, X2 As Long, _
                               Y1 As Long, Y2 As Long, _
                               PX As Single, PY As Single) As Boolean

    Dim dblTemp As Double
    
    Dim dblL As Double
    Dim dblR As Single
    Dim dblS As Double
    
    dblTemp = (X2 - X1) ^ 2
    dblTemp = dblTemp + ((Y2 - Y1) ^ 2)
    dblL = Sqr(dblTemp)
    
    ' Zit wel in de berekening (zie link), maar wordt niet gebruikt.
    'dblTemp = ((Y1 - PY) * (Y1 - Y2)) - ((X1 - PX) * (X2 - X1))
    'dblR = dblTemp / (dblL ^ 2)
    
    dblTemp = ((Y1 - PY) * (X2 - X1)) - ((X1 - PX) * (Y2 - Y1))
    dblS = dblTemp / (dblL ^ 2)
    
    If Abs(dblS) < 0.01 Then
        IsLineClicked = True
    Else
        IsLineClicked = False
    End If

End Function


Die 0.01 is de marge waarbinnen geklikt kan worden. Op deze manier kan je de gebruik iets meer marge/ruimte geven.

Iedereen bedankt voor de input!

  • Haploid
  • Registratie: Maart 2002
  • Laatst online: 29-12-2021

Haploid

Doh!

NTGiant schreef op zaterdag 13 november 2004 @ 09:31:
Visual Basic:
1
2
3
    ' Zit wel in de berekening (zie link), maar wordt niet gebruikt.
    'dblTemp = ((Y1 - PY) * (Y1 - Y2)) - ((X1 - PX) * (X2 - X1))
    'dblR = dblTemp / (dblL ^ 2)
Die dblR kun je ook nog gebruiken. Met de dblS controleer je hoe ver het punt van de (eeuwig doorlopende) lijn afligt, dat kan dus ook gebeuren kilometers voordat het lijnstuk begint. Het de dblR kun je vervolgens kijken of het punt wel binnen het lijnstuk plaatsvindt. Ik quote:
Distance from A to I = r*L
If r < 0 I is on backward extension of AB
If r>1 I is on ahead extension of AB
If 0<=r<=1 I is on AB
Verder kan dit wat simpeler:
code:
1
2
3
4
5
    If Abs(dblS) < 0.01 Then
        IsLineClicked = True
    Else
        IsLineClicked = False
    End If
Namelijk als volgt:
code:
1
IsLineClicked = (Abs(dblS) < 0.01)

Hey, I came here to be drugged, electrocuted and probed, not insulted.


  • DukeMan
  • Registratie: Mei 2000
  • Niet online
Haploid schreef op zaterdag 13 november 2004 @ 10:46:
[...]

Die dblR kun je ook nog gebruiken. Met de dblS controleer je hoe ver het punt van de (eeuwig doorlopende) lijn afligt, dat kan dus ook gebeuren kilometers voordat het lijnstuk begint. Het de dblR kun je vervolgens kijken of het punt wel binnen het lijnstuk plaatsvindt. Ik quote:

[...]

Verder kan dit wat simpeler:

[...]

Namelijk als volgt:
code:
1
IsLineClicked = (Abs(dblS) < 0.01)
Je hebt inderdaad gelijk.
De laatste regel heb ik nu als volgt aangepast waardoor je inderdaad niet voor of na de lijn kan klikken. (en bij de regel dblR = ... het commentaar weggehaald.)

Visual Basic:
1
IsLineClicked = (Abs(dblS) < 0.01) And (dblR >= 0 And dblR <= 1)
Pagina: 1