返回首页

|:一个32位的Windows XP(SP2)的Windows.Forms.ComboBox项目的工具提示
{S0}简介
这是一个快速的文章显示了如何创建一个混合Windows.Forms.ComboBox要解决的问题,其中一个项目的文本宽度超过下拉区的宽度。背景
一个前两天,我的一个客户问我如何完成这项任务。最初,我惊讶地发现,控制本身没有公开此功能,然后在无法找到一个简单的在线例子更惊讶。使用代码
只需添加到您的项目代码,并使用任何下拉Windows.Forms.ComboBox ComboBoxToolTip控制。
为了让事情简短的示例代码不支持。DropDownStyle = ComboBoxStyle.Simple或所有者绘制的组合项目。应该延长,以支持它的代码一个简单的锻炼,但如果有人需要就这一点帮助,请喊。
您将需要进口System.Drawing和System.Windows.Forms命名空间。

Private Class ToolTipWindow



    Inherits Control



    Private Declare Function SetParent Lib "user32" _

           (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer

    Private Declare Function ShowWindow Lib "user32" _

           (ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Integer

    Private Declare Function SendMessage Lib "user32" _

           (ByVal hWnd As IntPtr, ByVal Msg As Integer, _

            ByVal wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr



    Public Sub New()

        MyBase.New()

        Me.BackColor = SystemColors.Info

    End Sub



    Public Overloads Sub Show()



        If (Me.Handle.Equals(IntPtr.Zero)) Then Me.CreateControl()



        Dim h As IntPtr = Me.Handle



        If Not Me.Visible Then SetParent(h, IntPtr.Zero)



        ShowWindow(h, 1)



        Me.Invalidate()



    End Sub



    Protected Overrides ReadOnly Property CreateParams() As _

                        System.Windows.Forms.CreateParams

        Get



            Const WS_EX_TOOLWINDOW As Integer = &H80

            Const WS_EX_NOACTIVATE As Integer = &H8000000

            Const WS_EX_TOPMOST As Integer = &H8



            Dim p As CreateParams = MyBase.CreateParams



            p.ExStyle = p.ExStyle Or (WS_EX_NOACTIVATE Or _

                                      WS_EX_TOOLWINDOW Or WS_EX_TOPMOST)

            p.Parent = IntPtr.Zero



            Return p



        End Get

    End Property



    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)



        MyBase.OnPaint(e)



        If String.IsNullOrEmpty(Me.Text) Then Return

        

        Using brush As Brush = New SolidBrush(Me.ForeColor)

            e.Graphics.DrawString(Me.Text, Me.Font, brush, Me.ClientRectangle)

        End Using

      

        e.Graphics.DrawRectangle(SystemPens.ControlDarkDark, 0, 0, _

                   Me.ClientRectangle.Width - 1, Me.ClientRectangle.Height - 1)



    End Sub



End Class

我们在这个项目中有两个班。我们将看看第一个是我用来取代Windows.Forms.ToolTip框架为我们提供了一个。
这一切​​漂亮的selfexplanatory东西,所以我就迅速覆盖的基础。类继承Windows.Forms.Control。我这样做,因为它是一个简单的操作来描述一个适当的窗口类(的CreateParams)和油漆,而不调用本地代码(OnPaint中)。当然,高级用户可以调整的风格,更使油漆清洁等,但在这里,我的目标是保持代码的简单遵循尽可能。
这里的利益点..... 父窗口设置为IntPtr.Zero。这意味着我们的工具提示窗口可以"浮动",因为在桌面上拥有。请注意,我们所要做的显示方法(SetParent)如果窗口已经隐藏,否则Z -顺序低于活性形式。我们的工具提示是所有者绘制的,这意味着我们能够制作任何工具提示我们要的风格。
第二类是我们的ComboBox控件。{C}
这个类的混合型的本质是保持跟踪,当鼠标指针向下下拉ListBox控件的Y轴移动。因为它是确定的,鼠标在该项目的索引,然后项目文本的宽度计算。如果文本的宽度超过降下来列表框,刷新和显示工具提示。当工具提示不再需要,它是简单的隐藏,而不是销毁,并重复使用下一次。
也许,最棘手的位是方法,计算出该项目的鼠标下的指数。我用GetScrollPos的本地方法来考虑滚动偏移,但是这是32位机上唯一真正支持。 64位安全的方法,但不必要的复杂/扩展的示例代码,因此我的选择。那么,我做一个有点手册数学计算最终的指数。
我想唯一的其他有趣的一点是我选择的消息... ... WM_CTLCOLORLISTBOX。这是一个简单的选择,因为它是适合大多数始终与我们的模型,而消息的lParam值实际上是下拉列表框的窗口句柄的消息。可能的改进
毫无疑问,许多,但这里有几个春天在我脑海中... ...我主要是基于TreeView控件的工具提示行为。缺少的一件事是一个计时器,自动隐藏工具提示。我没有把这个,因为我喜欢它,不要隐瞒,但它会为这个漂亮的是开发商的选项。这可能是一个好主意,允许开发人员选择销毁工具提示,而不是简单地隐藏它。支持从右到左的地区。兴趣点
Windows.Forms.ComboBox控制仅仅是一个为母语的CComboBox类的包装。 CComboBox使用一个CListBox的下拉区域。我最初的方法是使用管理NativeWindow类继承这个窗口。虽然这工作得很好,我认为这将是尝试让事情尽可能多了几分乐趣。NET托管代码。历史2007年5月在C​​odeProject发布。混合动力版与所有者绘制的超级工具提示,2007年6月发布的文章。

回答

评论会员:游客 时间:2011/12/14
我在我的VB项目实施你的脚本在VisualStudio2010当您的ComboBox却因重点似乎火TextChanged事件,而如果你再重新选择组合似乎火约30倍的GotFocus事件。我有这些问题都在使用相同的代码在一个标准的ComboBox。PS-好像只有这样做时AutoCompleteMode建议,追加或SuggestAppend,这正是我所需要的
JFish222
评论会员:游客 时间:2011/12/14
嗨,。首先感谢你,这个职位正是我所需要的。你救了我大量的时间,盘算了这一点。第二,我只是想向几个,其他人可能会发现有用的功能:1)支持DisplayMember属性时到ComboBox绑定对象2)支持自定义字符串生成宿主容器通过一个委托。-如果这是很难读的,我很乐意以电子邮件的变化变化:私人小组RefreshToolTip(BYVALlbhWnd作为IntPtr的),我添加了一个方法来生成字符串昏暗的小号作为字符串=retrieveToolTipString(N)我再补充以下属性和方法,以生成提示字符串:codeprespanclass="code-preprocessor"#Region/spanspanclass="code-string""/spanspanclass="code-string"properties"/spanspanclass="code-keyword"Public/spanspanclass="code-keyword"Delegate/spanspanclass="code-keyword"Function/spanDelegate_GenerateToolTipString(spanclass="code-keyword"ByVal/spanentryspanclass="code-keyword"As/spanspanclass="code-keyword"Object/span)spanclass="code-keyword"As/spanspanclass="code-keyword"String/spanspanclass="code-keyword"Private/spanm_GenerateToolTipStringDelegatespanclass="code-keyword"As/spanDelegate_GenerateToolTipString=spanclass="code-keyword"Nothing/span<Browsable(spanclass="code-keyword"False/span)>_spanclass="code-keyword"Public/spanspanclass="code-keyword"Property/spanGenerateToolTipStringDelegate()spanclass="code-keyword"As/spanDelegate_GenerateToolTipStringspanclass="code-keyword"Get/spanspanclass="code-keyword"Return/spanm_GenerateToolTipStringDelegatespanclass="code-keyword"End/spanspanclass="code-keyword"Get/spanspanclass="code-keyword"Set/span(spanclass="code-keyword"ByVal/spanvaluespanclass="code-keyword"As/spanDelegate_GenerateToolTipString)m_GenerateToolTipStringDelegate=valuespanclass="code-keyword"End/spanspanclass="code-keyword"Set/spanspanclass="code-keyword"End/spanspanclass="code-keyword"Property/span spanclass="code-preprocessor"#End/spanRegion spanclass="code-keyword"Private/spanspanclass="code-keyword"Function/spanretrieveToolTipString(spanclass="code-keyword"ByVal/spanidxspanclass="code-keyword"As/spanspanclass="code-keyword"Integer/span)spanclass="code-keyword"As/spanspanclass="code-keyword"String/span\\Useaspanclass="code-keyword"delegate/spanspanclass="code-keyword"to/spangeneratethetooltipspanclass="code-keyword"If/spanspanclass="code-keyword"Not/spanGenerateToolTipStringDelegatespanclass="code-keyword"Is/spanspanclass="code-keyword"Nothing/spanspanclass="code-keyword"Then/spanspanclass="code-keyword"Return/spanGenerateToolTipStringDelegate(spanclass="code-keyword"Me/span.Items(idx))spanclass="code-keyword"End/spanspanclass="code-keyword"If/span \\usetheDisplayMemberspanclass="code-keyword"If/span(spanclass="code-keyword"Not/spanDisplayMemberspanclass="code-keyword"Is/spanspanclass="code-keyword"Nothing/span)spanclass="code-keyword"AndAlso/span(spanclass="code-keyword"Not/spanDisplayMember=spanclass="code-string""/spanspanclass="code-string""/span)spanclass="code-keyword"Then/spanspanclass="code-keyword"Dim/spantpspanclass="code-keyword"As/spanType=obj.spanclass="code-keyword"GetType/spanspanclass="code-keyword"Dim/spanpropInfospanclass="code-keyword"As/spanPropertyInfo=tp.GetProperty(propertyName)spanclass="code-keyword"Return/spanpropInfo.GetValue(obj,spanclass="code-keyword"Nothing/span)spanclass="code-keyword"End/spanspanclass="code-keyword"If/span\\assumetheitemspanclass="code-keyword"is/spanaspanclass="code-keyword"string/span/hasdefinedtoString()spanclass="code-keyword"Return/spanspanclass="code-keyword"Me/span.Items(idx).ToString.Replace(Environment.NewLine,spanclass="code-string""/spanspanclass="code-string"X"/spanc)spanclass="code-keyword"End/spanspanclass="code-keyword"Function/span/pre/code
理查德阿什曼
评论会员:游客 时间:2011/12/14
感谢的意见...它很高兴帮助您。也为代码;我敢肯定,其他海报的绑定问题之一,可能会发现。作为一个方面,另一个海报问我延长控制支持所有者绘制工具提示。你会发现imgsrc=http://www.orcode.com/upimg/2011_12_14_12_37_05_0.gif,可能会发现适合你的目的,更好一点。照顾理查德
会员1585512
评论会员:游客 时间:2011/12/14
很好的例子,谢谢您理查德我的问题是,为什么不工作,例如,如果我从一个DataTable填充ComboBox的,但它正常工作,如果我添加ComboBox项逐一编程?eleminate这个麻烦,我应该怎样做呢?请告诉我的例子。预先感谢您。谢尔盖Rychkov
理查德阿什曼
评论会员:游客 时间:2011/12/14
喜谢尔盖这是从过去的爆炸。我怕我不知道它为什么不工作与绑定数据源的原因。如果您可以张贴一些示例代码的地方,我会高兴地下载它,并采取快速浏览一下。理查德
MisterT99
评论会员:游客 时间:2011/12/14
喜唐尼,请您更新的示例代码的链接吗?它不工作。感谢
sal21
评论会员:游客 时间:2011/12/14
但有想法修改VB或VBA代码,可能?TKS。
Vipul梅塔
评论会员:游客 时间:2011/12/14
您好,我们可以在我们的Web应用程序实施上述下拉工具提示逻辑?的问候,Vipul梅塔高级软件工程师
迪克唐尼
评论会员:游客 时间:2011/12/14
喜Vipul我不是特别熟悉的Web控件,但我怀疑,很使用的任何代码,可以为你的目的。理查德
kewpcg
评论会员:游客 时间:2011/12/14
您好,这正是我所需要的,但我不确定如何实现这一。我有我的项目中创建这些类,但我的问题是:1。为什么ToolTipWindow类范围的在你的榜样私人吗?不,它需要其他类的公共(ComboboxToolTips)使用它呢?2。我看到这两个类的各种警告:"通过一个实例共享成员,常量成员,枚举成员或嵌套类型的访问;将不会评估合格的表达。"我想我要么错了地方的类的代码,我失去了一些关键点。你有一个小项目,展示你的,我可以参考这些类的使用吗?感谢kewpcg
迪克唐尼
评论会员:游客 时间:2011/12/14
1。ToolTipWindow私人范围内的,因为它是我的代码中的嵌套类。,我从来没有在我的文章清楚的歉意。您可以使用任何范围是适当的为您的项目。2。这一警告发出时通过变量访问的代码共享的函数,变量等类型名比相当。例如,公共类Foo公共共享子栏年底分末级暗淡了新的Fooa.bar()上面的代码将提出警告。访问方法的语法是"正确的"foo.bar的();然而,您的代码将仍然工作正常不看你的实现是很难猜测您的问题所在。我已经敲了一个简单的例子实施要求。这是一个VisualStudio2005项目,可以从下载http://code.iprogrammer.co.uk/comboboxtooltip.zip让我知道如果您有任何问题,下载或以下,我会尽力帮助。请让我知道如何使用控制,我真正感兴趣的是听到您的反馈。理查德
kewpcg
评论会员:游客 时间:2011/12/14
感谢,这似乎工作得很好。我认为这将是有益的一些项目,其中的文本可能无法完全显示。我真正需要的是一种方式,以显示与该项目有关的特定文本(即说明),但不是该项目的实际文本-我需要做我的ComboBox中的所有项目,而不仅仅是那些不适合。换句话说,我悬停在列表中的一个项目,它应该给我更多关于该项目的详细信息。因此,我认为它实际上在这种情况下,比我更需要它imgsrc=http://www.orcode.com/upimg/2011_12_14_12_37_06_1.gif但是,再次感谢这个伟大的例子,我将继续以供将来参考。
迪克唐尼
评论会员:游客 时间:2011/12/14
。感谢您的反馈,它的升值这将是一个相对简单的代码和改变工具提示来呈现交替显示..ALAsupertooltips你看到在新的应用程序。事实上,这是一个好主意......我会尽力敲起来为你的一个例子。 
kewpcg
评论会员:游客 时间:2011/12/14
大。非常感谢-这将不胜感激。虽然不着急。
迪克唐尼
评论会员:游客 时间:2011/12/14
。答应我发布了一个新的版本,它支持为每个项目的"超级"工具提示给我留言如果你有任何脱胶,但希望它是那种东西,你正在寻求(你现在控制整个工具提示外观)理查德http://www.codeproject.com/useritems/comboboxtooltip.asp
kewpcg
评论会员:游客 时间:2011/12/14
!感谢你这么多的超级工具提示的例子放在一起我有一个问题,我会把这个主题的页面上。