Создание элементов меню, содержащих растровые изображения
Элементы меню, создаваемые средствами Menu Editor (Редактор меню) Visual Basic, не всегда содержат только текст. В некоторых прикладных программах может потребоваться, чтобы элемент меню содержал растровое изображение. Добавить растровые изображения к элементам меню можно с помощью нескольких API-функции. Разработка таких элементов меню занимает немало времени, но результат того стоит Приложение MenuBMP (рис 13.4) позволяет создавать элементы меню с растровыми изображениями.
VB6 в действии: проект MenuBMP
В этом приложении используются такие API-функции:
• GetMenu()
• GetSubMenu()
• ModifyMenu()
• CreateCompatibleDC()
• CreateCompatibleBitmap()
• Select0bject()
Рис. 13.4. Приложение MenuBMP
Чтобы манипулировать элементами меню с помощью API-функций, необходимо получить дескриптор элемента меню. Элементы меню являются объектами, и поэтому им поставлены в соответствие дескрипторы, которые идентифицируют их с точки зрения операционной системы (точно так идентифицируются формы и растровые изображения). Более того, можно манипулировать элементами меню других приложений, запущенных в настоящий момент, если получить дескриптор этого элемента меню.
Для получения дескриптора элемента меню используется функция GetMenu(). Объявим ее:
Private Declare Function GetMenu Lib "user32" (ByVal hWnd _
As Long) As Long
Параметр
hWnd является дескриптором формы, элементами меню которой требуется манипулировать. Для получения дескриптора меню текущей формы используется следующее выражение.
MenuHandle = GetMenu(Me.hWnd)
Меню первого уровня содержат подменю, которые идентифицируются их порядком в главном меню. Подменю имеют свои дескрипторы, которые можно получить с помощью функции
GetSubMenu().
Private Declare Function GetSubMenu Lib "user32" _
(ByVal hMenu As Long, ByVal nPos As Long) As Long
Параметр
hMenu - это дескриптор меню, возвращаемый функцией GetMenu(), а параметр nPos — номер текущей позиции подменю. Если значение параметра nPos равно 0, то функция GetSubMenu() возвращает дескриптор первого подменю (им часто оказывается меню File (Файл)).
После того как дескриптор подменю получен, его можно модифицировать с помощью функции
ModifyMenu().
Private Declare Function ModifyMenu Lib "user32" Alias _
"ModifyMenuA" (ByVal hMenu As Long, ByVal nPosition _
As Long, ByVal wFlags As Long, ByVal wIDNewItem As _
Long, ByVal IpString As Any) As Long
Эта функция позволяет изменить элемент меню. Поясним это. Параметр hMenu — это дескриптор подменю, полученный с помощью функции GetSubMenu() Параметр nPosition
идентифицирует элемент меню, который требуется изменить. Если в параметре wFlags установлен флаг MF_BYCOMMAND, то этот параметр относится к ID (Идентификатору) команды меню, которая будет изменена. Если же установлен флаг MF_BYPOSITION, то параметр определяет номер позиции элемента подменю. Параметр wFlags является комбинацией флагов, описанных в табл. 13.4.
Таблица 13.4. Флаги меню
Значение |
Описание |
MF_BITMAP |
Указывает, что элемент меню содержит растровое |
изображение. Растровое изображение остается в |
|
памяти, пока используется указанный элемент меню |
|
MF_BYCOMMAND |
Определяет элемент меню командой ID меню |
MF_BYPOSITION |
Определяет элемент меню его позицией в подменю: |
номер позиции первого объекта равен нулю |
|
MF_CHECKED |
Отображает метку выбора, устанавливая ее слева от |
элемента меню |
|
MF_DISABLED |
Делает элемент меню недоступным |
MF_ENABLED |
Делает элемент меню доступным |
MF_G RAYED, |
Делает элемент меню недоступным и выводит его, |
заливая изображение серым цветом (вместо того, чтобы |
|
сделать его невидимым) |
|
M F_MENUBARBREAK |
Помещает элемент меню в новый столбец, отделяя его |
вертикальной линией |
|
MF_MENUBREAK |
Помещает элемент меню в новый столбец |
MF_POPUP |
Подключает дополнительное раскрывающееся меню к |
элементу меню |
|
MF_SEPARATOR |
Помещает горизонтальную линию разделителя под |
элементом меню |
|
MF_STRING |
Помещает строку в элемент меню |
MF_JJNCHECKED |
Снимает метку выбора слева от элемента меню (если |
элемент был выделен) |
Чтобы связать растровое изображение с пунктом меню, необходимо установить флаг MF_BITMAP в параметре wFlags
функции ModifyMenuO. Процедура изменения меню относительно проста, но с заданием растрового изображения, помещенного в заголовок элемента меню, дело обстоит иначе. Сначала необходимо создать контекст устройства (т.е. область памяти, в которой будет храниться растровое изображение) с помощью функции CreateCompatibleDC().
Набор данных, составляющих растровое изображение (обычно это BMP-файл), загружается в скрытый элемент управления PictureBox. Из него растровое изображение копируется в контекст устройства с помощью функции CreateCompatibleBitmap(). После того как растровое изображение помещено в контекст устройства, его можно связать с элементом меню, как строку текста Фрагмент программы 13.5 содержит код, реализующий добавление растрового изображения к элементу меню приложения MenuBMP.
Обратите внимание размеры растрового изображения должны быть переданы как параметры функции CreateCompatibleBitmap(). Создавая растровое изображение с помощью графического редактора, необходимо задавать изображению такие размеры, чтобы они соответствовали размерам элемента меню. Не следует делать его слишком высоким или слишком узким Растровые изображения в рассматриваемых примерах были созданы в программе PaintShopPro. Для создания растровых изображений можно использовать любой графический редактор, включая ImageEdit (папка Tools прилагаемого компакт-диска).
Меню Bitmaps приложения MenuBMP содержит три команды, соответствующие трем различным шрифтам (см. рис. 13.4). Три растровых изображения хранятся в файлах Verdana.bmp, Serif.bmp и Comic.bmp в той же папке, что и приложение. После разработки растровых изображений можно начинать работать с программой. Полный текст программы MenuBMP приведен ниже.
Программа 13.5. Приложение MenuBMP
Option Explicit
Private Declare Function GetMenu Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32"
( ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function GetMenuItemID Lib "user32"
(ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function ModifyMenu Lib "user32"
Alias "ModifyMenuA" (ByVal hMenu As Long, _
ByVal nPosition As Long, ByVal wFlags As Long, _
ByVal wIDNewItem As Long, ByVal IpString As Any) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
(ByVal hdc As Long, ByVal nWidth As Long,
_
ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32" _
(ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function BitBIt Lib "gdi32" _
(ByVal hDestDC As Long, ByVal x As Long, ByVal у As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal hSrcDC As Long, ByVal xSrc As Long, _
ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Const SRCCOPY &HCC0020
Const MF_BYPOSITION - &H400&
Const MF_BITMAP &H4&
Private Sub Form_Load()
Dim Width As Integer, Height As Integer
Dim hTmpDC As Long, hMenuID As Long
Dim hBitmap As Long, retValue As Long
Dim tmpID As Long
Dim fileName As String
Dim menuPos As Integer, menuID As Long
‘ Установка позиции меню и имени файла
menuPos = 0
fileName = App.Path & "\verdana.bmp"
Picturel.Picture = LoadPicture(fileName)
Width = 64
Height = 16
‘ Получение дескриптора меню
hMenuID = GetSubMenu(GetMenu(Me.hwnd), menuPos)
‘ Создание контекста устройства для хранения растрового
‘изображения
hTmpDC = CreateCompatibleDC(Picturel.hdc)
‘ Создание растрового изображения
hBitmap = CreateCompatibleBitmap(Picturel.hdc, Width, Height)
‘ Выбор растрового изображения во временный контекст
tmpID = SelectObject(hTmpDC, hBitmap)
‘ Копирование содержимого из элемента управления в контекст
‘ устройства
retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _
Picturel.hdc, 0, 0, SRCCOPY)
‘ Отмена выбора
tmpID = SelectObject(hTmpDC, tmpID)
‘ Модификация меню
menuID = GetMenuItemID(hMenuID, menuPos)
retValue = ModifyMenu(hMenuID, menuPos, _
MF_BYPOSITION Or MF_BITMAP, menuID, hBitmap)
‘ Второй пункт меню
menuPos = 1
fileName = App.Path & "\serif.bmp"
Picture1.Picture = LoadPicture(fileName)
‘ Создание растрового изображения для элемента меню
hBitmap = CreateCompatibleBitmap(Picturel.hdc. Width, Height)
‘ Выбор растрового изображения во временный контекст
‘ устройства
tmpID = SelectObject(hTmpDC, hBitmap)
retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _
Picture1.hdc. О, О, SRCCOPY)
tmpID = SelectObject(hTmpDC, tmpID)
menuID = GetMenuItemID(hMenuID, menuPos)
retValue = ModifyMenu(hMenuID, menuPos,
MF_BYPOSITION Or MF_BITMAP, menuID, hBitmap)
‘Третий пункт меню menu
Pos = 2
fileName = App.Path & "\comic.bmp"
Picture1.Picture = LoadPicture(fileName)
‘ Создание растрового изображения для элемента меню
hBitmap = CreateCompatibleBitmap(Picturel.hdc, Width, Height)
‘ Выбор растрового изображения во временный контекст устройства
tmpID = SelectObject(hTmpDC, hBitmap)
retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _
Picturel.hdc. О, О, SRCCOPY)
tmpID = SelectObject(hTmpDC, tmpID)
menuID = GetMenuItemID(hMenuID, menuPos)
retValue = ModifyMenu(hMenuID, menuPos, _
MF_BYPOSITION Or MF_BITMAP, menuID, hBitmap)
‘ Очистка
retValue = DeleteDC(hTmpDC)
End Sub
Private Sub MyMenu Click(Index As Integer)
Dim fName(3) As String
fName(0) = "Verdana"
fName(l) = "Serif"
fName(2) = "Comic Sans MS"
Me.CIs
Me.CurrentX = (Me.ScaleWidth - TextWidth(fName(Index)))/2
Me.CurrentY = (Me.ScaleHeight - TextHeight(fName(Index)))/2
Me.Font.Name = fName(Index)
Me.Print fName(Index)
End Sub