码迷,mamicode.com
首页 > 其他好文 > 详细

可以修改Autocomplete高度和宽度的TextBox.(ComboBox也试用)

时间:2015-05-08 19:51:08      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:

Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Text

Public Class TextBoxEx
    Inherits TextBox
    Private acDropDownHeight As Integer = 106
    Private acDropDownWidth As Integer = 170


    <EditorBrowsable(EditorBrowsableState.Always), _  

    <Browsable(True), Description("The width, in pixels, of the auto complete drop down box"), DefaultValue(170)> _
    Public Property AutoCompleteDropDownWidth() As Integer
        Get
            Return acDropDownWidth
        End Get

        Set(value As Integer)
            acDropDownWidth = value
        End Set
    End Property


    <EditorBrowsable(EditorBrowsableState.Always), _  

    <Browsable(True), Description("The height, in pixels, of the auto complete drop down box"), DefaultValue(106)> _
    Public Property AutoCompleteDropDownHeight() As Integer
        Get
            Return acDropDownHeight
        End Get

        Set(value As Integer)
            acDropDownHeight = value
        End Set
    End Property


    Protected Overrides Sub OnHandleCreated(e As EventArgs)
        MyBase.OnHandleCreated(e)

        ACWindow.RegisterOwner(Me)
    End Sub

    ‘‘‘ <summary>  
    ‘‘‘ Provides an encapsulation of an Auto complete drop down window   
    ‘‘‘ handle and window proc.  
    ‘‘‘ </summary>  
    Private Class ACWindow
        Inherits NativeWindow
        Private Shared ReadOnly ACWindows As Dictionary(Of IntPtr, ACWindow)


        Private Const WM_WINDOWPOSCHANGED As UInt32 = &H47

        Private Const WM_NCDESTROY As UInt32 = &H82


        Private Const SWP_NOSIZE As UInt32 = &H1

        Private Const SWP_NOMOVE As UInt32 = &H2

        Private Const SWP_NOZORDER As UInt32 = &H4

        Private Const SWP_NOREDRAW As UInt32 = &H8

        Private Const SWP_NOACTIVATE As UInt32 = &H10
        Private Const WM_SIZING As UInt32 = &H214

        Private Const GA_ROOT As UInt32 = 2
        Private Shared ReadOnly owners As List(Of TextBoxEx)


        <DllImport("user32.dll")> _
        Private Shared Function EnumThreadWindows(dwThreadId As Integer, lpfn As EnumThreadDelegate, lParam As IntPtr) As Boolean
        End Function


        <DllImport("user32.dll")> _
        Private Shared Function GetAncestor(hWnd As IntPtr, gaFlags As UInt32) As IntPtr
        End Function


        <DllImport("kernel32.dll")> _
        Private Shared Function GetCurrentThreadId() As Integer
        End Function


        <DllImport("user32.dll")> _
        Private Shared Sub GetClassName(hWnd As IntPtr, lpClassName As StringBuilder, nMaxCount As Integer)
        End Sub


        <DllImport("user32.dll")> _
        Private Shared Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As IntPtr, X As Integer, Y As Integer, cx As Integer, cy As Integer, _
            uFlags As UInteger) As Boolean
        End Function


        <DllImport("user32.dll")> _
        Private Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
        End Function


        Private Delegate Function EnumThreadDelegate(hWnd As IntPtr, lParam As IntPtr) As Boolean



        <StructLayout(LayoutKind.Sequential)> _
        Private Structure RECT
            Public ReadOnly Left As Integer

            Public ReadOnly Top As Integer

            Public ReadOnly Right As Integer

            Public ReadOnly Bottom As Integer


            Public ReadOnly Property Location() As Point
                Get
                    Return New Point(Left, Top)
                End Get
            End Property
        End Structure


        Private owner As TextBoxEx

        Shared Sub New()
            ACWindows = New Dictionary(Of IntPtr, ACWindow)()

            owners = New List(Of TextBoxEx)()
        End Sub


        ‘‘‘ <summary>  
        ‘‘‘ Creates a new ACWindow instance from a specific window handle.  
        ‘‘‘ </summary>  
        Private Sub New(handle As IntPtr)
            AssignHandle(handle)
        End Sub


        ‘‘‘ <summary>  
        ‘‘‘ Registers a ComboBoxEx for adjusting the Complete Dropdown window size.  
        ‘‘‘ </summary>  
        Public Shared Sub RegisterOwner(owner As TextBoxEx)
            If (owners.Contains(owner)) Then
                Return
            End If

            owners.Add(owner)

            EnumThreadWindows(GetCurrentThreadId(), AddressOf EnumThreadWindowCallback, IntPtr.Zero)
        End Sub


        ‘‘‘ <summary>  
        ‘‘‘ This callback will receive the handle for each window that is  
        ‘‘‘ associated with the current thread. Here we match the drop down window name   
        ‘‘‘ to the drop down window name and assign the top window to the collection  
        ‘‘‘ of auto complete windows.  
        ‘‘‘ </summary>  
        Private Shared Function EnumThreadWindowCallback(hWnd As IntPtr, lParam As IntPtr) As Boolean
            If (GetClassName(hWnd) = "Auto-Suggest Dropdown") Then
                Dim handle As IntPtr = GetAncestor(hWnd, GA_ROOT)


                If (Not ACWindows.ContainsKey(handle)) Then
                    ACWindows.Add(handle, New ACWindow(handle))
                End If
            End If

            Return True
        End Function


        ‘‘‘ <summary>  
        ‘‘‘ Gets the class name for a specific window handle.  
        ‘‘‘ </summary>  
        Private Shared Function GetClassName(hRef As IntPtr) As String
            Dim lpClassName = New StringBuilder(256)

            GetClassName(hRef, lpClassName, 256)

            Return lpClassName.ToString()
        End Function


        ‘‘‘ <summary>  
        ‘‘‘ Overrides the NativeWindow‘s WndProc to handle when the window  
        ‘‘‘ attributes changes.  
        ‘‘‘ </summary>  
        Protected Overrides Sub WndProc(ByRef m As Message)
            If m.Msg = WM_SIZING Then
                If owner IsNot Nothing Then
                    Dim rr As RECT = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(RECT)), RECT)
                    owner.acDropDownWidth = (rr.Right - rr.Left)
                    owner.acDropDownHeight = (rr.Bottom - rr.Top)
                End If
            End If
            Console.WriteLine(m.Msg.ToString())
            If (m.Msg = WM_WINDOWPOSCHANGED) Then
                 If the owner has not been set we need to find the ComboBoxEx that  

                 is associated with this dropdown window. We do it by checking if  

                 the upper-left location of the drop-down window is within the   

                 ComboxEx client rectangle.   

                If (owner Is Nothing) Then
                    Dim ownerRect As Rectangle = Nothing

                    Dim acRect = New RECT()

                    For Each cbo As TextBoxEx In owners
                        GetWindowRect(Handle, acRect)

                        ownerRect = cbo.RectangleToScreen(cbo.ClientRectangle)

                        If (ownerRect.Contains(acRect.Location)) Then
                        owner = cbo

                         TODO: might not be correct. Was : Exit For
                        Exit For
                         End If
                    Next

                    owners.Remove(owner)
                End If


                If ((owner IsNot Nothing)) Then
                    SetWindowPos(Handle, IntPtr.Zero, -5, 0, owner.AutoCompleteDropDownWidth, owner.AutoCompleteDropDownHeight, _
                        SWP_NOMOVE Or SWP_NOZORDER Or SWP_NOACTIVATE)
                End If
            End If


            If (m.Msg = WM_NCDESTROY) Then
                ACWindows.Remove(Handle)
            End If


            MyBase.WndProc(m)
        End Sub
    End Class

End Class

 

可以修改Autocomplete高度和宽度的TextBox.(ComboBox也试用)

标签:

原文地址:http://www.cnblogs.com/tony-MSDN/p/4488520.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!