2009-07-31 7 views
0

J'ai un ensemble de contrôles dans une ligne à l'intérieur de "FollowTableLayoutPanel1", contenue dans "TableLayoutPanel2". Je les ai redimensionnés en fonction de la position du curseur de la souris; plus le curseur de la souris est proche du centre vertical du contrôle, plus le contrôle est grand. Étant donné que FollowTableLayoutPanel1 a sa propriété d'ancrage définie sur "Top", il se recense lui-même dans TableLayoutPanel2.Essayer d'éviter le contrôle "oscillation" lors du redimensionnement des contrôles en fonction de la position de la souris

C'est là que j'ai un problème. Il est possible que le recentrage de FollowTableLayoutPanel1 déplace un contrôle d'un pixel plus loin du pointeur de la souris, ce qui provoque le rétrécissement du contrôle, ce qui provoque le recentrage de FollowTableLayoutPanel1, en rapprochant le contrôle du pointeur de la souris. , ce qui provoque le recentrage de FollowTableLayoutPanel1, ce qui éloigne le contrôle du curseur de la souris, etc., etc., etc. Le résultat final est que l'ensemble de l'installation pèse et vacille, se redimensionnant constamment. Est-ce que quelqu'un peut suggérer un moyen que je peux supprimer ce frémissement?

Le code exemple complet est fourni ci-dessous et peut être collé directement dans Form1 d'un nouveau projet. Positionner le curseur de la souris pour afficher correctement le problème est laissé comme un exercice pour le lecteur: P

