4

我正在尝试以多种方式继承 NumericUpDown 以获得更好的功能和外观。

由于 NUD 是由两个控件构成的,因此我想在属性“增量”设置为 0 的情况下隐藏向上/向下按钮。

此代码在子类中:

Protected Overrides Sub OnTextBoxResize(ByVal source As Object, ByVal e As System.EventArgs)

        Controls(0).Hide()
End Sub

...它工作正常。但是在那个函数中,我不能像这样检查 Increment 属性的值:

Protected Overrides Sub OnTextBoxResize(ByVal source As Object, ByVal e As System.EventArgs)

If Me.Increment = 0 Then
      Controls(0).Hide()
End if
End Sub

在此功能范围内,我无法访问。我也尝试使用局部变量,但找不到在 OnTextBoxResize 之前触发哪个事件来读取 Increment 属性的值。

在这种情况下该怎么做才能获得所需的功能?

4

2 回答 2

4

这似乎工作得很好。它对 Increment 属性进行阴影处理,以便在更改 Increment 值时设置微调器控件的可见性。基本控件调用了一个底层私有方法PositionControls,您无法停止该方法 - 该方法可能会产生一些闪烁,但在我的测试中,它没有。

Public Class MyNumBox
  Inherits NumericUpDown

  Shadows Property Increment As Decimal
    Get
      Return MyBase.Increment
    End Get
    Set(value As Decimal)
      MyBase.Increment = value
      OnTextBoxResize(Me, EventArgs.Empty)
    End Set
  End Property

  Protected Overrides Sub OnHandleCreated(e As EventArgs)
    MyBase.OnHandleCreated(e)
    OnTextBoxResize(Me, EventArgs.Empty)
  End Sub

  Protected Overrides Sub OnTextBoxResize(source As Object, e As EventArgs)
    If Me.IsHandleCreated Then
      Me.Height = Me.PreferredHeight
      Me.Controls(0).Visible = (MyBase.Increment > 0)
      Dim borderWidth As Integer = 0
      If Me.BorderStyle > BorderStyle.None Then
        borderWidth = SystemInformation.Border3DSize.Width
      End If
      Dim textWidth As Integer
      If Me.Increment = 0 Then
        textWidth = Me.ClientSize.Width - (borderWidth * 2)
      Else
        textWidth = Me.ClientSize.Width - Me.Controls(0).Width - (borderWidth * 2)
      End If
      If Me.UpDownAlign = LeftRightAlignment.Left Then
        If Me.Increment = 0 Then
          Me.Controls(1).SetBounds(borderWidth, borderWidth, _
                                   textWidth, Me.Controls(1).Height)
        Else
          Me.Controls(1).SetBounds(borderWidth + Me.Controls(0).Width, _
                                   Me.Controls(1).Top, textWidth, Me.Controls(1).Height)
        End If
      Else
        Me.Controls(1).SetBounds(borderWidth, Me.Controls(1).Top, _
                                 textWidth, Me.Controls(1).Height)
      End If
      Me.Refresh()
    End If
  End Sub
End Class

在 OnTextBoxResize 覆盖中,我将控件重新定位到适当的位置,并且此版本确实考虑了 UpDownAlign 属性。

于 2013-10-22T15:15:14.513 回答
1

如果可以,请在 EE 上阅读此主题,我在其中回答了类似的问题。它调整编辑部分的大小,以便在隐藏按钮和调整控件大小时正确重绘控件。*否则,以前按钮所在的控件部分会留下重影。

针对您的特定问题的一种解决方案是等待 VisibleChanged() 事件并从那里检查 Increment() 属性。这是我之前的答案的转换,有一些小的改动:

Public Class NoArrowNumericUpDown
    Inherits NumericUpDown

    Private itb As InnerTextBox = Nothing

    Protected Overrides Sub OnVisibleChanged(e As System.EventArgs)
        If Me.Visible Then
            If Me.Increment = 0 AndAlso IsNothing(itb) Then
                Dim ctl As Control = Me.Controls(0) ' get the spinners
                Me.Controls.Remove(ctl)  ' remove the spinners
                ctl = Me.Controls(0) ' get the edit control
                itb = New InnerTextBox(Me, ctl)
            End If
        End If

        MyBase.OnVisibleChanged(e)
    End Sub

    Public Class InnerTextBox
        Inherits NativeWindow

        Private parentControl As Control = Nothing
        Const WM_WINDOWPOSCHANGING As Integer = &H46

        Public Sub New(parentControl As Control, InnerTextBox As Control)
            Me.parentControl = parentControl
            Me.AssignHandle(InnerTextBox.Handle)
        End Sub

        Protected Overrides Sub WndProc(ByRef m As Message)
            Select Case m.Msg
                Case WM_WINDOWPOSCHANGING
                    Dim wp As WindowPos = CType(System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, GetType(WindowPos)), WindowPos)
                    If Me.parentControl IsNot Nothing Then
                        wp.cx = Me.parentControl.ClientSize.Width - 2 * wp.x
                        wp.cy = Me.parentControl.ClientSize.Height
                        System.Runtime.InteropServices.Marshal.StructureToPtr(wp, m.LParam, True)
                    End If
                    Exit Select
            End Select

            MyBase.WndProc(m)
        End Sub

        Public Structure WindowPos
            Public hwnd As IntPtr
            Public hwndInsertAfter As IntPtr
            Public x As Integer
            Public y As Integer
            Public cx As Integer
            Public cy As Integer
            Public flags As UInteger
        End Structure

    End Class

End Class

编辑:您可以将代码包含在 Try/Catch 块中吗?

Public Class NoArrowNumericUpDown
    Inherits NumericUpDown

    Protected Overrides Sub OnTextBoxResize(ByVal source As Object, ByVal e As System.EventArgs)
        Try
            If Me.Increment = 0 Then
                Controls(0).Hide()
            End If
        Catch ex As Exception
        End Try
    End Sub

End Class
于 2013-10-22T13:06:18.803 回答