Subclassing элемента управления
Теперь самое время перейти к более интересному варианту - расширим свойства стандартного элемента управления TextBox. Для этого снова создайте новый проект (либо, опять-таки возьмите мой из архива). Прежде всего определимся, чего бы нам хотелось получить от этого нового-старого контрола. На этот раз не будем проявлять особую оригинальность и создадим компонент позволяющий вводить только числа, такой контрол нам всегда пригодится. При этом этот контрол не позволяет производить копирование и вставку текста и не отображает ниспадающего меню по щелчку правой кнопкой мыши. Также, в качестве тренировки, добавим запрет на присвоение значения Text непосредственно из кода.
Добавьте в проект новый UserControl, назовите его NumbersBox . И переходите сразу к редактированию кода. По умолчанию новый класс наследуется от System.Windows.Forms.UserControl, но нам это не подходит, мы же не хотим добавить TextBox на наш контрол и создавать элемент управления содержащий TextBox. Наша задача - расширить функциональность TextBox непосредственно. Поэтому смело заменяем строку:
Inherits System.Windows.Forms.UserControl
На:
Inherits System.Windows.Forms.TextBox
Так мы получили контрол, который уже включает в себя все функции, методы и свойства стандартного элемента TextBox. Теперь в Toolbox на вкладке My User Controls отображается наш NumbersBox. Налюбовавшись на это чудо дивное, перейдем непосредственно к реализации задуманного. Опять-же, основная часть кода будет сосредоточена в WndProc.
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_CHAR
' Если не число или Backspace, то не надо нам этого вообще
If (m.WParam.ToInt32 > 57 Or m.WParam.ToInt32 < 48) And _
m.WParam.ToInt32 <> 8 Then Return
' Не пускаем Ctrl+C, Ctrl+V или Ctrl+X
If Me.ModifierKeys.Control And (m.WParam.ToInt32 = 3 Or _
m.WParam.ToInt32 = 22 Or m.WParam.ToInt32 = 24) Then Return
Case WM_RBUTTONDOWN ' Не надо нам никаких менюшек при правом клике
Return
End Select
MyBase.WndProc(m) ' Передаем события дальше
End Sub
А для того, чтобы запретить присвоение значения Text из кода (то есть текст может быть введен только непосредственно с клавиатуры), нужно переопределить свойство Text базового контрола TextBox. Заметьте, мы не можем сделать это свойство ReadOnly, т.к. базовое свойство таковым не является, но это легко обходится с помощью небольшой хитрости.
Public Overrides Property Text() As String
Get
Return MyBase.Text.ToString
End Get
Set(ByVal Value As String)
' А тут ничего не делаем
End Set
End Property
Теперь вы можете просто перетащить контрол на форму, запустить проект на выполнение и порадоваться этому "гениальному" творению.
'This project needs a TextBox
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Const GWL_STYLE = (-16)
Const ES_NUMBER = &H2000&
Public Sub SetNumber(NumberText As TextBox, Flag As Boolean)
 im curstyle As Long, newstyle As Long
'retrieve the window style
curstyle = GetWindowLong(NumberText.hwnd, GWL_STYLE)
If Flag Then
curstyle = curstyle Or ES_NUMBER
Else
curstyle = curstyle And (Not ES_NUMBER)
End If
'Set the new style
newstyle = SetWindowLong(NumberText.hwnd, GWL_STYLE, curstyle)
'refresh
NumberText.Refresh
End Sub
Private Sub Form_Load()
'KPD-Team 1999
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
SetNumber Text1, True
Me.Caption = "Now, try typing some letters into the textbox"
End Sub
yxaxa, я вроде все по инструкции делаю, но у меня такой контрол получается в точности как текст бокс.
проясните мне плиз,может библиотеки какие-то подключить нужно?
а еще сборки VB просит сделать.