Public Class Form1 
Private Sub myInitializeComponent() 
    Me.components = New System.ComponentModel.Container 
    Me.TableLayoutPanel2 = New System.Windows.Forms.TableLayoutPanel 
    Me.FollowTableLayoutPanel1 = New FollowTableLayoutPanel 
    Me.Button9 = New System.Windows.Forms.Button 
    Me.Button8 = New System.Windows.Forms.Button 
    Me.Button7 = New System.Windows.Forms.Button 
    Me.Button6 = New System.Windows.Forms.Button 
    Me.Button5 = New System.Windows.Forms.Button 
    Me.Button3 = New System.Windows.Forms.Button 
    Me.Button1 = New System.Windows.Forms.Button 
    Me.Button2 = New System.Windows.Forms.Button 
    Me.Button4 = New System.Windows.Forms.Button 
    Me.TableLayoutPanel2.SuspendLayout() 
    Me.FollowTableLayoutPanel1.SuspendLayout() 
    Me.SuspendLayout() 
    ' 
    'TableLayoutPanel2 
    ' 
    Me.TableLayoutPanel2.ColumnCount = 1 
    Me.TableLayoutPanel2.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) 
    Me.TableLayoutPanel2.Controls.Add(Me.FollowTableLayoutPanel1, 0, 0) 
    Me.TableLayoutPanel2.Location = New System.Drawing.Point(12, 115) 
    Me.TableLayoutPanel2.Name = "TableLayoutPanel2" 
    Me.TableLayoutPanel2.RowCount = 1 
    Me.TableLayoutPanel2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) 
    Me.TableLayoutPanel2.Size = New System.Drawing.Size(1194, 341) 
    Me.TableLayoutPanel2.TabIndex = 2 
    ' 
    'FollowTableLayoutPanel1 
    ' 
    Me.FollowTableLayoutPanel1.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.FollowTableLayoutPanel1.AutoSize = True 
    Me.FollowTableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink 
    Me.FollowTableLayoutPanel1.ColumnCount = 9 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button9, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button8, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button7, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button6, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button5, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button3, 2, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button1, 0, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button2, 1, 0) 
    Me.FollowTableLayoutPanel1.Controls.Add(Me.Button4, 3, 0) 
    Me.FollowTableLayoutPanel1.Location = New System.Drawing.Point(259, 0) 
    Me.FollowTableLayoutPanel1.Margin = New System.Windows.Forms.Padding(0) 
    Me.FollowTableLayoutPanel1.Name = "FollowTableLayoutPanel1" 
    Me.FollowTableLayoutPanel1.RowCount = 1 
    Me.FollowTableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle) 
    Me.FollowTableLayoutPanel1.Size = New System.Drawing.Size(675, 50) 
    Me.FollowTableLayoutPanel1.TabIndex = 1 
    Me.FollowTableLayoutPanel1.Text = "{X=0,Y=0}" & Global.Microsoft.VisualBasic.ChrW(9) & Global.Microsoft.VisualBasic.ChrW(9) & "00:00:00.0090009" 
    ' 
    'Button9 
    ' 
    Me.Button9.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button9.Location = New System.Drawing.Point(225, 0) 
    Me.Button9.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button9.Name = "Button9" 
    Me.Button9.Size = New System.Drawing.Size(75, 50) 
    Me.Button9.TabIndex = 5 
    Me.Button9.Text = "{Width=75, Height=50}" 
    Me.Button9.UseVisualStyleBackColor = True 
    ' 
    'Button8 
    ' 
    Me.Button8.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button8.Location = New System.Drawing.Point(300, 0) 
    Me.Button8.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button8.Name = "Button8" 
    Me.Button8.Size = New System.Drawing.Size(75, 50) 
    Me.Button8.TabIndex = 4 
    Me.Button8.Text = "{Width=75, Height=50}" 
    Me.Button8.UseVisualStyleBackColor = True 
    ' 
    'Button7 
    ' 
    Me.Button7.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button7.Location = New System.Drawing.Point(375, 0) 
    Me.Button7.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button7.Name = "Button7" 
    Me.Button7.Size = New System.Drawing.Size(75, 50) 
    Me.Button7.TabIndex = 3 
    Me.Button7.Text = "{Width=75, Height=50}" 
    Me.Button7.UseVisualStyleBackColor = True 
    ' 
    'Button6 
    ' 
    Me.Button6.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button6.Location = New System.Drawing.Point(0, 0) 
    Me.Button6.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button6.Name = "Button6" 
    Me.Button6.Size = New System.Drawing.Size(75, 50) 
    Me.Button6.TabIndex = 2 
    Me.Button6.Text = "{Width=75, Height=50}" 
    Me.Button6.UseVisualStyleBackColor = True 
    ' 
    'Button5 
    ' 
    Me.Button5.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button5.Location = New System.Drawing.Point(75, 0) 
    Me.Button5.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button5.Name = "Button5" 
    Me.Button5.Size = New System.Drawing.Size(75, 50) 
    Me.Button5.TabIndex = 1 
    Me.Button5.Text = "{Width=75, Height=50}" 
    Me.Button5.UseVisualStyleBackColor = True 
    ' 
    'Button3 
    ' 
    Me.Button3.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button3.Location = New System.Drawing.Point(525, 0) 
    Me.Button3.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button3.Name = "Button3" 
    Me.Button3.Size = New System.Drawing.Size(75, 50) 
    Me.Button3.TabIndex = 0 
    Me.Button3.Text = "{Width=75, Height=50}" 
    Me.Button3.UseVisualStyleBackColor = True 
    ' 
    'Button1 
    ' 
    Me.Button1.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button1.Location = New System.Drawing.Point(150, 0) 
    Me.Button1.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button1.Name = "Button1" 
    Me.Button1.Size = New System.Drawing.Size(75, 50) 
    Me.Button1.TabIndex = 0 
    Me.Button1.Text = "{Width=75, Height=50}" 
    Me.Button1.UseVisualStyleBackColor = True 
    ' 
    'Button2 
    ' 
    Me.Button2.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button2.Location = New System.Drawing.Point(450, 0) 
    Me.Button2.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button2.Name = "Button2" 
    Me.Button2.Size = New System.Drawing.Size(75, 50) 
    Me.Button2.TabIndex = 0 
    Me.Button2.Text = "{Width=75, Height=50}" 
    Me.Button2.UseVisualStyleBackColor = True 
    ' 
    'Button4 
    ' 
    Me.Button4.Anchor = System.Windows.Forms.AnchorStyles.Top 
    Me.Button4.Location = New System.Drawing.Point(600, 0) 
    Me.Button4.Margin = New System.Windows.Forms.Padding(0) 
    Me.Button4.Name = "Button4" 
    Me.Button4.Size = New System.Drawing.Size(75, 50) 
    Me.Button4.TabIndex = 0 
    Me.Button4.Text = "{Width=75, Height=50}" 
    Me.Button4.UseVisualStyleBackColor = True 
    ' 
    'Form1 
    ' 
    Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) 
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font 
    Me.ClientSize = New System.Drawing.Size(1218, 577) 
    Me.Controls.Add(Me.TableLayoutPanel2) 
    Me.Name = "Form1" 
    Me.Text = "Form1" 
    Me.TableLayoutPanel2.ResumeLayout(False) 
    Me.TableLayoutPanel2.PerformLayout() 
    Me.FollowTableLayoutPanel1.ResumeLayout(False) 
    Me.ResumeLayout(False) 

