2009-11-04 4 views
2

Я создаю образец графического интерфейса для нового приложения, которое мы разрабатываем на работе. Язык уже решен для меня, но мне разрешено использовать любые сторонние библиотеки DLL или надстройки или все, что мне нужно, чтобы сделать работу графического интерфейса максимально плавным..NET graphics Ghosting

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

Вот что кнопки выглядят как в конструкторе:

alt text

Вот некоторые фрагменты кода, которые я использую, чтобы сделать это:

треска ребенка кнопками под когда родитель парил

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 

То, что я знаю:

  1. Если у формы не было фонового изображения, у меня не было бы проблемы с ореолом.
  2. Если бы это была обычная кнопка, которую я рисую, у меня, вероятно, не было бы проблемы с ореолом.

Что я сделал, и как я пытался это исправить:

  1. Обеспечение doublebuffering форме повернуто на (это было)
  2. doublebuffering вручную с помощью класса bufferedGraphics (сделал не помогают или сделал это хуже)
  3. Убедить дизайнеров, которые не нуждаются в фоновых изображений или симпатичные кнопки стекла (не идти)
  4. Run Invalidate() на прямоугольник, содержащий форму (не помогло)
  5. Запустите Refresh() на форме (исправлено ореоление, но теперь весь экран мигает, когда он перезагружает изображение)
  6. Сядьте в углу моей кабинки и тихонько плачьте мне (помог стресс, но также не исправился выпуск)

Что я ищу являются ответы на эти вопросы:

  1. кто-нибудь есть идеи, как избавиться от двоения я описываю? Должен ли я сосредоточиться на изменении размера реже? следует ли сосредоточиться на буферизации фонового изображения?
  2. Существуют ли другие технологии, которые я должен использовать здесь? Есть ли элементы управления ActiveX, которые были бы лучше, чем унаследованные .NET-пользователи? Возможно ли сделать пользовательский контроль DirectX, чтобы использовать графическую карту для рисования?
  3. Есть ли что-то еще, о чем я не думаю здесь?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Обновление 1: ~~~~~~~~~~~~~~~~~~~~~~~~~

Я улучшил эффективность методов рисования, сначала проверив, нужно ли их перерисовывать проверяя, какие новые значения будут соответствовать тому, что они уже есть (код был изменен выше). Это фиксирует некоторые из ореолов, однако основная проблема все еще остается нерешенной.

+0

Ничего себе, я думаю, что вы помогаете нам всем этим щедрым кодом и описанием! –

+5

О «Есть ли другие технологии, которые я должен использовать здесь?»: * WPF * - это современное состояние создания пользовательских интерфейсов Mac/ubuntu/vista/Windows 7 с VB.NET.Похоже, вы все еще используете Winforms ... – Heinzi

+0

Да, я считаю, что WPF был привлечен к нашей команде менеджеров здесь, но они решили против нее, потому что она была «слишком новой». Так что да, я застрял в .NET 2005 (они сказали, что мы можем перейти на 2008 год, если у меня есть веские причины) – Jrud

ответ

3

Возможно, вы можете быстро исправить проблему. Вставьте этот код в форму:

public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 
     this.IsMdiContainer = true; 
     foreach (Control ctl in this.Controls) { 
     if (ctl is MdiClient) { 
      ctl.BackgroundImage = Properties.Resources.SampleImage; 
      break; 
     } 
     } 
    } 
    protected override CreateParams CreateParams { 
     get { 
     CreateParams cp = base.CreateParams; 
     cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED 
     return cp; 
     } 
    } 
    } 

Флаг стиля работает на XP SP1 и выше. Он дублирует всю форму, а не только каждый отдельный элемент управления, и должен устранить эффект ореола, который вы видите.

+0

Я уверен, что это исправляет проблему с ореолом, однако теперь я не вижу фоновые изображения мимо MDI Client control. есть идеи? – Jrud

+0

Я не знаю, что это значит. Установка свойства BackgroundImage в MdiClient работает отлично. –

+0

хм ... он не работает нормально на моем ПК. вместо фона BackgroundImage MDIClient отображается серый фон. – Jrud

1

Я не вижу в коде неправильного кода. Вот что вы можете попробовать:

Нарисуйте фоновое изображение на картинке размером с форму, а не форму. Вы можете держать кнопки перед ним, и он должен выглядеть одинаково. Затем вы можете управлять перерисованием фонового изображения, используя графический объект в событии рисования или используя постоянное изображение с полем изображения. Чтобы предотвратить мерцание, вы можете только перерисовать ту часть изображения, которая находится в пределах кнопок (или измененная кнопка, а справа - справа).

Это не идеальный вариант, но может быть полезным решением.

+0

Это действительно может быть жизнеспособным решением проблемы. Тем не менее, вы не можете сказать это на картинке, но серый фон здесь на самом деле является контейнером MDI, который будет содержать окна, запускаемые этими кнопками. Контейнер MDI имеет события рисования и т. Д., И я уже пробовал сделать недействительными определенные разделы и перерисовывать части и т.п. (и было непростой задачей выяснить, как изменить свойства на MDIClient, поскольку не является фактическим контролем формы). В некотором смысле, я как бы пытался, что вы говорите, насколько я мог. Спасибо за идею, хотя! – Jrud

Смежные вопросы