现在的位置: 首页 > 综合 > 正文

自定义VB系统控件三

2012年09月29日 ⁄ 综合 ⁄ 共 3265字 ⁄ 字号 评论关闭

除了使用子类的方法,我没还可以使用几个API函数向对象主动发消息。我们可以用SendMessage和PostMessage:

PostMessage将消息直接加入到应用程序的消息队列中,不等程序返回就退出;而SendMessage()则刚好相反,应用程序处理完此消息后,它才返回,可以参考下图:

下面就对具体实际应用举几个例子:

TextBox控件:

a.   控制Textbox输入格式,我想大多人都遇到这个问题,在TextBox作为输入接口时,有时我们希望用户只能输入数字、大写、字母等,一般的做法是对用户输入的字符这个检查。但是如果我们使用API,将很容易实现这些功能,比如:

?   只允许输入数字:

Public Function NumbersOnly(tBox As TextBox)

    Dim DefaultStyle As Long

    DefaultStyle = GetWindowLong(tBox.hwnd, GWL_STYLE)

    NumbersOnly = SetWindowLong(tBox.hwnd, GWL_STYLE, DefaultStyle Or ES_NUMBER)

End Function

?   只允许大写:

Public Function UpperCaseOnly(tBox As TextBox)

    Dim DefaultStyle As Long

    DefaultStyle = GetWindowLong(tBox.hwnd, GWL_STYLE)

    UpperCaseOnly = SetWindowLong(tBox.hwnd, GWL_STYLE, DefaultStyle Or ES_UPPERCASE)

End Function

?   只允许小写:

Public Function LowerCaseOnly(tBox As TextBox)

    Dim DefaultStyle As Long

    DefaultStyle = GetWindowLong(tBox.hwnd, GWL_STYLE)

    LowerCaseOnly = SetWindowLong(tBox.hwnd, GWL_STYLE, DefaultStyle Or ES_LOWERCASE)

End Function

当然上边三个函数可以合成一个函数,因为他们方法是一样的,只是风格参数不同而已。

b.外观风格:

VB本身提供两种风格:Flat和3D,但是也许你想改变一下外观,比如让TextBox的边界介于Flat和3D之间那种效果,如图:

怎么做呢?在VC中我们在创建一个窗口对象时可以制定它的风格,但是在VB中,IDE已经按照它自己的想法给我创建好了,如果我们想要改变它只能把已经存在的进行修改,这时我们就需要借助的GetWindowLong和SetWindowLong兄弟的帮助来完成这个任务了。

Public Sub FlatBorder(ByVal hwnd As Long)

Dim TFlat As Long

‘首先将原始的窗口属性读出来

    TFlat = GetWindowLong(hwnd, GWL_EXSTYLE)

‘进行适当修改

    TFlat = TFlat And Not WS_EX_CLIENTEDGE Or WS_EX_STATICEDGE

‘写回去

    SetWindowLong hwnd, GWL_EXSTYLE, TFlat

‘这个函数能为窗口指定一个新位置和状态。它也可改变窗口在内部窗口列表中的位置。该函数与DeferWindowPos函数相似,只是它的作用是立即表现出来的(在vb里使用:针对vb窗体,如它们在win32下屏蔽或最小化,则需重设最顶部状态。如有必要,请用一个子类处理模块来重设最顶部状态)

    SetWindowPos hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOZORDER Or _
 SWP_FRAMECHANGED Or SWP_NOSIZE Or SWP_NOMOVE

End Sub

*当然上边的函数可以用在所有窗口对象上,只不够有些窗口对象不需要这么做。

如果窗体中有很多TextBox需要这样设置,而且不都是控件数组,那么可以在包装一下上面的函数:

Public Sub AddBorderToAllTextBoxes(frmX As Form)

   Dim X As Control

   On Error Resume Next

   For Each X In frmX.Controls

        If TypeOf X Is TextBox Then

                FlatBorder X.hWnd

        End If

   Next

End Sub

b.   改变文字布局:

VB 中可以设置TextBox中文本水平方向居左、居右、居中,但是不能设置垂直方向,也不能微调文本距离左边界的距离,但是我们还是可以借助API的帮助来完成这个需求:

?   文本垂直居中:

Public Sub VerMiddleText(mText As TextBox)

   Dim rc As RECT

   Dim tmpTop As Long

   Dim tmpBot As Long

   '实现这个效果首先TextBox的MultiLine属性必须为True(多行文本,其实这个属性关系创建TextBox内部使用哪个类,因此一旦创建就不能修改这个属性,所以不能在代码中修改这个属性)

   If mText.MultiLine = False Then Exit Sub

   '获得没个窗口区域的边界我们可以通过发送EM_GETRECT消息来获得

   Call SendMessage(mText.hwnd, EM_GETRECT, 0, rc)

   '进行位置数据计算

   With Me.Font

      .Name = mText.Font.Name

      .Size = mText.Font.Size

      .Bold = mText.Font.Bold

   End With

   tmpTop = ((rc.Bottom - rc.Top) - (mText.Parent.TextHeight("H") / Screen.TwipsPerPixelY)) / 2

   tmpBot = ((rc.Bottom - rc.Top) + (mText.Parent.TextHeight("H") / Screen.TwipsPerPixelY)) / 2

   rc.Top = tmpTop

   rc.Bottom = tmpBot

   mText.Alignment = vbCenter

   '数据计算完毕,再发送EM_SETRECTNP消息(为一个编辑控件设置格式化矩形,与EM_SETRECT类似,只是控件此时不会重画)

   Call SendMessage(mText.hwnd, EM_SETRECTNP, 0&, rc)

   mText.Refresh

End Sub

这样我们就达到了文本垂直居中的目的,其实只要用的熟了,找到切入点,还是很容易实现的。

?   调整边距:

如果你查看TextBox中常用的消息,你会发现有这样一对消息:EM_GETMARGINS 和EM_SETMARGINS,MSDN的解释是:获取和设置编辑控件的左、右边距(不得用于NT3.51)。具体是左还是右由该消息的参数决定。

看到这些也许你就知道我们可以用这两个消息完成我们的需求,好下面实际着手进行验证:

Private Sub SetMargin(nLeft As Integer, nRight As Integer, lhWnd As Long)

Dim lLongValue As Long

    '高四位表示右边距,低四位为左边距

    lLongValue = nRight * &H10000 + nLeft

    SendMessage lhWnd, EM_SETMARGINS, _

        EC_LEFTMARGIN Or EC_RIGHTMARGIN, lLongValue

End Sub

好经过测试目的达到,但是这样做有什么意义呢?有的时候如果你想在texebox中放入其他对象,而又不希望文本被覆盖掉,你就需要用到这个方法。

抱歉!评论已关闭.