本人在作一个数据库录入界面时候,根据用户的需求ComboBox需要做成在获得焦点,自动弹出下拉列表,用户只用通过数字键,输入数据对应的编号,当达到编号满足的位数时,自动选择编号所对应的数据,然后焦点传过下一个TabIndex,例:在“优势树种”字段中有“红松”“云杉”“白杨”三种数,红松对应的编号为1,云杉对的编号为2,白杨编号为3,当代表“优势树种”的ComboBox获得焦点时,自动开打下拉列表,显示三个树种,这时我键入数字键2,编号的最大位数为1,满足了编号位数,则在ComboBox框中显示云杉,同时传出焦点。功能已基本实现,但问题在于,在送出焦点后,ComboBox框内必不是总会正常按预想的显示“云杉”贴出部份代码,请高手们多多赐教:
    1。ComboBox装入数据代码:
'将数据转换显示为对应下列表框信息
Public Sub AddInfo(ByVal aCtl As Control, ByVal aTabInfo As String)
'aTabInfo 为表名,aCtl 为控件名即ComboBox名
    Dim rsInfo As New ADODB.Recordset
    Dim StrSQL As String
    StrSQL = "Select * From " & aTabInfo
    Set rsInfo = g_connAdo.Execute(StrSQL)
'rsInfo!Desc为数据名称,即“云杉”,rsInfo!SeqId为数据编号,即2
    aCtl.Clear
    Do While Not rsInfo.EOF
        aCtl.AddItem Trim(rsInfo!Desc)
        aCtl.ItemData(aCtl.ListCount - 1) = rsInfo!SeqId
        rsInfo.MoveNext
    Loop
    2。获得焦点后,自动打开下拉列表,在调用的API函数
'代码打开CBO下拉框
Public Const CB_SHOWDROPDOWN = &H14F
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
'    如果想打开下拉列表,使用:
'         SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, 1, CLng(0)
'    如果想关闭下拉列表,使用:
'     SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, 0, CLng(0)
   在上一个控件失去后调用GotFocus事件
Private Sub cboTreeDegB_GotFocus()
    SendMessage ActiveControl.hwnd, CB_SHOWDROPDOWN, 1, CLng(0)
End Sub
   3。记录输入数据函数
   在KeyPress事件中调用
   Private Sub cboTreeDegB_KeyPress(KeyAscii As Integer)
    speedinput ActiveControl, KeyAscii, 1
   End Sub
'利用数字键快速输入
Public Sub speedinput(ByVal aCtl As Control, KeyAscii As Integer, Optional Length As Integer)
'm_intSel 为模块级变量,用以记录输入数据
    Dim intCnt As Integer
    If KeyAscii >= 48 And KeyAscii <= 57 And m_intSel < 999 Then
        m_intSel = CLng(CStr(m_intSel) & CStr(Int(Chr(KeyAscii))))
    End If
    With aCtl
'当输入回车时,显示输入的编号对应值,焦点传到下一个TabIndex
    If KeyAscii = 13 Then
        For intCnt = 0 To .ListCount - 1
            If Int(m_intSel) = .ItemData(intCnt) Then
                .ListIndex = intCnt
                m_intSel = 0
                Exit For
            End If
        Next
        m_intSel = 0
    End If
    If Len(CStr(m_intSel)) = Length Then
        For intCnt = 0 To .ListCount - 1
            If Int(m_intSel) = .ItemData(intCnt) Then
                .ListIndex = intCnt
                m_intSel = 0
                Exit For
            End If
        Next
        m_intSel = 0
    SendKeys "{TAB}"
    End If
    End With
    KeyAscii = 0
End Sub我现在考虑是否是因为调用了API函数,而倒置数据发生了冲突,而产生无法正常显示
请各位多多指教

