- •Form2.Show
- •Integer ‘целое число со знаком от –32 768 до 32767
- •Interval – 1000 (время, в миллисекундах, через которое таймер срабатывает, если конечно включен). Таймер будет срабатывать каждые 1000 мск, т.Е. Каждую секунду, как в нормальных часах.
- •InputBox("сообщение", "заголовок окна", "данные по умолчанию", расстояние между левой границей экрана и левым краем экрана,то же для верхней границы, "имя Help-файла" , номер раздела Help-файла)
- •Input #номерФайла, списокПеременных
- •15,"Пятнадцать" #true#,#2004-07-20#
- •Shell ("путь до файла программы", "вид окна, в котором откроется программа")
- •Private Sub Command1_Click() Combo1.AddItem Combo1.Text End Sub
- •Массив - это сколько угодно значений, объединенных одним именем.
- •Объект.PopupMenu имяменю, флаг, позицияX, позицияY, выделеннаястрока
- •Form1.PrintForm
- •CommonDialog1.ShowOpen
- •Dim Name As String Dim Kolichestvo As Long Dim Cost As Single
Form1.PrintForm
Запускаешь программу, нажимаешь эту созданную кнопку и у тебя на печать выходит Form1 со всеми элементами-объектами, видимыми на момент печати. Ты некоторое время смотришь на это безумие, потом перед командой PrintForm делаешь невидимыми кнопки и в надежде на чудо, снова повторяшь процесс, но чуда не произошло. Кнопок теперь нет, но распечатка красивше от этого не стала. И понося на чем свет VB, Microsoft и его хозяина, выключаешь все и идешь пить пиво.
Вот про печать и все.
Шучу. Во-первых на печать надо выводить именно то, что мы хотим, а не то, что можем, и в полном объеме. Во-вторых, расположение объектов на форме может быть красиво, но на листе дизайн должен быть совсем иной и объекты расположены по-другому, а форма для создания печатного документа вообще не годится.
А теперь скажу, что подготовка для печати красивой страницы - достаточно кропотливый процесс. То есть, надо программно расчитывать месторасположение всех элементов страницы, причем в зависимости от формата листа и размера шрифта и всего остального. Зато тщательно подготовленная страница выглядит, как настоящий документ, очень достойно.
Основной объект, с которым мы будем работать - Printer. Несмотря на то, что это объект, ни самого объекта в окне инструментов или на форме, ни свойств в окне свойств мы не увидим. Он невидим. Поэтому все надо делать программно. Но этот объект имеет очень много свойств и методов, большинство из которых нам нужны. Постараемся разобраться подробнее. Хочу заметить, что не все принтеры поддерживают все свойства объекта Printer. В этом случае разные свойства могут вызывать одинаковое действие, не вызвать никакого действия или же вообще привести к ошибке. Я использовал довольно-таки старый лазерный черно-белый принтер HP LaserJet 5L, и основываясь на его возможностях и готовил пример. Можно было взять цветной струйник, но струйники - дороги в эксплаутации и, как правило, документы печатаются на лазерных принтерах. Итак, начнем со свойств, список важнейших из них приведен в таблице ниже:
Свойство |
Характеристика |
Синтаксис |
.Copies |
определяет число печатаемых копий |
Printer.Copies=1 (одна копия) |
.ColorMode |
определяет цветную или монохромную (оттенки серого) печать vbPRCMMonochrome=1 (черно-белая) vbPRCMColor =2 (цветная). Монохромные принтеры это свойство игнорируют. |
Printer.ColorMode=1 или Printer.ColorMode=vbPRCMMonochrome |
.CurrentX и .CurrentY |
устанавливают горизонтальную (CurrentX) или вертикальную (CurrentY) координаты для начала (продолжения) печати. Определяется по-умолчанию в твипах, либо в текущих единицах измерения |
Printer.CurrentX=500 Printer.CurrentY=1000 |
.Duplex |
возвращает или устанавливает значение, которое определяет, будет ли страница печататься с двух сторон, константы: vbPRDPSimplex =1, vbPRDPHorizontal= 2, vbPRDPVertical=3. |
Printer.Duplex=1 (Одностороння печать с текущей ориентацией листа) Printer.Duplex=2 (Двухсторонняя печать горизонтальной страницы) Printer.Duplex=3 (Двухсторонняя печать вертикальной страницы) |
.Font |
определяет "жирность" текста, подчеркивание, перечеркивание, курсив и т.п. |
Printer.Font.Bold = True (жирный) Printer.Font.Underline = True (подчеркивание) |
.FontCount |
возвращает число доступных шрифтов |
Text1.Text=Printer.FontCount |
.FontName |
возвращает или устанавливает имя шрифта |
Printer.FontName="Arial" (устанавливает шрифт Arial) |
.Fonts |
возвращает имена всех доступных шрифтов |
Dim I As Long For I = 0 To Printer.FontCount -1 List1.AddItem Printer.Fonts (I) Next I |
.FontSize |
возвращает или устанавливает размер шрифта в пунктах (максимальное значение 2160). Задается после задания свойства FontName. При использовании шрифтов TrueType менее 8 пунктов, надо сначала задать свойство FontSize, затем FontName, а потом снова FontSize |
Printer.FontSize=18 |
.Height и .Width |
устанавливают физические размеры листа бумаги. Используются вместо установок PiperSize. Для Printer задается только в твипах. |
Printer.Height=5000 (Высота) Printer.Widtht=3000 (Ширина) |
.Orientation |
возвращает или устанавливает значение, указывающее, в вертикальном или горизонтальном расположении печатаются документы. Принимает значение двух констант: vbPRORPortrait =1 (вертикаль), vbPRORLandscape=2 (горизонт) |
Printer.Orientation=1 или Printer.Orientation=vbPRORPortrait |
.Page |
возвращает текущий номер страницы, начиная с единицы и шагом единица |
Printer.Print Printer.Page (вывод на печать текущей страницы) |
.PaperBin |
возвращает или устанавливает значение, указывающее для принтера установленный по умолчанию лоток для подачи бумаги. Константы перечислены в библиотеке объектов Visual Basic (VB) в Object Browser. |
Printer.PaperBin=1 (верхний лоток) Printer.PaperBin=2 (нижний лоток) Printer.PaperBin=3 (средний лоток) Printer.PaperBin=4 (ручная подача) Printer.PaperBin=7 (лоток по умолчанию) и т.д. |
.PaperSize |
возвращает или устанавливает значение, указывающее размер бумаги для текущего принтера. vbPRPSA4= 9 для листа A4, 210 x 297 мм vbPRPSUser=256 для пользовательского Константы перечислены в библиотеке объектов Visual Basic (VB) в Object Browser. |
Printer.PaperSize=9 или Printer.PaperSize=vbPRPSA4 (установка листа A4) |
.PrintQuality |
возвращает или устанавливает значение, указывающее разрешающую способность принтера (отрицательная константа). Можно также задавать положительные значения в точках на дюйм (dpi). |
Printer.PrintQuality=-1 (черновой- draft) Printer.PrintQuality=-2 (низкая- Low) Printer.PrintQuality=-3 (средняя- Medium) Printer.PrintQuality=-4 (высокая- High) Printer.PrintQuality=300 (разрешение 300 dpi) |
.Zoom |
возвращает или устанавливает процентное соотношение, по которому увеличивается или уменьшается масштаб вывода на печать. Число обозначает процент и по умолчанию равно 0, что соответствует стандартному размеру. |
Printer.Zoom=50 (лист с уменьшением 1:2) |
Теперь, как ни печально, надо переходить к методам, но их не так много. На мой взгляд важные приведены в таблице ниже:
Метод |
Характеристика |
Синтаксис |
.EndDoc |
завершает формирование листа для печати и начинает печать |
Printer.EndDoc |
.KillDoc |
немедленно завершает печать сформированной страницы |
Printer.KillDoc |
.NewPage |
завершает текущую страницу на объекте Printer и переходит на следующую |
Printer.NewPage |
.TextHeight и .TextWidth |
возвращают высоту (TextHeight ) и длину (TextWidth) текстовой строки, которая получится при ее выводе на печать или на форму с использованием текущего шрифта. В возвращаемое значение включаются и интервалы. |
Text1.Text=Printer.TextHeight("vbzero") Text2.Text=Printer.TextWidth("vbzero") |
Tеперь попробуем разобраться, как все это использовать на примере программки Printing. Чтобы у нас было, что выводить на печать, я набросал подобие программки, представляющую собой рабочее места продавца мобильных телефонов. Советую вам скачать ее вверху страницы, чтобы иметь перед глазами, а потом продолжать читать главу. Создадим новый exe-проект. Первая ее часть представляет собой интерфейс для работы с базой мобильных телефонов: вывод на экран изображения и технических характеристик телефона, две кнопки навигации - вперед и назад и кнопка Печать. Изображение и теххарактеристики грузятся из файлов, имеющих имена 1.jpg и 1.txt, 2.jpg и 2.txt, и так далее, т.е., аналогично программке Tester, которую мы разбирали в Главе 8.
Итак стандартное начало: Option Explicit Option Base 1
Объявляем статический одномерный массив для двенадцати строк технических характеристик телефона: Dim MassiveData(12) As String Затем несколько необходимых переменных Dim FileName As String 'для имени загружаемых файлов Dim F As Long 'для номера свободного файла Dim X As Long 'для переменной цикло For...Next Dim QuantityFonts As Long 'для числа найденых шрифтов
Затем процедура загрузки формы. Здесь мы просто изначально устанавливаем имя загружаемого файла - "1" ("1.jpg" и "1.txt") и переходим к созданной нами процедуре загрузки этих файловDataLoading(). Private Sub Form_Load() FileName = "1" DataLoading End Sub
Private Sub DataLoading() Загружаем изображение телефона в Image1 Image1.Picture = LoadPicture(App.Path & "\" & FileName & ".jpg") Восстанавливаем положение Image1 от левой и верхней границы экрана соответственно Image1.Left = 24 Image1.Top = 128 Центрируем положение картинки в зависимости от того, вертикальная она (Image1.Height > Image1.Width - высота больше ширины) или горизонтальная (Image1.Width > Image1.Height - ширина больше высоты) If Image1.Width > Image1.Height Then Image1.Top = Image1.Top + (250 - Image1.Height) / 2 If Image1.Height > Image1.Width Then Image1.Left = Image1.Left + (250 - Image1.Width) / 2 Открываем текстовой файл с тем же именем, что и картинка и грузим 12 строк текста в 12 элементов массива F = FreeFile Open App.Path & "\" & FileName & ".txt" For Input As #F For X = 1 To 12 Line Input #F, MassiveData(X) Тут же выводим содержание массива в Label9. Обратите внимание, что Label9 представляет собой Control Array (по сути - это одномерный массив объекта), т.е. группу лейблов с именемLabel9(индекс). По этому индексу мы можем перебирать Label9 в цикле. Делается это так: мы кладем на форму Label9, затем копируем его. VB спрашивает "Создавать Control Array?", ты отвечаешь "Да", после чего на форме появляется копия Label9 с именем Label9(1). Наш же просто лейбл Label9 становится Label9(0). Я про это писал, но повторюсь. Продолжаем этот процесс до получения нужного количества лейблов в Control Array. А потом, ненужные элементы надо уничтожить. У нас, поскольку мы используем оператор Option Base 1, и элементы массива начинаются с единицы - этоLabel9(0). Аналогично создается и Control Array и для Label8, куда присваиваются наименования технических характеристик телефона. Для облегчения кода я сделал это присвоение в окне свойствLabel8. Label9(X).Caption = MassiveData(X) Next X Close #F
End Sub
В кнопках Command1 и Command2 мы пишем код для смены имени загружаемого файла. Все это опять-таки похоже на программку Tester из Главы 8, и на этом я подробно останавливаться не буду. Private Sub Command1_Click() If Val(FileName) > 1 Then FileName = Str(Val(FileName) - 1) FileName = Right(FileName, Len(FileName) - 1) DataLoading End If End Sub
Private Sub Command2_Click() FileName = Str(Val(FileName) + 1) FileName = Right(FileName, Len(FileName) - 1) If Dir(App.Path & "\" & FileName & ".txt") <> "" Or Dir(App.Path & "\" & FileName & ".jpg") <> "" Then DataLoading Else FileName = Str(Val(FileName) - 1) FileName = Right(FileName, Len(FileName) - 1) DataLoading End If End Sub
А вот сейчас мы переходм к тому, ради чего мы все это затеяли. Попробуем подготовить для печать документ. В процедуре кнопки Command3 мы начнем формировать страницу для печати. Сперва объявим кое-какие переменные
Private Sub Command3_Click() Dim OrientTelefona As Single ' меняет отступ от картинки в зависимости горизонтальная она или вертикальная Dim Fonts() As String 'одномерный динамический массив для хранения существующих шрифтов Dim VertCoord As Single 'накапливает сдвиг по вертикали по мере создания строк в документе Dim NumberFont As Long ' номер шрифта
обнуляем переменную, содержащую количество шрифтов на всякий случай QuantityFonts = 0
В смысле определения шрифтов на текущем принтере я пошел по пути наименьшего сопротивления. Исходя из того, что на любом компьютере установлен хотя бы один из четырех общеупотребимых шрифтов, я проверяю их наличие и имена найденых шрифтов загружаю в динамический массив Fonts(). Для этого мы организуем цикл, где перебираем все существующие на текущем компьютере шрифты (их количество нам возвращает свойство .FontCount), и грузим их имена в массив Fonts(). При этом счетчик QuantityFonts отражает, сколько из четырех шрифтов найдено. For NumberFont = 0 To Printer.FontCount - 1 If Printer.Fonts(NumberFont) = "Arial Cyr" Or Printer.Fonts(NumberFont) = "Times New Roman" _ Or Printer.Fonts(NumberFont) = "Courier New" Or Printer.Fonts(NumberFont) = "MS Sans Serif" Then QuantityFonts = QuantityFonts + 1 ReDim Preserve Fonts(QuantityFonts) Fonts(QuantityFonts) = Printer.Fonts(NumberFont) End If Next NumberFont
Затем, если хоть один шрифт найден, мы устанавливаем его из первого элемента массива If QuantityFonts > 0 Then Printer.FontName = Fonts(1) Ну уж если не найдено ни одного шрифта, то в надежде, что какой-то там шрифт в принтере по умолчанию все же есть, продолжаем формировать документ. Для удобства и наглядности все будем мерять в сантиметрах, поэтому устанавливаем размерность в сантиметрах Printer.ScaleMode = vbCentimeters Хочу сказать, что начинать формирование страницы методом Printer.NewPage (создание новой страницы) не надо, иначе первой вылезет пустая страница. У тебя нет еще ни одной страницы, и нет необходимости переходить на новую. Вот для второй, третьей и т.д. страницы - пожалуйста. Устанавливаем размер шрифта для первой строки
Printer.FontSize = 12
'устанавливаем подчеркивание Printer.Font.Underline = True 'устананавливаем качество печати - среднее Printer.PrintQuality = 3
Прижимаем вправо первую строчку с названием фирмы. Для установки положения начала вывода по-горизонтали используется свойство .CurrentX. Чтобы строчка прижалась вправо мы из общей ширины нашего документа Printer.ScaleWidth вычтем длину нашей строчки Printer.TextWidth(Label1.Caption), которую она займет при печати объявленным нами шрифтом:
Printer.CurrentX = Printer.ScaleWidth - Printer.TextWidth(Label1.Caption)
В переменной VertCoord мы будем накапливать сдвиг по вертикали. Сначала запишем в нее, сколько высоты заняла первая строка (вместе с отступами).
VertCoord = Printer.TextHeight(Label1.Caption)
Теперь встраиваем в страницу первую строчку. Никакой печати при этом не происходит. Собственно принтер начинает работать только тогда, когда VB посчитает, что формирование документа полностью закончено. Это произойдет, если будет написан оператор Printer.EndDoc, либо если ты выйдешь из программы совсем.
Printer.Print Label1.Caption
'устанавливаем большой размер шрифта для названия модели телефона Printer.FontSize = 20 'отменяем подчеркивание Printer.Font.Underline = False 'зато ставим жирный Printer.Font.Bold = True 'делаем отступ вниз на 1,5 см от первой строчки, меняя вертикальную координату Printer.CurrentY = VertCoord + 1.5 'выравниваем вторую строчку по-середине Printer.CurrentX = (Printer.ScaleWidth - Printer.TextWidth(Label9(1).Caption & "Лидер продаж - телефон ")) / 2 'добавляем, сколько высоты мы использовали на вторую строчку вместе с отступами VertCoord = VertCoord + Printer.TextHeight(Label9(1).Caption) + 1.5 'встраиваем в страницу вторую строчку Printer.Print "Лидер продаж - телефон " & Label9(1).Caption 'устанавливаем размер шрифта поменьше для заглавия технических характеристик телефона Printer.FontSize = 14 'добавляем курсив Printer.Font.Italic = True 'отступаем вниз еще на 2 см Printer.CurrentY = VertCoord + 2 'добавляем высоту третьей строчки вместе с отступами VertCoord = VertCoord + Printer.TextHeight(Label4.Caption) + 2 'оставляем 8 см слева под картинку, а остальное справа - под текст 'строчку центрируем на ее Printer.ScaleWidth = 8 см Printer.CurrentX = (Printer.ScaleWidth - 8 - Printer.TextWidth(Label4.Caption)) / 2 'встраиваем в страницу третью строчку Printer.Print Label4.Caption
Для печати изображения телефона берем текущую координату по вертикали VertCoord. Печатаем картинку, центрируя ее на своей площади и меняя пустое расстояние перед ней, в зависимости от того, горизонтальная она (OrientTelefona = 0.5) или вертикальная (OrientTelefona = 2.25). Тогда картинка будет располагаться красиво, по центру выделенной ей площади. If Image1.Height > Image1.Width Then OrientTelefona = 2.25 Else OrientTelefona = 0.5 End If
Встраиваем картинку в наш документ
Printer.PaintPicture Image1.Picture, Printer.ScaleWidth - ScaleX(Image1.Width, vbPixels, vbCentimeters) - OrientTelefona, VertCoord 'отменяем курсив и жирность Printer.Font.Italic = False Printer.Font.Bold = False 'устанавливаем размер шрифта еще меньше Printer.FontSize = 12 'отступаем вниз от 3-ей строки на 1 см Printer.CurrentY = VertCoord + 1 VertCoord = VertCoord + 1 Теперь, остальные строки - технические данные( с 2-ой по 11-ую) мы встроим в цикле (всего 10 строк) не меняя размеров, жирности и т.п. шрифта. Обратите внимание, что наименование характеристик в Label8(X) и сами характеристики в Label9(X) прописаны отдельно друг от друга и перед каждым установлены свои координаты начала печатиPrinter.CurrentX и Printer.CurrentY. Тогда печать осуществится красиво, двумя столбиками. For X = 2 To 11 'отступаем слева по сантиметру Printer.CurrentX = 1 Printer.CurrentY = VertCoord Printer.Print Label8(X).Caption
Printer.CurrentX = 5 Printer.CurrentY = VertCoord Printer.Print Label9(X).Caption VertCoord = VertCoord + 0.6 'увеличение вертикальной координаты с каждой новой строчкой Next X Теперь для акцента на цену телефона, выведем на печать прямоугольник через все страницу. Подробно о рисовании простых графических фигур программным методом мы поговорим в следующей главе. Здесь мы используем метод Line. VertCoord = VertCoord + 1 Printer.Line (1, VertCoord)-(17.5, VertCoord + 0.7), vbBlack, BF
Printer.CurrentY = VertCoord + 0.1 Printer.CurrentX = 6 'теперь пишем цену Printer.Font.Bold = True Printer.Print "Самая лучшая цена: " & Label9(12).Caption & " руб." Printer.Font.Bold = False А вот теперь даем команду о завершении формирования страницы и принтер начинает печать: Printer.EndDoc End Sub
Этот пример имеет некоторую недоработочку. Строка, которая выводит особенности телефона (Label9(8)) длинная и не входит в рамки страницы, а при печати все, что не влезает в страницу безжалостно отсекается и на печать не выводится. Та же проблема возникает при печати неформатированного текста из текстового файла. Попробуй решить эту проблему самостоятельно. Возможно позже я по этому поводу чего-нибудь напишу, но не здесь, а в Части 3 - "Релизация некоторых задач".
Разбивать текст можно по пробелам. Возможно, ты захочешь использовать функцию InStr.
Функция InStr. |
Эта функция используется при текстовом поиске. Она возвращает значение (если совпадение обнаружено)- позицию (номер символа), с которого искомая строка входит в строку, в которой выполняется поиск. Если поиск не удался или строка, в которой проводится поиск - пустая, возвращаемое значение - 0. Ее синтаксис следующий
Числовая переменная=InStr(номер символа, строка поиска, критерий поиска, способ сравнения)
номер символа - необязательный аргумент определяет с какого символа в строке (третьего, десятого и т.п.) надо начинать поиск. Если не задан, поиск начинается с первого символа. строка поиска - строка, в которой ведется поиск критерий поиска - искомое строковое выражение способ сравнения - необязательно. Указывает способ сравнения строк (0-двоичное сравнение, 1 -посимвольное сравнение без учета регистра, 2 - только в Microsoft Access). Если аргумент опущен, способ сранения определяется параметром инструкции Option Compare.
Вот пример поиска фамилии Иванов по по критерию из четырех начальных букв "иван" в массиве A(4) без учета регистра.
Dim A(4) As String Dim X As Long A(1) = "Петров" A(2) = "Сидоров" A(3) = "Иванов" A(4) = "Глюкоза" For X = 1 To 4 If InStr(1, A(X), "иван", 1) > 0 Then MsgBox "Найден " & A(X) & " в строке " & X End If Next X
Удачи!
Поскольку мышь (она же крыса) является главным разрушительным орудием юзера, нам надо предоставить ему все возможности для пользования ее в мирных целях. Но прежде, чем начать мучать крысу, поговорим о том, что считалось само собой разумеющимся и как-бы не требующим особых пояснений. Это события.
События. |
Прежде всего хочу сказать, что ранее, при создании процедуры объекта мы довольствовались тем событием, которое нам предоставлял VB по умолчанию. Например для формы - это загрузкаForm1_Load(), для кнопки - щелчок мыши Command1_Click и так далее. Однако, для почти каждого объекта есть довольно-таки большой список и других доступных событий, которые можно посмотреть в правом поле вверху окна кода. То есть, если мы создали процедуру для формы, реагирующую на загрузку формы Form_Load, то щелкнув по полю, где находится надпись Load, мы в выпавшем списке видим еще массу событий и с каждым мы можем создать свою процедуру, например Form_Click, или там Form_MouseMove. По сути, событие - это машинное прерывание, вызванное пользователем, другой программой, системой или еще чем-нибудь. Таким образом, выполнение процедуры для объекта начинается когда наступает событие этой процедуры. Почему мы программный код обычно начинаем с процедуры Form_Load? Потому что при загрузке программы наша форма автоматически загружается, и хочешь-нехочешь, наступает событие Load, начинается выполнение процедуры Form_Load, в которой, поэтому, удобно выполнять предварительные действия по подготовке программы к работе: загрузка служебных файлов, установка свойств объектов, присвоение начальных значений переменным и т.п. А уж далее, либо из этой процедуры происходит переход к другим процедурам, либо программа ожидает наступления других событий для объектов, под которые должны быть написаны свои процедуры. Те же процедуры, которые мы писали сами, обзывали, как хотели, не будут выполнятся никогда, пока мы конкретно не вызовем их по имени. Эти процедуры ни с объектом, ни с событием никак не связаны.
Теперь перейдем к тем событиям, которые вызываются непредсказуемым воздействием юзера на мышь.
|
|
Private Sub объект_MouseMove ([индекс As Integer,]клавиша As Integer, shift As Integer, x As Single, y As Single) |
Возникает при перемешении мыши над объектом. По значению необязательной переменной индекс можно отследить, над каким элементом массива объектов Control Array (если массив существует) происходит перемещение. Переменная клавиша указывает состояние всех клавиш мыши, а не указывает на какую-нибудь одну, как при событиях _MouseDown или_MouseUp. Поэтому значения клавиш (1-левая, 2 - правая, 4 - средняя, 0 - никакая) складываются (1+2=3 нажаты левая и правая клавиши мыши одновременно). Переменная shift возвращает состояние кнопок shift, alt и ctrl в момент нажатия клавиш мыши (1- shift, 2- alt и 4 - ctrl). При удержании больше одной кнопки их значения складываются (ctrl-alt = 4+2=6). Значения переменных x и y возвращают текущие координаты курсора мыши (x - по-горизонтали, y - по-вертикали) в единицах измерения, заданных свойствами ScaleHeight, ScaleWidth. |
|
|
Private Sub объект_MouseDown ([индекс As Integer,]клавиша As Integer, shift As Integer, x As Single, y As Single) и Private Sub объект_MouseUp ([индекс As Integer,]клавиша As Integer, shift As Integer, x As Single, y As Single)
|
Возникает при нажатии (_MouseDown) или отпускании (_MouseUp) клавиши мыши, при нахождении курсора мыши над объектом. При этом по значению необязательной переменной индекс можно отследить, над каким элементом массива объектов Control Array (если массив существует) нажата клавиша. Также позволяет отследить, какая клавиша мыши нажата (не показывает состояние всех клавиш одновременно, как событие _MouseMove), по состоянию переменной кнопка (1- левая клавиша, 2 - правая клавиша, 4 - средняя клавиша). Переменная shift возвращает состояние кнопок shift, alt и ctrl в момент нажатия клавиш мыши (1- shift, 2- alt и 4 - ctrl). При удержании больше одной кнопки их значения складываются (ctrl-alt = 4+2=6). Значения переменных x и y возвращают текущие координаты курсора мыши (x - по-горизонтали, y - по-вертикали) в единицах измерения, заданных свойствами ScaleHeight, ScaleWidth. |
|
|
Private Sub объект_Click() |
Возникает при щелчке левой или правой клавиши мыши, при нахождении курсора мыши над объектом. Объекты CheckBox, CommandButton, Listbox или OptionButton реагируют только на щелчок левой клавиши. Кроме того, если у нас существует массив объектов Control Array (см. Главу 13), то введя переменную индекс в объявление процедуры, можно определить, по какому элементу массива щелкнула мышь. В этом случае объявлять процедуру надо так: |
Private Sub объект_Click (индекс As Integer). |
Индекс и возвратит номер элемента массива. Вот пример кода, когда на форме имеется массив Control Array из трех текстбоксов Text1(0), Text1(1) и Text1(2) и текстбокс Text2. При щелчке мышью по одному из элементов Text1 в текстбокс Text2 будет выводится индекс элемента Control Array. Private Sub Text1_Click(Nomer As Integer) Text2.Text = "Щелкнуто по номеру" & " " & Nomer End Sub При возникновении этого события порождаются события MouseUp и MouseDown. Чтобы различать нажатия клавиш, надо использовать события MouseUp и MouseDown. |
|
|
Private Sub объект_DblClick() |
Возникает при двойном щелчке клавиши мыши, при нахождении курсора мыши над объектом. |
Private Sub объект_DblClick (индекс As Integer). |
Аналогичен событию _Click. |
|
|
Тут надо помнить один очень важный момент. Порядок наступления событий различен для различных элементов. Нужно следить, чтобы события (время их наступления) не противоречили друг другу. Если написать две процедуры, одну на событие _Click, а вторую - на _DblClick в надежде, что они будут выполнятся в зависимости от наступившего события, то процедура _DblClick не будет выполнятся никогда, поскольку событие _Click наступит раньше, начнется выполнение ее процедуры и на _DblClick можно будет наплевать.
Рассмотрим самое мощное событие - _MouseMove на примере (поскольку остальные события используются аналогично) программки Mouse: сделаем новый exe-проект и для наших опытов в верхней части формы создадим массив из пяти TextBox'ов Text1(0), Text1(1), Text1(2), Text1(3), Text1(4), и положим один PictureBox. (Рис. 25).
Рисунок
25.
А
в нижней части формы расположим шесть
лейблов. В первый будем записывать, с
каким объектом работает мышь, во второй
- состояние клавиш мыши, в третий -
состояние кнопок SHIFT-CTRL-ALT, в четвертый
и пятый - координаты мыши, а в шестой -
номер элемента массива TextBox'ов, с которым
работает мышь.
'Объявим
пару переменных для записи пометок в
лейблах
Option
Explicit
Dim ValButton As
String
Dim ValShift As
String
'и
создадим процедуру для нашей формы с
событием _MouseMove и напишем код:
Private
Sub Form_MouseMove(Button As
Integer,
Shift As
Integer,
X As
Single,
Y As
Single)
Label1.Caption
= "Мышь работает с формой"
'в
зависимости от значения Button определяем,
какая клавиша мыши нажата
If Button
= 0 Then
ValButton
= " Ни одной клавиши мыши не
нажато"
ElseIf Button
= 1 Then
ValButton
= " Нажата левая клавиша мыши"
ElseIf Button
= 2 Then
ValButton
= " Нажата правая клавиша мыши"
ElseIf Button
= 4 Then
ValButton
= " Нажата средняя клавиша
мыши"
ElseIf Button
= 3 Then
ValButton
= " Нажаты левая и правая клавиши
мыши"
ElseIf Button
= 7 Then
ValButton
= " Нажаты все три клавиши мыши"
End
If
Label2.Caption
= "Значение Button= " & Button & ValButton
'в зависимости от значения Shift определяем, какая комбинация из кнопок SHIFT-CTRL-ALT нажата If Shift = 0 Then ValShift = " Ни одна из кнопок не нажата" ElseIf Shift = 1 Then ValShift = " Нажата кнопка SHIFT" ElseIf Shift = 2 Then ValShift = " Нажата кнопка CTRL" ElseIf Shift = 4 Then ValShift = " Нажата кнопка ALT" ElseIf Shift = 3 Then ValShift = " Нажаты кнопки SHIFT и CTRL" ElseIf Shift = 6 Then ValShift = " Нажаты кнопки ALT и CTRL" ElseIf Shift = 5 Then ValShift = " Нажаты кнопки SHIFT и ALT" ElseIf Shift = 7 Then ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT" End If Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift 'выводим координаты мыши Label4.Caption = "Координата x= " & X & " твипов" Label5.Caption = "Координата y= " & Y & " твипов" Label6.Caption = "Массива из форм Control Array быть не может" End Sub Обратите внимание, что все кнопки и клавиши отслеживаются только тогда, когда мышь движется. Ждать результатов на неподвижной мыши бесполезно. Теперь, если мы запустим программу, то увидим, что все нажатия кнопок и клавиш, а также изменение координат происходит только тогда, когда курсор мыши находтся над формой. Как только мы перемещаемся на любой объект, TextBox или PictureBox, видимых изменений не происходит. Поскольку мы написали процедуру для формы, над другими объектами она не работает. Кроме того, координаты возвращаются внутри именно того объекта, над которым находится мышь. Т.е., если мышь находится над PictureBox'ом, значит и координаты будут PictureBox'а, а не формы Form1. Для того, чтобы наша программка работала над всеми объектами, создадим аналогичные процедуры для объектов PictureBox и массива TextBox'ов Text1:
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Label1.Caption = "Мышь работает с PictureBox" If Button = 0 Then ValButton = " Ни одной клавиши мыши не нажато" ElseIf Button = 1 Then ValButton = " Нажата левая клавиша мыши" ElseIf Button = 2 Then ValButton = " Нажата правая клавиша мыши" ElseIf Button = 4 Then ValButton = " Нажата средняя клавиша мыши" ElseIf Button = 3 Then ValButton = " Нажаты левая и правая клавиши мыши" ElseIf Button = 7 Then ValButton = " Нажаты все три клавиши мыши" End If
Label2.Caption = "Значение Button= " & Button & ValButton
If Shift = 0 Then ValShift = " Ни одна из кнопок не нажата" ElseIf Shift = 1 Then ValShift = " Нажата кнопка SHIFT" ElseIf Shift = 2 Then ValShift = " Нажата кнопка CTRL" ElseIf Shift = 4 Then ValShift = " Нажата кнопка ALT" ElseIf Shift = 3 Then ValShift = " Нажаты кнопки SHIFT и CTRL" ElseIf Shift = 6 Then ValShift = " Нажаты кнопки ALT и CTRL" ElseIf Shift = 5 Then ValShift = " Нажаты кнопки SHIFT и ALT" ElseIf Shift = 7 Then ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT" End If Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift Label4.Caption = "Координата x= " & X & " твипов" Label5.Caption = "Координата y= " & Y & " твипов" Label6.Caption = "Массива из PictureBox'ов сейчас нет" End Sub
Private Sub Text1_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) Label1.Caption = "Мышь работает с массивом TextBox'ов" If Button = 0 Then ValButton = " Ни одной клавиши мыши не нажато" ElseIf Button = 1 Then ValButton = " Нажата левая клавиша мыши" ElseIf Button = 2 Then ValButton = " Нажата правая клавиша мыши" ElseIf Button = 4 Then ValButton = " Нажата средняя клавиша мыши" ElseIf Button = 3 Then ValButton = " Нажаты левая и правая клавиши мыши" ElseIf Button = 7 Then ValButton = " Нажаты все три клавиши мыши" End If
Label2.Caption = "Значение Button= " & Button & ValButton
If Shift = 0 Then ValShift = " Ни одна из кнопок не нажата" ElseIf Shift = 1 Then ValShift = " Нажата кнопка SHIFT" ElseIf Shift = 2 Then ValShift = " Нажата кнопка CTRL" ElseIf Shift = 4 Then ValShift = " Нажата кнопка ALT" ElseIf Shift = 3 Then ValShift = " Нажаты кнопки SHIFT и CTRL" ElseIf Shift = 6 Then ValShift = " Нажаты кнопки ALT и CTRL" ElseIf Shift = 5 Then ValShift = " Нажаты кнопки SHIFT и ALT" ElseIf Shift = 7 Then ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT" End If Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift Label4.Caption = "Координата x= " & X & " твипов" Label5.Caption = "Координата y= " & Y & " твипов" Label6.Caption = "Мышь находится над " & "Text1(" & Index & ")" End Sub
Конечно, все это можно написать короче, используя одну собственную процедуру - ведь код этих процедур почти одинаков, но сейчас так будет яснее. Теперь нажатия и координаты отслеживаются над всеми объектами, кроме лейблов. Для устранения этого, мы можем в их свойствах поставить значение свойства .Enabled в окне свойств в положениеFalse. Тогда при нахождении курсора мыши над лейблами будут показываться нажатия кнопок и координаты мыши при событии _MouseMove, наступающем для формы. Однако текст в лейблах изменится на серенький. Скачать исходник программы Mouse можно вверху страницы.
Рисование фигур программными методами. |
Теперь я скажу, что рисовать такие фигуры, как круг, овал, прямоугольник, линия можно не только с помощью объекта Shape, но и программно, путем написания операторов. Это очень просто.
Прямоугольник, линия - метод Line. |
Для рисования на объекте линии или прямоугольника существует метод Line. Синтаксис его такой
объект.Line [Step] (x1, y1) [Step] (x2, y2), [color], [B][F] Где
объект |
это объект на котором рисуется фигура. Если не задан, то используется объект на котором в этот момент установлен фокус. |
Step |
необязательное ключевое слово, устанавливает, что начальная точка прямоугольника - верхний левый угол, (или линии) задается не по абсолютными координатами x1, y1, а относительно текущих координат, определяемых значениями свойств CurrentX и CurrentY. |
x1, y1 |
координаты начальной точки прямоугольника (верхний левый угол) или линии (единицы измерения определяются свойством ScaleMode). |
Step |
необязательное ключевое слово, устанавливает, что конечная точка прямоугольника - нижний правый угол, (или линии) задается не по абсолютыми координатами x2, y2, а относительно координат начальной точки прямоугольника x1,y1. |
x2, y2 |
координаты конечной точки прямоугольника (нижний правый угол) или линии (единицы измерения определяются свойством ScaleMode). |
color |
определяет цвет линии или прямоугольника. Может задаваться как RGB - в формате шестнадцатиричного числа VB (&HFF0033), либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно использовать функции RGB или QBColor. Если не задан, цвет устанавливается тот, что задан свойством .ForeColor. |
B |
определяет, что будет прямоугольник. Если его опустить, рисоваться будет линия. |
F |
определяет, что прямоугольник будет закрашен тем же цветом, что и его границы (заливка). Используется с опцией B. |
Таким образом, чтобы нарисовать линию, например, в объекте Picture1, можно использовать такой код:
Private Sub Form_Load() 'задаем единицы измерения пиксели Picture1.ScaleMode = vbPixels 'устанавливаем свойство AutoRedraw в True, а то нашего рисования видно не будет Picture1.AutoRedraw = True 'ширину лини устанавливаем в 3 пикселя Picture1.DrawWidth = 3 'ставим цвет в свойстве ForeColor в фиолетовый Picture1.ForeColor = &HFF00FF 'рисум линию с начальной координатой X1=10, Y1=10 и конечной X2=150, Y2=150 пикселей 'поскольку цвет не задаем, линия будет фиолетовой по свойству ForeColor Picture1.Line Step(10, 10)-(150, 150) End Sub Если мы в оператор Picture.Line добавим B, то у нас получится прямоугольник (в общем-то квадрат) Picture1.Line (10, 10)-(150, 150), , B Чтобы изменить цвет линий, например, на красный, независимо от .ForeColor: Picture1.Line (10, 10)-(150, 150), vbRed, B И наконец можем залить наш квадратик Picture1.Line (10, 10)-(150, 150), vbRed, BF Ключевое слово Step можно использовать, если нужно привязаться к постоянно меняющимся значениям свойств .CurrentX и .CurrentY. Так, например, мы можем нарисовать наш квадратик там, куда щелкнем мышкой. Private Sub Form_Load() Picture1.ScaleMode = vbPixels Picture1.AutoRedraw = True Picture1.DrawWidth = 3 Picture1.ForeColor = &HFF00FF End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) Picture1.Cls 'очищаем Picture1 перед каждым кликом Picture1.CurrentX = X Picture1.CurrentY = Y Picture1.Line Step(0, 0)-Step(150, 150), vbRed, B End Sub
Окружность, эллипс, дуга - метод Circle. |
Для рисования на объекте окружности, эллипса или дуги применяется метод Circle. Его синтаксис:
объект.Circle [Step] (x, y), радиус, [color, start, end, aspect], Где
объект |
это объект на котором рисуется фигура. Если не задан, то используется объект на котором в этот момент установлен фокус. |
Step |
необязательное ключевое слово, устанавливает, что центр окружности задается не по абсолютным координатам x, y, а относительно текущих координат, определяемых значениями свойств CurrentX и CurrentY. |
x, y |
координаты центра окружности (единицы измерения определяются свойством ScaleMode) |
радиус |
радиус окружности, эллипса ил дуги (единицы измерения определяются свойством ScaleMode). |
color |
определяет цвет окружности, эллипса или дуги. Может задаваться как RGB - в формате шестнадцатиричного числа VB (&HFF0033), либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно использовать функции RGB или QBColor. Если не задан, цвет устанавливается тот, что задан свойством .ForeColor. |
start, end |
при создании дуги задают начальное и конечное значение угла дуги в радианах (от -2pi до 2pi) |
aspect |
коэффициент сжатия эллипса. По умолчанию равен 1,0, т.е. сжатия нет, выводится окружность. |
Ну-с, опять в нашем Picture1 рисуем окружность. Все происходит аналогично методу .Line Private Sub Form_Load() Picture1.ScaleMode = vbPixels Picture1.AutoRedraw = True Picture1.DrawWidth = 3 Picture1.ForeColor = &HFF00FF Picture1.Circle (200, 120), 70 End Sub Мы нарисовали фиолетную окружность с центром в точке X=200, Y=120 и и диаметром 70 пикселей. Теперь превратим ее в эллипс синего (&HFF0000) цвета. Коэффициент aspect установим в 0,5, т.е сожмем окружность в 2 раза. Picture1.Circle (200, 120), 70, &HFF0000, , , 0.5 Попробуем теперь нарисовать дугу окружности. Коэффициент эллипcности убираем (дуга эллипса - некрасиво). Цвет определим зеленый (&H8000&) Picture1.Circle (200, 120), 70, &H8000&, 0, 1 А вот пример маленького кода, где мы можем использовать "мышиные" события и рисование фигур. Эта программка рисует окружность, причем радиус и положение задается нажатием клавиши мыши. Когда клавиша отпускается, окружность фиксируется. Option Explicit Dim OldX As Single Dim OldY As Single Private Sub Form_Load() Picture1.ScaleMode = vbPixels Picture1.AutoRedraw = True Picture1.DrawWidth = 3 Picture1.ForeColor = &H8000& End Sub Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) OldX = X OldY = Y End Sub
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim Center As Long Picture1.CurrentX = X Picture1.CurrentY = Y If Button = 1 Then Picture1.Cls Picture1.Circle Step(OldX, OldY), Sqr((X - OldX) ^ 2 + (Y - OldY) ^ 2), &H8000& Center = Sqr((X - OldX) ^ 2 + (Y - OldY) ^ 2) End If End Sub
Практически каждая программа должна дать возможность пользователю загружать и сохранять файлы. Конечно, для этих целей можно использовать объекты Drive, Dir и File, об их использовании мы уже говорили в Главе 6. Однако, если ты заметил, большинство программ используют стандартные виндусовые окна, придающие программному продукту солидный вид. Имеем такую возможность и мы. Использование стандартных диалоговых окон проще и удобнее с точки зрения написания кода. Кроме того они позволяют пользователю выбирать цвет, шрифт, вводить свои установки для принтера и использовать Help (последнее мы опустим, так это сейчас не актуально).
Стандартные окна общего диалога CommonDialog. |
В Главе 12 мы уже использовали два элемента ActiveX - ProgressBar и Slider, добавив в панель инструментов средство Microsoft Windows Common Controls 6.0. Сейчас то же самое надо сделать с элементом ActiveX - Microsoft Common Dialog Control 6.0. Если ты не помнишь, как это делать, посмотри Главу 12, там все подробно расписано. После того, как ты отметишь галочкой (Проект - Компоненты - Microsoft Common Dialog Control 6.0) этот компонент и щелкнешь OK, у тебя в панели инструментов появится новый значок "CommonDialog". Этот компонент позволяет нам использовать отдельно стандартные окна Windows - открытия файлов (Open) с помощью метода ShowOpen - сохранения файлов (Save As) c помощью метода ShowSave - менять установки принтера (Printer) c помощью метода ShowPrinter - выбор шрифтов и стилей (Font) c помощью метода ShowFont - выбор цвета из палитры (Color) c помощью метода ShowColor
Рассмотрим все окна на примере маленькой программки DialogWindows. Создадим новый exe-проект, положим на форму наш новый компонент CommonDialog1, текстбокс Text1 и пять командных кнопокCommand, в каждой из которых будет процедура для своего стандартного окна. Мы будем работать с текстовыми файлами. Итак первое окно Open в процедуре кнопки Command1:
Диалоговое окно открытия файлов Open (метод ShowOpen). |
Чтобы открыть окно для открытия файлов, мы в процедуре командной кнопки Command1 пишем одну единственную строчку:
