Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Добавление иконки в SystemTray средствами Visual Basic

Кирилл Головин
www.vbrussian.com

Эта статья является самодостаточной, то есть в ней дана исчерпывающая информация по созданию иконки в SystemTray с помощью VB. Однако при этом она является компиляцией общедоступных источников, то есть заслуга автора состоит лишь в сборе этой информации в одном месте и пояснениях.

Основы создания иконки изложены в FAQ Льва Серебрякова. Используется пример на VB от Alexander Shherbakov. Описания функций и констант из книги Daniel Applemana и API.TXT. Вопросы связанные с редактором ресурсов не рассматриваются.

Единственная функция для работы с иконкой Shell_NotifyIcon. Ее описание на VB выглядит так:

Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _ 
(ByVal dwMessage As dwMess, lpData As NOTIFYICONDATA) As Long

Возвращает ноль в случае ошибки

Тип dwMess описывается так:

Public Enum dwMess


NIM_ADD = &H0 ' Добавление иконки
NIM_DELETE = &H2 ' Удаление иконки 
NIM_MODIFY = &H1 ' Изменение параметров иконки
End Enum

Переменная dwMessage должна иметь одно из этих значений.

Тип NOTIFYICONDATA имеет следующую структуру:

Type NOTIFYICONDATA

cbSize As Long ' Размер переменной типа NOTIFYICONDATA
hwnd As Long ' Указатель окна создающего иконку 
uID As Long ' Указатель на иконку в пределах приложения 
uFlags As uF ' Маска для следующих параметров 
uCallbackMessage As CallMess ' Возвращаемое событие 
hIcon As Long ' Указатель на изображение для иконки 
szTip As String * 64 ' Всплывающий над иконкой текст
End Type 

Где тип uF имеет вид:

Public Enum uF

NIF_MESSAGE = &H1 ' Значение имеет uCallbackMessage
NIF_ICON = &H2 ' Значение имеет hIcon 
NIF_TIP = &H4 ' Значение имеет szTip

End Enum 

Эти константы можно применять в любых сочетаниях, для определения какой из параметров имеет значение.
 

Тип CallMess:

Public Enum CallMess

WM_MOUSEMOVE = &H200 
WM_LBUTTONDOWN = &H201 
WM_LBUTTONUP = &H202
WM_LBUTTONDBLCLK = &H203
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
WM_RBUTTONDBLCLK = &H206


WM_MBUTTONDOWN = &H207
WM_MBUTTONUP = &H208
WM_MBUTTONDBLCLK = &H209
WM_SETFOCUS = &H7
WM_KEYDOWN = &H100
WM_KEYFIRST = &H100
WM_KEYLAST = &H108
WM_KEYUP = &H101

End Enum 

Эти константы обозначают, какое событие возвращается вызывающей форме. Буквально, все, что будет происходить с иконкой, будет вызывать у формы одно из перечисленных событий. Ясно, что самое частое событие самой иконки это MouseMove, но для формы оно будет выглядеть как событие заданное переменной uCallbackMessage. Как же узнать, что в действительности произошло с иконкой? Это можно узнать через переменные X и Y событий MouseMove, MouseDown и MouseUp вызывающей формы. При этом Y, если событие произошло с иконкой, а не формой, всегда будет равно нулю, а X несет информацию о событии с иконкой.
 

О параметре X следует сказать отдельно. Действительно, он передает информацию о событиях с иконкой, однако эти значения зависят от масштабного коэффициента системного шрифта, но не напрямую, а через параметр свойства TwipsPerPixelX объекта Screen. То есть для одной и той же системы, при разных величинах системного шрифта, значения будут разными. Начальными значениями событий являются следующие:

MouseMove - 512

LeftButtonDown - 513

LeftButtonUp - 514

LeftButtonDblClick - 515

RightButtonDown - 516

RightButtonUp - 517

RightButtonDblClick - 518
 

Для того чтобы узнать действующие в данной системе значения их следует умножить на Screen.TwipsPerPixelX

Как же узнать, что событие произошло с иконкой, а не с формой? Просто, по значению Y, равному нулю. Но есть и другой способ, если используется двухкнопочная мышь то параметр Button в событиях MouseDown и MouseUp формы, будет принимать значения 1 и 2, и при uCallbackMessage равно WM_MBUTTONDOWN=&H207 или WM_MBUTTONUP = &H208 Button равен 4, если событие с иконкой. Само собой разумеется, что возвращаемые X значения следуют одно за другим, как и события (Down->Up->DbClick),поэтому невозможно на одну кнопку мыши назначить два события, к примеру, Click и DbClick. События не связанные с мышью не несут практически ни какой информации, и обычно не используются, следует так же отметить, что количество констант uCallbackMessage намного больше и здесь приведена лишь небольшая часть

Из описанного видно, что с иконкой можно совершить одно из следующих действий: добавить, модифицировать и удалить, при этом, модифицируя можно заменить возвращаемое событие, картинку (указатель при этом останется тем же) и всплывающую надпись (ToolTips).

Следующий момент, который нужно осветить это получение hIcon (указателя на картинку). Предполагается, что иконка будет находится в исполняемом файле или в DLL с ресурсами, но ни в коем случае не валяется в виде ICO файла. Если иконка запакована в DLL, то нам понадобятся две функции:

Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal _ 
lpLibFileName As String) As Long

Возвращающая hInstance библиотеки с именем lpLibFileName. Достаточно указать только имя файла с расширением, без пути. Возвращает ноль в случае ошибки

Declare Function LoadIconA Lib "user32" (ByVal hInstance As Long, ByVal _
lpIconName As String) As Long