解决方案 »

  1.   

    aCtl.Clear
        Do While Not rsInfo.EOF
            aCtl.AddItem rsInfo!SeqId & vbTab & Trim(rsInfo!Desc)
            aCtl.ItemData(aCtl.NewIndex) = rsInfo!SeqId
            rsInfo.MoveNext
        Loop
      

  2.   

    楼上改的这段程序能说明原因吗?我个人感觉好像无关痛痒,现在的问题是combo在没有加API函数时,可以正常选择显示,加了之后才发生了有时选择后在某些情况下无法正常显示。这些情况的本质原因一直没有搞清楚,所以个人只能初步怀疑是API导致的某些紊乱
      

  3.   

    会有这种情况,我见过,我和你一样的用,你注意一下,是否有问题的都是英文开头的(但是不是所有)如果是的话,我也没有解决,等你好消息,我写的cboshow给你看一下,望有帮助Public Const CB_FINDSTRINGEXACT = &H158Public Const CB_SHOWDROPDOWN = &H14F
    Public Const CB_SETTOPINDEX = &H15CPublic Sub cboShow(ByVal strText As String, cbo As ComboBox, Optional intUsual As Integer = 0)
    '把strtext的内容赋给cbo两,并且是cbo发生单击事件'intUsual :是从开始开始查找还是到着找 0-从序号0开始,1-从末尾开始查找Dim intStyle As Integer
    Dim i As IntegerstrText = Trim(strText)
      
    If cbo.ListCount > 0 Then
        
        If intUsual = 0 Then
        
            i = SendMessageStr(cbo.hWnd, CB_FINDSTRINGEXACT, -1, ByVal strText)
            
            cbo.ListIndex = i
            
        
    '        For i = 0 To cbo.ListCount - 1
    '
    '           If Trim(cbo.List(i)) = strText Then
    '              cbo.ListIndex = i   '相当于点击
    '              Exit For
    '           End If
    '
    '        Next i
        
        Else
            
            For i = cbo.ListCount - 1 To 0 Step -1           If Trim(cbo.List(i)) = strText Then
               
                  cbo.ListIndex = i   '相当于点击
                  
                  Exit For
                  
               End If        Next i
        
        End If
         
    End If
           
    End Sub
      

  4.   

    还有问题可以讨论,我的email [email protected],qq常年不上,sorry
      

  5.   

    最好不要dropdown,直接show出来
    比如按2的时候,直接显示云杉,不要drop以后再显示,好运:)
      

  6.   

    楼主可能没看清需求,dropdown是必须的,因为要求该COMBO框获得焦点的时候,自动弹出下拉列表,以供用户看清各选项内容,如果这时我要选择“云杉”那么我直接输入数字2,就应该显示出来。
        还是把我的程序思想讲一下吧:首先我会在数据库里存一张辅助用表,存入名称和对应编号,如:红松对应的编号为1,云杉对的编号为2,白杨编号为3。在窗体load的时候,把名称加入list,把编号加入itemdate,代码如下:
    Public Sub AddInfo(ByVal aCtl As Control, ByVal aTabInfo As String)
    'aTabInfo 为表名,aCtl 为控件名即ComboBox名
        Dim rsInfo As New ADODB.Recordset
        Dim StrSQL As String
        StrSQL = "Select * From " & aTabInfo
        Set rsInfo = g_connAdo.Execute(StrSQL)
    'rsInfo!Desc为数据名称,即“云杉”,rsInfo!SeqId为数据编号,即2
        aCtl.Clear
        Do While Not rsInfo.EOF
            aCtl.AddItem Trim(rsInfo!Desc)
            aCtl.ItemData(aCtl.ListCount - 1) = rsInfo!SeqId
            rsInfo.MoveNext
        Loop
        界面由一系列文本框和列表框组成,提供数据录入接口,用户最先的需求是:各个控件由一定的顺序排列之后,当按下回车键的时候,焦点自动跳到下一个输入口(即文本框或列表框)我的解决方式是设置from的keypress属性为真,按排列顺序设置各式各控件的tabindex值,然后添加了from的keydown事件,代码如下:
    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    On Error GoTo ErrH:
        If KeyCode = 13 Then
            SendKeys "{TAB}"
        '设置按ESC取消CBO的选项
        ElseIf KeyCode = vbKeyEscape Then
            If Left(ActiveControl.Name, 3) = "cbo" Then
                ActiveControl.ListIndex = -1
            End If
        ElseIf KeyCode = vbKeyF6 Then
                    
        End If
        Exit Sub
    ErrH:
    End Sub
        接着处理,获得焦点后,打开列表框下拉列表,我使用的是COMBO的GotFocus事件 
    SendMessage ActiveControl.hwnd, CB_SHOWDROPDOWN, 1, CLng(0)
        然后处理,用户在下拉列表中选取自已需要的项目。这时用户提出了两个要求,1不用鼠标直接在键盘中输入数字编号,即可完成选取,2推测功能,如上例中编号只有1位字长,则我输入一位数字后不用回车,直接在COMBO中显示选项,并将焦点传出,我用keypress事件处理:
    Private Sub cboTreeDegB_KeyPress(KeyAscii As Integer)
        speedinput ActiveControl, KeyAscii, 1
    End Sub
    '利用数字键快速输入
    Public Sub speedinput(ByVal aCtl As Control, KeyAscii As Integer, Optional Length As Integer)
    'm_intSel 为模块级变量,用以记录输入数据
        Dim intCnt As Integer
        If KeyAscii >= 48 And KeyAscii <= 57 And m_intSel < 999 Then
            m_intSel = CLng(CStr(m_intSel) & CStr(Int(Chr(KeyAscii))))
        End If
        With aCtl
    '当输入回车时,显示输入的编号对应值,焦点传到下一个TabIndex
        If KeyAscii = 13 Then
            For intCnt = 0 To .ListCount - 1
                If Int(m_intSel) = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    m_intSel = 0
                    Exit For
                End If
            Next
            m_intSel = 0
        End If
    ‘推测功能实现
        If Len(CStr(m_intSel)) = Length Then
            For intCnt = 0 To .ListCount - 1
                If Int(m_intSel) = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    m_intSel = 0
                    Exit For
                End If
            Next
            m_intSel = 0
        SendKeys "{TAB}"
        End If
        End With
        KeyAscii = 0
    End Sub
        现在的问题是,在没有加入API和推测功能之前,输入数字编号并相应显示没有任何问题,加入这两段代码之后,有很多情况下,列表框并没有改变当前的选项显示状态。但实际上列表框该内容已经被选中了,我的依据是在该列表框被选择之后,我又做了另外一个推算功能。如:我选择“云杉”后,在另一个列表框中,将相应显示出树种的所属科目如“针叶树种”,和其它几个推算,代码如下:
    '根据亚林种推出林种
    Private Sub CboTypeC_Validate(Cancel As Boolean)
        Dim intSel As Integer
        Dim intCnt As Integer
    If cboTypeC.ListIndex <> -1 Then
        '推林种
        Select Case cboTypeC.ItemData(cboTypeC.ListIndex)
        Case 11 To 13
            intSel = 1
        Case 14
            intSel = 4
        Case 15 To 19
            intSel = 5
        Case 20 To 27
            intSel = 2
        Case 31 To 39
            intSel = 3
        End Select
        With cboPlantCls
            For intCnt = 0 To .ListCount - 1
                If intSel = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    intSel = 0
                    Exit For
                End If
            Next
            intSel = 0
        End With
        '推事权
        Select Case cboTypeC.ItemData(cboTypeC.ListIndex)
        Case 20
            intSel = 2
        Case Is > 20
            intSel = 1
        End Select
        With cboRelief
            For intCnt = 0 To .ListCount - 1
                If intSel = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    intSel = 0
                    Exit For
                End If
            Next
            intSel = 0
        End With
        '推保护等级
        Select Case cboTypeC.ItemData(cboTypeC.ListIndex)
        Case 20
            intSel = 2
        Case Is > 20
            intSel = 1
        End Select
        With cboSafeDeg
            For intCnt = 0 To .ListCount - 1
                If intSel = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    intSel = 0
                    Exit For
                End If
            Next
            intSel = 0
        End With
        '推森林类别
        Select Case cboTypeC.ItemData(cboTypeC.ListIndex)
        Case 20 To 42
            intSel = 2
        Case 11, 12, 13, 14, 15, 16, 17, 18, 19
            intSel = 1
        End Select
        With cboIrrigation
            For intCnt = 0 To .ListCount - 1
                If intSel = .ItemData(intCnt) Then
                    .ListIndex = intCnt
                    intSel = 0
                    Exit For
                End If
            Next
            intSel = 0
        End With
    End If
    End Sub
    我当在该列表框中输入2时,其它几个列表框都相应该显示出对应的数据,但是该列表框却没有显示出“云杉”,至今没有找到问题的根源