Précédent   Forum du club des développeurs et IT Pro > Dotnet > Développement Windows > Windows Presentation Foundation
Windows Presentation Foundation Forum d'entraide sur le développement d'applications Windows avec Windows Presentation Foundation
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 22/12/2012, 06h59   #1
ikeas
Membre émérite
 
Inscription : juillet 2008
Messages : 1 095
Détails du profil
Informations forums :
Inscription : juillet 2008
Messages : 1 095
Points : 942
Points : 942
Par défaut [Matrix] ou comment se faire un film

hello (excusez la vanne sur matrix )

bon voila je reccup une MatrixTransform
avec les valeurs suivante

M11 0.571584699453553
M12 0.0
M21 0.0
M22 0.571584699453553
OffsetX 184.0
OffsetY 118.71256830601092

avec un coef de zoom de 57 % donc tout vas bien
puisque M11 et M22 donne le zoom

si j'applique une rotation de -45° sur l'element j'ai alors

M11 0.404171417006082
M12 -0.40417141700608195
M21 0.40417141700608195
M22 0.404171417006082
OffsetX 166.69226289657158
OffsetY 228.39794001211757

le M11 et M22 changent alors que normalement ca correspond au ceof de zoom je comprend pas trop

les offsets sont bon mais pas le zoom et on a une inclinaison qui a changé

j'aimerais savoir si on peut a partir de M11 et M12 (eventuellement M21 et M22)
determiner l"angle de rotation et le coeficient de zoom correcte
__________________
IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
----------------------------------------------------
Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
ikeas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 17h46   #2
MABROUKI
Membre Expert
 
mebarek
Inscription : avril 2008
Messages : 1 043
Détails du profil
Informations personnelles :
Nom : mebarek
Âge : 53

Informations forums :
Inscription : avril 2008
Messages : 1 043
Points : 1 547
Points : 1 547
bonjour ikeas....
Vu la definition meme des operations matricielles(mul,add) on ne peut determiner à partir de la valeur d'un element de la matrice resultat,les valeurs des elements des matrices ayant servi dans les operations....
Exemple d'operations de produits matriciels generes par des transforms successives illustrant la difficulte du probleme(valeurs resultats M11,M12,M12,M22 sont entre crochets):
S denote un scale,R(theta) une rotation,Sk(tanX,tanY) un skew

1/S(sx,sx)*R(θ) = [sx*cosθ,sx*sinθ,-sx*sinθ,sx*cosθ]

2/S(sx,sx)*Sk(tanX,tanY) = [0,sx*tanθX,sx*tanθY,0]

3/S(sx,sx)*R(θ) *Sk(tanX,tanY)= [sx*sinθ*tanθY,sx*cosθ*tanθY,sx*cosθ*tanθX,-sx*sinθ*tanθX]

