Я делаю образец графического интерфейса для нового приложения, над которым мы работаем. Язык уже определен за меня, но мне разрешено использовать любые сторонние библиотеки DLL или надстройки или все, что мне нужно, чтобы графический интерфейс работал как можно более плавно.
Они хотят, чтобы это было очень похоже на mac / ubuntu / vista / Windows 7, поэтому я придумал несколько очень интересных элементов управления и симпатичных функций графического интерфейса. Одна из них - это кнопки увеличения / уменьшения в верхней части экрана, которые увеличиваются в размере при наведении на них указателя мыши (он использует формулу расстояния для расчета размера, на который необходимо увеличить). Когда вы убираете мышь с элементов управления, они снова сжимаются. Эффект выглядит очень профессионально и броско, за исключением того, что появляется эффект двоения, когда кнопка сжимается вниз (и кнопки справа от нее, поскольку они фиксируются на бедре).
Вот как выглядят кнопки в дизайнере:

Вот несколько фрагментов кода, которые я использую для этого:
всплывает дочерние кнопки внизу при наведении курсора на родительский
Private Sub buttonPop(ByVal sender As Object, ByVal e As System.EventArgs)
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.Y > sender.Location.Y AndAlso control.Location.X >= sender.Location.X AndAlso control.Width < sender.Width AndAlso control.Location.X + control.Width < sender.Location.X + sender.Width Then
control.Visible = True
End If
Next
End Sub
вернуться к нормальному размеру больших кнопок после того, как мышь покинет
Private Sub shrinkpop(ByVal sender As Object, ByVal e As System.EventArgs)
Dim oldSize As Size = sender.Size
sender.Size = New Size(60, 60)
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.X > sender.Location.X AndAlso (Not control.Location.X = control.Location.X + (sender.size.width - oldSize.Width)) Then
control.Location = New Point(control.Location.X + (sender.size.width - oldSize.Width), control.Location.Y)
End If
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.Y > sender.Location.Y AndAlso control.Location.X = sender.Location.X AndAlso control.Width < sender.Width Then
control.Location = New Point(control.Location.X, control.Location.Y + (sender.size.height - oldSize.Height))
If Windows.Forms.Control.MousePosition.X < control.Location.X Or Windows.Forms.Control.MousePosition.X > control.Location.X + control.Width Then
control.Visible = False
End If
End If
Next
End Sub
увеличение размера больших командных кнопок в зависимости от положения мыши в кнопке, происходит при перемещении мыши
Private Sub buttonMouseMovement(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim oldSize As Size = sender.Size
Dim middle As Point = New Point(30, 30)
Dim adder As Double = Math.Pow(Math.Pow(middle.X - e.X, 2) + Math.Pow(middle.Y - e.Y, 2), 0.5)
Dim total As Double = Math.Pow(1800, 0.5)
adder = (1 - (adder / total)) * 20
If Not (sender.size.width = 60 + adder And sender.size.height = 60 + adder) Then
sender.Size = New Size(60 + adder, 60 + adder)
End If
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.X > sender.Location.X AndAlso (Not control.Location.X = control.Location.X + (sender.size.width - oldSize.Width)) Then
control.Location = New Point(control.Location.X + (sender.size.width - oldSize.Width), control.Location.Y)
End If
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.Y > sender.Location.Y AndAlso control.Location.X >= sender.Location.X AndAlso control.Width < sender.Width AndAlso control.Location.X + control.Width < sender.Location.X + sender.Width AndAlso (Not control.Location.Y = control.Location.Y + (sender.size.height - oldSize.Height)) Then
control.Location = New Point(control.Location.X, control.Location.Y + (sender.size.height - oldSize.Height))
End If
Next
End Sub
увеличивать размер меньших командных кнопок
Private Sub SmallButtonMouseMovement(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim oldSize As Size = sender.Size
Dim middle As Point = New Point(22.5, 22.5)
Dim adder As Double = Math.Pow(Math.Pow(middle.X - e.X, 2) + Math.Pow(middle.Y - e.Y, 2), 0.5)
Dim total As Double = Math.Pow(1012.5, 0.5)
adder = (1 - (adder / total)) * 15
If Not (sender.size.Width = 45 + adder And sender.size.height = 45 + adder) Then
sender.Size = New Size(45 + adder, 45 + adder)
End If
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.Y > sender.Location.Y AndAlso control.Location.X = sender.location.X AndAlso (Not control.Location.Y = control.Location.Y + (sender.size.height - oldSize.Height)) Then
control.Location = New Point(control.Location.X, control.Location.Y + (sender.size.height - oldSize.Height))
End If
Next
End Sub
уменьшение возвращает командные кнопки в правильное положение и скрывает их, если необходимо
Private Sub SmallShrinkPop(ByVal sender As Object, ByVal e As System.EventArgs)
Dim oldsize As Size = sender.Size
If Not (sender.size.width = 45 AndAlso sender.size.height = 45) Then
sender.size = New Size(45, 45)
End If
Dim ChildCounter As Integer = 0
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.X = sender.location.X AndAlso control.Width = sender.width AndAlso control.Location.Y > sender.location.y Then
ChildCounter += 1
control.Location = New Point(control.Location.X, control.Location.Y + (sender.size.height - oldsize.Height))
If Windows.Forms.Control.MousePosition.X < control.Location.X Or Windows.Forms.Control.MousePosition.X > control.Location.X + control.Width Then
sender.visible = False
control.Visible = False
End If
End If
Next
If (ChildCounter = 0 AndAlso Windows.Forms.Control.MousePosition.Y > sender.Location.Y + sender.Height) Or (Windows.Forms.Control.MousePosition.X < sender.Location.X Or Windows.Forms.Control.MousePosition.X > sender.Location.X + sender.Width) Then
sender.visible = False
For Each control As System.Windows.Forms.Control In Me.Controls
If control.GetType.ToString = "Glass.GlassButton" AndAlso control.Location.X = sender.location.x AndAlso control.Width = sender.width Then
control.Visible = False
End If
Next
End If
End Sub
Что я знаю:
- Если бы в форме не было фонового изображения, у меня не было бы проблемы с ореолом.
- Если бы это была обычная кнопка, которую я рисую, у меня, вероятно, не было бы проблемы с ореолом.
Что я сделал и как пытался это исправить:
- Обеспечение включения двойной буферизации формы (было)
- Двойная буферизация вручную с использованием класса bufferedGraphics (не помогло или ухудшило ситуацию)
- Убедите дизайнеров, что для этого не нужны фоновые изображения или красивые стеклянные кнопки (нет)
- Запустите Invalidate () на прямоугольнике, содержащем форму (не помогло)
- Запустите Refresh () в форме (исправлено двоение, но теперь весь экран мигает при перезагрузке изображения)
- Сижу в углу кабинки и тихонько плачьте про себя (помогло стрессу, но также не устранило проблему)
Я ищу ответы на следующие вопросы:
- Кто-нибудь знает, как избавиться от описываемого мною ореола? Стоит ли реже фокусироваться на изменении размера? я должен сосредоточиться на буферизации фонового изображения?
- Есть ли здесь другие технологии, которые мне следует использовать? Существуют ли элементы управления ActiveX, которые были бы лучше, чем унаследованные пользователем .NET? Можно ли сделать так, чтобы пользовательский элемент управления DirectX использовал графическую карту для рисования?
- Есть что-то еще, о чем я здесь не думаю?
~~~~~~~~~~~~~~~~~~~~~~~~ Обновление 1: 17.11.2009 9:21 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Я повысил эффективность методов рисования, сначала проверив, нужно ли их перерисовывать, проверив, какими будут новые значения по сравнению с тем, что они уже есть (код изменен выше). Это устраняет некоторые проблемы с ореолом, однако основная проблема все еще не решена.