vb.net 隐藏 NumericUpDown 控件上的向上/向下按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19517661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 15:34:49  来源:igfitidea点击:

Hiding up/down buttons on NumericUpDown control

vb.net

提问by Wine Too

I am trying to subclass NumericUpDown in several ways to get better functionality and appearance.

我正在尝试以多种方式对 NumericUpDown 进行子类化,以获得更好的功能和外观。

Since NUD is construct of two controls I would like to hide up/down buttons in cases where property "Increment" is set to 0.

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

This code is in subclass:

此代码在子类中:

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

        Controls(0).Hide()
End Sub

... and it work OK. But in that function I cannot check a value of Increment property like this:

...它工作正常。但在该函数中,我无法检查 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

In scope of this function Me is not reachable. I am also try with using local variables but can't find which event is fired before OnTextBoxResize to read value of Increment property.

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

What to do in such case to get desired functionality?

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

采纳答案by LarsTech

This seems to work fairly well. It Shadows the Increment property in order to set the visibility of the spinner controls when the Increment value is being changed. There is an underlying private method the base control calls called PositionControlswhich you cannot stop — that method could create some flicker, but on my test, it didn't.

这似乎工作得很好。它隐藏 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

In the OnTextBoxResize override, I am re-positioning the controls into their proper place, and this version does account for the UpDownAlign property.

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

回答by Idle_Mind

If you can, read this threadover at EE where I answered a similar question. It resizes the edit portion so that the control is redrawn correctly when the buttons have been hidden and the control is resized. *Otherwise the portion of the control where the buttons used to be leaves ghosts behind.

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

One solution to your specific problem is to wait for the VisibleChanged() event and check the Increment() property from there. Here is a conversion of my previous answer with some minor changes:

您的特定问题的一种解决方案是等待 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

EDIT: You could just enclose your code in a Try/Catch block?

编辑:您可以将代码包含在 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