Visual Basic 6. Руководство разработчика

       

Ускорения операций вывода графических изображений


Операции вывода пикселей с помощью функций SetPixelV() и GetPixelV() занимают гораздо меньше времени, чем при использовании их аналогов в Visual Basic, но все же они выполняются не очень быстро. Для значительного увеличения быстродействия требуется использовать дополнительные API-функции.

Если вывод изображения в окно формы выполняется с помощью методов Visual Basic, то изображение, фактически, записывается в область памяти, содержимое которой затем отображается в окно формы. Visual Basic работает с этой областью памяти, в результате чего появляются несколько уровней обработки, которые лежат между программой и реальным окном на экране. API-функции, рассмотренные в предыдущем параграфе, позволяют выполнить те же операции, но они работают гораздо быстрее, чем программа Visual Basic. (На самом деле Visual Basic выполняет вызов этих же функций, однако, этот процесс скрыт от программиста VB. За счет этого использование функций упрощается, а время выполнения - увеличивается.)

Windows не позволяет приложению выполнять вывод графики непосредственно на экран. Следует помнить о том, что в Windows можно запускать одновременно несколько приложений, переключаться между ними и при этом не беспокоиться о том, как будут происходить перерисовка окон и переключение между палитрами -это делает Windows. Но Windows была бы не в состоянии уследить за всеми под­робностями, если бы приложениям был предоставлен прямой доступ к растровым изображениям окон на экране. Именно поэтому процедуры рисования в Windows выполняются медленно.

Независимо от того, как Windows выполняет вывод объектов и их заливку, в конечном счете, растровое изображение должно быть сохранено где-нибудь в памяти. Имеются соответствующие API-функции, которые позволяют приложениям обращаться к этой области памяти и осуществлять вывод изображения, устанавливая значения битов и байтов. Вывод изображения непосредственно в область памяти выполняется значительно быстрее, чем в контекст устройства, но его организация сложнее. Кроме того. когда вывод изображения выполняется в область памяти, на экране ничего не появляется. Необходимо написать программу, которая передает изображение из области памяти в окно на экране. Но даже с учетом этих дополни­тельных шагов вывод изображения в область памяти выполняется значительно быстрее, чем вывод в контекст устройства.


Чтобы вывести изображение в область памяти, необходимо выделить в памяти место для растрового изображения. Такая структура должна быть совместимой с контекстом устройства, в которое выполняется вывод изображения. Иными словами, для организации вывода изображения на принтер и на монитор требуется определять различные структуры. Чтобы создать в памяти растровую структуру для хранения изображения, требуется вызвать функцию

CreateCompatibleBitmap().

Public Declare Function CreateCompatibleBitmap Lib "gdi32" _

Alias "CreateCompatibleBitmap" (ByVal hdc As Long, _

ByVal nWidth As Long, ByVal nHeight As Long) As Long

Первый параметр функции — это контекст устройства, с которым совместимо растровое изображение. С другой стороны, это — контекст устройства, в который помещается растровое изображение, чтобы его можно было вывести на экран. Два оставшихся параметра определяют размер растрового изображения в пикселях.

Так как изображение будет выводиться на экран, необходимо создать контекст устройства с помощью функции

CreateCompatibleDC(), а затем выбрать растровую структуру в контекст устройства с помощью функции SelectObject(). Функция CreateCompatibleDCO объявляется так:



Public Declare Function CreateCompatibleDC Lib "gdi32" _

Alias "CreateCompatibleDC" (ByVal hdc As Long) As Long

Ее параметром является контекст элемента управления (или формы), в которую выводится изображение. Если требуется сначала подготовить растровое изображение в памяти, а затем вывести его в окно элемента управления PictureBoxl, то можно воспользоваться следующими операторами.

hBMPSource = CreateCompatibleBitmap(Picturel.hdc,

_

  Picturel.ScaleWidth, Picturel.ScaleHeight)

hSourceDC = CreateCompatibleDC(Picturel.hdc)

SelectObject hSourceDC, hBMPSource

После того как эти операторы выполнены, можно выполнить вывод изобра­жения в контекст устройства hSourceDC, используя рассмотренные выше функции. Обратите внимание: содержимое контекста устройства hSourceDC не выводится на монитор непосредственно. Это изображение остается в памяти и может быть изменено очень быстро. А вот чтобы вывести его на монитор (т.е. передать его содержимое в окно элемента управления PictureBox2), следует воспользоваться функцией BitBlt().



Для обработки команды Сору Fast (третья кнопка на форме проекта CopyPix) используется именно такой прием при чтении значений цвета пикселей из окна левого элемента управления PictureBox и записи в правый PictureBox. Текст программы обработчика команды Сору Fast приведен ниже.

Программа 13.15. Обработчик команды Сору

Fast

Private Sub Command3_Click()

Picture2.CIs

' Задание области-источника растрового изображения

hBMPSource = CreateCompatibleBitmap(Picurel.hdc, _

Picturel.ScaleWidth, Picturel.ScaleHeight)

hSourceDC = CreateCompatibleDC(Picturel.hdc)

SelectObject hSourceDC, hBMPSource

' Задание области-получателя растрового изображения

hBMPDest = CreateCompatibleBitmap(Picture2.hdc, _

Picture2.ScaleWidth, Picture2.ScaleHeight)

hDestDC = CreateCompatibleDC(Picture2.hdc)

SelectObject hDestDC, hBMPDest

' Копирование растрового изображения в область-источник

BitBIt hSourceDC, 0, 0, Picturel.ScaleWidth - 1, _

Picturel.ScaleHeight - 1, Picturel.hdc, 0, 0, &НСС0020

' Копирование пикселей из одной области в другую

For 1 = 0 То Picturel.ScaleWidth - 1

For j = 0 To Picturel.ScaleHeight - 1

  clr = GetPixel(hSourceDC, i, j)

  SetPixel hDestDC, i, j, clr

Next

Next

' Передача скопированных пикселей в другое окно PictureBox

BitBIt Picture2.hdc. О, О, Picturel.ScaleWidth - 1, _

Picture1.ScaleHeight - 1, hDestDC, 0, 0, &НСС0020

' Picture2.Refresh

' Заключительная очистка области памяти

Call DeleteDC(hSourceDC)

Call DeleteObject(hBMPSource)

Call DeleteDC(hDestDC)

Call DeleteObject(hBMPDest)

End Sub

Программа начинается с создания в памяти двух контекстов устройств, hSourceDC (соответствующего растровому изображению в окне левого элемента управления PictureBox) и hDestDC (соответствующего растровому изображению в правом элементе управления

PictureBox). Затем выполняется копирование пикселей из окна элемента управления PictureBox 1 в соответствующий контекст устройства (при создании контекст устройства содержит произвольные данные). Затем в двойном цикле выполняется копирование пикселей из контекста hSourceDC в контекст hDestDC с помощью API-функций GetPixelV() и SetPixelV(). Нетрудно заметить, что методы для вывода изображения в контекст устройства и в контекст области памяти одинаковы.



Во время копирования пикселей содержимое экрана не изменяется. Если создание изображения выполняется в памяти, то Windows неизвестно о том, что предполагается делать с этим изображением в дальнейшем, поэтому никаких изменений на экране не происходит. В конце концов, когда пиксели будут скопированы, следует переместить растровое изображение из памяти (контекст hDestDC) в окно элемента-получателя (окно элемента управления PictureBox2). Это выполняется с помощью функции BitBlt(). В заключение программа освобождает

все ресурсы, созданные во время выполнения операции, с помощью функций DeleteDC() и Delete Object().

Запустите проект CopyPix и щелкните на кнопке Сору Fast, чтобы увидеть, насколько быстрее он работает по сравнению с двумя другими методами. Недостаток этого метода состоит в том, что невозможно наблюдать за скоростью выполнения операции копирования пикселя. Второе изображение появится на экране только тогда, когда все пиксели буду скопированы. Если обрабатываются большие изображения, то функцию BitBlt() придется вызывать чаще (например, при копи­ровании каждого столбца пикселей). Это приводит к появлению некоторой задержки, но метод, описанный в этом параграфе, все равно быстрее двух других. Можно добавить в программу индикатор, позволяющий пользователю получить представление о скорости выполнения программы и времени, оставшемся до ее завершения.

Этим примером заканчивается рассмотрение API-функций. В следующей главе рассмотрены организация взаимодействия программ Visual Basic с внешними приложениями (такими, как Excel и Word) и управление их объектами с помощью VBA. Офисные приложения предоставляют много возможностей, которые можно использовать в VB-приложениях, поэтому не имеет смысла заново их разрабатывать в Visual Basic.

Глава 14 Автоматизация OLE и VBA

•           Расширение возможностей Visual Basic с помощью OLE

•           OLE-терминология

•           Связывание и встраивание

•           Применение элемента управления OLE Container

•           Автоматизация OLE и VBA



•           Программирование объектов Word

•           Программирование объектов Excel

•           Программирование объектов Outlook

Visual Basic — весьма эффективный объектно-ориентированный язык, позво­ ляющий скрывать от пользователя многие подробности использования объектов и управления ими. Элементы, используемые для организации интерфейса пользо­вателя, являются объектами, и управление ими осуществляется с использованием соответствующих свойств и методов. Предполагается, что в данный момент поль­зователь уже хорошо знаком со свойствами объектов Visual Basic.

В этой главе рассматриваются два достаточно сложных аспекта применения объектов Visual Basic: OLE и автоматизация OLE Automation. Средства OLE

позво­ляют организовать взаимодействие приложений, созданных с помощью Visual Basic, с приложениями, работающими в среде Windows. Средства управления, использо­вавшиеся до сих пор, были встроенными средствами Visual Basic. Они находятся на панели элементов управления (Tool-box), и их можно поместить в окно формы с помощью мыши. Однако некоторые объекты Windows не входят в состав встро­енных средств Visual Basic. Они поставляются вместе с другими приложениями, но их можно использовать и в прикладных программах.

К таким объектам относятся документы, созданные в текстовом процессоре Word, поэтому DOC-файлы можно встраивать в собственные приложения. При этом нет необходимости выяснять детали организации этих файлов или способ записи их на диск. Если нужно редактировать файлы, встроенные в приложение, то можно почти мгновенно вызвать на экран меню Word и соответствующие панели инструментов и отобразить их непосредственно в прикладной программе. После этого можно редактировать документ так, как если бы он находился в Word.

Можно организовать управление приложением, например.

Word, манипулируя его объектами с помощью средств, предоставляемых VBA (Visual Basic for Applications). VBA — популярный и мощный язык, позволяющий программистам быстро приспосабливать популярные прикладные программы (подобные Word и Excel) под выполнение определенных задач, а не разрабатывать новые прикладные программы, удовлетворяющие специфическим требованиям решаемых задач как в мелком бизнесе, так и в крупном. Знания, полученные при изучении Visual Basic, легко применимы при работе с VBA, но прежде следует ознакомиться со структурой и основными принципами функционирования VBA.

В первой части главы рассмотрено, как можно расширить возможности Visual Basic за счет использования OLE, позволяющего включать в ваши программы объекты, предоставляемые другими прикладными программами. Вторая часть главы является введением в VBA. В ней рассмотрены возможности использования всех средств Word, Excel и Outlook непосредственно из VB-приложений с помощью автоматизации OLE и VBA.


Содержание раздела