End Sub 
Friend WithEvents Button1 As System.Windows.Forms.Button 
Friend WithEvents Button2 As System.Windows.Forms.Button 
Friend WithEvents Button3 As System.Windows.Forms.Button 
Friend WithEvents Button4 As System.Windows.Forms.Button 
Friend WithEvents FollowTableLayoutPanel1 As FollowTableLayoutPanel 
Friend WithEvents TableLayoutPanel2 As System.Windows.Forms.TableLayoutPanel 
Friend WithEvents Button9 As System.Windows.Forms.Button 
Friend WithEvents Button8 As System.Windows.Forms.Button 
Friend WithEvents Button7 As System.Windows.Forms.Button 
Friend WithEvents Button6 As System.Windows.Forms.Button 
Friend WithEvents Button5 As System.Windows.Forms.Button 

Public Sub New() 
    ' This call is required by the Windows Form Designer. 
    InitializeComponent() 
    myInitializeComponent() 
    ' Add any initialization after the InitializeComponent() call. 
End Sub 

Private Sub FollowTableLayoutPanel1_TimerTick() Handles FollowTableLayoutPanel1.TimerTick 
    Me.Text = Me.FollowTableLayoutPanel1.Text 
End Sub 

Private Sub TableLayoutPanel1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TableLayoutPanel2.MouseMove 
    Me.FollowTableLayoutPanel1.parentMouseMove(e.Location) 
End Sub 
Private Sub TableLayoutPanel1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles TableLayoutPanel2.MouseLeave 
    Me.FollowTableLayoutPanel1.parentMouseLeave() 
End Sub 
End Class 
Public Class FollowTableLayoutPanel 
Inherits TableLayoutPanel 
Public WithEvents animTimer As Timer 
Private Class ControlSize 
    Private _sizing As Boolean 
    Private _bigSize As Size 
    Public ReadOnly Property BigSize() As Size 
     Get 
      Return _bigSize 
     End Get 
    End Property 
    Private _smallSize As Size 
    Public ReadOnly Property SmallSize() As Size 
     Get 
      Return _smallSize 
     End Get 
    End Property 
    Private WithEvents _thisControl As Control 
    Public ReadOnly Property ThisControl() As Control 
     Get 
      Return _thisControl 
     End Get 
    End Property 
    Public Sub New(ByVal thisControl As Control) 
     Me._sizing = False 
     Me._thisControl = thisControl 
     Me._bigSize = New Size(thisControl.Width * 2, thisControl.Height * 2) 
     Me._smallSize = thisControl.Size 
    End Sub 
    Public Sub Resize(ByVal sizeTo As Size) 
     Me._sizing = True 
     Me._thisControl.Size = sizeTo 
     Me._sizing = False 
    End Sub 
    Private Sub _thisControl_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _thisControl.SizeChanged 
     If Not Me._sizing Then 
      Me._bigSize = New Size(ThisControl.Width * 2, ThisControl.Height * 2) 
      Me._smallSize = ThisControl.Size 
     End If 
    End Sub 