Возвращающая hIcon для иконки указанной параметром lpIconName в библиотеке. Этот параметр может быть String или Long, в зависимости от данного вами наименования в Res файле, соответственно надо изменить декларацию. Можно передать и число как строку, для этого перед числом ставится знак #, а все это берется в кавычки. Следует заметить, что использование срокового параметра не желательно из за значительно большего размера занимаемой памяти и соответственно, большего времени на передачу параметра. Функция возвращает ноль в случае ошибки

Понадобится так же функция:

Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long

Выгружающая библиотеку из памяти. Параметр hLibModule это hInstanse, возвращаемое LoadLibrary. Возвращает ноль в случае ошибки.

Обязательно надо не забыть выгрузить из памяти библиотеку, для освобождения памяти. Выгрузку можно произвести сразу же после добавления иконки в SystemTray.

Обязательно надо не забыть выгрузить из памяти библиотеку, для освобождения памяти. Выгрузку можно произвести сразу же после добавления иконки в SystemTray.

Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" _ 
(ByVal lpModuleName As String) As Long

Возвращающей hInstanse нашего приложения. В качестве lpModuleName передается имя EXE файла с расширением. Следует быть внимательным, так как имя процесса в TaskMenager не всегда соответствует имени процесса для Windows. Я использую для определения имени DLLView, можно воспользоваться, встроенным в VB System Information. Функция возвращает действительное значение только при работе скомпилированного приложения, а в режиме отладки возвращает ноль, ведь реального процесса при отладке не существует. Свойство hInstanse объекта App всегда возвращает действительное значение, однако при отладке из за отсутствия процесса LoadIcon возвращает 0, и создается "пустая" иконка, тем не менее годная для отладки (реагирующая на все события).

Полученное hInstanse передаем LoadIconA, в качестве lpIconName указываем номер или имя иконки в Res файле, как и в случае с DLL. Выгружать в этом случае ничего не надо.

Создание иконки можно проиллюстрировать следующим примером.

Считается, что иконка с номером 101 находится в файле Project1.exe. Понятно, что пока мы его не скомпилировали, ее там нет (да и самого файла нет). Форма приложения называется Form1.

Dim NID As NOTIFYICONDATA 

Sub AddIcon() 

Dim IDLib As Long ' Указатель на библиотеку
Dim IDIcon As Long ' Указатель на иконку 
Const IDMyIcon = 101 ' Идентификатор иконки внутри приложения
Dim AddResult As Long ' Результат добавления иконки

IDLib = GetModuleHandle("Project1.exe") ' Получаем hInstanse
IDIcon = LoadIcon(IDLib, "#101") ' Получаем hIcon 

' Заполняем структуру NID типа NOTIFYICONDATA

NID.cbSize = Len(NID) ' Размер структуры
NID.hwnd = Form1.hWnd ' Указатель на форму
NID.uID = IDMyIcon ' Идентификатор иконки
'Указываем, что действующими являются поля 
NID.uFlags = NIF_MESSAGE + NIF_ICON + NIF_TIP 
'uCallBackMessage, hIcon и szTip.
' Указываем, что событием возвращаемым в форму 
NID.uCallbackMessage = WM_LBUTTONDOWN 
'является MouseDown с параметром Button = 2
NID.hIcon = IDIcon ' Указатель на иконку в файле
' Передаем всплывающую фразу "MyIcon", при этом обрезаем 
NID.szTip = Left$("MyIcon", 63) & Chr(0) 
'ее до 63 символов и добавляем 64-й символ с кодом ноль
' Вызываем функцию, через параметр dwMessage указываем, 

AddResult = Shell_NotifyIcon(NIM_ADD, NID) 
'что следует добавить иконку, и передаем заполненный NID

End Sub

Удаление созданной иконки можно сделать так:

Sub DeleteIcon()

Dim DeletResult As Long
DeleteResult = Shell_NotifyIcon(NIM_DELETE, NID) 

' Вызываем функцию, через dwMessage указываем, 
'что следует удалить иконку, при этом, раз переменная NID
' описана на уровне модуля, не следует 
'заполнять ее заново 

End Sub 

Размер структуры достаточно указывать один раз, так как за время жизни переменной он измениться не может, и в данном виде составляет 88 байт. Даже при изменении всплывающей строки ее длина (строки) не будет больше 64 байт.

Для модификации иконки надо вызвать Shell_NotifyIcon с параметром dwMessage равным NIM_MODIFY и NID с внесенными изменениями, при этом параметр uFlags будет указывать, какие из параметров изменены.

В форме Form1 для обработки, к примеру, DbClick левой кнопкой мыши по иконке можно применить следующий код:

Private Sub Form_MouseDown(Button As Integer, Shift As Integer _
X As Single, Y As Single)
' Событие MouseDown происходит не потому, 
'что пользователь нажал на кнопку мыши над иконкой, а из-за того, 
'что параметр uCallbackMessage имеет значение WM_LBUTTONDOWN 

If Y = 0 Then ' Y = 0 если событие с иконкой 
   Select Case X
      Case 515*Screen.TwipsPerPixelX ' Значение X при LeftDblClick 
                                     ' Код, выполняемый в случае LeftDblClick 
   End Select
End If

End Sub

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
22K
01 ноября 2006 года
UDmitriy
1 / / 01.11.2006
Мне нравитсяМне не нравится
1 ноября 2006, 03:16:18
Все прекрасно но как получить сообщение от формы в Excel ? о действиях с иконкой.
hwnd окна закинул в иконку всетаки но реакции обратной нет?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог