Hey,
Ik heb een class Shape met properties als Bounds (Rectangle), Location (Point) en Size (Size) (komen rechtstreeks uit Bounds) en een methode Draw.
Dit stelt een vorm voor, zeg een rechthoek, driehoek, cirkel, etc. De vorm wordt met de Draw methode op het scherm getekend, en er worden, als de vorm geselecteerd is, ook 'grab handles' getekend zoals in de Visual Studio form designer. Met deze grab handles kan de gebruiker de shape verplaatsen en ook resizen.
Een tijd geleden had ik hier een vraag gepost over het resizen van de shapes.
Dit hele verhaal is niet veranderd en kan in het oude topic nog gelezen worden. Alles tot de eerste code samples is nog relevant, dat daarna is het probleem wat ondertussen is opgelost.
\[VB.NET] Shapes resizen, rekening houden met minimum size?
Dit probleem is dus opgelost, ik kan de shapes nu mooi resizen.
Maar nu heb ik het volgende probleem: het moet mogelijk zijn om meerdere shapes tegenlijk te selecteren, en ze moeten dus ook tegenlijk worden verplaatst of resized. Nu probeer ik zo dicht mogelijk bij de implementatie van Visual Studio te blijven, en men kan dus net zoals in Visual Studio meerdere shapes selecteren, maar er is altijd 1 'hoofd' selectie (dat zie je aan het verschil in grab handles). Alle uitlijning (snapping met andere shapes en de rand bijvoorbeeld) wordt op deze hoofd shape gedaan.