Ensuite au vu de ton besoin (qui n'est pas tres precis à mon avis) :
1/dans le post sur la rotation de l'adorner c'est "faire pivoter" l'Adorner dans la passe de .....Disposition(pas de Rendu) .

2/dans ce post c'est filtrer des "transformations indesirables" sur l'Adorner...... mais pas l'AdornedElement dans la passe de .....Disposition.

Le 1er exemple repond au souci du 1/ et illustre comment le general "zapata"( GeneralTransformGroup) peut ajouter des transforms supplementaires au LayoutTransform de l'Adorner (scale,rotation)...

code behind.cs du CustAdornerA(simple Rectangle en TopLeft de l'AdorneElement):
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;
 
namespace WpfUserControlAdorner
{
    public class CustAdornerA : Adorner
    {
        private Rectangle _presenter;
        // To store and manage the adorner's visual children.
        VisualCollection visualChildren;
 
        public CustAdornerA(UIElement adornedElt)
            : base(adornedElt)
        {
            visualChildren = new VisualCollection(this);
            AddVisual();
 
 
        }
        protected override Size MeasureOverride(Size constraint)
        {
            _presenter.Measure(constraint);
            return constraint;
        }
 
        protected override Size ArrangeOverride(Size finalSize)
        {
            double desiredWidth = AdornedElement.DesiredSize.Width;
            double desiredHeight = AdornedElement.DesiredSize.Height;
 
            // adornerWidth & adornerHeight are used for placement as well.
            double adornerWidth = this.DesiredSize.Width;
            double adornerHeight = this.DesiredSize.Height;
 
            //arrange _presenter
            Rect  rect = new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight);
            _presenter.Arrange(rect);
            return finalSize;
        }
        // Override the VisualChildrenCount and GetVisualChild properties to interface with 
        // the adorner's visual collection.
        protected override int VisualChildrenCount { get { return visualChildren.Count; } }
        protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
 
        //  Add the Visual to  adorner's visual collection.
        private void AddVisual()
        {
            _presenter = new Rectangle ();
            _presenter.Stroke = Brushes.Black;
            _presenter.Fill= Brushes.LightBlue;
            _presenter.Width = 10;
            _presenter.Height = 10; 
            _presenter.IsHitTestVisible = true;
             visualChildren.Add(_presenter);
        }
 
        // Appele avant passe LayoutTransform(Disposition)
        // par le layer..en sous-main
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            // Rajout d'un GeneralTransformGroup aux transforms originales
            // renvoi  tout à layer
 
            GeneralTransformGroup result = new GeneralTransformGroup();
            //multiplie size de l'adorner par 2.0
            result.Children.Add(new ScaleTransform(2.0, 2.0));
            //pivote de 30.0 degres l'adorner
            result.Children.Add( new RotateTransform(30.0,0,0));
            result.Children.Add(new SkewTransform(0.0, 0.0));
            result.Children.Add(base.GetDesiredTransform(transform));
 
            return result;
        }
 
    }
}
code xaml du winform d'utilisation:
[code]
<Window x:Class="WpfUserControlAdorner.WinCustAdornerA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CustAdornerA" Height="300" Width="300"
Loaded="Window_Loaded">
<DockPanel >
<Slider
Name="sliderScale"
Orientation="Vertical"
DockPanel.Dock="Left"
Minimum="0.25"
Maximum="1.75"
Value="1">
</Slider>
<Separator
DockPanel.Dock="Left"
HorizontalAlignment="Center"
Width="10"/>
<Slider
Name="sliderRotation"
Orientation="Vertical"
DockPanel.Dock="Left"
Minimum="-180"
Maximum="180"
Value="0">
</Slider>
<Slider
Orientation="Vertical"
DockPanel.Dock="Right"
Name="sliderSkew"
Minimum="-180"
Maximum="180"
Value="0">
</Slider>
<ScrollViewer
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left">
<Border
DockPanel.Dock="Left"
x:Name="elementBase"
Background="Transparent"
Width="450"
Height="400"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderBrush="DarkBlue"
BorderThickness="1">
<Border.LayoutTransform>
<TransformGroup x:Name="myTransformGroup">
<ScaleTransform
ScaleX="{Binding Value, ElementName=sliderScale}"
ScaleY="{Binding Value, ElementName=sliderScale}" />
<SkewTransform
CenterX="0.5"
CenterY="0.5"
AngleX="{Binding Value, ElementName=sliderSkew}"
AngleY="{Binding Value, ElementName=sliderSkew}">
</SkewTransform>
<RotateTransform
CenterX="0.5"
CenterY="0.5"
Angle="{Binding Value, ElementName=sliderRotation}" >
</RotateTransform>
<TranslateTransform />
</TransformGroup>
</Border.LayoutTransform>
<Canvas
x:Name="MyCanvas"
Background="White"
ClipToBounds="True">
<Ellipse
Canvas.Left="100"
Canvas.Top="100"
Width="100"
Height="50"
Fill="Aquamarine">
</Ellipse>
<Button
Canvas.Left="150"
Canvas.Top="200"
Width="100"
Content="MyButton">
</Button >
</Canvas>
</Border>
</ScrollViewer>
</DockPanel>
</Window>
[CODE]
code .cs du winform:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
 
namespace WpfUserControlAdorner
{
    /// <summary>
    /// Logique d'interaction pour WinCustAdornerA.xaml
    /// </summary>
    public partial class WinCustAdornerA : Window
    {
        AdornerLayer layer;
        CustAdornerA adorner;
        public WinCustAdornerA()
        {
            InitializeComponent();
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            layer = AdornerLayer.GetAdornerLayer(this.MyCanvas);
            foreach (FrameworkElement elem in this.MyCanvas.Children)
            {
                adorner = new CustAdornerA(elem);
                layer.Add(adorner);
            }
        }
    }
}
Le 2e exemple repond au souci du 2/ et utilise le fait -oublie par toi-que l'on peut passer en parametre le TransformGroup de ton LayoutTrnsform à l'Adorner .
Ensuite on extrait chaque transform ,on l'inverse et on "refile" au layer en lieu et place un autre GeneralTransform modifie...

code behind .cs du CustAdornerB :
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;
 
namespace WpfUserControlAdorner
{
    public class CustAdornerB : Adorner
    {
 
        private Rectangle _presenter;
        // To store and manage the adorner's visual children.
        VisualCollection visualChildren;
 
        //Filtre GeneralTransformGroup
        private GeneralTransformGroup resultFilter;
 
        //parametre TransformGroup de la passe courante LayoutTransform ou Disposition
        //agit sur MeasureOverride =>DesiredSize et sur ArrangeOverride=>rect
 
        private TransformGroup myTrfGroup;
 
        // nos transforms courantes seront modifies
        // pour agir sur passe courante LayoutTransform(disposition)
        private ScaleTransform myScale;
        private RotateTransform myRotation;
        private SkewTransform mySkew;
        public CustAdornerB(UIElement adornedElt,TransformGroup trfGroup)
            : base(adornedElt)
        {
            myTrfGroup = trfGroup;
            visualChildren = new VisualCollection(this);
            AddVisual();
 
 
        }
        protected override Size MeasureOverride(Size constraint)
        {
            _presenter.Measure(constraint);
            return constraint;
        }
 
        protected override Size ArrangeOverride(Size finalSize)
        {
            double desiredWidth = AdornedElement.DesiredSize.Width;
            double desiredHeight = AdornedElement.DesiredSize.Height;
 
            // adornerWidth & adornerHeight are used for placement as well.
            double adornerWidth = this.DesiredSize.Width;
            double adornerHeight = this.DesiredSize.Height;
 
            //arrange _presenter
            Rect  rect = new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight);
            _presenter.Arrange(rect);
 
            return finalSize;
        }
        // Override the VisualChildrenCount and GetVisualChild properties to interface with 
        // the adorner's visual collection.
        protected override int VisualChildrenCount { get { return visualChildren.Count; } }
        protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
 
        //  Add the Visual to  adorner's visual collection.
        private void AddVisual()
        {
            _presenter = new Rectangle ();
            _presenter.Stroke = Brushes.Black;
            _presenter.Fill= Brushes.LightBlue;
            _presenter.Width = 10;
            _presenter.Height = 10; 
            _presenter.IsHitTestVisible = true;
            visualChildren.Add(_presenter);
        }
        //Appele avant passe LayoutTransform(Disposition)
        // par le layer..en sous-main
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            // Recupere nos transforms courantes apres modifications
            // renvoi tout ( en lieu et place des originales) à layer
 
            ModifiedTransforms(myTrfGroup);
            resultFilter.Children.Add(base.GetDesiredTransform(transform));
 
            return resultFilter;
        }
        //Modifie nos transforms courantes 
        private void ModifiedTransforms(TransformGroup currentGroupe)
        {
            resultFilter = new GeneralTransformGroup();
            for (int i = 0; i < currentGroupe.Children.Count; i++)
            {
                Transform trf = currentGroupe.Children[i];
                if (trf.GetType() == typeof(ScaleTransform))
                {
                    myScale = (ScaleTransform)currentGroupe.Children[i];
                    double x = myScale.ScaleX;
                    double y = myScale.ScaleY;
                    resultFilter.Children.Add(new ScaleTransform(1 / x, 1 / y));
                }
                else if (trf.GetType() == typeof(RotateTransform))
                {
                    myRotation = (RotateTransform)currentGroupe.Children[i];
                    double theta = myRotation.Angle;
                    resultFilter.Children.Add(new RotateTransform(-theta, 0.5, 0.5));
                }
                else if (trf.GetType() == typeof(SkewTransform))
                {
                    mySkew = (SkewTransform)currentGroupe.Children[i];
                    double thetaX = mySkew.AngleX;
                    double thetaY = mySkew.AngleY;
                    resultFilter.Children.Add(new SkewTransform(-thetaX, -thetaY));
 
                }
            }
 
        }
 
 
 
    }
}
code du winform utilisateur:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 
 
