.NET图形重影

.NET图形重影,.net,vb.net,winforms,graphics,drawing,.net,Vb.net,Winforms,Graphics,Drawing,我正在为我们正在开发的新应用程序制作一个示例GUI。语言已经为我决定,但我可以使用任何第三方DLL或加载项或任何我需要的东西,以使GUI尽可能无缝地工作 他们非常喜欢mac/ubuntu/vista/Windows7,所以我想出了一些非常有趣的控件和漂亮的GUI功能。其中之一是屏幕顶部附近的一些增大/缩小按钮,当您将鼠标移到这些按钮上时,它们的大小会增加(它使用距离公式来计算需要增加的大小)。当您将鼠标从控件上取下时,控件会收缩。这个效果看起来非常专业和浮华,除了当按钮缩回时有一个重影效果(按钮

我正在为我们正在开发的新应用程序制作一个示例GUI。语言已经为我决定,但我可以使用任何第三方DLL或加载项或任何我需要的东西,以使GUI尽可能无缝地工作

他们非常喜欢mac/ubuntu/vista/Windows7,所以我想出了一些非常有趣的控件和漂亮的GUI功能。其中之一是屏幕顶部附近的一些增大/缩小按钮,当您将鼠标移到这些按钮上时,它们的大小会增加(它使用距离公式来计算需要增加的大小)。当您将鼠标从控件上取下时,控件会收缩。这个效果看起来非常专业和浮华,除了当按钮缩回时有一个重影效果(按钮位于按钮右侧,因为它们固定在臀部)

以下是设计器中按钮的外观:

下面是一些我正在使用的代码片段:

当父项悬停时,在下方弹出子项按钮

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 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
Private Sub-SmallShrinkPop(ByVal sender作为对象,ByVal e作为System.EventArgs)
Dim oldsize As Size=发送方.Size
如果不是(sender.size.width=45,sender.size.height=45),则
sender.size=新尺寸(45,45)
如果结束
Dim ChildCounter为整数=0
对于每个控件,在Me.Controls中作为System.Windows.Forms.control
如果control.GetType.ToString=“Glass.GlassButton”AndAlso control.Location.X=sender.Location.X AndAlso control.Width=sender.Width AndAlso control.Location.Y>sender.Location.Y,则
ChildCounter+=1
control.Location=新点(control.Location.X,control.Location.Y+(sender.size.height-oldsize.height))
如果Windows.Forms.Control.MousePosition.XControl.Location.X+Control.Width,则
sender.visible=False
control.Visible=False
如果结束
如果结束
下一个
如果(ChildCounter=0,并且还有Windows.Forms.Control.MousePosition.Y>sender.Location.Y+sender.Height)或(Windows.Forms.Control.MousePosition.Xsender.Location.X+sender.Width),则
sender.visible=False
对于每个控件,在Me.Controls中作为System.Windows.Forms.control
如果control.GetType.ToString=“Glass.GlassButton”和also control.Location.X=sender.Location.X和also control.Width=sender.Width
control.Visible=False
如果结束
下一个
如果结束
端接头
据我所知:

  • 如果表单没有背景图像,我就不会有重影问题
  • 如果这只是我正在绘制的一个普通按钮,我可能不会有重影问题
  • 我做了什么,以及我是如何修复它的:

  • 确保窗体的双缓冲已打开(已打开)
  • 使用bufferedGraphics类手动双缓冲(没有帮助或使情况更糟)
  • 说服设计师,它不需要背景图像或漂亮的玻璃按钮(不需要)
  • 在包含表单的矩形上运行Invalidate()(没有帮助)
  • 在窗体上运行Refresh()(修复了重影,但现在整个屏幕在重新加载图像时闪烁)
  • 坐在我的隔间角落里,轻轻地对自己哭泣(缓解了压力,但也没有解决问题)
  • 我想要的是这些问题的答案:

  • 有人知道如何摆脱我描述的幽灵吗?我应该减少改变尺寸的频率吗?我应该专注于缓冲背景图像吗
  • 这里还有其他我应该使用的技术吗?是否有ActiveX控件在这方面比.NET用户继承的控件更好?是否可以使DirectX用户控件使用图形卡绘制自身
  • 还有什么我没想到的吗
  • 更新1:11/17/2009上午9:21~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    我已经提高了draw方法的效率,首先通过检查新值与已有值(上面更改的代码)来检查它们是否需要重新绘制。这修复了一些重影,但是核心问题仍然有待解决。

    我没有看到代码中有任何错误。以下是您可以尝试的:

    在图片盒上绘制窗体大小的背景图像,而不是窗体本身。你可以把按钮放在它前面,它看起来应该是一样的。然后,可以使用paint事件中的图形对象或使用带有图片框的持久图像来控制背景图像的重画。为了防止闪烁,您只能重新绘制按钮(或修改后的按钮及其右侧按钮)边界内的图像部分


    这并不理想,但可能是一个可用的解决方法。

    有一个可能的快速解决方案。将此代码粘贴到表单中:

      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及以上版本。它可以双重缓冲整个表单,而不仅仅是每个单独的控件,并且应该可以消除您看到的重影效果。

    哇,我认为您通过大量的代码和描述帮助了我们!关于“我应该在这里使用其他技术吗?”:WPF是目前最先进的使用VB.NET创建“mac/ubuntu/vista/Windows7-like”用户界面的技术。看起来您仍然在使用Winforms…是的,我相信WPF是在这里被带到我们的管理团队的,但他们决定不使用它,因为它“太新了”。所以是的,我被困在.NET2005(他们说如果我有充分的理由,我们可以搬到2008年)太新了??WPF可能相对较新,但它非常适合您正在创建的应用程序。阿尔索
    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
    
      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;
          }
        }
      }