Het tegenlijkertijd verplaatsen heb ik al uitgewerkt. Dat klinkt triviaal maar ik moest ook rekening houden met snapping enzo (als de hoofd selectie aan het snappen is moeten de andere natuurlijk ook niet bewegen). Nu ben ik al een hele tijd met het resizen bezig, maar het wil weer niet lukken...
Het resizen van een enkele shape is heel gemakkelijk met de Resize method. Deze accepteert een 'HitStatus' (dit bevat de informatie over aan welke kant de shape aan het resizen is, bijvoorbeeld van linksonder of van rechtsboven), en de positie van de muis relatief t.o.v. het 'canvas'.
Zo kan in een MouseMove methode bijvoorbeeld gewoon dit aangeroepen worden:
waarbij 'this' de Canvas is en hitStatus ergens anders bepaald wordt.
Nu heb ik dus nog meer selecties naast deze hoofd selectie, en de makkelijkste manier om die ook te laten resizen leek mij om 'simpelweg' de muislocatie (e.X, e.Y) te vertalen naar de overige shapes.
Ik deed dit eerst door simpelweg het punt (e.X, e.Y) relatief t.o.v. de hoofd shape te nemen (shape.Location aftrekken van e.Location), en daarna dit punt terug te verplaatsen naar de andere shape (optellen). In code:
NB: this.SelectedShape == this.SelectedShapes[0], vandaar de loop beginnen vanaf 1 (de hoofd shape
En Add en Subtract zijn extension methods die voor de hand liggen (p1.X + p2.X, p1.Y + p2.Y).
Dit werkt, maar alleen als de shapes precies even groot zijn!
Zodra een van de andere shapes bijvoorbeeld groter is, dan ligt het getransleerde punt niet meer op de rand van de shape en gaat het resizen helemaal mis.
Dus, ik moet het punt niet alleen transleren, maar ook 'schalen' naar de grootte van de andere shape.
Ik heb dit met een tekening geprobeerd duidelijk te maken:

Het rode punt links is de muislocatie. Ik ben dus shape1 aan het resizen. De muislocatie wordt getransleerd naar het doorzichtige rode punt rechts, op shape 2. Dit is natuurlijk niet goed! Hij moet ongeveer bij het groene punt liggen.
Om dit voor elkaar te krijgen dacht ik dat ik niet het exacte punt (e.X, e.Y) moet gebruiken, maar de relatieve waarden, relatief t.o.v. de grootte van de hoofd shape.
Dat wil zeggen: de x waarde delen door de breedte van de hoofd shape (dit wordt dus iets tussen 0.0 en 1.0), en dan vermenigvuldigen met de breedte van de andere shape. Eveneens voor de y waarde, maar dan met de hoogte.
Mijn code nu is als volgt:
Ik wist zeker dat dit zou werken! Maar helaas... Er gaat nog steeds iets mis, maar dit keer kom ik er niet achter wat...
Wat er nu gebeurt is lastig uit te leggen, maar het komt erop neer dat de andere shapes langzaam de grootte van de hoofd shape overnemen. Dat gaat niet meteen, maar als ik mijn muis beweeg (maakt niet uit welke richting) dan resizen de shapes beetje bij beetje totdat ze even groot zijn als de hoofd shape. En op dat moment resizen ze wel weer gewoon goed, zoals in mijn eerste methode.
Ik kom er even niet meer uit... Ik snap dat dit een hele hoop informatie is zonder dat jullie eigenlijk weten wat er aan de hand is, maar als iemand toch ziet wat er mis gaat dan hoor ik dat graag! Een extra paar ogen / hersenen komt vaak een heel eind
EDIT
Ik heb mijn project even gecompileerd en geupload:
http://www.megaupload.com/?d=3O711QJP
Met .NET Framework 3.5 of hoger zou je dit moeten kunnen draaien, en dan kun je zelf even kijken wat er precies gebeurt als je meerdere shapes selecteert (ctrl inhouden) en daarna resized. Als een shape een andere grootte heeft gaat het compleet mis.
Bedankt!
Ik heb een class Shape met properties als Bounds (Rectangle), Location (Point) en Size (Size) (komen rechtstreeks uit Bounds) en een methode Draw.
Dit stelt een vorm voor, zeg een rechthoek, driehoek, cirkel, etc. De vorm wordt met de Draw methode op het scherm getekend, en er worden, als de vorm geselecteerd is, ook 'grab handles' getekend zoals in de Visual Studio form designer. Met deze grab handles kan de gebruiker de shape verplaatsen en ook resizen.
Een tijd geleden had ik hier een vraag gepost over het resizen van de shapes.
Dit hele verhaal is niet veranderd en kan in het oude topic nog gelezen worden. Alles tot de eerste code samples is nog relevant, dat daarna is het probleem wat ondertussen is opgelost.
\[VB.NET] Shapes resizen, rekening houden met minimum size?
Dit probleem is dus opgelost, ik kan de shapes nu mooi resizen.
Maar nu heb ik het volgende probleem: het moet mogelijk zijn om meerdere shapes tegenlijk te selecteren, en ze moeten dus ook tegenlijk worden verplaatst of resized. Nu probeer ik zo dicht mogelijk bij de implementatie van Visual Studio te blijven, en men kan dus net zoals in Visual Studio meerdere shapes selecteren, maar er is altijd 1 'hoofd' selectie (dat zie je aan het verschil in grab handles). Alle uitlijning (snapping met andere shapes en de rand bijvoorbeeld) wordt op deze hoofd shape gedaan.

Het tegenlijkertijd verplaatsen heb ik al uitgewerkt. Dat klinkt triviaal maar ik moest ook rekening houden met snapping enzo (als de hoofd selectie aan het snappen is moeten de andere natuurlijk ook niet bewegen). Nu ben ik al een hele tijd met het resizen bezig, maar het wil weer niet lukken...
Het resizen van een enkele shape is heel gemakkelijk met de Resize method. Deze accepteert een 'HitStatus' (dit bevat de informatie over aan welke kant de shape aan het resizen is, bijvoorbeeld van linksonder of van rechtsboven), en de positie van de muis relatief t.o.v. het 'canvas'.
Zo kan in een MouseMove methode bijvoorbeeld gewoon dit aangeroepen worden:
C#:
1
| this.SelectedShape.Resize(hitStatus, e.X, e.Y); |
waarbij 'this' de Canvas is en hitStatus ergens anders bepaald wordt.
Nu heb ik dus nog meer selecties naast deze hoofd selectie, en de makkelijkste manier om die ook te laten resizen leek mij om 'simpelweg' de muislocatie (e.X, e.Y) te vertalen naar de overige shapes.
Ik deed dit eerst door simpelweg het punt (e.X, e.Y) relatief t.o.v. de hoofd shape te nemen (shape.Location aftrekken van e.Location), en daarna dit punt terug te verplaatsen naar de andere shape (optellen). In code:
code:
1
2
3
4
5
6
7
8
| this.SelectedShape.Resize(hitStatus, e.X, e.Y);
for (int i = 1; i < this.SelectedShapes.Count; i++)
{
var shape = this.SelectedShapes[i];
var relativePoint = shape.Location.Add( e.Location.Subtract( this.SelectedShape.Location ) );
shape.Resize(hitStatus, relativePoint.X, relativePoint.Y);
} |
NB: this.SelectedShape == this.SelectedShapes[0], vandaar de loop beginnen vanaf 1 (de hoofd shape
En Add en Subtract zijn extension methods die voor de hand liggen (p1.X + p2.X, p1.Y + p2.Y).
Dit werkt, maar alleen als de shapes precies even groot zijn!
Zodra een van de andere shapes bijvoorbeeld groter is, dan ligt het getransleerde punt niet meer op de rand van de shape en gaat het resizen helemaal mis.
Dus, ik moet het punt niet alleen transleren, maar ook 'schalen' naar de grootte van de andere shape.
Ik heb dit met een tekening geprobeerd duidelijk te maken:

Het rode punt links is de muislocatie. Ik ben dus shape1 aan het resizen. De muislocatie wordt getransleerd naar het doorzichtige rode punt rechts, op shape 2. Dit is natuurlijk niet goed! Hij moet ongeveer bij het groene punt liggen.
Om dit voor elkaar te krijgen dacht ik dat ik niet het exacte punt (e.X, e.Y) moet gebruiken, maar de relatieve waarden, relatief t.o.v. de grootte van de hoofd shape.
Dat wil zeggen: de x waarde delen door de breedte van de hoofd shape (dit wordt dus iets tussen 0.0 en 1.0), en dan vermenigvuldigen met de breedte van de andere shape. Eveneens voor de y waarde, maar dan met de hoogte.
Mijn code nu is als volgt:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| var mainShapeBounds = this.SelectedShape.Bounds; // 1. Resize main selected shape this.SelectedShape.Resize(hitStatus, e.X, e.Y); // 2. Resize remaining selected shapes for (var i = 1; i < this.SelectedShapes.Count; i++) { var shape = this.SelectedShapes[i]; var currentShapeBounds = shape.Bounds; // 2.1. Determine relative location of point in main shape var relativePoint = e.Location.Subtract(this.SelectedShape.Location); var relativePointF = new PointF(relativePoint.X / (float) mainShapeBounds.Width, relativePoint.Y / (float) mainShapeBounds.Height); // 2.2 Determine point relative to other shape relativePointF = new PointF(relativePointF.X * currentShapeBounds.Width + shape.Location.X, relativePointF.Y * currentShapeBounds.Height + shape.Location.Y); shape.Resize(hitStatus, (int) relativePointF.X, (int) relativePointF.Y); |
Ik wist zeker dat dit zou werken! Maar helaas... Er gaat nog steeds iets mis, maar dit keer kom ik er niet achter wat...
Wat er nu gebeurt is lastig uit te leggen, maar het komt erop neer dat de andere shapes langzaam de grootte van de hoofd shape overnemen. Dat gaat niet meteen, maar als ik mijn muis beweeg (maakt niet uit welke richting) dan resizen de shapes beetje bij beetje totdat ze even groot zijn als de hoofd shape. En op dat moment resizen ze wel weer gewoon goed, zoals in mijn eerste methode.
Ik kom er even niet meer uit... Ik snap dat dit een hele hoop informatie is zonder dat jullie eigenlijk weten wat er aan de hand is, maar als iemand toch ziet wat er mis gaat dan hoor ik dat graag! Een extra paar ogen / hersenen komt vaak een heel eind
EDIT
Ik heb mijn project even gecompileerd en geupload:
http://www.megaupload.com/?d=3O711QJP
Met .NET Framework 3.5 of hoger zou je dit moeten kunnen draaien, en dan kun je zelf even kijken wat er precies gebeurt als je meerdere shapes selecteert (ctrl inhouden) en daarna resized. Als een shape een andere grootte heeft gaat het compleet mis.
Bedankt!