none
vs2008 .net 自定义控件中的location,位置不正确? RRS feed

  • 问题

  • 我想写一个日期控件:可以手动输入的那种,我用一个combobox加一个form(frmDate)里面放一个MonthCalendar1控件,代码如下:
    Public Class myDate
        Inherits ComboBox
        Private _xPoint As Point
        Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
            Dim a, B, c As String
            '--------------------------------------
            '年份输入的控制
            '--------------------------------------
            '限制第一位必须为"1"或"2" ,也就说年份必须在1000-2999之间,够用吧!

            If Text.Length = 1 Then

                If Strings.Left(Text, 1) <> "1" And Strings.Left(Text, 1) <> "2" Then

                    Text = ""

                End If

            End If
            '限制第二、三、四位必须为“1、2、3、4、5、6、7、8、9、0”

            If Text.Length = 2 Or Text.Length = 3 Or Text.Length = 4 Then
                If Strings.Right(Text, 1) <> "0" And Strings.Right(Text, 1) <> "1" And _
                    Strings.Right(Text, 1) <> "2" And Strings.Right(Text, 1) <> "3" And _
                    Strings.Right(Text, 1) <> "4" And Strings.Right(Text, 1) <> "5" And _
                    Strings.Right(Text, 1) <> "6" And Strings.Right(Text, 1) <> "7" And _
                    Strings.Right(Text, 1) <> "8" And Strings.Right(Text, 1) <> "9" Then

                    Text = Strings.Left(Text, Text.Length - 1)

                    SelectionStart = Text.Length

                End If

            End If

            If Text.Length = 4 Then

                Text = Text + "-"

                SelectionStart = Text.Length

            End If '当年份正确输入后就自动加上的“-”分隔符
            '--------------------------------------
            '月份输入的控制
            '--------------------------------------

            If Text.Length = 6 Then

                If Strings.Right(Text, 1) <> "0" And Strings.Right(Text, 1) <> "1" Then
                    If Strings.Right(Text, 1) = "2" Or Strings.Right(Text, 1) = "3" Or _
                        Strings.Right(Text, 1) = "4" Or Strings.Right(Text, 1) = "5" Or _
                        Strings.Right(Text, 1) = "6" Or Strings.Right(Text, 1) = "7" Or _
                        Strings.Right(Text, 1) = "8" Or Strings.Right(Text, 1) = "9" Then
                        a = Strings.Right(Text, 1)

                        Text = Strings.Left(Text, 5) + "0" + a + "-"

                        '如果这样,那下面一段if Text.Length=7的判断自然就自动跳过去了。

                        SelectionStart = Text.Length

                    Else '限制只能输入“0-9”

                        Text = Strings.Left(Text, Text.Length - 1)

                        SelectionStart = Text.Length

                    End If

                End If

            End If

            If Text.Length = 7 Then

                If Strings.Left(Strings.Right(Text, 2), 1) = "0" Then '如果月份第一位为“0”

                    If Strings.Right(Text, 1) <> "1" And Strings.Right(Text, 1) <> "2" And _
                        Strings.Right(Text, 1) <> "3" And Strings.Right(Text, 1) <> "4" And _
                        Strings.Right(Text, 1) <> "5" And Strings.Right(Text, 1) <> "6" And _
                        Strings.Right(Text, 1) <> "7" And Strings.Right(Text, 1) <> "8" And _
                        Strings.Right(Text, 1) <> "9" Then

                        Text = Strings.Left(Text, Text.Length - 1)

                        SelectionStart = Text.Length

                    Else

                        Text = Text + "-" '当月份输入正确后自动加一个“-”分隔符

                        SelectionStart = Text.Length

                        Exit Sub '少不了!如果少,那当月份为“01”时,紧接的If...End IF就

                        '成立,这样会在这里出现死循环,而出现溢出堆栈空间的错误!
                        '注:本程序好几个地方都可以用上Exit Sub,要加你自己补上吧!

                    End If

                End If

                If Strings.Left(Strings.Right(Text, 2), 1) = "1" Then '如果月份第一位为“1”

                    If Strings.Right(Text, 1) <> "0" And Strings.Right(Text, 1) <> "1" And _
                    Strings.Right(Text, 1) <> "2" Then

                        Text = Strings.Left(Text, Text.Length - 1)

                        SelectionStart = Text.Length

                    Else

                        Text = Text + "-" '当月份输入正确后自动加一个“-”分隔符

                        SelectionStart = Text.Length

                    End If

                End If

            End If
            '--------------------------------------
            '日期输入的控制。
            '--------------------------------------

            If Text.Length = 9 Then
                If Strings.Right(Text, 1) <> "0" And Strings.Right(Text, 1) <> "1" And _
                Strings.Right(Text, 1) <> "2" And Strings.Right(Text, 1) <> "3" Then
                    If Strings.Right(Text, 1) = "4" Or Strings.Right(Text, 1) = "5" Or _
                    Strings.Right(Text, 1) = "6" Or Strings.Right(Text, 1) = "7" Or _
                    Strings.Right(Text, 1) = "8" Or Strings.Right(Text, 1) = "9" Then
                        a = Strings.Right(Text, 1)
                        Text = Strings.Left(Text, 8) + "0" + a
                        SelectionStart = Text.Length
                        Exit Sub
                        '日期小于10时下面字符长度为10的判断当然是正确的。让它执行又如何?
                    Else
                        Text = Strings.Left(Text, Text.Length - 1)
                        SelectionStart = Text.Length
                    End If
                End If
            End If
            '当要修改日期的最后一位时的控制。
            If Text.Length = 10 Then
                B = Strings.Left(Strings.Right(Text, 5), 2) '取月份值,用于下面的日期正确性判断!
                c = Strings.Left(Text, 4) '取年份值,用于下面的日期正确性判断!
                If Strings.Right(Text, 1) <> "0" And Strings.Right(Text, 1) <> "1" And _
                Strings.Right(Text, 1) <> "2" And Strings.Right(Text, 1) <> "3" And _
                Strings.Right(Text, 1) <> "4" And Strings.Right(Text, 1) <> "5" And _
                Strings.Right(Text, 1) <> "6" And Strings.Right(Text, 1) <> "7" And _
                Strings.Right(Text, 1) <> "8" And Strings.Right(Text, 1) <> "9" Then
                    Text = Strings.Left(Text, Text.Length - 1)
                    SelectionStart = Text.Length
                End If '限制非法字符的输入。
                If Strings.Right(Text, 2) = "00" Then
                    Text = Strings.Left(Text, Text.Length - 2)
                    SelectionStart = Text.Length
                End If '限制日期不能为0
                If (B = "01" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "03" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "05" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "07" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "08" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "10" And Val(Strings.Right(Text, 2)) > 31) Or _
                (B = "12" And Val(Strings.Right(Text, 2)) > 31) Then
                    Text = Strings.Left(Text, Text.Length - 2)
                    SelectionStart = Text.Length
                End If '当月份为大月份时日期不能大于31。
                If (B = "04" And Val(Strings.Right(Text, 2)) > 30) Or _
                (B = "06" And Val(Strings.Right(Text, 2)) > 30) Or _
                (B = "09" And Val(Strings.Right(Text, 2)) > 30) Or _
                (B = "11" And Val(Strings.Right(Text, 2)) > 30) Then
                    Text = Strings.Left(Text, Text.Length - 2)
                    SelectionStart = Text.Length
                End If '当月份为小月份时日期不能大于30。
                If B = "02" Then
                    If Val(c) Mod 4 <> 0 And Val(Strings.Right(Text, 2)) > 28 Then
                        Text = Strings.Left(Text, Text.Length - 2)
                        SelectionStart = Text.Length
                    End If '非闰年日期不得超过28。
                    If Val(c) Mod 4 = 0 And Val(Strings.Right(Text, 2)) > 29 Then
                        Text = Strings.Left(Text, Text.Length - 2)
                        SelectionStart = Text.Length
                    End If '闰年日期不得超过29。
                End If '当月份为2时的日期正确性判断!
            End If
            '--------------------------------------
            '当年月日输入后就不再接受其它字符了。方法如下:
            '--------------------------------------
            If Text.Length = 11 Then
                Text = Strings.Left(Text, Text.Length - 1)
                SelectionStart = Text.Length
            End If
            MyBase.OnTextChanged(e)
        End Sub
        Private Sub myDate_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DropDown
            Dim pDate As Point = New Point(Location.X + Width, Location.Y + Height)
            Dim newpDate As Point = PointToScreen(pDate)
            newpDate = New Point(IIf(newpDate.X - FrmDate.Width < 0, 0, newpDate.X - FrmDate.Width), newpDate.Y)
            FrmDate.Location = newpDate
            FrmDate.Intance(Me)
            FrmDate.Show()
            FrmDate.BringToFront()
        End Sub

    End Class
    问题,我将这个类放在不同的窗体中,frmDate显示的位置都不一样,谢谢

    2009年6月12日 5:22