<Window x:Class="WpfUserControlAdorner.WinCustAdornerB"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CustAdornerB" Height="300" Width="300"
        Loaded="Window_Loaded">
    <DockPanel >
        <Slider
            Name="sliderScale"  
            Orientation="Vertical"
            DockPanel.Dock="Left"
            Minimum="0.25"
            Maximum="1.75"
            Value="1">
        </Slider>
        <Separator 
            DockPanel.Dock="Left"
            HorizontalAlignment="Center"
            Width="10"/>
        <Slider
            Name="sliderRotation" 
            Orientation="Vertical"
            DockPanel.Dock="Left"
            Minimum="-180"
            Maximum="180"
            Value="0">
        </Slider>
        <Slider
            Orientation="Vertical"
            DockPanel.Dock="Right"
            Name="sliderSkew" 
            Minimum="-180"
            Maximum="180"
            Value="0">
        </Slider>
        <ScrollViewer
            ScrollViewer.HorizontalScrollBarVisibility="Auto"
            ScrollViewer.VerticalScrollBarVisibility="Auto"
            VerticalContentAlignment="Top"
            HorizontalContentAlignment="Left">
            <Border 
                DockPanel.Dock="Left"
                x:Name="elementBase"
                Background="Transparent"
                Width="450"
                Height="400"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                BorderBrush="DarkBlue"
                BorderThickness="1">
                <Border.LayoutTransform>
                    <TransformGroup x:Name="myTransformGroup">
                        <ScaleTransform
                                    ScaleX="{Binding Value, ElementName=sliderScale}"
                                    ScaleY="{Binding Value, ElementName=sliderScale}" />
                        <SkewTransform
                                     CenterX="0.5"
                                     CenterY="0.5"
                                     AngleX="{Binding Value, ElementName=sliderSkew}"
                                     AngleY="{Binding Value, ElementName=sliderSkew}">
                        </SkewTransform>
                        <RotateTransform 
                                    CenterX="0.5"
                                    CenterY="0.5"
                                    Angle="{Binding Value, ElementName=sliderRotation}" >
                        </RotateTransform>
                        <TranslateTransform />
                    </TransformGroup>
                </Border.LayoutTransform>
                <Canvas
                        x:Name="MyCanvas"
                        Background="White"
                        ClipToBounds="True">
                    <Ellipse
                        Canvas.Left="100"
                        Canvas.Top="100"
                        Width="100"
                        Height="50"
                        Fill="Aquamarine">
                    </Ellipse>
                    <Button 
                        Canvas.Left="150"
                        Canvas.Top="200"
                        Width="100"
                        Content="MyButton">
                    </Button >
                </Canvas>
            </Border>
        </ScrollViewer>
    </DockPanel>
</Window>
code .cs du winform:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
 
namespace WpfUserControlAdorner
{
    /// <summary>
    /// Logique d'interaction pour WinCustAdornerB.xaml
    /// </summary>
    public partial class WinCustAdornerB : Window
    {
        AdornerLayer layer;
        CustAdornerB adorner;
        public WinCustAdornerB()
        {
            InitializeComponent();
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            layer = AdornerLayer.GetAdornerLayer(this.MyCanvas);
            foreach (FrameworkElement elem in this.MyCanvas.Children)
            {
                adorner = new CustAdornerB(elem,this.myTransformGroup);
                layer.Add(adorner);
            }
        }
    }
}
Evidement l'Adorner peut etre -au lieu d'un simple rectangle- carrement un UserControl qui expose "4 corners" Rectangle en DependencyProperty et la modif de transform sera appliquee uniqument aux "4 corners" Rectangle...
Il n'est pas necessaire d'ecrirce du code en plus dans measureoverride ou arrangeoverride ....
bon code.............
MABROUKI est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 17h57   #3
MABROUKI
Membre Expert
 
mebarek
Inscription : avril 2008
Messages : 1 043
Détails du profil
Informations personnelles :
Nom : mebarek
Âge : 53

Informations forums :
Inscription : avril 2008
Messages : 1 043
Points : 1 547
Points : 1 547
bonjour ikeas....
Vu la definition meme des operations matricielles(mul,add) on ne peut determiner à partir de la valeur d'un element de la matrice resultat,les valeurs des elements des matrices ayant servi dans les operations....
Exemple d'operations de produits matriciels generes par des transforms successives illustrant la difficulte du probleme(valeurs resultats M11,M12,M12,M22 sont entre crochets):
S denote un scale,R(theta) une rotation,Sk(tanX,tanY) un skew

1/S(sx,sx)*R(θ) = [sx*cosθ,sx*sinθ,-sx*sinθ,sx*cosθ]

2/S(sx,sx)*Sk(tanX,tanY) = [0,sx*tanθX,sx*tanθY,0]

3/S(sx,sx)*R(θ) *Sk(tanX,tanY)= [sx*sinθ*tanθY,sx*cosθ*tanθY,sx*cosθ*tanθX,-sx*sinθ*tanθX]

Ensuite au vu de ton besoin (qui n'est pas tres precis à mon avis) :
1/dans le post sur la rotation de l'adorner c'est "faire pivoter" l'Adorner dans la passe de .....Disposition(pas de Rendu) .

2/dans ce post c'est filtrer des "transformations indesirables" sur l'Adorner...... mais pas l'AdornedElement dans la passe de .....Disposition.

Le 1er exemple repond au souci du 1/ et illustre comment le general "zapata"( GeneralTransformGroup) peut ajouter des transforms supplementaires au LayoutTransform de l'Adorner (scale,rotation)...

code behind.cs du CustAdornerA(simple Rectangle en TopLeft de l'AdorneElement):
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;
 
namespace WpfUserControlAdorner
{
    public class CustAdornerA : Adorner
    {
        private Rectangle _presenter;
        // To store and manage the adorner's visual children.
        VisualCollection visualChildren;
 
        public CustAdornerA(UIElement adornedElt)
            : base(adornedElt)
        {
            visualChildren = new VisualCollection(this);
            AddVisual();
 
 
        }
        protected override Size MeasureOverride(Size constraint)
        {
            _presenter.Measure(constraint);
            return constraint;
        }
 
        protected override Size ArrangeOverride(Size finalSize)
        {
            double desiredWidth = AdornedElement.DesiredSize.Width;
            double desiredHeight = AdornedElement.DesiredSize.Height;
 
            // adornerWidth & adornerHeight are used for placement as well.
            double adornerWidth = this.DesiredSize.Width;
            double adornerHeight = this.DesiredSize.Height;
 
            //arrange _presenter
            Rect  rect = new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight);
            _presenter.Arrange(rect);
            return finalSize;
        }
        // Override the VisualChildrenCount and GetVisualChild properties to interface with 
        // the adorner's visual collection.
        protected override int VisualChildrenCount { get { return visualChildren.Count; } }
        protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
 
        //  Add the Visual to  adorner's visual collection.
        private void AddVisual()
        {
            _presenter = new Rectangle ();
            _presenter.Stroke = Brushes.Black;
            _presenter.Fill= Brushes.LightBlue;
            _presenter.Width = 10;
            _presenter.Height = 10; 
            _presenter.IsHitTestVisible = true;
             visualChildren.Add(_presenter);
        }
 
        // Appele avant passe LayoutTransform(Disposition)
        // par le layer..en sous-main
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            // Rajout d'un GeneralTransformGroup aux transforms originales
            // renvoi  tout à layer
 
            GeneralTransformGroup result = new GeneralTransformGroup();
            //multiplie size de l'adorner par 2.0
            result.Children.Add(new ScaleTransform(2.0, 2.0));
            //pivote de 30.0 degres l'adorner
            result.Children.Add( new RotateTransform(30.0,0,0));
            result.Children.Add(new SkewTransform(0.0, 0.0));
            result.Children.Add(base.GetDesiredTransform(transform));
 
            return result;
        }
 
    }
}
code xaml du winform d'utilisation:
[code]
<Window x:Class="WpfUserControlAdorner.WinCustAdornerA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CustAdornerA" Height="300" Width="300"
Loaded="Window_Loaded">
<DockPanel >
<Slider
Name="sliderScale"
Orientation="Vertical"
DockPanel.Dock="Left"
Minimum="0.25"
Maximum="1.75"
Value="1">
</Slider>
<Separator
DockPanel.Dock="Left"
HorizontalAlignment="Center"
Width="10"/>
<Slider
Name="sliderRotation"
Orientation="Vertical"
DockPanel.Dock="Left"
Minimum="-180"
Maximum="180"
Value="0">
</Slider>
<Slider
Orientation="Vertical"
DockPanel.Dock="Right"
Name="sliderSkew"
Minimum="-180"
Maximum="180"
Value="0">
</Slider>
<ScrollViewer
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left">
<Border
DockPanel.Dock="Left"
x:Name="elementBase"
Background="Transparent"
Width="450"
Height="400"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderBrush="DarkBlue"
BorderThickness="1">
<Border.LayoutTransform>
<TransformGroup x:Name="myTransformGroup">
<ScaleTransform
ScaleX="{Binding Value, ElementName=sliderScale}"
ScaleY="{Binding Value, ElementName=sliderScale}" />
<SkewTransform
CenterX="0.5"
CenterY="0.5"
AngleX="{Binding Value, ElementName=sliderSkew}"
AngleY="{Binding Value, ElementName=sliderSkew}">
</SkewTransform>
<RotateTransform
CenterX="0.5"
CenterY="0.5"
Angle="{Binding Value, ElementName=sliderRotation}" >
</RotateTransform>
<TranslateTransform />
</TransformGroup>
</Border.LayoutTransform>
<Canvas
x:Name="MyCanvas"
Background="White"
ClipToBounds="True">
<Ellipse
Canvas.Left="100"
Canvas.Top="100"
Width="100"
Height="50"
Fill="Aquamarine">
</Ellipse>
<Button
Canvas.Left="150"
Canvas.Top="200"
Width="100"
Content="MyButton">
</Button >
</Canvas>
</Border>
</ScrollViewer>
</DockPanel>
</Window>
[CODE]
code .cs du winform:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
 
namespace WpfUserControlAdorner
{
    /// <summary>
    /// Logique d'interaction pour WinCustAdornerA.xaml
    /// </summary>
    public partial class WinCustAdornerA : Window
    {
        AdornerLayer layer;
        CustAdornerA adorner;
        public WinCustAdornerA()
        {
            InitializeComponent();
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            layer = AdornerLayer.GetAdornerLayer(this.MyCanvas);
            foreach (FrameworkElement elem in this.MyCanvas.Children)
            {
                adorner = new CustAdornerA(elem);
                layer.Add(adorner);
            }
        }
    }
}
Le 2e exemple repond au souci du 2/ et utilise le fait -oublie par toi-que l'on peut passer en parametre le TransformGroup de ton LayoutTrnsform à l'Adorner .
Ensuite on extrait chaque transform ,on l'inverse et on "refile" au layer en lieu et place un autre GeneralTransform modifie...

code behind .cs du CustAdornerB :
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;
 
namespace WpfUserControlAdorner
{
    public class CustAdornerB : Adorner
    {
 
        private Rectangle _presenter;
        // To store and manage the adorner's visual children.
        VisualCollection visualChildren;
 
        //Filtre GeneralTransformGroup
        private GeneralTransformGroup resultFilter;
 
        //parametre TransformGroup de la passe courante LayoutTransform ou Disposition
        //agit sur MeasureOverride =>DesiredSize et sur ArrangeOverride=>rect
 
        private TransformGroup myTrfGroup;
 
        // nos transforms courantes seront modifies
        // pour agir sur passe courante LayoutTransform(disposition)
        private ScaleTransform myScale;
        private RotateTransform myRotation;
        private SkewTransform mySkew;
        public CustAdornerB(UIElement adornedElt,TransformGroup trfGroup)
            : base(adornedElt)
        {
            myTrfGroup = trfGroup;
            visualChildren = new VisualCollection(this);
            AddVisual();
 
 
        }
        protected override Size MeasureOverride(Size constraint)
        {
            _presenter.Measure(constraint);
            return constraint;
        }
 
        protected override Size ArrangeOverride(Size finalSize)
        {
            double desiredWidth = AdornedElement.DesiredSize.Width;
            double desiredHeight = AdornedElement.DesiredSize.Height;
 
            // adornerWidth & adornerHeight are used for placement as well.
            double adornerWidth = this.DesiredSize.Width;
            double adornerHeight = this.DesiredSize.Height;
 
            //arrange _presenter
            Rect  rect = new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight);
            _presenter.Arrange(rect);
 
            return finalSize;
        }
        // Override the VisualChildrenCount and GetVisualChild properties to interface with 
        // the adorner's visual collection.
        protected override int VisualChildrenCount { get { return visualChildren.Count; } }
        protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
 
        //  Add the Visual to  adorner's visual collection.
        private void AddVisual()
        {
            _presenter = new Rectangle ();
            _presenter.Stroke = Brushes.Black;
            _presenter.Fill= Brushes.LightBlue;
            _presenter.Width = 10;
            _presenter.Height = 10; 
            _presenter.IsHitTestVisible = true;
            visualChildren.Add(_presenter);
        }
        //Appele avant passe LayoutTransform(Disposition)
        // par le layer..en sous-main
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            // Recupere nos transforms courantes apres modifications
            // renvoi tout ( en lieu et place des originales) à layer
 
            ModifiedTransforms(myTrfGroup);
            resultFilter.Children.Add(base.GetDesiredTransform(transform));
 
            return resultFilter;
        }
        //Modifie nos transforms courantes 
        private void ModifiedTransforms(TransformGroup currentGroupe)
        {
            resultFilter = new GeneralTransformGroup();
            for (int i = 0; i < currentGroupe.Children.Count; i++)
            {
                Transform trf = currentGroupe.Children[i];
                if (trf.GetType() == typeof(ScaleTransform))
                {
                    myScale = (ScaleTransform)currentGroupe.Children[i];
                    double x = myScale.ScaleX;
                    double y = myScale.ScaleY;
                    resultFilter.Children.Add(new ScaleTransform(1 / x, 1 / y));
                }
                else if (trf.GetType() == typeof(RotateTransform))
                {
                    myRotation = (RotateTransform)currentGroupe.Children[i];
                    double theta = myRotation.Angle;
                    resultFilter.Children.Add(new RotateTransform(-theta, 0.5, 0.5));
                }
                else if (trf.GetType() == typeof(SkewTransform))
                {
                    mySkew = (SkewTransform)currentGroupe.Children[i];
                    double thetaX = mySkew.AngleX;
                    double thetaY = mySkew.AngleY;
                    resultFilter.Children.Add(new SkewTransform(-thetaX, -thetaY));
 
                }
            }
 
        }
 
 
 
    }
}
code du winform utilisateur:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 
 
