Reputation: 830
I'm making a sample GUI for a new application we are developing at work. The language has already been decided for me, but I am allowed to use any 3rd party DLLs or add-ins or whatever I need in order to make the GUI work as seamlessly as possible.
They want it very mac/ubuntu/vista/Windows 7-like, so I've come up with some very interesting controls and pretty GUI features. One of which are some growing/shrinking buttons near the top of the screen that increase in size when you mouse over them (it uses the distance formula to calculate the size it needs to increase by). When you take your mouse off of the controls, they shrink back down. The effect looks very professional and flashy, except that there is a ghosting effect as the button shrinks back down (and the buttons to the right of it since they are fixed-at-the-hip).
Here is what the buttons look like in the designer:
Here are some code snippets that I am using to do this:
pops child buttons underneath when parent is hovered
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
size large buttons back to normal after mouse leaves
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
increase size of large command buttons based on the mouse location in the button, happens on mouse move
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
increase size of smaller command buttons
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
decrease puts command buttons back to correct location and hides them if appropriate
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
What I know:
What I've done, and how I've tried to fix it:
What I am looking for are the answers to these questions:
~~~~~~~~~~~~~~~~~~~~~~~~~ Update 1: 11/17/2009 9:21 AM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I've improved the efficiency of the draw methods by first checking to see if they need to be redrawn by checking what the new values will be vs what they already are(code changed above). This fixes some of the ghosting, however the core problem still remains to be solved.
Upvotes: 2
Views: 1579
Reputation: 941218
There is a possible quick fix for your problem. Paste this code into your form:
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;
}
}
}
The style flag works on XP SP1 and up. It double-buffers your entire form, not just each individual control, and should eliminate the ghosting effect you see.
Upvotes: 3
Reputation: 15813
I don't see anything wrong in the code. Here is something you can try:
Draw the background image on a picturebox the size of the form, instead of the form itself. You can keep the buttons in front of it and it should look the same. Then you can control the redraw of the background image, either using the graphics object in the paint event or using a persistent image with the picture box. To prevent flickering, you can only redraw that part of the image that is within the bounds of the buttons (or the modified button and those to its right).
This isn't ideal, but it might be a usable workaround.
Upvotes: 1