Visual Basic - Трюки и Хитрости,
советы и ответы на вопросы.
Здравствуйте, уважаемые читатели!
Я слегка ошалел, когда увидел, какими темпами растет число подписчков этой
рассылки. Видимо VB становится достаточно популярным и в России. Что-же,
надеюсь эта рассылка и сайт "Visual Basic на русском" http://vbrussian.com
помогут популяризаци этого мощного и доступного пониманию языка.
Сегодняшний выпуск посвящен разностям, а точнее полезным хитростям, которые
могут вам пригодится в нелегкой програмистской жизни.
Ведет этот выпуск Константин Рудой ( mailto:kosty@vbrussian.com )
==================================================================
Все знают, что можно загрузить контрол используя стейтмент Load. Но для
этого нужно иметь такой же контрол на форме, да к тому же он должен быть
инициализирован как массив. А как быть, если на форму не хочется класть
ничего лишнего? Оказывается нет ничего сложного. Думаю, что ни для кого не
секрет, что у формы есть коллекция Controlls?
Так вот, почему бы и не воспользоваться методом Add коллекции.
(VB6)
Этот метод имеет 3 параметра :
1 - строковый идентификатор контролла (например "VB.CommandButton")
2 - строка - имя контролла
3 - необязательный параметр - контейнер в который этот контролл будет
положен
Допустим мы хотим создать кнопку на форме. что же для этого нужно сделать?
Всего несколько строк:
В Genegal - Declaration:
Dim WithEvents cmdDynamicButton As Button
В том месте кода где мы хотим создать новую кнопку (например на Form_Load):
Me.Controls.Add "VB.CommandButton", "NewButton"
Set cmdDynamicButton = Me.Controls("NewButton")
Просто? Конечно.
Но у вас может возникнуть законный вопрос, а как же обрабатывать события от
такого контролла? Но ведь для этого мы м опичывали переменную
cmdDynamicButton как WithEvents.
Теперь добавтье к коду следующие строки и наслаждайтесь...
Private Sub cmdDynamicButton_Click()
MsgBox "This is a dynamically added button"
End Sub
И еще пара замечаний напоследок:
1) Для того чтобы удалить такой контролл мспользуйте метод Remove всe: той
же коллекции
2) Для добавления контролла на который у вас нет ссылки в проекте (его нет
в тулбоксе) его лицензию еще нужно добавить в коллекцию Licenses.
подробности можно прочесть в MSDN.
======================================================================
Жизнь течет, а нам хочется всe: большего и большего...
Вам никогда не хотелось сделать размер вашего листбокса пропорционально
количеству строк? Нет? А мне вот захотелось...
И для этого окозалось достаточно всего трех API-функций:
GetTextMetrics, CetWindowRect и GetClientRect.
Private Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA"
(ByVal hdc As Long, lpMetrics As TEXTMETRIC) As Long
Private Type TEXTMETRIC
tmHeight As Long
tmAscent As Long
tmDescent As Long
tmInternalLeading As Long
tmExternalLeading As Long
tmAveCharWidth As Long
tmMaxCharWidth As Long
tmWeight As Long
tmOverhang As Long
tmDigitizedAspectX As Long
tmDigitizedAspectY As Long
tmFirstChar As Byte
tmLastChar As Byte
tmDefaultChar As Byte
tmBreakChar As Byte
tmItalic As Byte
tmUnderlined As Byte
tmStruckOut As Byte
tmPitchAndFamily As Byte
tmCharSet As Byte
End Type
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long,
lpRect As RECT) As Long
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long,
lpRect As RECT) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Но не всe: так просто... Всe: дело в том, что для GetTextMetrics в качестве
первого параметра необходимо задать hDC. А для этого нужен контролл,
который умеет его возвращать или пытаться его добыть какими-то иными
средствами, что гораздо сложнее.
Итак. У нас на форме есть листбокс List1 (хотя это может быть и любой иной
контролл) и пикчербокс Picture1, который мы или создаем динмически в
Form_Load (см. Как динамически загрудить контролл) или просто кладем его на
форму. Желательно чтоб он был спрятан, т.к. в Form_Load должна быть
следующая строка:
Set Picture1.Font = List1.Font
Ну и функция, которая возвращает размер контрола по количеству строк:
' hwnd - хэндл контролла (в нашем случае - List1.Hwnd
' Count - количество строк
Private Function GetHeightByLinesCount(hwnd As Long, Count As Integer) As
Long
Dim tm As TEXTMETRIC
Dim rc As RECT
Dim winrc As RECT
' Получаем размер окна
GetWindowRect hwnd, winrc
' Получаем размер клиетской области окна
GetClientRect hwnd, rc
' Получаем параметры шрифта из Picture1
GetTextMetrics pic.hdc, tm
' winrc.Bottom - winrc.Top - rc.Bottom + rc.Top - это размер бордера
контролла
' в пикселах
' tm.tmHeight - высота строки тоже в пикселах
' поскольку всe: в пикселах, то переводим в Твипсы
GetHeightByLinesCount = (tm.tmHeight Count + winrc.Bottom - winrc.Top
- rc.Bottom + rc.Top) Screen.TwipsPerPixelY
End Function
Ну теперь уж точно всe:. Можно пользоваться и наслаждаться...
Констстантин Рудой
======================================================================
ДА, напоследок: Cвежая информация о том, что же будет завтра, что нового
предпологается в версии VB7 - ждет вас по адресу:
http://vbrussian.com/vb7_2.html