<Window x:Class="WpfUserControlAdorner.WinCustAdornerB"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CustAdornerB" Height="300" Width="300"
        Loaded="Window_Loaded">
    <DockPanel >
        <Slider
            Name="sliderScale"  
            Orientation="Vertical"
            DockPanel.Dock="Left"
            Minimum="0.25"
            Maximum="1.75"
            Value="1">
        </Slider>
        <Separator 
            DockPanel.Dock="Left"
            HorizontalAlignment="Center"
            Width="10"/>
        <Slider
            Name="sliderRotation" 
            Orientation="Vertical"
            DockPanel.Dock="Left"
            Minimum="-180"
            Maximum="180"
            Value="0">
        </Slider>
        <Slider
            Orientation="Vertical"
            DockPanel.Dock="Right"
            Name="sliderSkew" 
            Minimum="-180"
            Maximum="180"
            Value="0">
        </Slider>
        <ScrollViewer
            ScrollViewer.HorizontalScrollBarVisibility="Auto"
            ScrollViewer.VerticalScrollBarVisibility="Auto"
            VerticalContentAlignment="Top"
            HorizontalContentAlignment="Left">
            <Border 
                DockPanel.Dock="Left"
                x:Name="elementBase"
                Background="Transparent"
                Width="450"
                Height="400"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                BorderBrush="DarkBlue"
                BorderThickness="1">
                <Border.LayoutTransform>
                    <TransformGroup x:Name="myTransformGroup">
                        <ScaleTransform
                                    ScaleX="{Binding Value, ElementName=sliderScale}"
                                    ScaleY="{Binding Value, ElementName=sliderScale}" />
                        <SkewTransform
                                     CenterX="0.5"
                                     CenterY="0.5"
                                     AngleX="{Binding Value, ElementName=sliderSkew}"
                                     AngleY="{Binding Value, ElementName=sliderSkew}">
                        </SkewTransform>
                        <RotateTransform 
                                    CenterX="0.5"
                                    CenterY="0.5"
                                    Angle="{Binding Value, ElementName=sliderRotation}" >
                        </RotateTransform>
                        <TranslateTransform />
                    </TransformGroup>
                </Border.LayoutTransform>
                <Canvas
                        x:Name="MyCanvas"
                        Background="White"
                        ClipToBounds="True">
                    <Ellipse
                        Canvas.Left="100"
                        Canvas.Top="100"
                        Width="100"
                        Height="50"
                        Fill="Aquamarine">
                    </Ellipse>
                    <Button 
                        Canvas.Left="150"
                        Canvas.Top="200"
                        Width="100"
                        Content="MyButton">
                    </Button >
                </Canvas>
            </Border>
        </ScrollViewer>
    </DockPanel>
</Window>
code .cs du winform:
Code :
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
29
30
31
32
33
34
35
36
37
38
39
40
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
 
namespace WpfUserControlAdorner
{
    /// <summary>
    /// Logique d'interaction pour WinCustAdornerB.xaml
    /// </summary>
    public partial class WinCustAdornerB : Window
    {
        AdornerLayer layer;
        CustAdornerB adorner;
        public WinCustAdornerB()
        {
            InitializeComponent();
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            layer = AdornerLayer.GetAdornerLayer(this.MyCanvas);
            foreach (FrameworkElement elem in this.MyCanvas.Children)
            {
                adorner = new CustAdornerB(elem,this.myTransformGroup);
                layer.Add(adorner);
            }
        }
    }
}
Evidement l'Adorner peut etre -au lieu d'un simple rectangle- carrement un UserControl qui expose "4 corners" Rectangle en DependencyProperty et la modif de transform sera appliquee uniqument aux "4 corners" Rectangle...
Il n'est pas necessaire d'ecrirce du code en plus dans measureoverride ou arrangeoverride ....
bon code.............
MABROUKI est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/01/2013, 18h41   #4
ikeas
Membre émérite
 
Inscription : juillet 2008
Messages : 1 095
Détails du profil
Informations forums :
Inscription : juillet 2008
Messages : 1 095
Points : 942
Points : 942
en fait j'ai trouvé bcp plus simple pour evaluer les bounds d'un objet en rotation

Code :
1
2
3
4
5
6
7
private Rect GetBounds(FrameworkElement of, FrameworkElement from)
        {
            // Might throw an exception if of and from are not in the same visual tree
            GeneralTransform transform = of.TransformToVisual(from);
 
            return transform.TransformBounds(new Rect(0, 0, of.ActualWidth, of.ActualHeight));
        }
en utilisant les transformations

mais merci quand meme
__________________
IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
----------------------------------------------------
Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
ikeas est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 08h00.


 
 
 
 
Partenaires

Hébergement Web