End Class 
Private sizeDict As List(Of ControlSize) 
Public Sub New() 
    MyBase.New() 
    Me.sizeDict = New List(Of ControlSize) 
    Me.DoubleBuffered = True 
    Me.animTimer = New Timer() 
    Me.animTimer.Interval = 10 
    Me.animTimer.Start() 
End Sub 
Protected Overrides Sub OnControlAdded(ByVal e As System.Windows.Forms.ControlEventArgs) 
    MyBase.OnControlAdded(e) 
    e.Control.Text = String.Empty 
    sizeDict.Add(New ControlSize(e.Control)) 
    AddHandler e.Control.MouseMove, AddressOf ControlIn_MouseMove 
    AddHandler e.Control.MouseLeave, AddressOf ControlIn_MouseLeave 
End Sub 
Protected Overrides Sub OnControlRemoved(ByVal e As System.Windows.Forms.ControlEventArgs) 
    MyBase.OnControlRemoved(e) 
    For Each controlSizeIn As ControlSize In Me.sizeDict 
     If controlSizeIn.ThisControl Is e.Control Then 
      sizeDict.Remove(controlSizeIn) 
      Exit For 
     End If 
    Next 
    RemoveHandler e.Control.MouseMove, AddressOf ControlIn_MouseMove 
    RemoveHandler e.Control.MouseLeave, AddressOf ControlIn_MouseLeave 
End Sub 
Public Event TimerTick() 
Private Sub animTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles animTimer.Tick 
    Me.SuspendLayout() 
    moveButton() 
    Me.PerformLayout() 
    Me.ResumeLayout() 
    RaiseEvent TimerTick() 
End Sub 
Private Sub moveButton() 
    Static lastTime As Long = DateTime.Now.Ticks 
    If mouseLocation.X <> 0 Then 
     For Each csIn As ControlSize In Me.sizeDict 
      Dim controlIn As Control = csIn.ThisControl 
      Dim controlCentrePoint As New Point(CInt(controlIn.Left + (controlIn.Width/2)), CInt(controlIn.Top + (controlIn.Height/2))) 

      Dim differenceX As Integer = Math.Abs(controlCentrePoint.X - mouseLocation.X) 
      Dim setDifferenceX As Integer = csIn.BigSize.Width - differenceX 
      Dim setTargetX As Integer = If(setDifferenceX < csIn.SmallSize.Width, csIn.SmallSize.Width, setDifferenceX) 

      Dim targetChangeX As Integer = CInt((Math.Abs(setTargetX - controlIn.Width))/5) 
      Dim setChangeX As Integer = If(targetChangeX = 0, 1, targetChangeX) 
      If setTargetX < controlIn.Width AndAlso controlIn.Width <= csIn.BigSize.Width Then 
       Dim setX As Integer = controlIn.Width - setChangeX 
       csIn.Resize(New Size(setX, CInt(csIn.SmallSize.Height * (setX/csIn.SmallSize.Width)))) 
      ElseIf setTargetX > controlIn.Width AndAlso controlIn.Width >= csIn.SmallSize.Width Then 
       Dim setX As Integer = controlIn.Width + setChangeX 
       csIn.Resize(New Size(setX, CInt(csIn.SmallSize.Height * (setX/csIn.SmallSize.Width)))) 
      End If 

      controlIn.Text = controlIn.Size.ToString 
     Next 
    Else 
     For Each csIn As ControlSize In Me.sizeDict 
      Dim controlIn As Control = csIn.ThisControl 
      If csIn.SmallSize.Width < controlIn.Width AndAlso controlIn.Width <= csIn.BigSize.Width Then 
       Dim targetChangeX As Integer = CInt((Math.Abs(csIn.SmallSize.Width - controlIn.Width))/5) 
       Dim setChangeX As Integer = If(targetChangeX = 0, 1, targetChangeX) 
       Dim setX As Integer = controlIn.Width - setChangeX 
       Dim setY As Integer = CInt(csIn.SmallSize.Height * (setX/csIn.SmallSize.Width)) 
       csIn.Resize(New Size(setX, setY)) 
      End If 
      controlIn.Text = controlIn.Size.ToString 
     Next 
    End If 
    Dim nowTicks As Long = DateTime.Now.Ticks 
    Dim ts As New TimeSpan(nowTicks - lastTime) 
    lastTime = nowTicks 
    Me.Text = Me.mouseLocation.ToString & vbTab & vbTab & ts.ToString 
