试一试用 一TextBox、一Button、一窗口 代替ComboBox

解决方案 »

  1.   

    最先将 一TextBox、一Button 摆成 ComboBox 的样子,再做好一个窗体(代替ListBox),在Button的Click事件中显示窗体。
      

  2.   

    如果你对SDK比较明白的话……按我说的去做
    ComboBox实际是一个Windows预定义的一个窗口类,你可以用SetWindowLong重新设定它的窗口函数,用自己的代替,然后在自己的窗口函数中用GDI函数自己画出需要的东西,最后别忘了调用DefWindowProc,否则……
      

  3.   

    zyl910(910)与zyl910(910)说的是一种办法,但不理想,谢谢!TO idoloveyou():
    我曾用c SDK只作过一些简单的东西。对于用setWindowLong重新设定它的窗口函数不知怎样作,劳您费点心给点代码好吗?!
    不胜感激!!!
      

  4.   

    GetCursorPos,WindowFromPoint,在ComboBox的Click时SendMessage一个WM_CLOSE消息,并弹出你的窗(没实验过)
      

  5.   

    TO:dbcontrols(泰山) 
    谢谢!
    [email protected]
      

  6.   

    没人知道吗?(dbcontrols(泰山),你在哪里)
      

  7.   

    原来你就相信他?他能做出来早给你了!算了,帮人如同还债,我还是给你一个例子代码:这是用ListView做下拉的例子,你试试!!!'In a module
    =====
    Option Explicit
    Public defWinProc As LongPublic Const GWL_WNDPROC As Long = -4
    Private Const CBN_DROPDOWN As Long = 7
    Private Const WM_LBUTTONDOWN As Long = &H201
    Private Const WM_KEYDOWN As Long = &H100
    Private Const VK_F4 As Long = &H73Private Declare Function CallWindowProc _
    Lib "user32" Alias "CallWindowProcA" _
    (ByVal lpPrevWndFunc As Long, _
    ByVal hwnd As Long, ByVal Msg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As LongPrivate Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" _
    (ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As LongPublic Declare Function SetWindowLong _
    Lib "user32" Alias "SetWindowLongA" _
    (ByVal hwnd As Long, ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long
    Public Sub Unhook(hwnd As Long)If defWinProc <> 0 ThenCall SetWindowLong(hwnd, _
    GWL_WNDPROC, _
    defWinProc)
    defWinProc = 0
    End IfEnd Sub
    Public Sub Hook(hwnd As Long)'Don't hook twice or you will
    'be unable to unhook it.
    If defWinProc = 0 ThendefWinProc = SetWindowLong(hwnd, _
    GWL_WNDPROC, _
    AddressOf WindowProc)End IfEnd Sub
    Public Function WindowProc(ByVal hwnd As Long, _
    ByVal uMsg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long'only if the window is the combo box...
    If hwnd = Form1.Combo1.hwnd ThenSelect Case uMsgCase CBN_DROPDOWN 'the list box of a combo
    'box is about to be made visible.'return 1 to indicate we ate the message
    WindowProc = 1Case WM_KEYDOWN 'prevent the F4 key from showing
    'the combo's listIf wParam = VK_F4 Then'set up the parameters as though a
    'mouse click occurred on the combo,
    'and call this routine again
    Call WindowProc(hwnd, WM_LBUTTONDOWN, 1, 1000)Else'there's nothing to do keyboard-wise
    'with the combo, so return 1 to
    'indicate we ate the message
    WindowProc = 1End IfCase WM_LBUTTONDOWN 'process mouse clicks'if the listview is hidden, position and show it
    If Form1.ListView1.Visible = False ThenWith Form1
    .ListView1.Left = .Combo1.Left
    .ListView1.Width = .Combo1.Width
    .ListView1.Top = .Combo1.Top + .Combo1.Height + 1
    .ListView1.Visible = True
    .ListView1.SetFocus
    End WithElse'the listview must be visible, so hide it
    Form1.ListView1.Visible = False
    End If'return 1 to indicate we processed the message
    WindowProc = 1Case Else'call the default window handler
    WindowProc = CallWindowProc(defWinProc, _
    hwnd, _
    uMsg, _
    wParam, _
    lParam)End SelectEnd If 'If hwnd = Form1.Combo1.hwndEnd Function===='In a form, add a combo box, a listview and three command buttons=====
    Option ExplicitPrivate bKeepOpen As BooleanPrivate Sub Form_Load()Dim c As Long
    Dim chd As ColumnHeader
    Dim itmx As ListItem'Add some dummy data to the listview and hide
    With ListView1Set chd = .ColumnHeaders.Add(, , "Name", 1000)
    Set chd = .ColumnHeaders.Add(, , "Col 2", 1000)
    Set chd = .ColumnHeaders.Add(, , "Col 3", 1000)
    Set chd = .ColumnHeaders.Add(, , "Col 4", 600)For c = 1 To 15
    Set itmx = .ListItems.Add(, , Screen.Fonts(c))
    itmx.SubItems(1) = "screen"
    itmx.SubItems(2) = "font"
    itmx.SubItems(3) = c
    Next.View = lvwReport
    .FullRowSelect = True 'vb6 only
    .BorderStyle = ccNone
    .Visible = FalseEnd With'set inital state of command buttons
    Command1.Caption = "hook combo"
    Command2.Caption = "unhook combo"
    Command3.Caption = "unhook && end"
    Command1.Enabled = True
    Command2.Enabled = False
    End Sub
    Private Sub Command1_Click()If defWinProc = 0 Then
    Hook Combo1.hwnd
    Command1.Enabled = False
    Command2.Enabled = True
    End IfEnd Sub
    Private Sub Command2_Click()'unhook the combo
    If defWinProc <> 0 Then
    Unhook Combo1.hwnd
    defWinProc = 0
    Command1.Enabled = True
    Command2.Enabled = False
    End IfEnd Sub
    Private Sub Command3_Click()Unload MeEnd Sub
    Private Sub Form_Unload(Cancel As Integer)If defWinProc <> 0 Then Unhook Combo1.hwndEnd Sub
    Private Sub List1_KeyDown(KeyCode As Integer, Shift As Integer)'set flag to allow arrow and enter
    'keys to simulate behaviour of normal
    'combo
    bKeepOpen = TrueEnd Sub
    Private Sub List1_KeyPress(KeyAscii As Integer)'set flag to allow arrow and enter
    'keys to simulate behaviour of normal
    'combo
    If KeyAscii = vbKeyReturn Then'simulate selecting item with enter
    bKeepOpen = False
    Call ListView1_Click
    Else'alpha or arrow keys being used,
    'so keep open
    bKeepOpen = TrueEnd IfEnd Sub
    Private Sub ListView1_Click()Dim itmx As ListItemIf ListView1.ListItems.Count > 0 ThenSet itmx = ListView1.SelectedItem'For a style 0 combo, you can not assign
    'to the Text property from within the click
    'event, so the selected item must be 'added'
    'as the only combo item, and selected using
    'its listindex property.
    '
    'For a style 2 combo, the text property
    'can't be set unless there is an exact
    'match to a list item, so again we fake it
    'by adding the selection to the combo and
    'selecting it.
    '
    'Finally, since the tabs can't be used
    'in the combo's edit window, as it doesn't
    'support tabstops either, on selection we'll
    'display the main listview item
    With Combo1
    .Clear
    .AddItem itmx.Text
    .ListIndex = 0
    End WithEnd IfIf bKeepOpen = False Then
    ListView1.Visible = False
    Combo1.SetFocus
    End IfEnd Sub
    =====
      

  8.   

    非常感谢Bardo(巴顿)!我刚才看了一下(还没来得急仔细研究),基本上能达到要求,好象有一点还不太到理想:当combo失去焦点时,listview并没有自动隐藏(例如切换到别的窗口,或在本窗口空白地方点一个)。为了答谢各位对我的支持,给这个贴子再加30分,以期将它完善!
      

  9.   

    要自动隐藏
    下一代码有此原理:Form1:       Sub Form_Load()
            'Store handle to this form's window
            gHW = Me.hWnd        'Call procedure to begin capturing messages for this window
            Hook
          End Sub      Private Sub Form_Unload(Cancel As Integer)
            'Call procedure to stop intercepting the messages for this window
            Unhook
          End Subthe module:       Option Explicit      Declare Function CallWindowProc Lib "user32" Alias _
            "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
            ByVal hwnd As Long, ByVal Msg As Long, _
            ByVal wParam As Long, ByVal lParam As Long) As Long      Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
            (ByVal hwnd As Long, ByVal nIndex As Long, _
            ByVal dwNewLong As Long) As Long      Public Const WM_ACTIVATEAPP = &H1C
          Public Const GWL_WNDPROC = -4      Global lpPrevWndProc As Long
          Global gHW As Long      Public Sub Hook()
            'Establish a hook to capture messages to this window
            lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
              AddressOf WindowProc)
          End Sub      Public Sub Unhook()
            Dim temp As Long        'Reset the message handler for this window
            temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
          End Sub      Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
            ByVal wParam As Long, ByVal lParam As Long) As Long
            'Check for the ActivateApp message        If uMsg = WM_ACTIVATEAPP Then
                'Check to see if Activating the application
                If wParam <> 0 Then
                    'Application Received Focus
                    Form1.Caption = "Focus Restored"
                Else
                    'Application Lost Focus
                    Form1.Caption = "Focus Lost"
                End If
            End If        'Pass message on to the original window message handler
            WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, _
              lParam)
          End Function
      

  10.   

    如果你用Form做下拉
    请参考:
    http://www.csdn.net/expert/topic/442/442025.shtm
      

  11.   

    目前的问题基本解决。只是存在小小的遗憾:如果在本窗体空白的地方点击mouse,listview1也能自动消失就好了,而且我曾用一个form代替listview,用setparent将它设为子窗口,当这个form弹出时父窗口的标题栏的颜色变灰,我的目标是它的颜色不变灰,一切效果就象标准combo一样。
    所以我决定再给贴子加50分,希望高手再赐教!
    (巴顿:暂时还没有加分,请再等一等,见凉!)
      

  12.   

    目标是它的颜色不变灰:用下列两个函数:
    Public Declare Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
    '第二个参数的常量,可用 Or 逻辑相加
    Public Const SW_NORMAL = 1
    Public Const SW_RESTORE = 9
    Public Const SW_SHOWNOACTIVATE = 4Public Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
    '第二个参数
    Const HWND_TOPMOST = -1
    '最后一个参数的常量
    Public Const SWP_NOMOVE = &H2
    Public Const SWP_NOSIZE = &H1
    Public Const SWP_NOZORDER = &H4如果仍是这样,则我再想办法!
      

  13.   

    你还可以参照:
    http://www.csdn.net/expert/topic/484/484431.shtm
    http://www.csdn.net/expert/topic/487/487941.shtm
      

  14.   

    TO:Bardo
    (2002-1-21 17:52:03) 的方法不行,因为mouse点击时一个窗口会activated 另一个则deactivated另外,同时再请看一下这个贴子,我已经没法回复了
    http://www.csdn.net/expert/TopicView.asp?id=484448
    谢谢
      

  15.   

    xdd1125():
    你能够运行的代码能否给我发一个,我也一直想做这个控件,想用TREEVIEW代替弹出的LISTBOX。但是遇到了好多问题无法解决。能把代码给我参考一下吗。
    [email protected]
      

  16.   

    只要能作出来我会发一个给你的!
    问题是我现在的关键问题还没解决(没有达到标准combo的效果),你帮我up吧!目前的问题---遗憾:如果在本窗体空白的地方点击mouse,listview1也能自动消失就好了,而且我曾用一个form代替listview,用setparent将它设为子窗口,当这个form弹出时父窗口的标题栏的颜色变灰,我的目标是它的颜色不变灰,一切效果就象标准combo一样。
      

  17.   

    问题已经解决::
    请用:
    Private Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
    设定下拉窗口的父窗口为控件所在窗口即可!你再查一下,这样,
    上面的自动消失代码是否仍有效!!!!!!
      

  18.   

    SetParen我用过的,不能达到普通combo的效果的(正如前面提到的)
      

  19.   

    看了http://www.csdn.net/expert/topic/490/490739.shtm!
    继续跟贴!给分!
      

  20.   

    回复人: xdd1125(成长快乐) (2002-1-21 22:03:43)  得0分 
    TO:Bardo
    (2002-1-21 17:52:03) 的方法不行,因为mouse点击时一个窗口会activated 另一个则deactivated另外,同时再请看一下这个贴子,我已经没法回复了http://www.csdn.net/expert/TopicView.asp?id=484448
    谢谢  这个贴子我已给了新的回复!请注意!
    http://www.csdn.net/Expert/topic/484/484448.shtm
      

  21.   

    回复人: xdd1125(成长快乐) (2002-1-21 22:03:43)  得0分 
    TO:Bardo
    (2002-1-21 17:52:03) 的方法不行,因为mouse点击时一个窗口会activated 另一个则deactivated另外,同时再请看一下这个贴子,我已经没法回复了http://www.csdn.net/expert/TopicView.asp?id=484448
    谢谢  这个贴子我已给了新的回复!请注意!
    http://www.csdn.net/Expert/topic/484/484448.shtm 
      

  22.   

    回复人: xdd1125(成长快乐) (2002-1-21 22:03:43)  得0分 
    TO:Bardo
    (2002-1-21 17:52:03) 的方法不行,因为mouse点击时一个窗口会activated 另一个则deactivated另外,同时再请看一下这个贴子,我已经没法回复了http://www.csdn.net/expert/TopicView.asp?id=484448
    谢谢  这个贴子我已给了新的回复!请注意!
    http://www.csdn.net/Expert/topic/484/484448.shtm 
      

  23.   

    感谢Bardo(巴顿)!!!您已经解决了http://www.csdn.net/Expert/topic/484/484448.shtm,已经结贴!本贴子希望高手继续关注!
    up
      

  24.   

    检测combo的CBN_CLOSEUP消息可以让自已的窗体也消去,但是拦了mouse或kbd的消息或者CBN_DROPDOWN消息,列表框是否出现了(我想不会的),那么windows这种情况会不会向combo发CNB_CLOSEUP消息呢(也不大可能)怎么办呢!!!
      

  25.   

    应当从消息上考虑,我认为是可以做到的。
    同时,如果做成activeX,则必须要用窗口,可以仿制IME窗口,
    但须要找到对应的函数。
    思路是,要在Windows中注册新的窗口类,参看CreateWindowEx函数的帮助。
    然后再用那儿的代码显示出来。须要明了这个新类的参数一部分要与Combo下拉list或Edit的共有参数相同。(Combo的下拉有List与edit两种)
    你可以用Spy查看常见Combo与Office中的Combo的子窗口的参数。前者是list,后者是Edit当然,
    还要解决的是如何将这个建好的下拉窗体映射到你注册的窗口类中。操作注册表要写到程序代码中。工作量较大,主要是以前都未做过,所以一下子不可能有代码给你!抱歉!
      

  26.   

    我觉得要搞清combo中list是怎样与text相结合的,比如CBN_DROPDOWN和CBN_CLOSEUP消息windows是怎样产生的,知道这个原理就好办了(我不一定要作控件,可以直接在程序中应用)
      

  27.   

    响应光消息,然后显示Combo的子窗口。VB这一点可能做不到。当然不妨试试。
    因为你不可能将整个控件作为新的窗口类注册。
    因为注册窗口类,所以下拉显示时,只是让数值窗口失去焦点。原理就是这样!
      

  28.   

    响应消息,然后显示Combo的子窗口。VB这一点可能做不到。当然不妨试试。
    因为你不可能将整个控件作为新的窗口类注册。
    因为是注册窗口类,即二者已绑定,所以下拉显示时,只是让数值窗口失去焦点。原理就是这样!
      

  29.   

    谢谢Bardo
    原来在combo中list是它的子窗口!