答案

  •  Private Sub myDate_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DropDown
            Dim pDate As Point = New Point(Location.X + Width, Location.Y + Height)
            Dim newpDate As Point = Me.Parent.PointToScreen(pDate)
            newpDate = New Point(IIf(newpDate.X - FrmDate.Width < 0, 0, newpDate.X - FrmDate.Width), newpDate.Y)

            FrmDate.StartPosition = FormStartPosition.Manual
            FrmDate.Location = (newpDate)

            FrmDate.Show()
            FrmDate.BringToFront()
        End Sub


    http://feiyun0112.cnblogs.com/
    • 已标记为答案 Weber Li 2009年6月12日 13:22
    2009年6月12日 7:56
    版主

全部回复

  • 问题出在 PointToScreen 上,你可以去掉它试试

    知识改变命运,奋斗成就人生!
    2009年6月12日 5:44
    版主
  • 版主的意思是不是这样:
        Private Sub myDate_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DropDown
            Dim pDate As Point = New Point(IIf(Location.X + Width - FrmDate.Width < 0, 0, Location.X + Width - FrmDate.Width), Location.Y + Height)
            FrmDate.Location = pDate
            FrmDate.Intance(Me)
            FrmDate.Show()
            FrmDate.BringToFront()
        End Sub
    这样好像位置也不对,并且这样如果将这个类不放在form容器,而放在其他容器中位置就不对啦(例如在form中放TabPage,在TabPage中放这个类)
    2009年6月12日 5:53
  • 你希望他始终显示在什么位置?
    http://feiyun0112.cnblogs.com/
    2009年6月12日 6:53
    版主
  • 在ComboBox正下方,右边对齐,就像DateTimePicker那样显示MonthCalendar,谢谢
    2009年6月12日 6:56
  • 你好!
         你需要把窗体的StartPosition属性设置为Manual,这样Location属性的设置才会有效!
    周雪峰
    2009年6月12日 7:17
    版主
  • 我是那样设置的,可是还不行啊

    2009年6月12日 7:28
  • 相对 Combobox 的话你计算时需要使用 combobox 的 location,怎么用 form 的 location 呢?



    知识改变命运,奋斗成就人生!
    2009年6月12日 7:52
    版主
  • form要显示在combobox正下方啊,我主要想确定form.location啊?
    • 已标记为答案 Weber Li 2009年6月12日 13:22
    • 取消答案标记 Weber Li 2009年6月12日 13:23
    2009年6月12日 7:54
  •  Private Sub myDate_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DropDown
            Dim pDate As Point = New Point(Location.X + Width, Location.Y + Height)
            Dim newpDate As Point = Me.Parent.PointToScreen(pDate)
            newpDate = New Point(IIf(newpDate.X - FrmDate.Width < 0, 0, newpDate.X - FrmDate.Width), newpDate.Y)

            FrmDate.StartPosition = FormStartPosition.Manual
            FrmDate.Location = (newpDate)

            FrmDate.Show()
            FrmDate.BringToFront()
        End Sub


    http://feiyun0112.cnblogs.com/
    • 已标记为答案 Weber Li 2009年6月12日 13:22
    2009年6月12日 7:56
    版主