End Sub 
Private mouseLocation As Point 
Private Sub Form1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave 
    mouseLocation = New Point(0, 0) 
End Sub 
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove 
    mouseLocation = e.Location 
End Sub 
Private Sub ControlIn_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) 
    mouseLocation = New Point(CInt(e.X + CType(sender, Control).Left), CInt(e.Y + CType(sender, Control).Top)) 
End Sub 
Private Sub ControlIn_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) 
    mouseLocation = New Point(0, 0) 
End Sub 
Public Sub parentMouseMove(ByVal mouseCoordinates As Point) 
    mouseLocation = New Point(mouseCoordinates.X - Me.Left, mouseCoordinates.Y - Me.Top) 
End Sub 
Public Sub parentMouseLeave() 
    mouseLocation = New Point(0, 0) 
End Sub 
End Class 

Répondre

1

Vous essayez de mettre en œuvre un effet oeil de poisson semblable à quai dans OSX? Au lieu de gérer les événements de souris sur chaque niveau de contrôle individuel, essayez de gérer la souris au niveau parent. Lorsque le parent reçoit un mouvement de souris, calculez les nouvelles positions pour tous les contrôles et ajustez-les.

J'ai utilisé l'approche suivante pour calculer les positions pour l'effet œil de poisson. Fondamentalement, l'idée est de mettre à l'échelle/déplacer les éléments en fonction de la position de la souris. pt est la coordonnée de la souris. target.Pos est des coordonnées non scalées. ScaledPos est de nouvelles coordonnées mises à l'échelle

double dx = target.Pos.X + target.Pos.Width/2 - pt.X; 
double scale = DistanceToScale(Math.Sqrt(dx * dx + dy * dy)); 
double xRel = pt.X - target.Pos.X; 
double dxTarget = xRel * scale - xRel; 

target.ScaledPos = new Rect(target.Pos.X - dxTarget, 
          target.Pos.Y, 
          target.Pos.Width * scale, 
          target.Pos.Height); 

Vous devez calculer des positions pour tous les éléments. La fonction DistanceToScale définit la rapidité avec laquelle l'échelle passe de l'échelle maximale (lorsque la souris est au-dessus de l'élément) à 1 (les éléments ne sont pas mis à l'échelle). La fonction devrait être lisse pour éviter de sauter.

double DistanceToScale(double distance) 
{ 
    double dblScale = _c1/(1.0 + (distance * distance * _c2)); 
    if (dblScale < 1.0) 
    { 
     dblScale = 1.0; 
    } 

    return dblScale; 
} 

où c1 et c2

_c1 = maximun_scale; 
_c2 = (c1/scale_at_distance_dx) - 1/(dx^2); 
+0

Eh oui. Faisant cela. Besoin d'idées sur la façon d'éviter les effets secondaires entre le repositionnement d'une image et la suivante. – Frosty840

+0

N'utilisez pas de dispositions. Au lieu de cela, placez manuellement les contrôles où vous voulez qu'ils soient et ajustez les coordonnées lors de l'application de l'effet. – AlexEzh

+0

Oui, mais même si je le fais, le calcul effectué produira * toujours * l'effet d'oscillation indésirable. – Frosty840

Questions connexes